checker: do not allow nil sum types init
parent
dcab79146b
commit
6f318be96c
|
@ -0,0 +1,5 @@
|
||||||
|
module builtin
|
||||||
|
|
||||||
|
struct string {
|
||||||
|
len int
|
||||||
|
}
|
|
@ -12,25 +12,25 @@ pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
|
||||||
|
|
||||||
pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral |
|
pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral |
|
||||||
CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall |
|
CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall |
|
||||||
ComptimeSelector | ConcatExpr | DumpExpr | EnumVal | FloatLiteral | GoExpr | Ident |
|
ComptimeSelector | ConcatExpr | DumpExpr | EmptyExpr | EnumVal | FloatLiteral | GoExpr |
|
||||||
IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
|
Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
|
||||||
MapInit | MatchExpr | NodeError | None | OffsetOf | OrExpr | ParExpr | PostfixExpr |
|
MapInit | MatchExpr | NodeError | None | OffsetOf | OrExpr | ParExpr | PostfixExpr |
|
||||||
PrefixExpr | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral |
|
PrefixExpr | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral |
|
||||||
StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
|
StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
|
||||||
|
|
||||||
pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl |
|
pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl |
|
||||||
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl |
|
DeferStmt | EmptyStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt |
|
||||||
GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | NodeError |
|
GlobalDecl | GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module |
|
||||||
Return | SqlStmt | StructDecl | TypeDecl
|
NodeError | Return | SqlStmt | StructDecl | TypeDecl
|
||||||
|
|
||||||
// NB: when you add a new Expr or Stmt type with a .pos field, remember to update
|
// NB: when you add a new Expr or Stmt type with a .pos field, remember to update
|
||||||
// the .position() token.Position methods too.
|
// the .position() token.Position methods too.
|
||||||
pub type ScopeObject = AsmRegister | ConstField | GlobalField | Var
|
pub type ScopeObject = AsmRegister | ConstField | GlobalField | Var
|
||||||
|
|
||||||
// TOOD: replace table.Param
|
// TODO: replace table.Param
|
||||||
pub type Node = CallArg | ConstField | EnumField | Expr | Field | File | GlobalField |
|
pub type Node = CallArg | ConstField | EnumField | Expr | Field | File | GlobalField |
|
||||||
IfBranch | MatchBranch | ScopeObject | SelectBranch | Stmt | StructField | StructInitField |
|
IfBranch | MatchBranch | NodeError | ScopeObject | SelectBranch | Stmt | StructField |
|
||||||
table.Param
|
StructInitField | table.Param
|
||||||
|
|
||||||
pub struct Type {
|
pub struct Type {
|
||||||
pub:
|
pub:
|
||||||
|
@ -38,6 +38,21 @@ pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct EmptyExpr {}
|
||||||
|
|
||||||
|
pub fn empty_expr() Expr {
|
||||||
|
return EmptyExpr{}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EmptyStmt {
|
||||||
|
pub:
|
||||||
|
pos token.Position
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn empty_stmt() Stmt {
|
||||||
|
return EmptyStmt{}
|
||||||
|
}
|
||||||
|
|
||||||
// `{stmts}` or `unsafe {stmts}`
|
// `{stmts}` or `unsafe {stmts}`
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
pub:
|
pub:
|
||||||
|
@ -1431,6 +1446,10 @@ pub fn (expr Expr) position() token.Position {
|
||||||
AnonFn {
|
AnonFn {
|
||||||
return expr.decl.pos
|
return expr.decl.pos
|
||||||
}
|
}
|
||||||
|
EmptyExpr {
|
||||||
|
println('compiler bug, unhandled EmptyExpr position()')
|
||||||
|
return token.Position{}
|
||||||
|
}
|
||||||
NodeError, ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral, CallExpr, CastExpr,
|
NodeError, ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral, CallExpr, CastExpr,
|
||||||
ChanInit, CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector, EnumVal, DumpExpr,
|
ChanInit, CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector, EnumVal, DumpExpr,
|
||||||
FloatLiteral, GoExpr, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit,
|
FloatLiteral, GoExpr, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit,
|
||||||
|
@ -1540,6 +1559,9 @@ pub:
|
||||||
|
|
||||||
pub fn (node Node) position() token.Position {
|
pub fn (node Node) position() token.Position {
|
||||||
match node {
|
match node {
|
||||||
|
NodeError {
|
||||||
|
return token.Position{}
|
||||||
|
}
|
||||||
Stmt {
|
Stmt {
|
||||||
mut pos := node.pos
|
mut pos := node.pos
|
||||||
if node is Import {
|
if node is Import {
|
||||||
|
@ -1736,15 +1758,19 @@ pub fn (node Node) children() []Node {
|
||||||
// a dependency cycle between v.ast and v.table, for the single
|
// a dependency cycle between v.ast and v.table, for the single
|
||||||
// field table.Field.default_expr, which should be ast.Expr
|
// field table.Field.default_expr, which should be ast.Expr
|
||||||
pub fn fe2ex(x table.FExpr) Expr {
|
pub fn fe2ex(x table.FExpr) Expr {
|
||||||
res := Expr{}
|
unsafe {
|
||||||
unsafe { C.memcpy(&res, &x, sizeof(Expr)) }
|
res := Expr{}
|
||||||
return res
|
C.memcpy(&res, &x, sizeof(Expr))
|
||||||
|
return res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ex2fe(x Expr) table.FExpr {
|
pub fn ex2fe(x Expr) table.FExpr {
|
||||||
res := table.FExpr{}
|
unsafe {
|
||||||
unsafe { C.memcpy(&res, &x, sizeof(table.FExpr)) }
|
res := table.FExpr{}
|
||||||
return res
|
C.memcpy(&res, &x, sizeof(table.FExpr))
|
||||||
|
return res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper for dealing with `m[k1][k2][k3][k3] = value`
|
// helper for dealing with `m[k1][k2][k3][k3] = value`
|
||||||
|
|
|
@ -9,9 +9,9 @@ pub fn resolve_init(node StructInit, typ table.Type, t &table.Table) Expr {
|
||||||
mut has_len := false
|
mut has_len := false
|
||||||
mut has_cap := false
|
mut has_cap := false
|
||||||
mut has_default := false
|
mut has_default := false
|
||||||
mut len_expr := Expr{}
|
mut len_expr := empty_expr()
|
||||||
mut cap_expr := Expr{}
|
mut cap_expr := empty_expr()
|
||||||
mut default_expr := Expr{}
|
mut default_expr := empty_expr()
|
||||||
mut exprs := []Expr{}
|
mut exprs := []Expr{}
|
||||||
for field in node.fields {
|
for field in node.fields {
|
||||||
match field.name {
|
match field.name {
|
||||||
|
|
|
@ -469,6 +469,9 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||||
utyp := c.unwrap_generic(struct_init.typ)
|
utyp := c.unwrap_generic(struct_init.typ)
|
||||||
c.ensure_type_exists(utyp, struct_init.pos) or {}
|
c.ensure_type_exists(utyp, struct_init.pos) or {}
|
||||||
type_sym := c.table.get_type_symbol(utyp)
|
type_sym := c.table.get_type_symbol(utyp)
|
||||||
|
if !c.inside_unsafe && type_sym.kind == .sum_type {
|
||||||
|
c.warn('direct sum type init (`x := SumType{}`) will be removed soon', struct_init.pos)
|
||||||
|
}
|
||||||
// Make sure the first letter is capital, do not allow e.g. `x := string{}`,
|
// Make sure the first letter is capital, do not allow e.g. `x := string{}`,
|
||||||
// but `x := T{}` is ok.
|
// but `x := T{}` is ok.
|
||||||
if !c.is_builtin_mod && !c.inside_unsafe && type_sym.language == .v
|
if !c.is_builtin_mod && !c.inside_unsafe && type_sym.language == .v
|
||||||
|
@ -3386,6 +3389,10 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
// c.expected_type = table.void_type
|
// c.expected_type = table.void_type
|
||||||
match mut node {
|
match mut node {
|
||||||
|
ast.EmptyStmt {
|
||||||
|
print_backtrace()
|
||||||
|
eprintln('Checker.stmt() EmptyStmt')
|
||||||
|
}
|
||||||
ast.NodeError {}
|
ast.NodeError {}
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
c.asm_stmt(mut node)
|
c.asm_stmt(mut node)
|
||||||
|
@ -3532,9 +3539,13 @@ fn (mut c Checker) branch_stmt(node ast.BranchStmt) {
|
||||||
fn (mut c Checker) for_c_stmt(node ast.ForCStmt) {
|
fn (mut c Checker) for_c_stmt(node ast.ForCStmt) {
|
||||||
c.in_for_count++
|
c.in_for_count++
|
||||||
prev_loop_label := c.loop_label
|
prev_loop_label := c.loop_label
|
||||||
c.stmt(node.init)
|
if node.has_init {
|
||||||
|
c.stmt(node.init)
|
||||||
|
}
|
||||||
c.expr(node.cond)
|
c.expr(node.cond)
|
||||||
c.stmt(node.inc)
|
if node.has_inc {
|
||||||
|
c.stmt(node.inc)
|
||||||
|
}
|
||||||
c.check_loop_label(node.label, node.pos)
|
c.check_loop_label(node.label, node.pos)
|
||||||
c.stmts(node.stmts)
|
c.stmts(node.stmts)
|
||||||
c.loop_label = prev_loop_label
|
c.loop_label = prev_loop_label
|
||||||
|
@ -3975,6 +3986,10 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
}
|
}
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.NodeError {}
|
ast.NodeError {}
|
||||||
|
ast.EmptyExpr {
|
||||||
|
print_backtrace()
|
||||||
|
c.error('checker.expr(): unhandled EmptyExpr', token.Position{})
|
||||||
|
}
|
||||||
ast.CTempVar {
|
ast.CTempVar {
|
||||||
return node.typ
|
return node.typ
|
||||||
}
|
}
|
||||||
|
@ -5567,7 +5582,7 @@ fn (mut c Checker) find_obj_definition(obj ast.ScopeObject) ?ast.Expr {
|
||||||
match obj {
|
match obj {
|
||||||
ast.Var, ast.ConstField, ast.GlobalField, ast.AsmRegister { name = obj.name }
|
ast.Var, ast.ConstField, ast.GlobalField, ast.AsmRegister { name = obj.name }
|
||||||
}
|
}
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.empty_expr()
|
||||||
if obj is ast.Var {
|
if obj is ast.Var {
|
||||||
if obj.is_mut {
|
if obj.is_mut {
|
||||||
return error('`$name` is mut and may have changed since its definition')
|
return error('`$name` is mut and may have changed since its definition')
|
||||||
|
@ -6202,7 +6217,9 @@ fn (mut c Checker) sql_stmt(mut node ast.SqlStmt) table.Type {
|
||||||
c.expr(expr)
|
c.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.expr(node.where_expr)
|
if node.where_expr !is ast.EmptyExpr {
|
||||||
|
c.expr(node.where_expr)
|
||||||
|
}
|
||||||
|
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
vlib/v/checker/tests/sum_type_assign_non_variant_err.vv:11:6: error: cannot assign to `w`: expected `Stmt`, not `IfExpr`
|
vlib/v/checker/tests/sum_type_assign_non_variant_err.vv:11:6: error: cannot assign to `w`: expected `Stmt`, not `IfExpr`
|
||||||
9 | fn main() {
|
9 | fn main() {
|
||||||
10 | mut w := Stmt{}
|
10 | mut w := Stmt(AnotherThing{})
|
||||||
11 | w = IfExpr{}
|
11 | w = IfExpr{}
|
||||||
| ~~~~~~~~
|
| ~~~~~~~~
|
||||||
12 | }
|
12 | }
|
||||||
|
|
|
@ -7,6 +7,6 @@ type Stmt = Expr | AnotherThing
|
||||||
struct AnotherThing {}
|
struct AnotherThing {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
mut w := Stmt{}
|
mut w := Stmt(AnotherThing{})
|
||||||
w = IfExpr{}
|
w = IfExpr{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,7 +365,7 @@ pub fn (mut f Fmt) node_str(node ast.Node) string {
|
||||||
//=== General Stmt-related methods and helpers ===//
|
//=== General Stmt-related methods and helpers ===//
|
||||||
|
|
||||||
pub fn (mut f Fmt) stmts(stmts []ast.Stmt) {
|
pub fn (mut f Fmt) stmts(stmts []ast.Stmt) {
|
||||||
mut prev_stmt := if stmts.len > 0 { stmts[0] } else { ast.Stmt{} }
|
mut prev_stmt := if stmts.len > 0 { stmts[0] } else { ast.empty_stmt() }
|
||||||
f.indent++
|
f.indent++
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
if !f.pref.building_v && f.should_insert_newline_before_node(stmt, prev_stmt) {
|
if !f.pref.building_v && f.should_insert_newline_before_node(stmt, prev_stmt) {
|
||||||
|
@ -383,6 +383,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
match node {
|
match node {
|
||||||
ast.NodeError {}
|
ast.NodeError {}
|
||||||
|
ast.EmptyStmt {}
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
f.asm_stmt(node)
|
f.asm_stmt(node)
|
||||||
}
|
}
|
||||||
|
@ -482,6 +483,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.NodeError {}
|
ast.NodeError {}
|
||||||
|
ast.EmptyExpr {}
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
f.fn_decl(node.decl)
|
f.fn_decl(node.decl)
|
||||||
}
|
}
|
||||||
|
@ -897,7 +899,11 @@ pub fn (mut f Fmt) const_decl(node ast.ConstDecl) {
|
||||||
}
|
}
|
||||||
f.indent++
|
f.indent++
|
||||||
}
|
}
|
||||||
mut prev_field := if node.fields.len > 0 { ast.Node(node.fields[0]) } else { ast.Node{} }
|
mut prev_field := if node.fields.len > 0 {
|
||||||
|
ast.Node(node.fields[0])
|
||||||
|
} else {
|
||||||
|
ast.Node(ast.NodeError{})
|
||||||
|
}
|
||||||
for field in node.fields {
|
for field in node.fields {
|
||||||
if field.comments.len > 0 {
|
if field.comments.len > 0 {
|
||||||
if f.should_insert_newline_before_node(ast.Expr(field.comments[0]), prev_field) {
|
if f.should_insert_newline_before_node(ast.Expr(field.comments[0]), prev_field) {
|
||||||
|
|
|
@ -1010,6 +1010,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
// println('g.stmt()')
|
// println('g.stmt()')
|
||||||
// g.writeln('//// stmt start')
|
// g.writeln('//// stmt start')
|
||||||
match node {
|
match node {
|
||||||
|
ast.EmptyStmt {}
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
g.write_v_source_line_info(node.pos)
|
g.write_v_source_line_info(node.pos)
|
||||||
g.gen_asm_stmt(node)
|
g.gen_asm_stmt(node)
|
||||||
|
@ -2789,6 +2790,9 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
// NB: please keep the type names in the match here in alphabetical order:
|
// NB: please keep the type names in the match here in alphabetical order:
|
||||||
match mut node {
|
match mut node {
|
||||||
|
ast.EmptyExpr {
|
||||||
|
g.error('g.expr(): unhandled EmptyExpr', token.Position{})
|
||||||
|
}
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
// TODO: dont fiddle with buffers
|
// TODO: dont fiddle with buffers
|
||||||
g.gen_anon_fn_decl(mut node)
|
g.gen_anon_fn_decl(mut node)
|
||||||
|
@ -4158,7 +4162,7 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
|
||||||
mut is_push := []bool{cap: n_channels}
|
mut is_push := []bool{cap: n_channels}
|
||||||
mut has_else := false
|
mut has_else := false
|
||||||
mut has_timeout := false
|
mut has_timeout := false
|
||||||
mut timeout_expr := ast.Expr{}
|
mut timeout_expr := ast.empty_expr()
|
||||||
mut exception_branch := -1
|
mut exception_branch := -1
|
||||||
for j, branch in node.branches {
|
for j, branch in node.branches {
|
||||||
if branch.is_else {
|
if branch.is_else {
|
||||||
|
@ -4182,7 +4186,7 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
|
||||||
elem_types << ''
|
elem_types << ''
|
||||||
} else {
|
} else {
|
||||||
// must be evaluated to tmp var before real `select` is performed
|
// must be evaluated to tmp var before real `select` is performed
|
||||||
objs << ast.Expr{}
|
objs << ast.empty_expr()
|
||||||
tmp_obj := g.new_tmp_var()
|
tmp_obj := g.new_tmp_var()
|
||||||
tmp_objs << tmp_obj
|
tmp_objs << tmp_obj
|
||||||
el_stype := g.typ(g.table.mktyp(expr.right_type))
|
el_stype := g.typ(g.table.mktyp(expr.right_type))
|
||||||
|
@ -5283,6 +5287,14 @@ fn (mut g Gen) write_builtin_types() {
|
||||||
for builtin_name in c.builtins {
|
for builtin_name in c.builtins {
|
||||||
sym := g.table.type_symbols[g.table.type_idxs[builtin_name]]
|
sym := g.table.type_symbols[g.table.type_idxs[builtin_name]]
|
||||||
if sym.kind == .interface_ {
|
if sym.kind == .interface_ {
|
||||||
|
if g.pref.is_verbose {
|
||||||
|
println('XAXAXA $sym.name')
|
||||||
|
if isnil(sym.info) {
|
||||||
|
println('FFF')
|
||||||
|
}
|
||||||
|
println(sym.info)
|
||||||
|
println(sym.kind)
|
||||||
|
}
|
||||||
g.write_interface_typesymbol_declaration(sym)
|
g.write_interface_typesymbol_declaration(sym)
|
||||||
} else {
|
} else {
|
||||||
builtin_types << sym
|
builtin_types << sym
|
||||||
|
|
|
@ -356,6 +356,7 @@ fn (mut g JsGen) stmts(stmts []ast.Stmt) {
|
||||||
fn (mut g JsGen) stmt(node ast.Stmt) {
|
fn (mut g JsGen) stmt(node ast.Stmt) {
|
||||||
g.stmt_start_pos = g.ns.out.len
|
g.stmt_start_pos = g.ns.out.len
|
||||||
match node {
|
match node {
|
||||||
|
ast.EmptyStmt{}
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
panic('inline asm is not supported by js')
|
panic('inline asm is not supported by js')
|
||||||
}
|
}
|
||||||
|
@ -447,6 +448,7 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
|
||||||
fn (mut g JsGen) expr(node ast.Expr) {
|
fn (mut g JsGen) expr(node ast.Expr) {
|
||||||
match node {
|
match node {
|
||||||
ast.NodeError {}
|
ast.NodeError {}
|
||||||
|
ast.EmptyExpr {}
|
||||||
ast.CTempVar {
|
ast.CTempVar {
|
||||||
g.write('/* ast.CTempVar: node.name */')
|
g.write('/* ast.CTempVar: node.name */')
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ pub fn (mut w Walker) mark_root_fns(all_fn_root_names []string) {
|
||||||
|
|
||||||
pub fn (mut w Walker) stmt(node ast.Stmt) {
|
pub fn (mut w Walker) stmt(node ast.Stmt) {
|
||||||
match mut node {
|
match mut node {
|
||||||
|
ast.EmptyStmt {}
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
w.asm_io(node.output)
|
w.asm_io(node.output)
|
||||||
w.asm_io(node.input)
|
w.asm_io(node.input)
|
||||||
|
@ -153,6 +154,9 @@ fn (mut w Walker) exprs(exprs []ast.Expr) {
|
||||||
|
|
||||||
fn (mut w Walker) expr(node ast.Expr) {
|
fn (mut w Walker) expr(node ast.Expr) {
|
||||||
match mut node {
|
match mut node {
|
||||||
|
ast.EmptyExpr {
|
||||||
|
panic('Walker: EmptyExpr')
|
||||||
|
}
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
w.fn_decl(mut node.decl)
|
w.fn_decl(mut node.decl)
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
||||||
r0 := right[0]
|
r0 := right[0]
|
||||||
mut v := ast.Var{
|
mut v := ast.Var{
|
||||||
name: lx.name
|
name: lx.name
|
||||||
expr: if left.len == right.len { right[i] } else { ast.Expr{} }
|
expr: if left.len == right.len { right[i] } else { ast.empty_expr() }
|
||||||
share: share
|
share: share
|
||||||
is_mut: lx.is_mut || p.inside_for
|
is_mut: lx.is_mut || p.inside_for
|
||||||
pos: lx.pos
|
pos: lx.pos
|
||||||
|
|
|
@ -21,7 +21,7 @@ fn (mut p Parser) array_init() ast.ArrayInit {
|
||||||
mut has_val := false
|
mut has_val := false
|
||||||
mut has_type := false
|
mut has_type := false
|
||||||
mut has_default := false
|
mut has_default := false
|
||||||
mut default_expr := ast.Expr{}
|
mut default_expr := ast.empty_expr()
|
||||||
if p.tok.kind == .rsbr {
|
if p.tok.kind == .rsbr {
|
||||||
last_pos = p.tok.position()
|
last_pos = p.tok.position()
|
||||||
// []typ => `[]` and `typ` must be on the same line
|
// []typ => `[]` and `typ` must be on the same line
|
||||||
|
@ -103,8 +103,8 @@ fn (mut p Parser) array_init() ast.ArrayInit {
|
||||||
}
|
}
|
||||||
mut has_len := false
|
mut has_len := false
|
||||||
mut has_cap := false
|
mut has_cap := false
|
||||||
mut len_expr := ast.Expr{}
|
mut len_expr := ast.empty_expr()
|
||||||
mut cap_expr := ast.Expr{}
|
mut cap_expr := ast.empty_expr()
|
||||||
if p.tok.kind == .lcbr && exprs.len == 0 && array_type != table.void_type {
|
if p.tok.kind == .lcbr && exprs.len == 0 && array_type != table.void_type {
|
||||||
// `[]int{ len: 10, cap: 100}` syntax
|
// `[]int{ len: 10, cap: 100}` syntax
|
||||||
p.next()
|
p.next()
|
||||||
|
|
|
@ -129,7 +129,7 @@ pub fn (mut p Parser) call_args() []ast.CallArg {
|
||||||
p.next()
|
p.next()
|
||||||
array_decompose = true
|
array_decompose = true
|
||||||
}
|
}
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.empty_expr()
|
||||||
if p.tok.kind == .name && p.peek_tok.kind == .colon {
|
if p.tok.kind == .name && p.peek_tok.kind == .colon {
|
||||||
// `foo(key:val, key2:val2)`
|
// `foo(key:val, key2:val2)`
|
||||||
expr = p.struct_init(true) // short_syntax:true
|
expr = p.struct_init(true) // short_syntax:true
|
||||||
|
|
|
@ -35,9 +35,9 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
if p.tok.kind == .key_mut {
|
if p.tok.kind == .key_mut {
|
||||||
return p.error('`mut` is not needed in `for ;;` loops: use `for i := 0; i < n; i ++ {`')
|
return p.error('`mut` is not needed in `for ;;` loops: use `for i := 0; i < n; i ++ {`')
|
||||||
}
|
}
|
||||||
mut init := ast.Stmt{}
|
mut init := ast.empty_stmt()
|
||||||
mut cond := p.new_true_expr()
|
mut cond := p.new_true_expr()
|
||||||
mut inc := ast.Stmt{}
|
mut inc := ast.empty_stmt()
|
||||||
mut has_init := false
|
mut has_init := false
|
||||||
mut has_cond := false
|
mut has_cond := false
|
||||||
mut has_inc := false
|
mut has_inc := false
|
||||||
|
@ -136,7 +136,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
// 0 .. 10
|
// 0 .. 10
|
||||||
// start := p.tok.lit.int()
|
// start := p.tok.lit.int()
|
||||||
// TODO use RangeExpr
|
// TODO use RangeExpr
|
||||||
mut high_expr := ast.Expr{}
|
mut high_expr := ast.empty_expr()
|
||||||
mut is_range := false
|
mut is_range := false
|
||||||
if p.tok.kind == .dotdot {
|
if p.tok.kind == .dotdot {
|
||||||
is_range = true
|
is_range = true
|
||||||
|
|
|
@ -79,7 +79,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
||||||
return ast.IfExpr{}
|
return ast.IfExpr{}
|
||||||
}
|
}
|
||||||
comments << p.eat_comments({})
|
comments << p.eat_comments({})
|
||||||
mut cond := ast.Expr{}
|
mut cond := ast.empty_expr()
|
||||||
mut is_guard := false
|
mut is_guard := false
|
||||||
// `if x := opt() {`
|
// `if x := opt() {`
|
||||||
if !is_comptime && p.peek_tok.kind == .decl_assign {
|
if !is_comptime && p.peek_tok.kind == .decl_assign {
|
||||||
|
@ -290,7 +290,7 @@ fn (mut p Parser) select_expr() ast.SelectExpr {
|
||||||
// final else
|
// final else
|
||||||
mut is_else := false
|
mut is_else := false
|
||||||
mut is_timeout := false
|
mut is_timeout := false
|
||||||
mut stmt := ast.Stmt{}
|
mut stmt := ast.empty_stmt()
|
||||||
if p.tok.kind == .key_else {
|
if p.tok.kind == .key_else {
|
||||||
if has_timeout {
|
if has_timeout {
|
||||||
p.error_with_pos('timeout `> t` and `else` are mutually exclusive `select` keys',
|
p.error_with_pos('timeout `> t` and `else` are mutually exclusive `select` keys',
|
||||||
|
|
|
@ -597,7 +597,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
|
||||||
}
|
}
|
||||||
// TODO remove dummy return statement
|
// TODO remove dummy return statement
|
||||||
// the compiler complains if it's not there
|
// the compiler complains if it's not there
|
||||||
return ast.Stmt{}
|
return ast.empty_stmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO [if vfmt]
|
// TODO [if vfmt]
|
||||||
|
@ -1757,7 +1757,7 @@ fn (p &Parser) is_generic_call() bool {
|
||||||
|
|
||||||
pub fn (mut p Parser) name_expr() ast.Expr {
|
pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
prev_tok_kind := p.prev_tok.kind
|
prev_tok_kind := p.prev_tok.kind
|
||||||
mut node := ast.Expr{}
|
mut node := ast.empty_expr()
|
||||||
if p.expecting_type {
|
if p.expecting_type {
|
||||||
p.expecting_type = false
|
p.expecting_type = false
|
||||||
// get type position before moving to next
|
// get type position before moving to next
|
||||||
|
@ -1801,7 +1801,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
mut last_pos := first_pos
|
mut last_pos := first_pos
|
||||||
chan_type := p.parse_chan_type()
|
chan_type := p.parse_chan_type()
|
||||||
mut has_cap := false
|
mut has_cap := false
|
||||||
mut cap_expr := ast.Expr{}
|
mut cap_expr := ast.empty_expr()
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
if p.tok.kind == .rcbr {
|
if p.tok.kind == .rcbr {
|
||||||
last_pos = p.tok.position()
|
last_pos = p.tok.position()
|
||||||
|
@ -1910,8 +1910,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
// without the next line int would result in int*
|
// without the next line int would result in int*
|
||||||
p.is_amp = false
|
p.is_amp = false
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.empty_expr()
|
||||||
mut arg := ast.Expr{}
|
mut arg := ast.empty_expr()
|
||||||
mut has_arg := false
|
mut has_arg := false
|
||||||
expr = p.expr(0)
|
expr = p.expr(0)
|
||||||
// TODO, string(b, len)
|
// TODO, string(b, len)
|
||||||
|
@ -2013,7 +2013,7 @@ fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
||||||
left: left
|
left: left
|
||||||
pos: pos
|
pos: pos
|
||||||
index: ast.RangeExpr{
|
index: ast.RangeExpr{
|
||||||
low: ast.Expr{}
|
low: ast.empty_expr()
|
||||||
high: high
|
high: high
|
||||||
has_high: true
|
has_high: true
|
||||||
pos: pos
|
pos: pos
|
||||||
|
@ -2025,7 +2025,7 @@ fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
||||||
if p.tok.kind == .dotdot {
|
if p.tok.kind == .dotdot {
|
||||||
// [start..end] or [start..]
|
// [start..end] or [start..]
|
||||||
p.next()
|
p.next()
|
||||||
mut high := ast.Expr{}
|
mut high := ast.empty_expr()
|
||||||
if p.tok.kind != .rsbr {
|
if p.tok.kind != .rsbr {
|
||||||
has_high = true
|
has_high = true
|
||||||
high = p.expr(0)
|
high = p.expr(0)
|
||||||
|
@ -2263,7 +2263,7 @@ fn (mut p Parser) string_expr() ast.Expr {
|
||||||
if is_raw || is_cstr {
|
if is_raw || is_cstr {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
mut node := ast.Expr{}
|
mut node := ast.empty_expr()
|
||||||
val := p.tok.lit
|
val := p.tok.lit
|
||||||
pos := p.tok.position()
|
pos := p.tok.position()
|
||||||
if p.peek_tok.kind != .str_dollar {
|
if p.peek_tok.kind != .str_dollar {
|
||||||
|
@ -2372,7 +2372,7 @@ fn (mut p Parser) parse_number_literal() ast.Expr {
|
||||||
}
|
}
|
||||||
lit := p.tok.lit
|
lit := p.tok.lit
|
||||||
full_lit := if is_neg { '-' + lit } else { lit }
|
full_lit := if is_neg { '-' + lit } else { lit }
|
||||||
mut node := ast.Expr{}
|
mut node := ast.empty_expr()
|
||||||
if lit.index_any('.eE') >= 0 && lit[..2] !in ['0x', '0X', '0o', '0O', '0b', '0B'] {
|
if lit.index_any('.eE') >= 0 && lit[..2] !in ['0x', '0X', '0o', '0O', '0b', '0B'] {
|
||||||
node = ast.FloatLiteral{
|
node = ast.FloatLiteral{
|
||||||
val: full_lit
|
val: full_lit
|
||||||
|
@ -2714,7 +2714,7 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
|
||||||
p.error('global assign must have the type around the value, use `__global ( name = type(value) )`')
|
p.error('global assign must have the type around the value, use `__global ( name = type(value) )`')
|
||||||
return ast.GlobalDecl{}
|
return ast.GlobalDecl{}
|
||||||
}
|
}
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.empty_expr()
|
||||||
if has_expr {
|
if has_expr {
|
||||||
if p.tok.kind != .lpar {
|
if p.tok.kind != .lpar {
|
||||||
p.error('global assign must have a type and value, use `__global ( name = type(value) )` or `__global ( name type )`')
|
p.error('global assign must have a type and value, use `__global ( name = type(value) )` or `__global ( name type )`')
|
||||||
|
@ -2769,7 +2769,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||||
pos := p.tok.position()
|
pos := p.tok.position()
|
||||||
val := p.check_name()
|
val := p.check_name()
|
||||||
vals << val
|
vals << val
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.empty_expr()
|
||||||
mut has_expr := false
|
mut has_expr := false
|
||||||
// p.warn('enum val $val')
|
// p.warn('enum val $val')
|
||||||
if p.tok.kind == .assign {
|
if p.tok.kind == .assign {
|
||||||
|
@ -2854,7 +2854,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
|
||||||
if name.len == 1 && name[0].is_capital() {
|
if name.len == 1 && name[0].is_capital() {
|
||||||
p.error_with_pos('single letter capital names are reserved for generic template types.',
|
p.error_with_pos('single letter capital names are reserved for generic template types.',
|
||||||
decl_pos)
|
decl_pos)
|
||||||
return ast.TypeDecl{}
|
return ast.FnTypeDecl{}
|
||||||
}
|
}
|
||||||
mut sum_variants := []ast.SumTypeVariant{}
|
mut sum_variants := []ast.SumTypeVariant{}
|
||||||
p.check(.assign)
|
p.check(.assign)
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
eprintln('parsing file: ${p.file_name:-30} | tok.kind: ${p.tok.kind:-10} | tok.lit: ${p.tok.lit:-10} | tok_pos: ${tok_pos.str():-45} | expr($precedence)')
|
eprintln('parsing file: ${p.file_name:-30} | tok.kind: ${p.tok.kind:-10} | tok.lit: ${p.tok.lit:-10} | tok_pos: ${tok_pos.str():-45} | expr($precedence)')
|
||||||
}
|
}
|
||||||
// println('\n\nparser.expr()')
|
// println('\n\nparser.expr()')
|
||||||
mut node := ast.Expr{}
|
mut node := ast.empty_expr()
|
||||||
is_stmt_ident := p.is_stmt_ident
|
is_stmt_ident := p.is_stmt_ident
|
||||||
p.is_stmt_ident = false
|
p.is_stmt_ident = false
|
||||||
if !p.pref.is_fmt {
|
if !p.pref.is_fmt {
|
||||||
|
@ -439,7 +439,7 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||||
precedence := p.tok.precedence()
|
precedence := p.tok.precedence()
|
||||||
mut pos := p.tok.position()
|
mut pos := p.tok.position()
|
||||||
p.next()
|
p.next()
|
||||||
mut right := ast.Expr{}
|
mut right := ast.empty_expr()
|
||||||
prev_expecting_type := p.expecting_type
|
prev_expecting_type := p.expecting_type
|
||||||
if op in [.key_is, .not_is] {
|
if op in [.key_is, .not_is] {
|
||||||
p.expecting_type = true
|
p.expecting_type = true
|
||||||
|
|
|
@ -22,7 +22,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
||||||
}
|
}
|
||||||
table_pos := p.tok.position()
|
table_pos := p.tok.position()
|
||||||
table_type := p.parse_type() // `User`
|
table_type := p.parse_type() // `User`
|
||||||
mut where_expr := ast.Expr{}
|
mut where_expr := ast.empty_expr()
|
||||||
has_where := p.tok.kind == .name && p.tok.lit == 'where'
|
has_where := p.tok.kind == .name && p.tok.lit == 'where'
|
||||||
mut query_one := false // one object is returned, not an array
|
mut query_one := false // one object is returned, not an array
|
||||||
if has_where {
|
if has_where {
|
||||||
|
@ -40,11 +40,11 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut has_limit := false
|
mut has_limit := false
|
||||||
mut limit_expr := ast.Expr{}
|
mut limit_expr := ast.empty_expr()
|
||||||
mut has_offset := false
|
mut has_offset := false
|
||||||
mut offset_expr := ast.Expr{}
|
mut offset_expr := ast.empty_expr()
|
||||||
mut has_order := false
|
mut has_order := false
|
||||||
mut order_expr := ast.Expr{}
|
mut order_expr := ast.empty_expr()
|
||||||
mut has_desc := false
|
mut has_desc := false
|
||||||
if p.tok.kind == .name && p.tok.lit == 'order' {
|
if p.tok.kind == .name && p.tok.lit == 'order' {
|
||||||
p.check_name() // `order`
|
p.check_name() // `order`
|
||||||
|
@ -172,7 +172,7 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
||||||
}
|
}
|
||||||
|
|
||||||
mut table_pos := p.tok.position()
|
mut table_pos := p.tok.position()
|
||||||
mut where_expr := ast.Expr{}
|
mut where_expr := ast.empty_expr()
|
||||||
if kind == .insert {
|
if kind == .insert {
|
||||||
table_pos = p.tok.position()
|
table_pos = p.tok.position()
|
||||||
table_type = p.parse_type()
|
table_type = p.parse_type()
|
||||||
|
|
|
@ -239,7 +239,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
||||||
// attrs are stored in `p.attrs`
|
// attrs are stored in `p.attrs`
|
||||||
p.attributes()
|
p.attributes()
|
||||||
}
|
}
|
||||||
mut default_expr := ast.Expr{}
|
mut default_expr := ast.empty_expr()
|
||||||
mut has_default_expr := false
|
mut has_default_expr := false
|
||||||
if !is_embed {
|
if !is_embed {
|
||||||
if p.tok.kind == .assign {
|
if p.tok.kind == .assign {
|
||||||
|
@ -352,12 +352,12 @@ fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||||
// p.warn(is_short_syntax.str())
|
// p.warn(is_short_syntax.str())
|
||||||
saved_is_amp := p.is_amp
|
saved_is_amp := p.is_amp
|
||||||
p.is_amp = false
|
p.is_amp = false
|
||||||
mut update_expr := ast.Expr{}
|
mut update_expr := ast.empty_expr()
|
||||||
mut update_expr_comments := []ast.Comment{}
|
mut update_expr_comments := []ast.Comment{}
|
||||||
mut has_update_expr := false
|
mut has_update_expr := false
|
||||||
for p.tok.kind !in [.rcbr, .rpar, .eof] {
|
for p.tok.kind !in [.rcbr, .rpar, .eof] {
|
||||||
mut field_name := ''
|
mut field_name := ''
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.empty_expr()
|
||||||
mut field_pos := token.Position{}
|
mut field_pos := token.Position{}
|
||||||
mut first_field_pos := token.Position{}
|
mut first_field_pos := token.Position{}
|
||||||
mut comments := []ast.Comment{}
|
mut comments := []ast.Comment{}
|
||||||
|
|
Loading…
Reference in New Issue