diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index f67cbb513f..800d86008f 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -9,7 +9,7 @@ import v.errors pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl | UnionSumTypeDecl -pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral | CTempVar | +pub __type Expr = AnonFn | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral | CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | @@ -559,18 +559,19 @@ pub mut: pub struct MatchExpr { pub: - tok_kind token.Kind - cond Expr - branches []MatchBranch - pos token.Position - is_mut bool // `match mut ast_node {` - var_name string // `match cond as var_name {` + tok_kind token.Kind + cond Expr + branches []MatchBranch + pos token.Position + is_mut bool // `match mut ast_node {` + var_name string // `match cond as var_name {` + is_union_match bool // temporary union key after match pub mut: - is_expr bool // returns a value - return_type table.Type - cond_type table.Type // type of `x` in `match x {` - expected_type table.Type // for debugging only - is_sum_type bool + is_expr bool // returns a value + return_type table.Type + cond_type table.Type // type of `x` in `match x {` + expected_type table.Type // for debugging only + is_sum_type bool } pub struct MatchBranch { @@ -1057,7 +1058,7 @@ pub mut: [inline] pub fn (expr Expr) is_blank_ident() bool { - match expr { + match union expr { Ident { return expr.kind == .blank_ident } else { return false } } @@ -1065,7 +1066,7 @@ pub fn (expr Expr) is_blank_ident() bool { pub fn (expr Expr) position() token.Position { // all uncommented have to be implemented - match expr { + match union expr { // KEKW2 AnonFn { return expr.decl.pos @@ -1101,7 +1102,7 @@ pub fn (expr Expr) position() token.Position { } pub fn (expr Expr) is_lvalue() bool { - match expr { + match union expr { Ident { return true } CTempVar { return true } IndexExpr { return expr.left.is_lvalue() } @@ -1112,7 +1113,7 @@ pub fn (expr Expr) is_lvalue() bool { } pub fn (expr Expr) is_expr() bool { - match expr { + match union expr { IfExpr { return expr.is_expr } MatchExpr { return expr.is_expr } else {} diff --git a/vlib/v/ast/scope.v b/vlib/v/ast/scope.v index f8b0710edd..1accba82b4 100644 --- a/vlib/v/ast/scope.v +++ b/vlib/v/ast/scope.v @@ -210,10 +210,10 @@ pub fn (sc &Scope) str() string { // ``` // Since x is mutable, it returns true. pub fn (s &Scope) is_selector_root_mutable(t &table.Table, selector_expr SelectorExpr) bool { - if selector_expr.expr is SelectorExpr as left_expr { - return s.is_selector_root_mutable(t, left_expr) - } else if selector_expr.expr is Ident as left_expr { - if v := s.find_var(left_expr.name) { + if mut selector_expr.expr is SelectorExpr { + return s.is_selector_root_mutable(t, selector_expr.expr) + } else if mut selector_expr.expr is Ident { + if v := s.find_var(selector_expr.expr.name) { return v.is_mut } } diff --git a/vlib/v/ast/str.v b/vlib/v/ast/str.v index 727b353623..90754b7bda 100644 --- a/vlib/v/ast/str.v +++ b/vlib/v/ast/str.v @@ -129,21 +129,21 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) { if !needs_braces { mut sub_expr := lit.exprs[i] for { - match sub_expr as sx { + match union mut sub_expr { Ident { - if sx.name[0] == `@` { + if sub_expr.name[0] == `@` { needs_braces = true } break } CallExpr { - if sx.args.len != 0 { + if sub_expr.args.len != 0 { needs_braces = true } break } SelectorExpr { - sub_expr = sx.expr + sub_expr = sub_expr.expr continue } else { @@ -176,7 +176,7 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) { // string representation of expr pub fn (x Expr) str() string { - match x { + match union x { CTempVar { return x.orig.str() } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index aae238b83f..8ed39d7dfd 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -414,20 +414,20 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) { if field.typ.is_ptr() { continue } - if field.default_expr is ast.IntegerLiteral as lit { - if lit.val == '0' { + if field.default_expr is ast.IntegerLiteral { + if field.default_expr.val == '0' { c.warn('unnecessary default value of `0`: struct fields are zeroed by default', - lit.pos) + field.default_expr.pos) } - } else if field.default_expr is ast.StringLiteral as lit { - if lit.val == '' { + } else if field.default_expr is ast.StringLiteral { + if field.default_expr.val == '' { c.warn("unnecessary default value of '': struct fields are zeroed by default", - lit.pos) + field.default_expr.pos) } - } else if field.default_expr is ast.BoolLiteral as lit { - if lit.val == false { + } else if field.default_expr is ast.BoolLiteral { + if field.default_expr.val == false { c.warn('unnecessary default value `false`: struct fields are zeroed by default', - lit.pos) + field.default_expr.pos) } } } @@ -732,17 +732,17 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { } } if infix_expr.op in [.div, .mod] { - match infix_expr.right as infix_right { + match union mut infix_expr.right { ast.FloatLiteral { - if infix_right.val.f64() == 0.0 { + if infix_expr.right.val.f64() == 0.0 { oper := if infix_expr.op == .div { 'division' } else { 'modulo' } - c.error('$oper by zero', infix_right.pos) + c.error('$oper by zero', infix_expr.right.pos) } } ast.IntegerLiteral { - if infix_right.val.int() == 0 { + if infix_expr.right.val.int() == 0 { oper := if infix_expr.op == .div { 'division' } else { 'modulo' } - c.error('$oper by zero', infix_right.pos) + c.error('$oper by zero', infix_expr.right.pos) } } else {} @@ -843,9 +843,9 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { // use `()` to make the boolean expression clear error // for example: `(a && b) || c` instead of `a && b || c` if infix_expr.op in [.logical_or, .and] { - if infix_expr.left is ast.InfixExpr { - e := infix_expr.left as ast.InfixExpr - if e.op in [.logical_or, .and] && e.op != infix_expr.op { + if mut infix_expr.left is ast.InfixExpr { + if infix_expr.left.op in [.logical_or, .and] && + infix_expr.left.op != infix_expr.op { c.error('use `()` to make the boolean expression clear', infix_expr.pos) } } @@ -897,7 +897,7 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) { mut to_lock := '' // name of variable that needs lock mut pos := token.Position{} // and its position mut explicit_lock_needed := false - match mut expr { + match union mut expr { ast.CastExpr { // TODO return '', pos @@ -1053,7 +1053,8 @@ pub fn (mut c Checker) call_expr(mut call_expr ast.CallExpr) table.Type { fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ table.Type, call_expr ast.CallExpr) { elem_sym := c.table.get_type_symbol(elem_typ) - match call_expr.args[0].expr as arg_expr { + arg_expr := call_expr.args[0].expr + match union arg_expr { ast.AnonFn { if arg_expr.decl.params.len > 1 { c.error('function needs exactly 1 argument', call_expr.pos) @@ -1385,12 +1386,11 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { mut found := false mut found_in_args := false // anon fn direct call - if call_expr.left is ast.AnonFn { + if mut call_expr.left is ast.AnonFn { // it was set to anon for checker errors, clear for gen call_expr.name = '' c.expr(call_expr.left) - anon_fn := call_expr.left as ast.AnonFn - anon_fn_sym := c.table.get_type_symbol(anon_fn.typ) + anon_fn_sym := c.table.get_type_symbol(call_expr.left.typ) f = (anon_fn_sym.info as table.FnType).func found = true } @@ -1741,7 +1741,7 @@ pub fn (mut c Checker) check_or_expr(or_expr ast.OrExpr, ret_type table.Type, ex } fn is_expr_panic_or_exit(expr ast.Expr) bool { - match expr { + match union expr { ast.CallExpr { return expr.name in ['panic', 'exit'] } else { return false } } @@ -1752,16 +1752,16 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T c.prevent_sum_type_unwrapping_once = false // T.name, typeof(expr).name mut name_type := 0 - match selector_expr.expr as left { + match union mut selector_expr.expr { ast.Ident { - if left.name == 'T' { + if selector_expr.expr.name == 'T' { name_type = table.Type(c.table.find_type_idx('T')).set_flag(.generic) } } // Note: in future typeof() should be a type known at compile-time // sum types should not be handled dynamically ast.TypeOf { - name_type = c.expr(left.expr) + name_type = c.expr(selector_expr.expr.expr) } else {} } @@ -1911,21 +1911,20 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) { } } if field.has_expr { - match field.expr as field_expr { + match union field.expr { ast.IntegerLiteral { - val := field_expr.val.i64() + val := field.expr.val.i64() if val < int_min || val > int_max { - c.error('enum value `$val` overflows int', field_expr.pos) + c.error('enum value `$val` overflows int', field.expr.pos) } else if !decl.is_multi_allowed && int(val) in seen { - c.error('enum value `$val` already exists', field_expr.pos) + c.error('enum value `$val` already exists', field.expr.pos) } seen << int(val) } ast.PrefixExpr {} else { if field.expr is ast.Ident { - expr := field.expr as ast.Ident - if expr.language == .c { + if field.expr.language == .c { continue } } @@ -1988,13 +1987,12 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { if left_first is ast.Ident { assigned_var := left_first if node.right is ast.Ident { - ident := node.right as ast.Ident scope := c.file.scope.innermost(node.pos.pos) - if v := scope.find_var(ident.name) { + if v := scope.find_var(node.right.name) { right_type0 = v.typ if node.op == .amp { if !v.is_mut && assigned_var.is_mut && !c.inside_unsafe { - c.error('`$ident.name` is immutable, cannot have a mutable reference to it', + c.error('`$node.right.name` is immutable, cannot have a mutable reference to it', node.pos) } } @@ -2049,7 +2047,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { negative = true } } - if expr is ast.IntegerLiteral { + if mut expr is ast.IntegerLiteral { mut is_large := false if expr.val.len > 8 { val := expr.val.i64() @@ -2073,7 +2071,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { // left_type = c.expr(left) } assign_stmt.left_types << left_type - match mut left { + match union mut left { ast.Ident { if left.kind == .blank_ident { left_type = right_type @@ -2327,7 +2325,8 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type { } else if array_init.is_fixed && array_init.exprs.len == 1 && array_init.elem_type != table.void_type { // [50]byte mut fixed_size := 1 - match array_init.exprs[0] as init_expr { + init_expr := array_init.exprs[0] + match union init_expr { ast.IntegerLiteral { fixed_size = init_expr.val.int() } @@ -2369,8 +2368,8 @@ fn const_int_value(cfield ast.ConstField) ?int { } fn is_const_integer(cfield ast.ConstField) ?ast.IntegerLiteral { - match cfield.expr { - ast.IntegerLiteral { return *it } + match union cfield.expr { + ast.IntegerLiteral { return cfield.expr } else {} } return none @@ -2562,18 +2561,17 @@ fn (mut c Checker) stmt(node ast.Stmt) { c.error('expression in `go` must be a function call', node.call_expr.position()) } c.expr(node.call_expr) - if node.call_expr is ast.CallExpr { - call_expr := node.call_expr as ast.CallExpr + if mut node.call_expr is ast.CallExpr { // Make sure there are no mutable arguments - for arg in call_expr.args { + for arg in node.call_expr.args { if arg.is_mut && !arg.typ.is_ptr() { c.error('function in `go` statement cannot contain mutable non-reference arguments', arg.expr.position()) } } - if call_expr.is_method && call_expr.receiver_type.is_ptr() && !call_expr.left_type.is_ptr() { + if node.call_expr.is_method && node.call_expr.receiver_type.is_ptr() && !node.call_expr.left_type.is_ptr() { c.error('method in `go` statement cannot have non-reference mutable receiver', - call_expr.left.position()) + node.call_expr.left.position()) } } } @@ -2743,7 +2741,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { c.error('checker: too many expr levels: $c.expr_level ', node.position()) return table.void_type } - match mut node { + match union mut node { ast.CTempVar { return node.typ } @@ -2894,10 +2892,11 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { if node.right is ast.StringLiteral || node.right is ast.StringInterLiteral { c.error('cannot take the address of a string', node.pos) } - if node.right is ast.IndexExpr as index { - typ_sym := c.table.get_type_symbol(index.left_type) + if mut node.right is ast.IndexExpr { + typ_sym := c.table.get_type_symbol(node.right.left_type) mut is_mut := false - if index.left is ast.Ident as ident { + if mut node.right.left is ast.Ident { + ident := node.right.left if ident.obj is ast.Var { v := ident.obj as ast.Var is_mut = v.is_mut @@ -2906,11 +2905,11 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { if !c.inside_unsafe && is_mut { if typ_sym.kind == .map { c.error('cannot take the address of mutable map values outside unsafe blocks', - index.pos) + node.right.pos) } if typ_sym.kind == .array { c.error('cannot take the address of mutable array elements outside unsafe blocks', - index.pos) + node.right.pos) } } } @@ -3049,10 +3048,9 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type { } else if node.expr_type == table.string_type { if to_type_sym.kind != .alias { mut error_msg := 'cannot cast a string' - if node.expr is ast.StringLiteral { - str_lit := node.expr as ast.StringLiteral - if str_lit.val.len == 1 { - error_msg += ", for denoting characters use `$str_lit.val` instead of '$str_lit.val'" + if mut node.expr is ast.StringLiteral { + if node.expr.val.len == 1 { + error_msg += ", for denoting characters use `$node.expr.val` instead of '$node.expr.val'" } } c.error(error_msg, node.pos) @@ -3203,9 +3201,8 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type { c.prevent_sum_type_unwrapping_once = false mut typ := if is_sum_type_cast { obj.sum_type_cast } else { obj.typ } if typ == 0 { - if obj.expr is ast.Ident { - inner_ident := obj.expr as ast.Ident - if inner_ident.kind == .unresolved { + if mut obj.expr is ast.Ident { + if obj.expr.kind == .unresolved { c.error('unresolved variable: `$ident.name`', ident.pos) return table.void_type } @@ -3446,7 +3443,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol } continue } - match expr { + match union expr { ast.Type { key = c.table.type_to_str(expr.typ) expr_types << expr @@ -3518,28 +3515,28 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol expr_type = expr_types[0].typ } mut scope := c.file.scope.innermost(branch.pos.pos) - match node.cond as node_cond { + match mut node.cond { ast.SelectorExpr { - expr_sym := c.table.get_type_symbol(node_cond.expr_type) - field := c.table.struct_find_field(expr_sym, node_cond.field_name) or { + expr_sym := c.table.get_type_symbol(node.cond.expr_type) + field := c.table.struct_find_field(expr_sym, node.cond.field_name) or { table.Field{} } is_mut := field.is_mut - is_root_mut := scope.is_selector_root_mutable(c.table, node_cond) + is_root_mut := scope.is_selector_root_mutable(c.table, node.cond) // smartcast either if the value is immutable or if the mut argument is explicitly given if (!is_root_mut && !is_mut) || node.is_mut { scope.register_struct_field(ast.ScopeStructField{ - struct_type: node_cond.expr_type - name: node_cond.field_name + struct_type: node.cond.expr_type + name: node.cond.field_name typ: node.cond_type sum_type_cast: expr_type - pos: node_cond.pos + pos: node.cond.pos }) } } ast.Ident { mut is_mut := false - if v := scope.find_var(node_cond.name) { + if v := scope.find_var(node.cond.name) { is_mut = v.is_mut } // smartcast either if the value is immutable or if the mut argument is explicitly given @@ -3547,7 +3544,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol scope.register(node.var_name, ast.Var{ name: node.var_name typ: node.cond_type - pos: node_cond.pos + pos: node.cond.pos is_used: true is_mut: node.is_mut sum_type_cast: expr_type @@ -3648,10 +3645,10 @@ pub fn (mut c Checker) select_expr(mut node ast.SelectExpr) table.Type { stmt.pos) } } else { - if stmt.expr is ast.InfixExpr as expr { - if expr.left !is ast.Ident && - expr.left !is ast.SelectorExpr && expr.left !is ast.IndexExpr { - c.error('channel in `select` key must be predefined', expr.left.position()) + if stmt.expr is ast.InfixExpr { + if stmt.expr.left !is ast.Ident && + stmt.expr.left !is ast.SelectorExpr && stmt.expr.left !is ast.IndexExpr { + c.error('channel in `select` key must be predefined', stmt.expr.left.position()) } } else { c.error('invalid expression for `select` key', stmt.expr.position()) @@ -3659,7 +3656,8 @@ pub fn (mut c Checker) select_expr(mut node ast.SelectExpr) table.Type { } } ast.AssignStmt { - match stmt.right[0] as expr { + expr := stmt.right[0] + match union expr { ast.PrefixExpr { if expr.right !is ast.Ident && expr.right !is ast.SelectorExpr && expr.right !is ast.IndexExpr { @@ -3774,15 +3772,14 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { if (infix.left is ast.Ident || infix.left is ast.SelectorExpr) && infix.right is ast.Type { - is_variable := if infix.left is ast.Ident { (infix.left as ast.Ident).kind == - .variable } else { true } + is_variable := if mut infix.left is ast.Ident { infix.left.kind == .variable } else { true } // Register shadow variable or `as` variable with actual type if is_variable { if left_sym.kind in [.sum_type, .interface_, .union_sum_type] { mut is_mut := false mut scope := c.file.scope.innermost(branch.body_pos.pos) - if infix.left is ast.Ident as infix_left { - if v := scope.find_var(infix_left.name) { + if mut infix.left is ast.Ident { + if v := scope.find_var(infix.left.name) { is_mut = v.is_mut } // smartcast either if the value is immutable or if the mut argument is explicitly given @@ -3792,29 +3789,29 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { name: branch.left_as_name typ: infix.left_type sum_type_cast: right_expr.typ - pos: infix.left.position() + pos: infix.left.pos is_used: true is_mut: is_mut }) } - } else if infix.left is ast.SelectorExpr as selector { - expr_sym := c.table.get_type_symbol(selector.expr_type) - field := c.table.struct_find_field(expr_sym, selector.field_name) or { + } else if mut infix.left is ast.SelectorExpr { + expr_sym := c.table.get_type_symbol(infix.left.expr_type) + field := c.table.struct_find_field(expr_sym, infix.left.field_name) or { table.Field{} } is_mut = field.is_mut is_root_mut := scope.is_selector_root_mutable(c.table, - selector) + infix.left) // smartcast either if the value is immutable or if the mut argument is explicitly given if ((!is_root_mut && !is_mut) || branch.is_mut_name) && left_sym.kind == .union_sum_type { scope.register_struct_field(ast.ScopeStructField{ - struct_type: selector.expr_type - name: selector.field_name + struct_type: infix.left.expr_type + name: infix.left.field_name typ: infix.left_type sum_type_cast: right_expr.typ - pos: infix.left.position() + pos: infix.left.pos }) } } @@ -3946,7 +3943,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { // saying whether that branch's contents should be skipped (targets a different os for example) fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool { // TODO: better error messages here - match cond { + match union cond { ast.ParExpr { return c.comp_if_branch(cond.expr, pos) } @@ -3959,8 +3956,8 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool { ast.PostfixExpr { if cond.op != .question { c.error('invalid \$if postfix operator', cond.pos) - } else if cond.expr is ast.Ident as ident { - return ident.name !in c.pref.compile_defines_all + } else if cond.expr is ast.Ident { + return cond.expr.name !in c.pref.compile_defines_all } else { c.error('invalid `\$if` condition', cond.pos) } @@ -4093,10 +4090,9 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type { } if !c.inside_unsafe && (typ.is_ptr() || typ.is_pointer()) { mut is_ok := false - if node.left is ast.Ident { - ident := node.left as ast.Ident - scope := c.file.scope.innermost(ident.pos.pos) - if v := scope.find_var(ident.name) { + if mut node.left is ast.Ident { + scope := c.file.scope.innermost(node.left.pos.pos) + if v := scope.find_var(node.left.name) { // `mut param []T` function parameter is_ok = v.is_mut && v.is_arg && !typ.deref().is_ptr() } @@ -4105,13 +4101,13 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type { c.warn('pointer indexing is only allowed in `unsafe` blocks', node.pos) } } - if node.index is ast.RangeExpr as range { // [1..2] - if range.has_low { - index_type := c.expr(range.low) + if mut node.index is ast.RangeExpr { // [1..2] + if node.index.has_low { + index_type := c.expr(node.index.low) c.check_index_type(typ_sym, index_type, node.pos) } - if range.has_high { - index_type := c.expr(range.high) + if node.index.has_high { + index_type := c.expr(node.index.high) c.check_index_type(typ_sym, index_type, node.pos) } // array[1..2] => array @@ -4559,8 +4555,8 @@ fn has_top_return(stmts []ast.Stmt) bool { return true } } else if stmt is ast.ExprStmt { - if stmt.expr is ast.CallExpr as ce { - if ce.name in ['panic', 'exit'] { + if stmt.expr is ast.CallExpr { + if stmt.expr.name in ['panic', 'exit'] { return true } } diff --git a/vlib/v/doc/doc.v b/vlib/v/doc/doc.v index 331cee4ad0..c1b7c663ce 100644 --- a/vlib/v/doc/doc.v +++ b/vlib/v/doc/doc.v @@ -222,8 +222,8 @@ pub fn (mut d Doc) file_ast(file_ast ast.File) map[string]DocNode { for sidx, stmt in stmts { // eprintln('stmt typeof: ' + typeof(stmt)) if stmt is ast.ExprStmt { - if stmt.expr is ast.Comment as cmt { - prev_comments << cmt + if stmt.expr is ast.Comment { + prev_comments << stmt.expr continue } } diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 27d1cd1a1f..e238a6329d 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -771,7 +771,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) { if f.is_debug { eprintln('expr: ${node.position():-42} | node: ${typeof(node):-20} | $node.str()') } - match mut node { + match union mut node { ast.CTempVar { eprintln('ast.CTempVar of $node.orig.str() should be generated/used only in cgen') } @@ -1366,9 +1366,9 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) { } f.expr_bufs << f.out.str() mut penalty := 3 - match node.left as left { + match union mut node.left { ast.InfixExpr { - if int(token.precedences[left.op]) > int(token.precedences[node.op]) { + if int(token.precedences[node.left.op]) > int(token.precedences[node.op]) { penalty-- } } @@ -1377,7 +1377,7 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) { } else {} } - match node.right as right { + match union node.right { ast.InfixExpr { penalty-- } ast.ParExpr { penalty = 1 } else {} @@ -1418,11 +1418,11 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) { for i, branch in it.branches { // Check `sum is T` smartcast mut smartcast_as := false - if branch.cond is ast.InfixExpr as infix { - if infix.op == .key_is { - // left_as_name is either empty, infix.left.str() or the `as` name + if branch.cond is ast.InfixExpr { + if branch.cond.op == .key_is { + // left_as_name is either empty, branch.cond.left.str() or the `as` name smartcast_as = branch.left_as_name.len > 0 && - infix.left.str() != branch.left_as_name + branch.cond.left.str() != branch.left_as_name } } if i == 0 { @@ -1513,16 +1513,15 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) { } } if node.left is ast.Ident { - left := node.left as ast.Ident // `time.now()` without `time imported` is processed as a method call with `time` being // a `node.left` expression. Import `time` automatically. // TODO fetch all available modules - if left.name in ['time', 'os', 'strings', 'math', 'json', 'base64'] { - if left.name !in f.auto_imports { - f.auto_imports << left.name + if node.left.name in ['time', 'os', 'strings', 'math', 'json', 'base64'] { + if node.left.name !in f.auto_imports { + f.auto_imports << node.left.name f.file.imports << ast.Import{ - mod: left.name - alias: left.name + mod: node.left.name + alias: node.left.name } } // for imp in f.file.imports { @@ -1540,8 +1539,8 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) { f.or_expr(node.or_block) } else { f.write_language_prefix(node.language) - if node.left is ast.AnonFn as anon_fn { - f.fn_decl(anon_fn.decl) + if node.left is ast.AnonFn { + f.fn_decl(node.left.decl) } else { mut name := f.short_module(node.name) f.mark_module_as_used(name) @@ -1565,13 +1564,16 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) { pub fn (mut f Fmt) match_expr(it ast.MatchExpr) { f.write('match ') + // TODO: temporary, remove again + if it.is_union_match { + f.write('union ') + } if it.is_mut { f.write('mut ') } f.expr(it.cond) if it.cond is ast.Ident { - ident := it.cond as ast.Ident - f.it_name = ident.name + f.it_name = it.cond.name } else if it.cond is ast.SelectorExpr { // `x.y as z` // if ident.name != it.var_name && it.var_name != '' { @@ -1702,7 +1704,7 @@ fn stmt_is_single_line(stmt ast.Stmt) bool { } fn expr_is_single_line(expr ast.Expr) bool { - match expr { + match union expr { ast.IfExpr { return false } ast.Comment { return false } else {} diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 5de884f8e3..f2d0ae6559 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1418,13 +1418,12 @@ fn (mut g Gen) gen_attrs(attrs []table.Attr) { fn (mut g Gen) gen_assert_stmt(original_assert_statement ast.AssertStmt) { mut a := original_assert_statement g.writeln('// assert') - if a.expr is ast.InfixExpr { - mut aie := a.expr as ast.InfixExpr - if aie.left is ast.CallExpr { - aie.left = g.new_ctemp_var_then_gen(aie.left, aie.left_type) + if mut a.expr is ast.InfixExpr { + if mut a.expr.left is ast.CallExpr { + a.expr.left = g.new_ctemp_var_then_gen(a.expr.left, a.expr.left_type) } - if aie.right is ast.CallExpr { - aie.right = g.new_ctemp_var_then_gen(aie.right, aie.right_type) + if mut a.expr.right is ast.CallExpr { + a.expr.right = g.new_ctemp_var_then_gen(a.expr.right, a.expr.right_type) } } g.inside_ternary++ @@ -1471,17 +1470,17 @@ fn (mut g Gen) gen_assert_metainfo(a ast.AssertStmt) string { g.writeln('\t${metaname}.line_nr = $line_nr;') g.writeln('\t${metaname}.fn_name = ${ctoslit(fn_name)};') g.writeln('\t${metaname}.src = ${cnewlines(ctoslit(src))};') - match a.expr { + match union mut a.expr { ast.InfixExpr { - g.writeln('\t${metaname}.op = ${ctoslit(it.op.str())};') - g.writeln('\t${metaname}.llabel = ${cnewlines(ctoslit(it.left.str()))};') - g.writeln('\t${metaname}.rlabel = ${cnewlines(ctoslit(it.right.str()))};') + g.writeln('\t${metaname}.op = ${ctoslit(a.expr.op.str())};') + g.writeln('\t${metaname}.llabel = ${cnewlines(ctoslit(a.expr.left.str()))};') + g.writeln('\t${metaname}.rlabel = ${cnewlines(ctoslit(a.expr.right.str()))};') g.write('\t${metaname}.lvalue = ') - g.gen_assert_single_expr(it.left, it.left_type) + g.gen_assert_single_expr(a.expr.left, a.expr.left_type) g.writeln(';') // g.write('\t${metaname}.rvalue = ') - g.gen_assert_single_expr(it.right, it.right_type) + g.gen_assert_single_expr(a.expr.right, a.expr.right_type) g.writeln(';') } ast.CallExpr { @@ -1494,7 +1493,7 @@ fn (mut g Gen) gen_assert_metainfo(a ast.AssertStmt) string { fn (mut g Gen) gen_assert_single_expr(e ast.Expr, t table.Type) { unknown_value := '*unknown value*' - match e { + match union e { ast.CastExpr, ast.IndexExpr, ast.MatchExpr { g.write(ctoslit(unknown_value)) } @@ -1544,9 +1543,11 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { mut return_type := table.void_type op := if assign_stmt.op == .decl_assign { token.Kind.assign } else { assign_stmt.op } is_decl := assign_stmt.op == .decl_assign - match assign_stmt.right[0] { - ast.CallExpr, ast.MatchExpr { return_type = it.return_type } - ast.IfExpr { return_type = it.typ } + right_expr := assign_stmt.right[0] + match union right_expr { + ast.CallExpr { return_type = right_expr.return_type } + ast.MatchExpr { return_type = right_expr.return_type } + ast.IfExpr { return_type = right_expr.typ } else {} } // Free the old value assigned to this string var (only if it's `str = [new value]`) @@ -1630,13 +1631,10 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { g.is_assign_rhs = false g.writeln(';') for i, lx in assign_stmt.left { - match lx { - ast.Ident { - if lx.kind == .blank_ident { - continue - } + if lx is ast.Ident { + if lx.kind == .blank_ident { + continue } - else {} } styp := g.typ(assign_stmt.left_types[i]) if assign_stmt.op == .decl_assign { @@ -1656,7 +1654,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { // TODO: non idents on left (exprs) if assign_stmt.has_cross_var { for i, left in assign_stmt.left { - match left { + match union left { ast.Ident { left_typ := assign_stmt.left_types[i] left_sym := g.table.get_type_symbol(left_typ) @@ -1720,6 +1718,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { g.write('$styp _var_$left.pos.pos = ') g.expr(left.expr) if left.expr_type.is_ptr() { + g.write('/* left.expr_type */') g.writeln('->$left.field_name;') } else { g.writeln('.$left.field_name;') @@ -1738,7 +1737,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { mut blank_assign := false mut ident := ast.Ident{} if left is ast.Ident { - ident = *left + ident = left // id_info := ident.var_info() // var_type = id_info.typ blank_assign = left.kind == .blank_ident @@ -1755,7 +1754,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { styp := g.typ(var_type) mut is_fixed_array_init := false mut has_val := false - match val { + match union val { ast.ArrayInit { is_fixed_array_init = val.is_fixed has_val = val.has_val @@ -1775,7 +1774,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { g.fn_args(val.decl.params, val.decl.is_variadic) g.definitions.go_back(g.definitions.len - def_pos) g.write(') = ') - g.expr(*val) + g.expr(val) g.writeln(';') if blank_assign { g.write('}') @@ -1956,7 +1955,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) { val_ := val - match val { + match union val { ast.Ident { mut has_var := false for lx in left { @@ -2195,7 +2194,7 @@ fn (mut g Gen) gen_anon_fn_decl(it ast.AnonFn) { fn (mut g Gen) expr(node ast.Expr) { // println('cgen expr() line_nr=$node.pos.line_nr') // NB: please keep the type names in the match here in alphabetical order: - match node { + match union node { ast.AnonFn { // TODO: dont fiddle with buffers g.gen_anon_fn_decl(node) @@ -2668,7 +2667,7 @@ fn (mut g Gen) typeof_expr(node ast.TypeOf) { } fn (mut g Gen) enum_expr(node ast.Expr) { - match node { + match union node { ast.EnumVal { g.write(node.val) } else { g.expr(node) } } @@ -2832,19 +2831,16 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { g.write('!') } if right_sym.kind == .array { - match node.right { - ast.ArrayInit { - if it.exprs.len > 0 { - // `a in [1,2,3]` optimization => `a == 1 || a == 2 || a == 3` - // avoids an allocation - // g.write('/*in opt*/') - g.write('(') - g.in_optimization(node.left, it) - g.write(')') - return - } + if mut node.right is ast.ArrayInit { + if node.right.exprs.len > 0 { + // `a in [1,2,3]` optimization => `a == 1 || a == 2 || a == 3` + // avoids an allocation + // g.write('/*in opt*/') + g.write('(') + g.in_optimization(node.left, node.right) + g.write(')') + return } - else {} } if left_sym.kind == .function { g.write('_IN(voidptr, ') @@ -3163,9 +3159,9 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str } else if expr is ast.RangeExpr { // if type is unsigned and low is 0, check is unneeded mut skip_low := false - if expr.low is ast.IntegerLiteral as expr_low { + if expr.low is ast.IntegerLiteral { if node.cond_type in [table.u16_type, table.u32_type, table.u64_type] && - expr_low.val == '0' { + expr.low.val == '0' { skip_low = true } } @@ -3526,14 +3522,14 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { g.writeln('\tint errcode = ${cvar_name}.ecode;') } } else { - match branch.cond as cond { + match union branch.cond { ast.IfGuardExpr { var_name := guard_vars[i] g.write('if ($var_name = ') - g.expr(it.expr) + g.expr(branch.cond.expr) g.writeln(', ${var_name}.ok) {') - if cond.var_name != '_' { - g.writeln('\t${g.typ(cond.expr_type)} $cond.var_name = $var_name;') + if branch.cond.var_name != '_' { + g.writeln('\t${g.typ(branch.cond.expr_type)} $branch.cond.var_name = $var_name;') } } else { @@ -3575,7 +3571,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { } fn (mut g Gen) index_expr(node ast.IndexExpr) { - match node.index { + match union node.index { ast.RangeExpr { sym := g.table.get_type_symbol(node.left_type) if sym.kind == .string { @@ -3602,14 +3598,14 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.expr(node.left) } g.write(', ') - if it.has_low { - g.expr(it.low) + if node.index.has_low { + g.expr(node.index.low) } else { g.write('0') } g.write(', ') - if it.has_high { - g.expr(it.high) + if node.index.has_high { + g.expr(node.index.high) } else { g.expr(node.left) g.write('.len') @@ -3828,7 +3824,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { [inline] fn (g &Gen) expr_is_multi_return_call(expr ast.Expr) bool { - match expr { + match union expr { ast.CallExpr { return g.table.get_type_symbol(expr.return_type).kind == .multi_return } else { return false } } @@ -4051,13 +4047,13 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { } } else { */ - match field.expr { + match union field.expr { ast.CharLiteral, ast.FloatLiteral, ast.IntegerLiteral { g.const_decl_simple_define(name, val) } ast.ArrayInit { - if it.is_fixed { - styp := g.typ(it.typ) + if field.expr.is_fixed { + styp := g.typ(field.expr.typ) g.definitions.writeln('$styp _const_$name = $val; // fixed array const') } else { g.const_decl_init_later(field.mod, name, val, field.typ) @@ -4710,7 +4706,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool { g.expr(expr) return true } else if sym.kind == .enum_ { - is_var := match expr { + is_var := match union expr { ast.SelectorExpr, ast.Ident { true } else { false } } @@ -4808,19 +4804,20 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { g.expr(node.left) g.writeln('.data)[$i];') g.write('\t$ret_elem_type ti = ') - match node.args[0].expr { + expr := node.args[0].expr + match union expr { ast.AnonFn { - g.gen_anon_fn_decl(it) - g.write('${it.decl.name}(it)') + g.gen_anon_fn_decl(expr) + g.write('${expr.decl.name}(it)') } ast.Ident { - if it.kind == .function { - g.write('${c_name(it.name)}(it)') - } else if it.kind == .variable { - var_info := it.var_info() + if expr.kind == .function { + g.write('${c_name(expr.name)}(it)') + } else if expr.kind == .variable { + var_info := expr.var_info() sym := g.table.get_type_symbol(var_info.typ) if sym.kind == .function { - g.write('${c_name(it.name)}(it)') + g.write('${c_name(expr.name)}(it)') } else { g.expr(node.args[0].expr) } @@ -4962,19 +4959,20 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) { g.expr(node.left) g.writeln('.data)[i];') g.write('if (') - match node.args[0].expr { + expr := node.args[0].expr + match union expr { ast.AnonFn { - g.gen_anon_fn_decl(it) - g.write('${it.decl.name}(it)') + g.gen_anon_fn_decl(expr) + g.write('${expr.decl.name}(it)') } ast.Ident { - if it.kind == .function { - g.write('${c_name(it.name)}(it)') - } else if it.kind == .variable { - var_info := it.var_info() + if expr.kind == .function { + g.write('${c_name(expr.name)}(it)') + } else if expr.kind == .variable { + var_info := expr.var_info() sym_t := g.table.get_type_symbol(var_info.typ) if sym_t.kind == .function { - g.write('${c_name(it.name)}(it)') + g.write('${c_name(expr.name)}(it)') } else { g.expr(node.args[0].expr) } @@ -5152,7 +5150,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table. } fn (mut g Gen) type_of_call_expr(node ast.Expr) string { - match node { + match union node { ast.CallExpr { return g.typ(node.return_type) } else { return typeof(node) } } @@ -5461,9 +5459,9 @@ fn (mut g Gen) go_stmt(node ast.GoStmt) { if expr.is_method { receiver_sym := g.table.get_type_symbol(expr.receiver_type) name = receiver_sym.name + '_' + name - } else if expr.left is ast.AnonFn as anon_fn { - g.gen_anon_fn_decl(anon_fn) - fsym := g.table.get_type_symbol(anon_fn.typ) + } else if expr.left is ast.AnonFn { + g.gen_anon_fn_decl(expr.left) + fsym := g.table.get_type_symbol(expr.left.typ) name = fsym.name } name = util.no_dots(name) diff --git a/vlib/v/gen/comptime.v b/vlib/v/gen/comptime.v index 61375eb1b6..31a966a376 100644 --- a/vlib/v/gen/comptime.v +++ b/vlib/v/gen/comptime.v @@ -45,8 +45,7 @@ fn (mut g Gen) comptime_call(node ast.ComptimeCall) { } for i in 1 .. m.params.len { if node.left is ast.Ident { - left_name := node.left as ast.Ident - if m.params[i].name == left_name.name { + if m.params[i].name == node.left.name { continue } } @@ -175,7 +174,7 @@ fn (mut g Gen) comp_if(node ast.IfExpr) { } fn (mut g Gen) comp_if_expr(cond ast.Expr) { - match cond { + match union cond { ast.ParExpr { g.write('(') g.comp_if_expr(cond.expr) diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index ddeecabd07..09a0ab720d 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -403,7 +403,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) { mut is_range_slice := false if node.receiver_type.is_ptr() && !node.left_type.is_ptr() { if node.left is ast.IndexExpr { - idx := (node.left as ast.IndexExpr).index + idx := node.left.index if idx is ast.RangeExpr { // expr is arr[range].clone() // use array_clone_static instead of array_clone @@ -569,7 +569,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { g.writeln('); ${print_method}($tmp); string_free(&$tmp); //MEM2 $styp') } else { expr := node.args[0].expr - is_var := match expr { + is_var := match union expr { ast.SelectorExpr { true } ast.Ident { true } else { false } @@ -665,7 +665,7 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) { if arg.expr is ast.CallExpr { // Any argument can be an expression that has to be freed. Generate a tmp expression // for each of those recursively. - g.autofree_call_pregen(arg.expr as ast.CallExpr) + g.autofree_call_pregen(arg.expr) } free_tmp_arg_vars = true // t := g.new_tmp_var() + '_arg_expr_${name}_$i' diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index cfb5bd7978..bcc0f920e2 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -523,7 +523,7 @@ fn (mut g JsGen) stmt(node ast.Stmt) { } fn (mut g JsGen) expr(node ast.Expr) { - match node { + match union node { ast.CTempVar { g.write('/* ast.CTempVar: node.name */') } @@ -1008,19 +1008,19 @@ fn (mut g JsGen) gen_for_stmt(it ast.ForStmt) { fn (mut g JsGen) gen_go_stmt(node ast.GoStmt) { // x := node.call_expr as ast.CallEpxr // TODO - match node.call_expr { + match union node.call_expr { ast.CallExpr { - mut name := it.name - if it.is_method { - receiver_sym := g.table.get_type_symbol(it.receiver_type) + mut name := node.call_expr.name + if node.call_expr.is_method { + receiver_sym := g.table.get_type_symbol(node.call_expr.receiver_type) name = receiver_sym.name + '.' + name } g.writeln('await new Promise(function(resolve){') g.inc_indent() g.write('${name}(') - for i, arg in it.args { + for i, arg in node.call_expr.args { g.expr(arg.expr) - if i < it.args.len - 1 { + if i < node.call_expr.args.len - 1 { g.write(', ') } } @@ -1184,21 +1184,22 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) { node := it g.write(it.name) g.write('(') - match node.args[0].expr { + expr := node.args[0].expr + match union expr { ast.AnonFn { - g.gen_fn_decl(it.decl) + g.gen_fn_decl(expr.decl) g.write(')') return } ast.Ident { - if it.kind == .function { - g.write(g.js_name(it.name)) + if expr.kind == .function { + g.write(g.js_name(expr.name)) g.write(')') return - } else if it.kind == .variable { - v_sym := g.table.get_type_symbol(it.var_info().typ) + } else if expr.kind == .variable { + v_sym := g.table.get_type_symbol(expr.var_info().typ) if v_sym.kind == .function { - g.write(g.js_name(it.name)) + g.write(g.js_name(expr.name)) g.write(')') return } @@ -1302,17 +1303,16 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) { left_typ := g.table.get_type_symbol(expr.left_type) // TODO: Handle splice setting if it's implemented if expr.index is ast.RangeExpr { - range := expr.index as ast.RangeExpr g.expr(expr.left) g.write('.slice(') - if range.has_low { - g.expr(range.low) + if expr.index.has_low { + g.expr(expr.index.low) } else { g.write('0') } g.write(', ') - if range.has_high { - g.expr(range.high) + if expr.index.has_high { + g.expr(expr.index.high) } else { g.expr(expr.left) g.write('.length') diff --git a/vlib/v/gen/sql.v b/vlib/v/gen/sql.v index 04972ffff8..1e2de38bcc 100644 --- a/vlib/v/gen/sql.v +++ b/vlib/v/gen/sql.v @@ -256,7 +256,7 @@ fn (mut g Gen) expr_to_sql(expr ast.Expr) { // // TODO `where id = some_column + 1` needs literal generation of `some_column` as a string, // not a V variable. Need to distinguish column names from V variables. - match expr { + match union expr { ast.InfixExpr { g.sql_side = .left g.expr_to_sql(expr.left) @@ -275,22 +275,22 @@ fn (mut g Gen) expr_to_sql(expr ast.Expr) { else {} } g.sql_side = .right - g.expr_to_sql(it.right) + g.expr_to_sql(expr.right) } ast.StringLiteral { // g.write("'$it.val'") g.inc_sql_i() - g.sql_bind_string('"$it.val"', it.val.len.str()) + g.sql_bind_string('"$expr.val"', expr.val.len.str()) } ast.IntegerLiteral { g.inc_sql_i() - g.sql_bind_int(it.val) + g.sql_bind_int(expr.val) } ast.BoolLiteral { // true/false literals were added to Sqlite 3.23 (2018-04-02) // but lots of apps/distros use older sqlite (e.g. Ubuntu 18.04 LTS ) g.inc_sql_i() - g.sql_bind_int(if it.val { + g.sql_bind_int(if expr.val { '1' } else { '0' diff --git a/vlib/v/gen/x64/gen.v b/vlib/v/gen/x64/gen.v index 47f2ed7df8..e7ce4d7bdb 100644 --- a/vlib/v/gen/x64/gen.v +++ b/vlib/v/gen/x64/gen.v @@ -479,7 +479,7 @@ pub fn (mut g Gen) save_main_fn_addr() { } pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, newline bool) { - match expr { + match union expr { ast.StringLiteral { if newline { g.gen_print(expr.val + '\n') @@ -575,7 +575,7 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) { // g.mov(.eax, 0) for i in 0 .. node.args.len { expr := node.args[i].expr - match expr { + match union expr { ast.IntegerLiteral { // `foo(2)` => `mov edi,0x2` g.mov(fn_arg_registers[i], expr.val.int()) @@ -648,7 +648,7 @@ fn C.strtol() int fn (mut g Gen) expr(node ast.Expr) { // println('cgen expr()') - match node { + match union node { ast.ArrayInit {} ast.BoolLiteral {} ast.CallExpr { @@ -719,7 +719,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) { name := left.str() // if left is ast.Ident { // ident := left as ast.Ident - match right { + match union right { ast.IntegerLiteral { g.allocate_var(name, 4, right.val.int()) } @@ -755,13 +755,12 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { if node.left is ast.InfixExpr { verror('only simple expressions are supported right now (not more than 2 operands)') } - match node.left { - ast.Ident { g.mov_var_to_reg(.eax, g.get_var_offset(it.name)) } + match union mut node.left { + ast.Ident { g.mov_var_to_reg(.eax, g.get_var_offset(node.left.name)) } else {} } - if node.right is ast.Ident { - ident := node.right as ast.Ident - var_offset := g.get_var_offset(ident.name) + if mut node.right is ast.Ident { + var_offset := g.get_var_offset(node.right.name) match node.op { .plus { g.add8_var(.eax, var_offset) } .mul { g.mul8_var(.eax, var_offset) } @@ -775,10 +774,10 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { branch := node.branches[0] infix_expr := branch.cond as ast.InfixExpr mut jne_addr := 0 // location of `jne *00 00 00 00*` - match infix_expr.left { + match union mut infix_expr.left { ast.Ident { lit := infix_expr.right as ast.IntegerLiteral - g.cmp_var(it.name, lit.val.int()) + g.cmp_var(infix_expr.left.name, lit.val.int()) jne_addr = g.jne() } else { @@ -798,10 +797,10 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) { // g.mov(.eax, 0x77777777) mut jump_addr := 0 // location of `jne *00 00 00 00*` start := g.pos() - match infix_expr.left { + match union mut infix_expr.left { ast.Ident { lit := infix_expr.right as ast.IntegerLiteral - g.cmp_var(it.name, lit.val.int()) + g.cmp_var(infix_expr.left.name, lit.val.int()) jump_addr = g.jge() } else { diff --git a/vlib/v/parser/assign.v b/vlib/v/parser/assign.v index b1afd45f5e..9f2d34d052 100644 --- a/vlib/v/parser/assign.v +++ b/vlib/v/parser/assign.v @@ -12,7 +12,7 @@ fn (mut p Parser) assign_stmt() ast.Stmt { } fn (mut p Parser) check_undefined_variables(exprs []ast.Expr, val ast.Expr) { - match val { + match union val { ast.Ident { for expr in exprs { if expr is ast.Ident { @@ -46,7 +46,7 @@ fn (mut p Parser) check_undefined_variables(exprs []ast.Expr, val ast.Expr) { fn (mut p Parser) check_cross_variables(exprs []ast.Expr, val ast.Expr) bool { val_ := val - match val_ { + match union val_ { ast.Ident { for expr in exprs { if expr is ast.Ident { @@ -113,7 +113,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme } mut is_static := false for i, lx in left { - match mut lx { + match union mut lx { ast.Ident { if op == .decl_assign { if p.scope.known_var(lx.name) { diff --git a/vlib/v/parser/if_match.v b/vlib/v/parser/if_match.v index 66302e1f24..8b8a029c92 100644 --- a/vlib/v/parser/if_match.v +++ b/vlib/v/parser/if_match.v @@ -122,17 +122,17 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { } comments << p.eat_comments() mut left_as_name := '' - if cond is ast.InfixExpr as infix { + if mut cond is ast.InfixExpr { // if sum is T - is_is_cast := infix.op == .key_is - is_ident := infix.left is ast.Ident + is_is_cast := cond.op == .key_is + is_ident := cond.left is ast.Ident left_as_name = if is_comptime { '' } else if is_is_cast && p.tok.kind == .key_as { p.next() p.check_name() } else if is_ident { - ident := infix.left as ast.Ident + ident := cond.left as ast.Ident ident.name } else { '' @@ -223,7 +223,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr { p.peek_tok.kind == .dot) && (p.tok.lit in table.builtin_type_names || p.tok.lit[0].is_capital() || (p.peek_tok.kind == .dot && p.peek_tok2.lit[0].is_capital())) { if var_name.len == 0 { - match cond { + match union cond { ast.Ident { // shadow match cond variable var_name = cond.name @@ -366,6 +366,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr { branches: branches cond: cond is_sum_type: is_sum_type + is_union_match: is_union_match pos: pos is_mut: is_mut var_name: var_name @@ -447,11 +448,11 @@ fn (mut p Parser) select_expr() ast.SelectExpr { if !stmt.is_expr { p.error_with_pos('select: invalid expression', stmt.pos) } else { - match stmt.expr as expr { + match union stmt.expr { ast.InfixExpr { - if expr.op != .arrow { + if stmt.expr.op != .arrow { p.error_with_pos('select key: `<-` operator expected', - expr.pos) + stmt.expr.pos) } } else { @@ -462,7 +463,8 @@ fn (mut p Parser) select_expr() ast.SelectExpr { } } ast.AssignStmt { - match stmt.right[0] as expr { + expr := stmt.right[0] + match union expr { ast.PrefixExpr { if expr.op != .arrow { p.error_with_pos('select key: `<-` operator expected', diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index ab4230b8f0..a504b3f8dc 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -353,7 +353,7 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr { p.next() mut right := if op == .minus { p.expr(token.Precedence.call) } else { p.expr(token.Precedence.prefix) } p.is_amp = false - if right is ast.CastExpr { + if mut right is ast.CastExpr { right.in_prexpr = true } mut or_stmts := []ast.Stmt{} diff --git a/vlib/v/parser/sql.v b/vlib/v/parser/sql.v index 63268058a5..87d56fe792 100644 --- a/vlib/v/parser/sql.v +++ b/vlib/v/parser/sql.v @@ -129,7 +129,7 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt { mut table_name := '' if kind != .delete { expr := p.expr(0) - match expr { + match union expr { ast.Ident { if kind == .insert { inserted_var_name = expr.name diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index 8b1acdaef2..7788915a75 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -203,7 +203,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl { // default_expr = p.tok.lit // p.expr(0) default_expr = p.expr(0) - match mut default_expr { + match union mut default_expr { ast.EnumVal { default_expr.typ = typ } // TODO: implement all types?? else {}