all: refactor ast.Expr to use the new sum type implementation (#6792)

pull/6896/head
Daniel Däschle 2020-11-21 00:05:57 +01:00 committed by GitHub
parent ff1752dfff
commit 838ad16296
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 277 additions and 280 deletions

View File

@ -9,7 +9,7 @@ import v.errors
pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl | UnionSumTypeDecl 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 | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal |
FloatLiteral | Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | FloatLiteral | Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral |
Likely | LockExpr | MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | Likely | LockExpr | MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr | PrefixExpr |
@ -559,18 +559,19 @@ pub mut:
pub struct MatchExpr { pub struct MatchExpr {
pub: pub:
tok_kind token.Kind tok_kind token.Kind
cond Expr cond Expr
branches []MatchBranch branches []MatchBranch
pos token.Position pos token.Position
is_mut bool // `match mut ast_node {` is_mut bool // `match mut ast_node {`
var_name string // `match cond as var_name {` var_name string // `match cond as var_name {`
is_union_match bool // temporary union key after match
pub mut: pub mut:
is_expr bool // returns a value is_expr bool // returns a value
return_type table.Type return_type table.Type
cond_type table.Type // type of `x` in `match x {` cond_type table.Type // type of `x` in `match x {`
expected_type table.Type // for debugging only expected_type table.Type // for debugging only
is_sum_type bool is_sum_type bool
} }
pub struct MatchBranch { pub struct MatchBranch {
@ -1057,7 +1058,7 @@ pub mut:
[inline] [inline]
pub fn (expr Expr) is_blank_ident() bool { pub fn (expr Expr) is_blank_ident() bool {
match expr { match union expr {
Ident { return expr.kind == .blank_ident } Ident { return expr.kind == .blank_ident }
else { return false } else { return false }
} }
@ -1065,7 +1066,7 @@ pub fn (expr Expr) is_blank_ident() bool {
pub fn (expr Expr) position() token.Position { pub fn (expr Expr) position() token.Position {
// all uncommented have to be implemented // all uncommented have to be implemented
match expr { match union expr {
// KEKW2 // KEKW2
AnonFn { AnonFn {
return expr.decl.pos return expr.decl.pos
@ -1101,7 +1102,7 @@ pub fn (expr Expr) position() token.Position {
} }
pub fn (expr Expr) is_lvalue() bool { pub fn (expr Expr) is_lvalue() bool {
match expr { match union expr {
Ident { return true } Ident { return true }
CTempVar { return true } CTempVar { return true }
IndexExpr { return expr.left.is_lvalue() } IndexExpr { return expr.left.is_lvalue() }
@ -1112,7 +1113,7 @@ pub fn (expr Expr) is_lvalue() bool {
} }
pub fn (expr Expr) is_expr() bool { pub fn (expr Expr) is_expr() bool {
match expr { match union expr {
IfExpr { return expr.is_expr } IfExpr { return expr.is_expr }
MatchExpr { return expr.is_expr } MatchExpr { return expr.is_expr }
else {} else {}

View File

@ -210,10 +210,10 @@ pub fn (sc &Scope) str() string {
// ``` // ```
// Since x is mutable, it returns true. // Since x is mutable, it returns true.
pub fn (s &Scope) is_selector_root_mutable(t &table.Table, selector_expr SelectorExpr) bool { pub fn (s &Scope) is_selector_root_mutable(t &table.Table, selector_expr SelectorExpr) bool {
if selector_expr.expr is SelectorExpr as left_expr { if mut selector_expr.expr is SelectorExpr {
return s.is_selector_root_mutable(t, left_expr) return s.is_selector_root_mutable(t, selector_expr.expr)
} else if selector_expr.expr is Ident as left_expr { } else if mut selector_expr.expr is Ident {
if v := s.find_var(left_expr.name) { if v := s.find_var(selector_expr.expr.name) {
return v.is_mut return v.is_mut
} }
} }

View File

@ -129,21 +129,21 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
if !needs_braces { if !needs_braces {
mut sub_expr := lit.exprs[i] mut sub_expr := lit.exprs[i]
for { for {
match sub_expr as sx { match union mut sub_expr {
Ident { Ident {
if sx.name[0] == `@` { if sub_expr.name[0] == `@` {
needs_braces = true needs_braces = true
} }
break break
} }
CallExpr { CallExpr {
if sx.args.len != 0 { if sub_expr.args.len != 0 {
needs_braces = true needs_braces = true
} }
break break
} }
SelectorExpr { SelectorExpr {
sub_expr = sx.expr sub_expr = sub_expr.expr
continue continue
} }
else { else {
@ -176,7 +176,7 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
// string representation of expr // string representation of expr
pub fn (x Expr) str() string { pub fn (x Expr) str() string {
match x { match union x {
CTempVar { CTempVar {
return x.orig.str() return x.orig.str()
} }

View File

@ -414,20 +414,20 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
if field.typ.is_ptr() { if field.typ.is_ptr() {
continue continue
} }
if field.default_expr is ast.IntegerLiteral as lit { if field.default_expr is ast.IntegerLiteral {
if lit.val == '0' { if field.default_expr.val == '0' {
c.warn('unnecessary default value of `0`: struct fields are zeroed by default', 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 { } else if field.default_expr is ast.StringLiteral {
if lit.val == '' { if field.default_expr.val == '' {
c.warn("unnecessary default value of '': struct fields are zeroed by default", 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 { } else if field.default_expr is ast.BoolLiteral {
if lit.val == false { if field.default_expr.val == false {
c.warn('unnecessary default value `false`: struct fields are zeroed by default', 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] { if infix_expr.op in [.div, .mod] {
match infix_expr.right as infix_right { match union mut infix_expr.right {
ast.FloatLiteral { 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' } 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 { ast.IntegerLiteral {
if infix_right.val.int() == 0 { if infix_expr.right.val.int() == 0 {
oper := if infix_expr.op == .div { 'division' } else { 'modulo' } 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 {} 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 // use `()` to make the boolean expression clear error
// for example: `(a && b) || c` instead of `a && b || c` // for example: `(a && b) || c` instead of `a && b || c`
if infix_expr.op in [.logical_or, .and] { if infix_expr.op in [.logical_or, .and] {
if infix_expr.left is ast.InfixExpr { if mut infix_expr.left is ast.InfixExpr {
e := infix_expr.left as ast.InfixExpr if infix_expr.left.op in [.logical_or, .and] &&
if e.op in [.logical_or, .and] && e.op != infix_expr.op { infix_expr.left.op != infix_expr.op {
c.error('use `()` to make the boolean expression clear', infix_expr.pos) 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 to_lock := '' // name of variable that needs lock
mut pos := token.Position{} // and its position mut pos := token.Position{} // and its position
mut explicit_lock_needed := false mut explicit_lock_needed := false
match mut expr { match union mut expr {
ast.CastExpr { ast.CastExpr {
// TODO // TODO
return '', pos 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) { 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) 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 { ast.AnonFn {
if arg_expr.decl.params.len > 1 { if arg_expr.decl.params.len > 1 {
c.error('function needs exactly 1 argument', call_expr.pos) 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 := false
mut found_in_args := false mut found_in_args := false
// anon fn direct call // 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 // it was set to anon for checker errors, clear for gen
call_expr.name = '' call_expr.name = ''
c.expr(call_expr.left) c.expr(call_expr.left)
anon_fn := call_expr.left as ast.AnonFn anon_fn_sym := c.table.get_type_symbol(call_expr.left.typ)
anon_fn_sym := c.table.get_type_symbol(anon_fn.typ)
f = (anon_fn_sym.info as table.FnType).func f = (anon_fn_sym.info as table.FnType).func
found = true 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 { fn is_expr_panic_or_exit(expr ast.Expr) bool {
match expr { match union expr {
ast.CallExpr { return expr.name in ['panic', 'exit'] } ast.CallExpr { return expr.name in ['panic', 'exit'] }
else { return false } 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 c.prevent_sum_type_unwrapping_once = false
// T.name, typeof(expr).name // T.name, typeof(expr).name
mut name_type := 0 mut name_type := 0
match selector_expr.expr as left { match union mut selector_expr.expr {
ast.Ident { 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) 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 // Note: in future typeof() should be a type known at compile-time
// sum types should not be handled dynamically // sum types should not be handled dynamically
ast.TypeOf { ast.TypeOf {
name_type = c.expr(left.expr) name_type = c.expr(selector_expr.expr.expr)
} }
else {} else {}
} }
@ -1911,21 +1911,20 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
} }
} }
if field.has_expr { if field.has_expr {
match field.expr as field_expr { match union field.expr {
ast.IntegerLiteral { ast.IntegerLiteral {
val := field_expr.val.i64() val := field.expr.val.i64()
if val < int_min || val > int_max { 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 { } 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) seen << int(val)
} }
ast.PrefixExpr {} ast.PrefixExpr {}
else { else {
if field.expr is ast.Ident { if field.expr is ast.Ident {
expr := field.expr as ast.Ident if field.expr.language == .c {
if expr.language == .c {
continue continue
} }
} }
@ -1988,13 +1987,12 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
if left_first is ast.Ident { if left_first is ast.Ident {
assigned_var := left_first assigned_var := left_first
if node.right is ast.Ident { if node.right is ast.Ident {
ident := node.right as ast.Ident
scope := c.file.scope.innermost(node.pos.pos) 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 right_type0 = v.typ
if node.op == .amp { if node.op == .amp {
if !v.is_mut && assigned_var.is_mut && !c.inside_unsafe { 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) node.pos)
} }
} }
@ -2049,7 +2047,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
negative = true negative = true
} }
} }
if expr is ast.IntegerLiteral { if mut expr is ast.IntegerLiteral {
mut is_large := false mut is_large := false
if expr.val.len > 8 { if expr.val.len > 8 {
val := expr.val.i64() 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) // left_type = c.expr(left)
} }
assign_stmt.left_types << left_type assign_stmt.left_types << left_type
match mut left { match union mut left {
ast.Ident { ast.Ident {
if left.kind == .blank_ident { if left.kind == .blank_ident {
left_type = right_type 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 { } else if array_init.is_fixed && array_init.exprs.len == 1 && array_init.elem_type != table.void_type {
// [50]byte // [50]byte
mut fixed_size := 1 mut fixed_size := 1
match array_init.exprs[0] as init_expr { init_expr := array_init.exprs[0]
match union init_expr {
ast.IntegerLiteral { ast.IntegerLiteral {
fixed_size = init_expr.val.int() 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 { fn is_const_integer(cfield ast.ConstField) ?ast.IntegerLiteral {
match cfield.expr { match union cfield.expr {
ast.IntegerLiteral { return *it } ast.IntegerLiteral { return cfield.expr }
else {} else {}
} }
return none 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.error('expression in `go` must be a function call', node.call_expr.position())
} }
c.expr(node.call_expr) c.expr(node.call_expr)
if node.call_expr is ast.CallExpr { if mut node.call_expr is ast.CallExpr {
call_expr := node.call_expr as ast.CallExpr
// Make sure there are no mutable arguments // 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() { if arg.is_mut && !arg.typ.is_ptr() {
c.error('function in `go` statement cannot contain mutable non-reference arguments', c.error('function in `go` statement cannot contain mutable non-reference arguments',
arg.expr.position()) 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', 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()) c.error('checker: too many expr levels: $c.expr_level ', node.position())
return table.void_type return table.void_type
} }
match mut node { match union mut node {
ast.CTempVar { ast.CTempVar {
return node.typ 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 { if node.right is ast.StringLiteral || node.right is ast.StringInterLiteral {
c.error('cannot take the address of a string', node.pos) c.error('cannot take the address of a string', node.pos)
} }
if node.right is ast.IndexExpr as index { if mut node.right is ast.IndexExpr {
typ_sym := c.table.get_type_symbol(index.left_type) typ_sym := c.table.get_type_symbol(node.right.left_type)
mut is_mut := false 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 { if ident.obj is ast.Var {
v := ident.obj as ast.Var v := ident.obj as ast.Var
is_mut = v.is_mut 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 !c.inside_unsafe && is_mut {
if typ_sym.kind == .map { if typ_sym.kind == .map {
c.error('cannot take the address of mutable map values outside unsafe blocks', c.error('cannot take the address of mutable map values outside unsafe blocks',
index.pos) node.right.pos)
} }
if typ_sym.kind == .array { if typ_sym.kind == .array {
c.error('cannot take the address of mutable array elements outside unsafe blocks', 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 { } else if node.expr_type == table.string_type {
if to_type_sym.kind != .alias { if to_type_sym.kind != .alias {
mut error_msg := 'cannot cast a string' mut error_msg := 'cannot cast a string'
if node.expr is ast.StringLiteral { if mut node.expr is ast.StringLiteral {
str_lit := node.expr as ast.StringLiteral if node.expr.val.len == 1 {
if str_lit.val.len == 1 { error_msg += ", for denoting characters use `$node.expr.val` instead of '$node.expr.val'"
error_msg += ", for denoting characters use `$str_lit.val` instead of '$str_lit.val'"
} }
} }
c.error(error_msg, node.pos) 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 c.prevent_sum_type_unwrapping_once = false
mut typ := if is_sum_type_cast { obj.sum_type_cast } else { obj.typ } mut typ := if is_sum_type_cast { obj.sum_type_cast } else { obj.typ }
if typ == 0 { if typ == 0 {
if obj.expr is ast.Ident { if mut obj.expr is ast.Ident {
inner_ident := obj.expr as ast.Ident if obj.expr.kind == .unresolved {
if inner_ident.kind == .unresolved {
c.error('unresolved variable: `$ident.name`', ident.pos) c.error('unresolved variable: `$ident.name`', ident.pos)
return table.void_type return table.void_type
} }
@ -3446,7 +3443,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
} }
continue continue
} }
match expr { match union expr {
ast.Type { ast.Type {
key = c.table.type_to_str(expr.typ) key = c.table.type_to_str(expr.typ)
expr_types << expr 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 expr_type = expr_types[0].typ
} }
mut scope := c.file.scope.innermost(branch.pos.pos) mut scope := c.file.scope.innermost(branch.pos.pos)
match node.cond as node_cond { match mut node.cond {
ast.SelectorExpr { ast.SelectorExpr {
expr_sym := c.table.get_type_symbol(node_cond.expr_type) expr_sym := c.table.get_type_symbol(node.cond.expr_type)
field := c.table.struct_find_field(expr_sym, node_cond.field_name) or { field := c.table.struct_find_field(expr_sym, node.cond.field_name) or {
table.Field{} table.Field{}
} }
is_mut := field.is_mut 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 // smartcast either if the value is immutable or if the mut argument is explicitly given
if (!is_root_mut && !is_mut) || node.is_mut { if (!is_root_mut && !is_mut) || node.is_mut {
scope.register_struct_field(ast.ScopeStructField{ scope.register_struct_field(ast.ScopeStructField{
struct_type: node_cond.expr_type struct_type: node.cond.expr_type
name: node_cond.field_name name: node.cond.field_name
typ: node.cond_type typ: node.cond_type
sum_type_cast: expr_type sum_type_cast: expr_type
pos: node_cond.pos pos: node.cond.pos
}) })
} }
} }
ast.Ident { ast.Ident {
mut is_mut := false 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 is_mut = v.is_mut
} }
// smartcast either if the value is immutable or if the mut argument is explicitly given // 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{ scope.register(node.var_name, ast.Var{
name: node.var_name name: node.var_name
typ: node.cond_type typ: node.cond_type
pos: node_cond.pos pos: node.cond.pos
is_used: true is_used: true
is_mut: node.is_mut is_mut: node.is_mut
sum_type_cast: expr_type sum_type_cast: expr_type
@ -3648,10 +3645,10 @@ pub fn (mut c Checker) select_expr(mut node ast.SelectExpr) table.Type {
stmt.pos) stmt.pos)
} }
} else { } else {
if stmt.expr is ast.InfixExpr as expr { if stmt.expr is ast.InfixExpr {
if expr.left !is ast.Ident && if stmt.expr.left !is ast.Ident &&
expr.left !is ast.SelectorExpr && expr.left !is ast.IndexExpr { stmt.expr.left !is ast.SelectorExpr && stmt.expr.left !is ast.IndexExpr {
c.error('channel in `select` key must be predefined', expr.left.position()) c.error('channel in `select` key must be predefined', stmt.expr.left.position())
} }
} else { } else {
c.error('invalid expression for `select` key', stmt.expr.position()) 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 { ast.AssignStmt {
match stmt.right[0] as expr { expr := stmt.right[0]
match union expr {
ast.PrefixExpr { ast.PrefixExpr {
if expr.right !is ast.Ident && if expr.right !is ast.Ident &&
expr.right !is ast.SelectorExpr && expr.right !is ast.IndexExpr { 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 || if (infix.left is ast.Ident ||
infix.left is ast.SelectorExpr) && infix.left is ast.SelectorExpr) &&
infix.right is ast.Type { infix.right is ast.Type {
is_variable := if infix.left is ast.Ident { (infix.left as ast.Ident).kind == is_variable := if mut infix.left is ast.Ident { infix.left.kind == .variable } else { true }
.variable } else { true }
// Register shadow variable or `as` variable with actual type // Register shadow variable or `as` variable with actual type
if is_variable { if is_variable {
if left_sym.kind in [.sum_type, .interface_, .union_sum_type] { if left_sym.kind in [.sum_type, .interface_, .union_sum_type] {
mut is_mut := false mut is_mut := false
mut scope := c.file.scope.innermost(branch.body_pos.pos) mut scope := c.file.scope.innermost(branch.body_pos.pos)
if infix.left is ast.Ident as infix_left { if mut infix.left is ast.Ident {
if v := scope.find_var(infix_left.name) { if v := scope.find_var(infix.left.name) {
is_mut = v.is_mut is_mut = v.is_mut
} }
// smartcast either if the value is immutable or if the mut argument is explicitly given // 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 name: branch.left_as_name
typ: infix.left_type typ: infix.left_type
sum_type_cast: right_expr.typ sum_type_cast: right_expr.typ
pos: infix.left.position() pos: infix.left.pos
is_used: true is_used: true
is_mut: is_mut is_mut: is_mut
}) })
} }
} else if infix.left is ast.SelectorExpr as selector { } else if mut infix.left is ast.SelectorExpr {
expr_sym := c.table.get_type_symbol(selector.expr_type) expr_sym := c.table.get_type_symbol(infix.left.expr_type)
field := c.table.struct_find_field(expr_sym, selector.field_name) or { field := c.table.struct_find_field(expr_sym, infix.left.field_name) or {
table.Field{} table.Field{}
} }
is_mut = field.is_mut is_mut = field.is_mut
is_root_mut := scope.is_selector_root_mutable(c.table, 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 // smartcast either if the value is immutable or if the mut argument is explicitly given
if ((!is_root_mut && !is_mut) || if ((!is_root_mut && !is_mut) ||
branch.is_mut_name) && branch.is_mut_name) &&
left_sym.kind == .union_sum_type { left_sym.kind == .union_sum_type {
scope.register_struct_field(ast.ScopeStructField{ scope.register_struct_field(ast.ScopeStructField{
struct_type: selector.expr_type struct_type: infix.left.expr_type
name: selector.field_name name: infix.left.field_name
typ: infix.left_type typ: infix.left_type
sum_type_cast: right_expr.typ 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) // 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 { fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
// TODO: better error messages here // TODO: better error messages here
match cond { match union cond {
ast.ParExpr { ast.ParExpr {
return c.comp_if_branch(cond.expr, pos) 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 { ast.PostfixExpr {
if cond.op != .question { if cond.op != .question {
c.error('invalid \$if postfix operator', cond.pos) c.error('invalid \$if postfix operator', cond.pos)
} else if cond.expr is ast.Ident as ident { } else if cond.expr is ast.Ident {
return ident.name !in c.pref.compile_defines_all return cond.expr.name !in c.pref.compile_defines_all
} else { } else {
c.error('invalid `\$if` condition', cond.pos) 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()) { if !c.inside_unsafe && (typ.is_ptr() || typ.is_pointer()) {
mut is_ok := false mut is_ok := false
if node.left is ast.Ident { if mut node.left is ast.Ident {
ident := node.left as ast.Ident scope := c.file.scope.innermost(node.left.pos.pos)
scope := c.file.scope.innermost(ident.pos.pos) if v := scope.find_var(node.left.name) {
if v := scope.find_var(ident.name) {
// `mut param []T` function parameter // `mut param []T` function parameter
is_ok = v.is_mut && v.is_arg && !typ.deref().is_ptr() 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) c.warn('pointer indexing is only allowed in `unsafe` blocks', node.pos)
} }
} }
if node.index is ast.RangeExpr as range { // [1..2] if mut node.index is ast.RangeExpr { // [1..2]
if range.has_low { if node.index.has_low {
index_type := c.expr(range.low) index_type := c.expr(node.index.low)
c.check_index_type(typ_sym, index_type, node.pos) c.check_index_type(typ_sym, index_type, node.pos)
} }
if range.has_high { if node.index.has_high {
index_type := c.expr(range.high) index_type := c.expr(node.index.high)
c.check_index_type(typ_sym, index_type, node.pos) c.check_index_type(typ_sym, index_type, node.pos)
} }
// array[1..2] => array // array[1..2] => array
@ -4559,8 +4555,8 @@ fn has_top_return(stmts []ast.Stmt) bool {
return true return true
} }
} else if stmt is ast.ExprStmt { } else if stmt is ast.ExprStmt {
if stmt.expr is ast.CallExpr as ce { if stmt.expr is ast.CallExpr {
if ce.name in ['panic', 'exit'] { if stmt.expr.name in ['panic', 'exit'] {
return true return true
} }
} }

View File

@ -222,8 +222,8 @@ pub fn (mut d Doc) file_ast(file_ast ast.File) map[string]DocNode {
for sidx, stmt in stmts { for sidx, stmt in stmts {
// eprintln('stmt typeof: ' + typeof(stmt)) // eprintln('stmt typeof: ' + typeof(stmt))
if stmt is ast.ExprStmt { if stmt is ast.ExprStmt {
if stmt.expr is ast.Comment as cmt { if stmt.expr is ast.Comment {
prev_comments << cmt prev_comments << stmt.expr
continue continue
} }
} }

View File

@ -771,7 +771,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
if f.is_debug { if f.is_debug {
eprintln('expr: ${node.position():-42} | node: ${typeof(node):-20} | $node.str()') eprintln('expr: ${node.position():-42} | node: ${typeof(node):-20} | $node.str()')
} }
match mut node { match union mut node {
ast.CTempVar { ast.CTempVar {
eprintln('ast.CTempVar of $node.orig.str() should be generated/used only in cgen') 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() f.expr_bufs << f.out.str()
mut penalty := 3 mut penalty := 3
match node.left as left { match union mut node.left {
ast.InfixExpr { 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-- penalty--
} }
} }
@ -1377,7 +1377,7 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) {
} }
else {} else {}
} }
match node.right as right { match union node.right {
ast.InfixExpr { penalty-- } ast.InfixExpr { penalty-- }
ast.ParExpr { penalty = 1 } ast.ParExpr { penalty = 1 }
else {} else {}
@ -1418,11 +1418,11 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
for i, branch in it.branches { for i, branch in it.branches {
// Check `sum is T` smartcast // Check `sum is T` smartcast
mut smartcast_as := false mut smartcast_as := false
if branch.cond is ast.InfixExpr as infix { if branch.cond is ast.InfixExpr {
if infix.op == .key_is { if branch.cond.op == .key_is {
// left_as_name is either empty, infix.left.str() or the `as` name // left_as_name is either empty, branch.cond.left.str() or the `as` name
smartcast_as = branch.left_as_name.len > 0 && 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 { if i == 0 {
@ -1513,16 +1513,15 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
} }
} }
if node.left is ast.Ident { 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 // `time.now()` without `time imported` is processed as a method call with `time` being
// a `node.left` expression. Import `time` automatically. // a `node.left` expression. Import `time` automatically.
// TODO fetch all available modules // TODO fetch all available modules
if left.name in ['time', 'os', 'strings', 'math', 'json', 'base64'] { if node.left.name in ['time', 'os', 'strings', 'math', 'json', 'base64'] {
if left.name !in f.auto_imports { if node.left.name !in f.auto_imports {
f.auto_imports << left.name f.auto_imports << node.left.name
f.file.imports << ast.Import{ f.file.imports << ast.Import{
mod: left.name mod: node.left.name
alias: left.name alias: node.left.name
} }
} }
// for imp in f.file.imports { // 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) f.or_expr(node.or_block)
} else { } else {
f.write_language_prefix(node.language) f.write_language_prefix(node.language)
if node.left is ast.AnonFn as anon_fn { if node.left is ast.AnonFn {
f.fn_decl(anon_fn.decl) f.fn_decl(node.left.decl)
} else { } else {
mut name := f.short_module(node.name) mut name := f.short_module(node.name)
f.mark_module_as_used(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) { pub fn (mut f Fmt) match_expr(it ast.MatchExpr) {
f.write('match ') f.write('match ')
// TODO: temporary, remove again
if it.is_union_match {
f.write('union ')
}
if it.is_mut { if it.is_mut {
f.write('mut ') f.write('mut ')
} }
f.expr(it.cond) f.expr(it.cond)
if it.cond is ast.Ident { if it.cond is ast.Ident {
ident := it.cond as ast.Ident f.it_name = it.cond.name
f.it_name = ident.name
} else if it.cond is ast.SelectorExpr { } else if it.cond is ast.SelectorExpr {
// `x.y as z` // `x.y as z`
// if ident.name != it.var_name && it.var_name != '' { // 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 { fn expr_is_single_line(expr ast.Expr) bool {
match expr { match union expr {
ast.IfExpr { return false } ast.IfExpr { return false }
ast.Comment { return false } ast.Comment { return false }
else {} else {}

View File

@ -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) { fn (mut g Gen) gen_assert_stmt(original_assert_statement ast.AssertStmt) {
mut a := original_assert_statement mut a := original_assert_statement
g.writeln('// assert') g.writeln('// assert')
if a.expr is ast.InfixExpr { if mut a.expr is ast.InfixExpr {
mut aie := a.expr as ast.InfixExpr if mut a.expr.left is ast.CallExpr {
if aie.left is ast.CallExpr { a.expr.left = g.new_ctemp_var_then_gen(a.expr.left, a.expr.left_type)
aie.left = g.new_ctemp_var_then_gen(aie.left, aie.left_type)
} }
if aie.right is ast.CallExpr { if mut a.expr.right is ast.CallExpr {
aie.right = g.new_ctemp_var_then_gen(aie.right, aie.right_type) a.expr.right = g.new_ctemp_var_then_gen(a.expr.right, a.expr.right_type)
} }
} }
g.inside_ternary++ 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}.line_nr = $line_nr;')
g.writeln('\t${metaname}.fn_name = ${ctoslit(fn_name)};') g.writeln('\t${metaname}.fn_name = ${ctoslit(fn_name)};')
g.writeln('\t${metaname}.src = ${cnewlines(ctoslit(src))};') g.writeln('\t${metaname}.src = ${cnewlines(ctoslit(src))};')
match a.expr { match union mut a.expr {
ast.InfixExpr { ast.InfixExpr {
g.writeln('\t${metaname}.op = ${ctoslit(it.op.str())};') g.writeln('\t${metaname}.op = ${ctoslit(a.expr.op.str())};')
g.writeln('\t${metaname}.llabel = ${cnewlines(ctoslit(it.left.str()))};') g.writeln('\t${metaname}.llabel = ${cnewlines(ctoslit(a.expr.left.str()))};')
g.writeln('\t${metaname}.rlabel = ${cnewlines(ctoslit(it.right.str()))};') g.writeln('\t${metaname}.rlabel = ${cnewlines(ctoslit(a.expr.right.str()))};')
g.write('\t${metaname}.lvalue = ') 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.writeln(';')
// //
g.write('\t${metaname}.rvalue = ') 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(';') g.writeln(';')
} }
ast.CallExpr { 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) { fn (mut g Gen) gen_assert_single_expr(e ast.Expr, t table.Type) {
unknown_value := '*unknown value*' unknown_value := '*unknown value*'
match e { match union e {
ast.CastExpr, ast.IndexExpr, ast.MatchExpr { ast.CastExpr, ast.IndexExpr, ast.MatchExpr {
g.write(ctoslit(unknown_value)) 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 mut return_type := table.void_type
op := if assign_stmt.op == .decl_assign { token.Kind.assign } else { assign_stmt.op } op := if assign_stmt.op == .decl_assign { token.Kind.assign } else { assign_stmt.op }
is_decl := assign_stmt.op == .decl_assign is_decl := assign_stmt.op == .decl_assign
match assign_stmt.right[0] { right_expr := assign_stmt.right[0]
ast.CallExpr, ast.MatchExpr { return_type = it.return_type } match union right_expr {
ast.IfExpr { return_type = it.typ } ast.CallExpr { return_type = right_expr.return_type }
ast.MatchExpr { return_type = right_expr.return_type }
ast.IfExpr { return_type = right_expr.typ }
else {} else {}
} }
// Free the old value assigned to this string var (only if it's `str = [new value]`) // 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.is_assign_rhs = false
g.writeln(';') g.writeln(';')
for i, lx in assign_stmt.left { for i, lx in assign_stmt.left {
match lx { if lx is ast.Ident {
ast.Ident { if lx.kind == .blank_ident {
if lx.kind == .blank_ident { continue
continue
}
} }
else {}
} }
styp := g.typ(assign_stmt.left_types[i]) styp := g.typ(assign_stmt.left_types[i])
if assign_stmt.op == .decl_assign { 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) // TODO: non idents on left (exprs)
if assign_stmt.has_cross_var { if assign_stmt.has_cross_var {
for i, left in assign_stmt.left { for i, left in assign_stmt.left {
match left { match union left {
ast.Ident { ast.Ident {
left_typ := assign_stmt.left_types[i] left_typ := assign_stmt.left_types[i]
left_sym := g.table.get_type_symbol(left_typ) 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.write('$styp _var_$left.pos.pos = ')
g.expr(left.expr) g.expr(left.expr)
if left.expr_type.is_ptr() { if left.expr_type.is_ptr() {
g.write('/* left.expr_type */')
g.writeln('->$left.field_name;') g.writeln('->$left.field_name;')
} else { } else {
g.writeln('.$left.field_name;') 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 blank_assign := false
mut ident := ast.Ident{} mut ident := ast.Ident{}
if left is ast.Ident { if left is ast.Ident {
ident = *left ident = left
// id_info := ident.var_info() // id_info := ident.var_info()
// var_type = id_info.typ // var_type = id_info.typ
blank_assign = left.kind == .blank_ident 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) styp := g.typ(var_type)
mut is_fixed_array_init := false mut is_fixed_array_init := false
mut has_val := false mut has_val := false
match val { match union val {
ast.ArrayInit { ast.ArrayInit {
is_fixed_array_init = val.is_fixed is_fixed_array_init = val.is_fixed
has_val = val.has_val 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.fn_args(val.decl.params, val.decl.is_variadic)
g.definitions.go_back(g.definitions.len - def_pos) g.definitions.go_back(g.definitions.len - def_pos)
g.write(') = ') g.write(') = ')
g.expr(*val) g.expr(val)
g.writeln(';') g.writeln(';')
if blank_assign { if blank_assign {
g.write('}') 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) { fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) {
val_ := val val_ := val
match val { match union val {
ast.Ident { ast.Ident {
mut has_var := false mut has_var := false
for lx in left { 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) { fn (mut g Gen) expr(node ast.Expr) {
// println('cgen expr() line_nr=$node.pos.line_nr') // println('cgen expr() line_nr=$node.pos.line_nr')
// 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 node { match union node {
ast.AnonFn { ast.AnonFn {
// TODO: dont fiddle with buffers // TODO: dont fiddle with buffers
g.gen_anon_fn_decl(node) 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) { fn (mut g Gen) enum_expr(node ast.Expr) {
match node { match union node {
ast.EnumVal { g.write(node.val) } ast.EnumVal { g.write(node.val) }
else { g.expr(node) } else { g.expr(node) }
} }
@ -2832,19 +2831,16 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
g.write('!') g.write('!')
} }
if right_sym.kind == .array { if right_sym.kind == .array {
match node.right { if mut node.right is ast.ArrayInit {
ast.ArrayInit { if node.right.exprs.len > 0 {
if it.exprs.len > 0 { // `a in [1,2,3]` optimization => `a == 1 || a == 2 || a == 3`
// `a in [1,2,3]` optimization => `a == 1 || a == 2 || a == 3` // avoids an allocation
// avoids an allocation // g.write('/*in opt*/')
// g.write('/*in opt*/') g.write('(')
g.write('(') g.in_optimization(node.left, node.right)
g.in_optimization(node.left, it) g.write(')')
g.write(')') return
return
}
} }
else {}
} }
if left_sym.kind == .function { if left_sym.kind == .function {
g.write('_IN(voidptr, ') 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 { } else if expr is ast.RangeExpr {
// if type is unsigned and low is 0, check is unneeded // if type is unsigned and low is 0, check is unneeded
mut skip_low := false 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] && 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 skip_low = true
} }
} }
@ -3526,14 +3522,14 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
g.writeln('\tint errcode = ${cvar_name}.ecode;') g.writeln('\tint errcode = ${cvar_name}.ecode;')
} }
} else { } else {
match branch.cond as cond { match union branch.cond {
ast.IfGuardExpr { ast.IfGuardExpr {
var_name := guard_vars[i] var_name := guard_vars[i]
g.write('if ($var_name = ') g.write('if ($var_name = ')
g.expr(it.expr) g.expr(branch.cond.expr)
g.writeln(', ${var_name}.ok) {') g.writeln(', ${var_name}.ok) {')
if cond.var_name != '_' { if branch.cond.var_name != '_' {
g.writeln('\t${g.typ(cond.expr_type)} $cond.var_name = $var_name;') g.writeln('\t${g.typ(branch.cond.expr_type)} $branch.cond.var_name = $var_name;')
} }
} }
else { else {
@ -3575,7 +3571,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
} }
fn (mut g Gen) index_expr(node ast.IndexExpr) { fn (mut g Gen) index_expr(node ast.IndexExpr) {
match node.index { match union node.index {
ast.RangeExpr { ast.RangeExpr {
sym := g.table.get_type_symbol(node.left_type) sym := g.table.get_type_symbol(node.left_type)
if sym.kind == .string { if sym.kind == .string {
@ -3602,14 +3598,14 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
g.expr(node.left) g.expr(node.left)
} }
g.write(', ') g.write(', ')
if it.has_low { if node.index.has_low {
g.expr(it.low) g.expr(node.index.low)
} else { } else {
g.write('0') g.write('0')
} }
g.write(', ') g.write(', ')
if it.has_high { if node.index.has_high {
g.expr(it.high) g.expr(node.index.high)
} else { } else {
g.expr(node.left) g.expr(node.left)
g.write('.len') g.write('.len')
@ -3828,7 +3824,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
[inline] [inline]
fn (g &Gen) expr_is_multi_return_call(expr ast.Expr) bool { 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 } ast.CallExpr { return g.table.get_type_symbol(expr.return_type).kind == .multi_return }
else { return false } else { return false }
} }
@ -4051,13 +4047,13 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
} }
} else { } else {
*/ */
match field.expr { match union field.expr {
ast.CharLiteral, ast.FloatLiteral, ast.IntegerLiteral { ast.CharLiteral, ast.FloatLiteral, ast.IntegerLiteral {
g.const_decl_simple_define(name, val) g.const_decl_simple_define(name, val)
} }
ast.ArrayInit { ast.ArrayInit {
if it.is_fixed { if field.expr.is_fixed {
styp := g.typ(it.typ) styp := g.typ(field.expr.typ)
g.definitions.writeln('$styp _const_$name = $val; // fixed array const') g.definitions.writeln('$styp _const_$name = $val; // fixed array const')
} else { } else {
g.const_decl_init_later(field.mod, name, val, field.typ) 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) g.expr(expr)
return true return true
} else if sym.kind == .enum_ { } else if sym.kind == .enum_ {
is_var := match expr { is_var := match union expr {
ast.SelectorExpr, ast.Ident { true } ast.SelectorExpr, ast.Ident { true }
else { false } else { false }
} }
@ -4808,19 +4804,20 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
g.expr(node.left) g.expr(node.left)
g.writeln('.data)[$i];') g.writeln('.data)[$i];')
g.write('\t$ret_elem_type ti = ') g.write('\t$ret_elem_type ti = ')
match node.args[0].expr { expr := node.args[0].expr
match union expr {
ast.AnonFn { ast.AnonFn {
g.gen_anon_fn_decl(it) g.gen_anon_fn_decl(expr)
g.write('${it.decl.name}(it)') g.write('${expr.decl.name}(it)')
} }
ast.Ident { ast.Ident {
if it.kind == .function { if expr.kind == .function {
g.write('${c_name(it.name)}(it)') g.write('${c_name(expr.name)}(it)')
} else if it.kind == .variable { } else if expr.kind == .variable {
var_info := it.var_info() var_info := expr.var_info()
sym := g.table.get_type_symbol(var_info.typ) sym := g.table.get_type_symbol(var_info.typ)
if sym.kind == .function { if sym.kind == .function {
g.write('${c_name(it.name)}(it)') g.write('${c_name(expr.name)}(it)')
} else { } else {
g.expr(node.args[0].expr) 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.expr(node.left)
g.writeln('.data)[i];') g.writeln('.data)[i];')
g.write('if (') g.write('if (')
match node.args[0].expr { expr := node.args[0].expr
match union expr {
ast.AnonFn { ast.AnonFn {
g.gen_anon_fn_decl(it) g.gen_anon_fn_decl(expr)
g.write('${it.decl.name}(it)') g.write('${expr.decl.name}(it)')
} }
ast.Ident { ast.Ident {
if it.kind == .function { if expr.kind == .function {
g.write('${c_name(it.name)}(it)') g.write('${c_name(expr.name)}(it)')
} else if it.kind == .variable { } else if expr.kind == .variable {
var_info := it.var_info() var_info := expr.var_info()
sym_t := g.table.get_type_symbol(var_info.typ) sym_t := g.table.get_type_symbol(var_info.typ)
if sym_t.kind == .function { if sym_t.kind == .function {
g.write('${c_name(it.name)}(it)') g.write('${c_name(expr.name)}(it)')
} else { } else {
g.expr(node.args[0].expr) 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 { 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) } ast.CallExpr { return g.typ(node.return_type) }
else { return typeof(node) } else { return typeof(node) }
} }
@ -5461,9 +5459,9 @@ fn (mut g Gen) go_stmt(node ast.GoStmt) {
if expr.is_method { if expr.is_method {
receiver_sym := g.table.get_type_symbol(expr.receiver_type) receiver_sym := g.table.get_type_symbol(expr.receiver_type)
name = receiver_sym.name + '_' + name name = receiver_sym.name + '_' + name
} else if expr.left is ast.AnonFn as anon_fn { } else if expr.left is ast.AnonFn {
g.gen_anon_fn_decl(anon_fn) g.gen_anon_fn_decl(expr.left)
fsym := g.table.get_type_symbol(anon_fn.typ) fsym := g.table.get_type_symbol(expr.left.typ)
name = fsym.name name = fsym.name
} }
name = util.no_dots(name) name = util.no_dots(name)

View File

@ -45,8 +45,7 @@ fn (mut g Gen) comptime_call(node ast.ComptimeCall) {
} }
for i in 1 .. m.params.len { for i in 1 .. m.params.len {
if node.left is ast.Ident { if node.left is ast.Ident {
left_name := node.left as ast.Ident if m.params[i].name == node.left.name {
if m.params[i].name == left_name.name {
continue continue
} }
} }
@ -175,7 +174,7 @@ fn (mut g Gen) comp_if(node ast.IfExpr) {
} }
fn (mut g Gen) comp_if_expr(cond ast.Expr) { fn (mut g Gen) comp_if_expr(cond ast.Expr) {
match cond { match union cond {
ast.ParExpr { ast.ParExpr {
g.write('(') g.write('(')
g.comp_if_expr(cond.expr) g.comp_if_expr(cond.expr)

View File

@ -403,7 +403,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
mut is_range_slice := false mut is_range_slice := false
if node.receiver_type.is_ptr() && !node.left_type.is_ptr() { if node.receiver_type.is_ptr() && !node.left_type.is_ptr() {
if node.left is ast.IndexExpr { if node.left is ast.IndexExpr {
idx := (node.left as ast.IndexExpr).index idx := node.left.index
if idx is ast.RangeExpr { if idx is ast.RangeExpr {
// expr is arr[range].clone() // expr is arr[range].clone()
// use array_clone_static instead of array_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') g.writeln('); ${print_method}($tmp); string_free(&$tmp); //MEM2 $styp')
} else { } else {
expr := node.args[0].expr expr := node.args[0].expr
is_var := match expr { is_var := match union expr {
ast.SelectorExpr { true } ast.SelectorExpr { true }
ast.Ident { true } ast.Ident { true }
else { false } else { false }
@ -665,7 +665,7 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
if arg.expr is ast.CallExpr { if arg.expr is ast.CallExpr {
// Any argument can be an expression that has to be freed. Generate a tmp expression // Any argument can be an expression that has to be freed. Generate a tmp expression
// for each of those recursively. // 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 free_tmp_arg_vars = true
// t := g.new_tmp_var() + '_arg_expr_${name}_$i' // t := g.new_tmp_var() + '_arg_expr_${name}_$i'

View File

@ -523,7 +523,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 union node {
ast.CTempVar { ast.CTempVar {
g.write('/* ast.CTempVar: node.name */') 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) { fn (mut g JsGen) gen_go_stmt(node ast.GoStmt) {
// x := node.call_expr as ast.CallEpxr // TODO // x := node.call_expr as ast.CallEpxr // TODO
match node.call_expr { match union node.call_expr {
ast.CallExpr { ast.CallExpr {
mut name := it.name mut name := node.call_expr.name
if it.is_method { if node.call_expr.is_method {
receiver_sym := g.table.get_type_symbol(it.receiver_type) receiver_sym := g.table.get_type_symbol(node.call_expr.receiver_type)
name = receiver_sym.name + '.' + name name = receiver_sym.name + '.' + name
} }
g.writeln('await new Promise(function(resolve){') g.writeln('await new Promise(function(resolve){')
g.inc_indent() g.inc_indent()
g.write('${name}(') g.write('${name}(')
for i, arg in it.args { for i, arg in node.call_expr.args {
g.expr(arg.expr) g.expr(arg.expr)
if i < it.args.len - 1 { if i < node.call_expr.args.len - 1 {
g.write(', ') g.write(', ')
} }
} }
@ -1184,21 +1184,22 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
node := it node := it
g.write(it.name) g.write(it.name)
g.write('(') g.write('(')
match node.args[0].expr { expr := node.args[0].expr
match union expr {
ast.AnonFn { ast.AnonFn {
g.gen_fn_decl(it.decl) g.gen_fn_decl(expr.decl)
g.write(')') g.write(')')
return return
} }
ast.Ident { ast.Ident {
if it.kind == .function { if expr.kind == .function {
g.write(g.js_name(it.name)) g.write(g.js_name(expr.name))
g.write(')') g.write(')')
return return
} else if it.kind == .variable { } else if expr.kind == .variable {
v_sym := g.table.get_type_symbol(it.var_info().typ) v_sym := g.table.get_type_symbol(expr.var_info().typ)
if v_sym.kind == .function { if v_sym.kind == .function {
g.write(g.js_name(it.name)) g.write(g.js_name(expr.name))
g.write(')') g.write(')')
return 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) left_typ := g.table.get_type_symbol(expr.left_type)
// TODO: Handle splice setting if it's implemented // TODO: Handle splice setting if it's implemented
if expr.index is ast.RangeExpr { if expr.index is ast.RangeExpr {
range := expr.index as ast.RangeExpr
g.expr(expr.left) g.expr(expr.left)
g.write('.slice(') g.write('.slice(')
if range.has_low { if expr.index.has_low {
g.expr(range.low) g.expr(expr.index.low)
} else { } else {
g.write('0') g.write('0')
} }
g.write(', ') g.write(', ')
if range.has_high { if expr.index.has_high {
g.expr(range.high) g.expr(expr.index.high)
} else { } else {
g.expr(expr.left) g.expr(expr.left)
g.write('.length') g.write('.length')

View File

@ -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, // 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. // not a V variable. Need to distinguish column names from V variables.
match expr { match union expr {
ast.InfixExpr { ast.InfixExpr {
g.sql_side = .left g.sql_side = .left
g.expr_to_sql(expr.left) g.expr_to_sql(expr.left)
@ -275,22 +275,22 @@ fn (mut g Gen) expr_to_sql(expr ast.Expr) {
else {} else {}
} }
g.sql_side = .right g.sql_side = .right
g.expr_to_sql(it.right) g.expr_to_sql(expr.right)
} }
ast.StringLiteral { ast.StringLiteral {
// g.write("'$it.val'") // g.write("'$it.val'")
g.inc_sql_i() 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 { ast.IntegerLiteral {
g.inc_sql_i() g.inc_sql_i()
g.sql_bind_int(it.val) g.sql_bind_int(expr.val)
} }
ast.BoolLiteral { ast.BoolLiteral {
// true/false literals were added to Sqlite 3.23 (2018-04-02) // 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 ) // but lots of apps/distros use older sqlite (e.g. Ubuntu 18.04 LTS )
g.inc_sql_i() g.inc_sql_i()
g.sql_bind_int(if it.val { g.sql_bind_int(if expr.val {
'1' '1'
} else { } else {
'0' '0'

View File

@ -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) { pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, newline bool) {
match expr { match union expr {
ast.StringLiteral { ast.StringLiteral {
if newline { if newline {
g.gen_print(expr.val + '\n') g.gen_print(expr.val + '\n')
@ -575,7 +575,7 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) {
// g.mov(.eax, 0) // g.mov(.eax, 0)
for i in 0 .. node.args.len { for i in 0 .. node.args.len {
expr := node.args[i].expr expr := node.args[i].expr
match expr { match union expr {
ast.IntegerLiteral { ast.IntegerLiteral {
// `foo(2)` => `mov edi,0x2` // `foo(2)` => `mov edi,0x2`
g.mov(fn_arg_registers[i], expr.val.int()) 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) { fn (mut g Gen) expr(node ast.Expr) {
// println('cgen expr()') // println('cgen expr()')
match node { match union node {
ast.ArrayInit {} ast.ArrayInit {}
ast.BoolLiteral {} ast.BoolLiteral {}
ast.CallExpr { ast.CallExpr {
@ -719,7 +719,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
name := left.str() name := left.str()
// if left is ast.Ident { // if left is ast.Ident {
// ident := left as ast.Ident // ident := left as ast.Ident
match right { match union right {
ast.IntegerLiteral { ast.IntegerLiteral {
g.allocate_var(name, 4, right.val.int()) 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 { if node.left is ast.InfixExpr {
verror('only simple expressions are supported right now (not more than 2 operands)') verror('only simple expressions are supported right now (not more than 2 operands)')
} }
match node.left { match union mut node.left {
ast.Ident { g.mov_var_to_reg(.eax, g.get_var_offset(it.name)) } ast.Ident { g.mov_var_to_reg(.eax, g.get_var_offset(node.left.name)) }
else {} else {}
} }
if node.right is ast.Ident { if mut node.right is ast.Ident {
ident := node.right as ast.Ident var_offset := g.get_var_offset(node.right.name)
var_offset := g.get_var_offset(ident.name)
match node.op { match node.op {
.plus { g.add8_var(.eax, var_offset) } .plus { g.add8_var(.eax, var_offset) }
.mul { g.mul8_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] branch := node.branches[0]
infix_expr := branch.cond as ast.InfixExpr infix_expr := branch.cond as ast.InfixExpr
mut jne_addr := 0 // location of `jne *00 00 00 00*` mut jne_addr := 0 // location of `jne *00 00 00 00*`
match infix_expr.left { match union mut infix_expr.left {
ast.Ident { ast.Ident {
lit := infix_expr.right as ast.IntegerLiteral 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() jne_addr = g.jne()
} }
else { else {
@ -798,10 +797,10 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
// g.mov(.eax, 0x77777777) // g.mov(.eax, 0x77777777)
mut jump_addr := 0 // location of `jne *00 00 00 00*` mut jump_addr := 0 // location of `jne *00 00 00 00*`
start := g.pos() start := g.pos()
match infix_expr.left { match union mut infix_expr.left {
ast.Ident { ast.Ident {
lit := infix_expr.right as ast.IntegerLiteral 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() jump_addr = g.jge()
} }
else { else {

View File

@ -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) { fn (mut p Parser) check_undefined_variables(exprs []ast.Expr, val ast.Expr) {
match val { match union val {
ast.Ident { ast.Ident {
for expr in exprs { for expr in exprs {
if expr is ast.Ident { 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 { fn (mut p Parser) check_cross_variables(exprs []ast.Expr, val ast.Expr) bool {
val_ := val val_ := val
match val_ { match union val_ {
ast.Ident { ast.Ident {
for expr in exprs { for expr in exprs {
if expr is ast.Ident { 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 mut is_static := false
for i, lx in left { for i, lx in left {
match mut lx { match union mut lx {
ast.Ident { ast.Ident {
if op == .decl_assign { if op == .decl_assign {
if p.scope.known_var(lx.name) { if p.scope.known_var(lx.name) {

View File

@ -122,17 +122,17 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
} }
comments << p.eat_comments() comments << p.eat_comments()
mut left_as_name := '' mut left_as_name := ''
if cond is ast.InfixExpr as infix { if mut cond is ast.InfixExpr {
// if sum is T // if sum is T
is_is_cast := infix.op == .key_is is_is_cast := cond.op == .key_is
is_ident := infix.left is ast.Ident is_ident := cond.left is ast.Ident
left_as_name = if is_comptime { left_as_name = if is_comptime {
'' ''
} else if is_is_cast && p.tok.kind == .key_as { } else if is_is_cast && p.tok.kind == .key_as {
p.next() p.next()
p.check_name() p.check_name()
} else if is_ident { } else if is_ident {
ident := infix.left as ast.Ident ident := cond.left as ast.Ident
ident.name ident.name
} else { } 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.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())) { (p.peek_tok.kind == .dot && p.peek_tok2.lit[0].is_capital())) {
if var_name.len == 0 { if var_name.len == 0 {
match cond { match union cond {
ast.Ident { ast.Ident {
// shadow match cond variable // shadow match cond variable
var_name = cond.name var_name = cond.name
@ -366,6 +366,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
branches: branches branches: branches
cond: cond cond: cond
is_sum_type: is_sum_type is_sum_type: is_sum_type
is_union_match: is_union_match
pos: pos pos: pos
is_mut: is_mut is_mut: is_mut
var_name: var_name var_name: var_name
@ -447,11 +448,11 @@ fn (mut p Parser) select_expr() ast.SelectExpr {
if !stmt.is_expr { if !stmt.is_expr {
p.error_with_pos('select: invalid expression', stmt.pos) p.error_with_pos('select: invalid expression', stmt.pos)
} else { } else {
match stmt.expr as expr { match union stmt.expr {
ast.InfixExpr { ast.InfixExpr {
if expr.op != .arrow { if stmt.expr.op != .arrow {
p.error_with_pos('select key: `<-` operator expected', p.error_with_pos('select key: `<-` operator expected',
expr.pos) stmt.expr.pos)
} }
} }
else { else {
@ -462,7 +463,8 @@ fn (mut p Parser) select_expr() ast.SelectExpr {
} }
} }
ast.AssignStmt { ast.AssignStmt {
match stmt.right[0] as expr { expr := stmt.right[0]
match union expr {
ast.PrefixExpr { ast.PrefixExpr {
if expr.op != .arrow { if expr.op != .arrow {
p.error_with_pos('select key: `<-` operator expected', p.error_with_pos('select key: `<-` operator expected',

View File

@ -353,7 +353,7 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr {
p.next() p.next()
mut right := if op == .minus { p.expr(token.Precedence.call) } else { p.expr(token.Precedence.prefix) } mut right := if op == .minus { p.expr(token.Precedence.call) } else { p.expr(token.Precedence.prefix) }
p.is_amp = false p.is_amp = false
if right is ast.CastExpr { if mut right is ast.CastExpr {
right.in_prexpr = true right.in_prexpr = true
} }
mut or_stmts := []ast.Stmt{} mut or_stmts := []ast.Stmt{}

View File

@ -129,7 +129,7 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt {
mut table_name := '' mut table_name := ''
if kind != .delete { if kind != .delete {
expr := p.expr(0) expr := p.expr(0)
match expr { match union expr {
ast.Ident { ast.Ident {
if kind == .insert { if kind == .insert {
inserted_var_name = expr.name inserted_var_name = expr.name

View File

@ -203,7 +203,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
// default_expr = p.tok.lit // default_expr = p.tok.lit
// p.expr(0) // p.expr(0)
default_expr = p.expr(0) default_expr = p.expr(0)
match mut default_expr { match union mut default_expr {
ast.EnumVal { default_expr.typ = typ } ast.EnumVal { default_expr.typ = typ }
// TODO: implement all types?? // TODO: implement all types??
else {} else {}