From 6f318be96ce09719b8df6bd919d976dcaa2f4373 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 31 Mar 2021 11:13:15 +0300 Subject: [PATCH] checker: do not allow nil sum types init --- vlib/builtin/bare/builtin.v | 5 ++ .../{bare => linux_bare}/.checks/.gitignore | 0 .../{bare => linux_bare}/.checks/checks.v | 0 .../.checks/consts/consts.v | 0 .../.checks/forkedtest/forkedtest.v | 0 .../.checks/linuxsys/linuxsys.v | 0 .../{bare => linux_bare}/.checks/readme.md | 0 .../.checks/sample_text1.txt | 0 .../.checks/string/string.v | 0 .../.checks/structs/structs.v | 0 .../builtin/{bare => linux_bare}/array_bare.v | 0 .../{bare => linux_bare}/builtin_bare.v | 0 .../{bare => linux_bare}/linuxsys_bare.v | 0 vlib/builtin/{bare => linux_bare}/mm_bare.v | 0 .../{bare => linux_bare}/string_bare.v | 0 .../syscallwrapper_test.v | 0 vlib/v/ast/ast.v | 54 ++++++++++++++----- vlib/v/ast/init.v | 6 +-- vlib/v/checker/checker.v | 25 +++++++-- .../tests/sum_type_assign_non_variant_err.out | 4 +- .../tests/sum_type_assign_non_variant_err.vv | 4 +- vlib/v/fmt/fmt.v | 10 +++- vlib/v/gen/c/cgen.v | 16 +++++- vlib/v/gen/js/js.v | 2 + vlib/v/markused/walker.v | 4 ++ vlib/v/parser/assign.v | 2 +- vlib/v/parser/containers.v | 6 +-- vlib/v/parser/fn.v | 2 +- vlib/v/parser/for.v | 6 +-- vlib/v/parser/if_match.v | 4 +- vlib/v/parser/parser.v | 24 ++++----- vlib/v/parser/pratt.v | 4 +- vlib/v/parser/sql.v | 10 ++-- vlib/v/parser/struct.v | 6 +-- 34 files changed, 133 insertions(+), 61 deletions(-) create mode 100644 vlib/builtin/bare/builtin.v rename vlib/builtin/{bare => linux_bare}/.checks/.gitignore (100%) rename vlib/builtin/{bare => linux_bare}/.checks/checks.v (100%) rename vlib/builtin/{bare => linux_bare}/.checks/consts/consts.v (100%) rename vlib/builtin/{bare => linux_bare}/.checks/forkedtest/forkedtest.v (100%) rename vlib/builtin/{bare => linux_bare}/.checks/linuxsys/linuxsys.v (100%) rename vlib/builtin/{bare => linux_bare}/.checks/readme.md (100%) rename vlib/builtin/{bare => linux_bare}/.checks/sample_text1.txt (100%) rename vlib/builtin/{bare => linux_bare}/.checks/string/string.v (100%) rename vlib/builtin/{bare => linux_bare}/.checks/structs/structs.v (100%) rename vlib/builtin/{bare => linux_bare}/array_bare.v (100%) rename vlib/builtin/{bare => linux_bare}/builtin_bare.v (100%) rename vlib/builtin/{bare => linux_bare}/linuxsys_bare.v (100%) rename vlib/builtin/{bare => linux_bare}/mm_bare.v (100%) rename vlib/builtin/{bare => linux_bare}/string_bare.v (100%) rename vlib/builtin/{bare => linux_bare}/syscallwrapper_test.v (100%) diff --git a/vlib/builtin/bare/builtin.v b/vlib/builtin/bare/builtin.v new file mode 100644 index 0000000000..d64aa2be1b --- /dev/null +++ b/vlib/builtin/bare/builtin.v @@ -0,0 +1,5 @@ +module builtin + +struct string { + len int +} diff --git a/vlib/builtin/bare/.checks/.gitignore b/vlib/builtin/linux_bare/.checks/.gitignore similarity index 100% rename from vlib/builtin/bare/.checks/.gitignore rename to vlib/builtin/linux_bare/.checks/.gitignore diff --git a/vlib/builtin/bare/.checks/checks.v b/vlib/builtin/linux_bare/.checks/checks.v similarity index 100% rename from vlib/builtin/bare/.checks/checks.v rename to vlib/builtin/linux_bare/.checks/checks.v diff --git a/vlib/builtin/bare/.checks/consts/consts.v b/vlib/builtin/linux_bare/.checks/consts/consts.v similarity index 100% rename from vlib/builtin/bare/.checks/consts/consts.v rename to vlib/builtin/linux_bare/.checks/consts/consts.v diff --git a/vlib/builtin/bare/.checks/forkedtest/forkedtest.v b/vlib/builtin/linux_bare/.checks/forkedtest/forkedtest.v similarity index 100% rename from vlib/builtin/bare/.checks/forkedtest/forkedtest.v rename to vlib/builtin/linux_bare/.checks/forkedtest/forkedtest.v diff --git a/vlib/builtin/bare/.checks/linuxsys/linuxsys.v b/vlib/builtin/linux_bare/.checks/linuxsys/linuxsys.v similarity index 100% rename from vlib/builtin/bare/.checks/linuxsys/linuxsys.v rename to vlib/builtin/linux_bare/.checks/linuxsys/linuxsys.v diff --git a/vlib/builtin/bare/.checks/readme.md b/vlib/builtin/linux_bare/.checks/readme.md similarity index 100% rename from vlib/builtin/bare/.checks/readme.md rename to vlib/builtin/linux_bare/.checks/readme.md diff --git a/vlib/builtin/bare/.checks/sample_text1.txt b/vlib/builtin/linux_bare/.checks/sample_text1.txt similarity index 100% rename from vlib/builtin/bare/.checks/sample_text1.txt rename to vlib/builtin/linux_bare/.checks/sample_text1.txt diff --git a/vlib/builtin/bare/.checks/string/string.v b/vlib/builtin/linux_bare/.checks/string/string.v similarity index 100% rename from vlib/builtin/bare/.checks/string/string.v rename to vlib/builtin/linux_bare/.checks/string/string.v diff --git a/vlib/builtin/bare/.checks/structs/structs.v b/vlib/builtin/linux_bare/.checks/structs/structs.v similarity index 100% rename from vlib/builtin/bare/.checks/structs/structs.v rename to vlib/builtin/linux_bare/.checks/structs/structs.v diff --git a/vlib/builtin/bare/array_bare.v b/vlib/builtin/linux_bare/array_bare.v similarity index 100% rename from vlib/builtin/bare/array_bare.v rename to vlib/builtin/linux_bare/array_bare.v diff --git a/vlib/builtin/bare/builtin_bare.v b/vlib/builtin/linux_bare/builtin_bare.v similarity index 100% rename from vlib/builtin/bare/builtin_bare.v rename to vlib/builtin/linux_bare/builtin_bare.v diff --git a/vlib/builtin/bare/linuxsys_bare.v b/vlib/builtin/linux_bare/linuxsys_bare.v similarity index 100% rename from vlib/builtin/bare/linuxsys_bare.v rename to vlib/builtin/linux_bare/linuxsys_bare.v diff --git a/vlib/builtin/bare/mm_bare.v b/vlib/builtin/linux_bare/mm_bare.v similarity index 100% rename from vlib/builtin/bare/mm_bare.v rename to vlib/builtin/linux_bare/mm_bare.v diff --git a/vlib/builtin/bare/string_bare.v b/vlib/builtin/linux_bare/string_bare.v similarity index 100% rename from vlib/builtin/bare/string_bare.v rename to vlib/builtin/linux_bare/string_bare.v diff --git a/vlib/builtin/bare/syscallwrapper_test.v b/vlib/builtin/linux_bare/syscallwrapper_test.v similarity index 100% rename from vlib/builtin/bare/syscallwrapper_test.v rename to vlib/builtin/linux_bare/syscallwrapper_test.v diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 95e362c993..faa7dbdc6d 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -12,25 +12,25 @@ pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral | CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall | - ComptimeSelector | ConcatExpr | DumpExpr | EnumVal | FloatLiteral | GoExpr | Ident | - IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | + ComptimeSelector | ConcatExpr | DumpExpr | EmptyExpr | EnumVal | FloatLiteral | GoExpr | + Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr | NodeError | None | OffsetOf | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral | StructInit | Type | TypeOf | UnsafeExpr pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl | - DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | - GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | NodeError | - Return | SqlStmt | StructDecl | TypeDecl + DeferStmt | EmptyStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | + GlobalDecl | GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | + NodeError | Return | SqlStmt | StructDecl | TypeDecl // NB: when you add a new Expr or Stmt type with a .pos field, remember to update // the .position() token.Position methods too. 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 | - IfBranch | MatchBranch | ScopeObject | SelectBranch | Stmt | StructField | StructInitField | - table.Param + IfBranch | MatchBranch | NodeError | ScopeObject | SelectBranch | Stmt | StructField | + StructInitField | table.Param pub struct Type { pub: @@ -38,6 +38,21 @@ pub: 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}` pub struct Block { pub: @@ -1431,6 +1446,10 @@ pub fn (expr Expr) position() token.Position { AnonFn { return expr.decl.pos } + EmptyExpr { + println('compiler bug, unhandled EmptyExpr position()') + return token.Position{} + } NodeError, ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral, CallExpr, CastExpr, ChanInit, CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector, EnumVal, DumpExpr, FloatLiteral, GoExpr, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit, @@ -1540,6 +1559,9 @@ pub: pub fn (node Node) position() token.Position { match node { + NodeError { + return token.Position{} + } Stmt { mut pos := node.pos 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 // field table.Field.default_expr, which should be ast.Expr pub fn fe2ex(x table.FExpr) Expr { - res := Expr{} - unsafe { C.memcpy(&res, &x, sizeof(Expr)) } - return res + unsafe { + res := Expr{} + C.memcpy(&res, &x, sizeof(Expr)) + return res + } } pub fn ex2fe(x Expr) table.FExpr { - res := table.FExpr{} - unsafe { C.memcpy(&res, &x, sizeof(table.FExpr)) } - return res + unsafe { + res := table.FExpr{} + C.memcpy(&res, &x, sizeof(table.FExpr)) + return res + } } // helper for dealing with `m[k1][k2][k3][k3] = value` diff --git a/vlib/v/ast/init.v b/vlib/v/ast/init.v index b730d988ca..81ad29ad8c 100644 --- a/vlib/v/ast/init.v +++ b/vlib/v/ast/init.v @@ -9,9 +9,9 @@ pub fn resolve_init(node StructInit, typ table.Type, t &table.Table) Expr { mut has_len := false mut has_cap := false mut has_default := false - mut len_expr := Expr{} - mut cap_expr := Expr{} - mut default_expr := Expr{} + mut len_expr := empty_expr() + mut cap_expr := empty_expr() + mut default_expr := empty_expr() mut exprs := []Expr{} for field in node.fields { match field.name { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 5a67b16f74..3a454bf95b 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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) c.ensure_type_exists(utyp, struct_init.pos) or {} 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{}`, // but `x := T{}` is ok. 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 match mut node { + ast.EmptyStmt { + print_backtrace() + eprintln('Checker.stmt() EmptyStmt') + } ast.NodeError {} ast.AsmStmt { 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) { c.in_for_count++ prev_loop_label := c.loop_label - c.stmt(node.init) + if node.has_init { + c.stmt(node.init) + } 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.stmts(node.stmts) c.loop_label = prev_loop_label @@ -3975,6 +3986,10 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { } match mut node { ast.NodeError {} + ast.EmptyExpr { + print_backtrace() + c.error('checker.expr(): unhandled EmptyExpr', token.Position{}) + } ast.CTempVar { return node.typ } @@ -5567,7 +5582,7 @@ fn (mut c Checker) find_obj_definition(obj ast.ScopeObject) ?ast.Expr { match obj { 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_mut { 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(node.where_expr) + if node.where_expr !is ast.EmptyExpr { + c.expr(node.where_expr) + } return table.void_type } diff --git a/vlib/v/checker/tests/sum_type_assign_non_variant_err.out b/vlib/v/checker/tests/sum_type_assign_non_variant_err.out index b9a8079f72..62893b3e1c 100644 --- a/vlib/v/checker/tests/sum_type_assign_non_variant_err.out +++ b/vlib/v/checker/tests/sum_type_assign_non_variant_err.out @@ -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` 9 | fn main() { - 10 | mut w := Stmt{} + 10 | mut w := Stmt(AnotherThing{}) 11 | w = IfExpr{} | ~~~~~~~~ - 12 | } \ No newline at end of file + 12 | } diff --git a/vlib/v/checker/tests/sum_type_assign_non_variant_err.vv b/vlib/v/checker/tests/sum_type_assign_non_variant_err.vv index 98dcaac1bb..68f36ec1b1 100644 --- a/vlib/v/checker/tests/sum_type_assign_non_variant_err.vv +++ b/vlib/v/checker/tests/sum_type_assign_non_variant_err.vv @@ -7,6 +7,6 @@ type Stmt = Expr | AnotherThing struct AnotherThing {} fn main() { - mut w := Stmt{} + mut w := Stmt(AnotherThing{}) w = IfExpr{} -} \ No newline at end of file +} diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index e97af6ecd1..ed8d84fcd1 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -365,7 +365,7 @@ pub fn (mut f Fmt) node_str(node ast.Node) string { //=== General Stmt-related methods and helpers ===// 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++ for stmt in stmts { 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 { ast.NodeError {} + ast.EmptyStmt {} ast.AsmStmt { f.asm_stmt(node) } @@ -482,6 +483,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) { } match mut node { ast.NodeError {} + ast.EmptyExpr {} ast.AnonFn { f.fn_decl(node.decl) } @@ -897,7 +899,11 @@ pub fn (mut f Fmt) const_decl(node ast.ConstDecl) { } 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 { if field.comments.len > 0 { if f.should_insert_newline_before_node(ast.Expr(field.comments[0]), prev_field) { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index deded48156..8fb1f8f6c5 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -1010,6 +1010,7 @@ fn (mut g Gen) stmt(node ast.Stmt) { // println('g.stmt()') // g.writeln('//// stmt start') match node { + ast.EmptyStmt {} ast.AsmStmt { g.write_v_source_line_info(node.pos) 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: match mut node { + ast.EmptyExpr { + g.error('g.expr(): unhandled EmptyExpr', token.Position{}) + } ast.AnonFn { // TODO: dont fiddle with buffers 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 has_else := false mut has_timeout := false - mut timeout_expr := ast.Expr{} + mut timeout_expr := ast.empty_expr() mut exception_branch := -1 for j, branch in node.branches { if branch.is_else { @@ -4182,7 +4186,7 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) { elem_types << '' } else { // 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_objs << tmp_obj 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 { sym := g.table.type_symbols[g.table.type_idxs[builtin_name]] 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) } else { builtin_types << sym diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 2cfa596d91..8854f1e304 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -356,6 +356,7 @@ fn (mut g JsGen) stmts(stmts []ast.Stmt) { fn (mut g JsGen) stmt(node ast.Stmt) { g.stmt_start_pos = g.ns.out.len match node { + ast.EmptyStmt{} ast.AsmStmt { 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) { match node { ast.NodeError {} + ast.EmptyExpr {} ast.CTempVar { g.write('/* ast.CTempVar: node.name */') } diff --git a/vlib/v/markused/walker.v b/vlib/v/markused/walker.v index a14b74301a..488b383f97 100644 --- a/vlib/v/markused/walker.v +++ b/vlib/v/markused/walker.v @@ -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) { match mut node { + ast.EmptyStmt {} ast.AsmStmt { w.asm_io(node.output) 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) { match mut node { + ast.EmptyExpr { + panic('Walker: EmptyExpr') + } ast.AnonFn { w.fn_decl(mut node.decl) } diff --git a/vlib/v/parser/assign.v b/vlib/v/parser/assign.v index 4c3c316264..136018704f 100644 --- a/vlib/v/parser/assign.v +++ b/vlib/v/parser/assign.v @@ -149,7 +149,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme r0 := right[0] mut v := ast.Var{ 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 is_mut: lx.is_mut || p.inside_for pos: lx.pos diff --git a/vlib/v/parser/containers.v b/vlib/v/parser/containers.v index dcd840e83d..18ff477c23 100644 --- a/vlib/v/parser/containers.v +++ b/vlib/v/parser/containers.v @@ -21,7 +21,7 @@ fn (mut p Parser) array_init() ast.ArrayInit { mut has_val := false mut has_type := false mut has_default := false - mut default_expr := ast.Expr{} + mut default_expr := ast.empty_expr() if p.tok.kind == .rsbr { last_pos = p.tok.position() // []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_cap := false - mut len_expr := ast.Expr{} - mut cap_expr := ast.Expr{} + mut len_expr := ast.empty_expr() + mut cap_expr := ast.empty_expr() if p.tok.kind == .lcbr && exprs.len == 0 && array_type != table.void_type { // `[]int{ len: 10, cap: 100}` syntax p.next() diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 56051f1a60..f66bfa8c61 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -129,7 +129,7 @@ pub fn (mut p Parser) call_args() []ast.CallArg { p.next() array_decompose = true } - mut expr := ast.Expr{} + mut expr := ast.empty_expr() if p.tok.kind == .name && p.peek_tok.kind == .colon { // `foo(key:val, key2:val2)` expr = p.struct_init(true) // short_syntax:true diff --git a/vlib/v/parser/for.v b/vlib/v/parser/for.v index 252a92e591..546585fa90 100644 --- a/vlib/v/parser/for.v +++ b/vlib/v/parser/for.v @@ -35,9 +35,9 @@ fn (mut p Parser) for_stmt() ast.Stmt { if p.tok.kind == .key_mut { 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 inc := ast.Stmt{} + mut inc := ast.empty_stmt() mut has_init := false mut has_cond := false mut has_inc := false @@ -136,7 +136,7 @@ fn (mut p Parser) for_stmt() ast.Stmt { // 0 .. 10 // start := p.tok.lit.int() // TODO use RangeExpr - mut high_expr := ast.Expr{} + mut high_expr := ast.empty_expr() mut is_range := false if p.tok.kind == .dotdot { is_range = true diff --git a/vlib/v/parser/if_match.v b/vlib/v/parser/if_match.v index 01e93098e3..dd37d18f33 100644 --- a/vlib/v/parser/if_match.v +++ b/vlib/v/parser/if_match.v @@ -79,7 +79,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { return ast.IfExpr{} } comments << p.eat_comments({}) - mut cond := ast.Expr{} + mut cond := ast.empty_expr() mut is_guard := false // `if x := opt() {` if !is_comptime && p.peek_tok.kind == .decl_assign { @@ -290,7 +290,7 @@ fn (mut p Parser) select_expr() ast.SelectExpr { // final else mut is_else := false mut is_timeout := false - mut stmt := ast.Stmt{} + mut stmt := ast.empty_stmt() if p.tok.kind == .key_else { if has_timeout { p.error_with_pos('timeout `> t` and `else` are mutually exclusive `select` keys', diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 6ac5193c34..91b495b254 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -597,7 +597,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt { } // TODO remove dummy return statement // the compiler complains if it's not there - return ast.Stmt{} + return ast.empty_stmt() } // TODO [if vfmt] @@ -1757,7 +1757,7 @@ fn (p &Parser) is_generic_call() bool { pub fn (mut p Parser) name_expr() ast.Expr { prev_tok_kind := p.prev_tok.kind - mut node := ast.Expr{} + mut node := ast.empty_expr() if p.expecting_type { p.expecting_type = false // 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 chan_type := p.parse_chan_type() mut has_cap := false - mut cap_expr := ast.Expr{} + mut cap_expr := ast.empty_expr() p.check(.lcbr) if p.tok.kind == .rcbr { 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* p.is_amp = false p.check(.lpar) - mut expr := ast.Expr{} - mut arg := ast.Expr{} + mut expr := ast.empty_expr() + mut arg := ast.empty_expr() mut has_arg := false expr = p.expr(0) // TODO, string(b, len) @@ -2013,7 +2013,7 @@ fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr { left: left pos: pos index: ast.RangeExpr{ - low: ast.Expr{} + low: ast.empty_expr() high: high has_high: true pos: pos @@ -2025,7 +2025,7 @@ fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr { if p.tok.kind == .dotdot { // [start..end] or [start..] p.next() - mut high := ast.Expr{} + mut high := ast.empty_expr() if p.tok.kind != .rsbr { has_high = true high = p.expr(0) @@ -2263,7 +2263,7 @@ fn (mut p Parser) string_expr() ast.Expr { if is_raw || is_cstr { p.next() } - mut node := ast.Expr{} + mut node := ast.empty_expr() val := p.tok.lit pos := p.tok.position() if p.peek_tok.kind != .str_dollar { @@ -2372,7 +2372,7 @@ fn (mut p Parser) parse_number_literal() ast.Expr { } lit := p.tok.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'] { node = ast.FloatLiteral{ 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) )`') return ast.GlobalDecl{} } - mut expr := ast.Expr{} + mut expr := ast.empty_expr() if has_expr { if p.tok.kind != .lpar { 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() val := p.check_name() vals << val - mut expr := ast.Expr{} + mut expr := ast.empty_expr() mut has_expr := false // p.warn('enum val $val') 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() { p.error_with_pos('single letter capital names are reserved for generic template types.', decl_pos) - return ast.TypeDecl{} + return ast.FnTypeDecl{} } mut sum_variants := []ast.SumTypeVariant{} p.check(.assign) diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index 40536d2e30..39b1fd53d1 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -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)') } // println('\n\nparser.expr()') - mut node := ast.Expr{} + mut node := ast.empty_expr() is_stmt_ident := p.is_stmt_ident p.is_stmt_ident = false if !p.pref.is_fmt { @@ -439,7 +439,7 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr { precedence := p.tok.precedence() mut pos := p.tok.position() p.next() - mut right := ast.Expr{} + mut right := ast.empty_expr() prev_expecting_type := p.expecting_type if op in [.key_is, .not_is] { p.expecting_type = true diff --git a/vlib/v/parser/sql.v b/vlib/v/parser/sql.v index 686005b2d5..83de05debf 100644 --- a/vlib/v/parser/sql.v +++ b/vlib/v/parser/sql.v @@ -22,7 +22,7 @@ fn (mut p Parser) sql_expr() ast.Expr { } table_pos := p.tok.position() 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' mut query_one := false // one object is returned, not an array if has_where { @@ -40,11 +40,11 @@ fn (mut p Parser) sql_expr() ast.Expr { } } mut has_limit := false - mut limit_expr := ast.Expr{} + mut limit_expr := ast.empty_expr() mut has_offset := false - mut offset_expr := ast.Expr{} + mut offset_expr := ast.empty_expr() mut has_order := false - mut order_expr := ast.Expr{} + mut order_expr := ast.empty_expr() mut has_desc := false if p.tok.kind == .name && p.tok.lit == 'order' { p.check_name() // `order` @@ -172,7 +172,7 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt { } mut table_pos := p.tok.position() - mut where_expr := ast.Expr{} + mut where_expr := ast.empty_expr() if kind == .insert { table_pos = p.tok.position() table_type = p.parse_type() diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index 4c4527897f..ac8a921a9d 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -239,7 +239,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl { // attrs are stored in `p.attrs` p.attributes() } - mut default_expr := ast.Expr{} + mut default_expr := ast.empty_expr() mut has_default_expr := false if !is_embed { 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()) saved_is_amp := p.is_amp p.is_amp = false - mut update_expr := ast.Expr{} + mut update_expr := ast.empty_expr() mut update_expr_comments := []ast.Comment{} mut has_update_expr := false for p.tok.kind !in [.rcbr, .rpar, .eof] { mut field_name := '' - mut expr := ast.Expr{} + mut expr := ast.empty_expr() mut field_pos := token.Position{} mut first_field_pos := token.Position{} mut comments := []ast.Comment{}