all: refactor ast.Expr to use the new sum type implementation (#6792)
parent
ff1752dfff
commit
838ad16296
|
@ -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 {}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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{}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
Loading…
Reference in New Issue