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 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 {}

View File

@ -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
}
}

View File

@ -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()
}

View File

@ -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
}
}

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 {
// 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
}
}

View File

@ -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 {}

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) {
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)

View File

@ -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)

View File

@ -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'

View File

@ -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')

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,
// 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'

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) {
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 {

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) {
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) {

View File

@ -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',

View File

@ -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{}

View File

@ -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

View File

@ -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 {}