checker: use new match syntax everywhere

pull/5647/head
joe-conigliaro 2020-07-04 19:23:41 +10:00
parent cdd4a7c880
commit da98c3c135
No known key found for this signature in database
GPG Key ID: C12F7136C08206F1
1 changed files with 83 additions and 84 deletions

View File

@ -736,23 +736,23 @@ 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 { match call_expr.args[0].expr as arg_expr {
ast.AnonFn { ast.AnonFn {
if it.decl.args.len > 1 { if arg_expr.decl.args.len > 1 {
c.error('function needs exactly 1 argument', call_expr.pos) c.error('function needs exactly 1 argument', call_expr.pos)
} else if is_map && (it.decl.return_type != elem_typ || it.decl.args[0].typ != elem_typ) { } else if is_map && (arg_expr.decl.return_type != elem_typ || arg_expr.decl.args[0].typ != elem_typ) {
c.error('type mismatch, should use `fn(a $elem_sym.name) $elem_sym.name {...}`', c.error('type mismatch, should use `fn(a $elem_sym.name) $elem_sym.name {...}`',
call_expr.pos) call_expr.pos)
} else if !is_map && (it.decl.return_type != table.bool_type || } else if !is_map && (arg_expr.decl.return_type != table.bool_type ||
it.decl.args[0].typ != elem_typ) { arg_expr.decl.args[0].typ != elem_typ) {
c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`', c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`',
call_expr.pos) call_expr.pos)
} }
} }
ast.Ident { ast.Ident {
if it.kind == .function { if arg_expr.kind == .function {
func := c.table.find_fn(it.name) or { func := c.table.find_fn(arg_expr.name) or {
c.error('$it.name is not exist', it.pos) c.error('$arg_expr.name is not exist', arg_expr.pos)
return return
} }
if func.args.len > 1 { if func.args.len > 1 {
@ -805,8 +805,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
arg_sym := c.table.get_type_symbol(arg_type) arg_sym := c.table.get_type_symbol(arg_type)
// FIXME: match expr failed for now // FIXME: match expr failed for now
mut ret_type := 0 mut ret_type := 0
match arg_sym.info { match arg_sym.info as info {
table.FnType { ret_type = it.func.return_type } table.FnType { ret_type = info.func.return_type }
else { ret_type = arg_type } else { ret_type = arg_type }
} }
call_expr.return_type = c.table.find_or_register_array(ret_type, 1, c.mod) call_expr.return_type = c.table.find_or_register_array(ret_type, 1, c.mod)
@ -1679,19 +1679,19 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
array_init.elem_type != table.void_type { array_init.elem_type != table.void_type {
// [50]byte // [50]byte
mut fixed_size := 1 mut fixed_size := 1
match array_init.exprs[0] { match array_init.exprs[0] as init_expr {
ast.IntegerLiteral { ast.IntegerLiteral {
fixed_size = it.val.int() fixed_size = init_expr.val.int()
} }
ast.Ident { ast.Ident {
// if obj := c.file.global_scope.find_const(it.name) { // if obj := c.file.global_scope.find_const(init_expr.name) {
// if obj := scope.find(it.name) { // if obj := scope.find(init_expr.name) {
// scope := c.file.scope.innermost(array_init.pos.pos) // scope := c.file.scope.innermost(array_init.pos.pos)
// eprintln('scope: ${scope.str()}') // eprintln('scope: ${scope.str()}')
// scope.find(it.name) or { // scope.find(init_expr.name) or {
// c.error('undefined ident: `$it.name`', array_init.pos) // c.error('undefined ident: `$init_expr.name`', array_init.pos)
// } // }
mut full_const_name := it.mod + '.' + it.name mut full_const_name := init_expr.mod + '.' + init_expr.name
if obj := c.file.global_scope.find_const(full_const_name) { if obj := c.file.global_scope.find_const(full_const_name) {
if cint := const_int_value(obj) { if cint := const_int_value(obj) {
fixed_size = cint fixed_size = cint
@ -1756,7 +1756,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.stmts(node.stmts) c.stmts(node.stmts)
} }
ast.CompIf { ast.CompIf {
// c.expr(it.cond) // c.expr(node.cond)
c.stmts(node.stmts) c.stmts(node.stmts)
if node.has_else { if node.has_else {
c.stmts(node.else_stmts) c.stmts(node.else_stmts)
@ -1814,7 +1814,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.expected_type = table.void_type c.expected_type = table.void_type
c.check_expr_opt_call(node.expr, table.void_type) c.check_expr_opt_call(node.expr, table.void_type)
// TODO This should work, even if it's prolly useless .-. // TODO This should work, even if it's prolly useless .-.
// it.typ = c.check_expr_opt_call(it.expr, table.void_type) // node.typ = c.check_expr_opt_call(node.expr, table.void_type)
} }
ast.FnDecl { ast.FnDecl {
c.fn_decl(node) c.fn_decl(node)
@ -1824,7 +1824,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.stmt(node.init) c.stmt(node.init)
c.expr(node.cond) c.expr(node.cond)
c.stmt(node.inc) c.stmt(node.inc)
// c.expr(it.inc)
c.stmts(node.stmts) c.stmts(node.stmts)
c.in_for_count-- c.in_for_count--
} }
@ -1856,45 +1855,45 @@ fn (mut c Checker) stmt(node ast.Stmt) {
.map { sym.map_info().key_type } .map { sym.map_info().key_type }
else { table.int_type } else { table.int_type }
} }
it.key_type = key_type node.key_type = key_type
scope.update_var_type(it.key_var, key_type) scope.update_var_type(node.key_var, key_type)
} }
value_type := c.table.value_type(typ) value_type := c.table.value_type(typ)
if value_type == table.void_type || typ.has_flag(.optional) { if value_type == table.void_type || typ.has_flag(.optional) {
if typ != table.void_type { if typ != table.void_type {
c.error('for in: cannot index `${c.table.type_to_str(typ)}`', c.error('for in: cannot index `${c.table.type_to_str(typ)}`',
it.cond.position()) node.cond.position())
} }
} }
it.cond_type = typ node.cond_type = typ
it.kind = sym.kind node.kind = sym.kind
it.val_type = value_type node.val_type = value_type
scope.update_var_type(it.val_var, value_type) scope.update_var_type(node.val_var, value_type)
} }
c.stmts(it.stmts) c.stmts(node.stmts)
c.in_for_count-- c.in_for_count--
} }
ast.ForStmt { ast.ForStmt {
c.in_for_count++ c.in_for_count++
typ := c.expr(it.cond) typ := c.expr(node.cond)
if !it.is_inf && typ.idx() != table.bool_type_idx { if !node.is_inf && typ.idx() != table.bool_type_idx {
c.error('non-bool used as for condition', it.pos) c.error('non-bool used as for condition', node.pos)
} }
// TODO: update loop var type // TODO: update loop var type
// how does this work currenly? // how does this work currenly?
c.stmts(it.stmts) c.stmts(node.stmts)
c.in_for_count-- c.in_for_count--
} }
ast.GlobalDecl { ast.GlobalDecl {
c.check_valid_snake_case(it.name, 'global name', it.pos) c.check_valid_snake_case(node.name, 'global name', node.pos)
} }
ast.GoStmt { ast.GoStmt {
if !(it.call_expr is ast.CallExpr) { if !(node.call_expr is ast.CallExpr) {
c.error('expression in `go` must be a function call', it.call_expr.position()) c.error('expression in `go` must be a function call', node.call_expr.position())
} }
c.expr(it.call_expr) c.expr(node.call_expr)
if it.call_expr is ast.CallExpr { if node.call_expr is ast.CallExpr {
call_expr := it.call_expr as 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 call_expr.args {
if arg.is_mut && !arg.typ.is_ptr() { if arg.is_mut && !arg.typ.is_ptr() {
@ -1911,30 +1910,30 @@ fn (mut c Checker) stmt(node ast.Stmt) {
// ast.HashStmt {} // ast.HashStmt {}
ast.Import {} ast.Import {}
ast.InterfaceDecl { ast.InterfaceDecl {
c.interface_decl(it) c.interface_decl(node)
} }
ast.Module { ast.Module {
c.mod = it.name c.mod = node.name
c.is_builtin_mod = it.name == 'builtin' c.is_builtin_mod = node.name == 'builtin'
c.check_valid_snake_case(it.name, 'module name', it.pos) c.check_valid_snake_case(node.name, 'module name', node.pos)
} }
ast.Return { ast.Return {
c.returns = true c.returns = true
c.return_stmt(mut it) c.return_stmt(mut node)
c.scope_returns = true c.scope_returns = true
} }
ast.SqlStmt { ast.SqlStmt {
c.sql_stmt(node) c.sql_stmt(node)
} }
ast.StructDecl { ast.StructDecl {
c.struct_decl(it) c.struct_decl(node)
} }
ast.TypeDecl { ast.TypeDecl {
c.type_decl(it) c.type_decl(node)
} }
ast.UnsafeStmt { ast.UnsafeStmt {
c.inside_unsafe = true c.inside_unsafe = true
c.stmts(it.stmts) c.stmts(node.stmts)
c.inside_unsafe = false c.inside_unsafe = false
} }
else { else {
@ -2010,14 +2009,14 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
} }
if node.typ !in info.variants { if node.typ !in info.variants {
c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos) c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos)
// c.error('only $info.variants can be casted to `$typ`', it.pos) // c.error('only $info.variants can be casted to `$typ`', node.pos)
} }
} else { } else {
// //
c.error('cannot cast non sum type `$type_sym.name` using `as`', node.pos) c.error('cannot cast non sum type `$type_sym.name` using `as`', node.pos)
} }
return node.typ.to_ptr() return node.typ.to_ptr()
// return it.typ // return node.typ
} }
ast.Assoc { ast.Assoc {
scope := c.file.scope.innermost(node.pos.pos) scope := c.file.scope.innermost(node.pos.pos)
@ -2096,7 +2095,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
return table.any_flt_type return table.any_flt_type
} }
ast.Ident { ast.Ident {
// c.checked_ident = it.name // c.checked_ident = node.name
res := c.ident(mut node) res := c.ident(mut node)
// c.checked_ident = '' // c.checked_ident = ''
return res return res
@ -2398,14 +2397,14 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
c.stmts(branch.stmts) c.stmts(branch.stmts)
// If the last statement is an expression, return its type // If the last statement is an expression, return its type
if branch.stmts.len > 0 { if branch.stmts.len > 0 {
match branch.stmts[branch.stmts.len - 1] { match branch.stmts[branch.stmts.len - 1] as stmt {
ast.ExprStmt { ast.ExprStmt {
ret_type = c.expr(it.expr) ret_type = c.expr(stmt.expr)
it.typ = ret_type stmt.typ = ret_type
} }
else { else {
// TODO: ask alex about this // TODO: ask alex about this
// typ := c.expr(it.expr) // typ := c.expr(stmt.expr)
// type_sym := c.table.get_type_symbol(typ) // type_sym := c.table.get_type_symbol(typ)
// p.warn('match expr ret $type_sym.name') // p.warn('match expr ret $type_sym.name')
// node.typ = typ // node.typ = typ
@ -2449,8 +2448,8 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
// by listing all variants or values // by listing all variants or values
mut is_exhaustive := true mut is_exhaustive := true
mut unhandled := []string{} mut unhandled := []string{}
match type_sym.info { match type_sym.info as info {
table.SumType { for v in it.variants { table.SumType { for v in info.variants {
v_str := c.table.type_to_str(v) v_str := c.table.type_to_str(v)
if v_str !in branch_exprs { if v_str !in branch_exprs {
is_exhaustive = false is_exhaustive = false
@ -2458,7 +2457,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
} }
} } } }
// //
table.Enum { for v in it.vals { table.Enum { for v in info.vals {
if v !in branch_exprs { if v !in branch_exprs {
is_exhaustive = false is_exhaustive = false
unhandled << '`.$v`' unhandled << '`.$v`'
@ -2600,14 +2599,14 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type {
typ := c.expr(node.left) typ := c.expr(node.left)
node.left_type = typ node.left_type = typ
mut is_range := false // TODO is_range := node.index is ast.RangeExpr mut is_range := false // TODO is_range := node.index is ast.RangeExpr
match node.index { match node.index as index {
ast.RangeExpr { ast.RangeExpr {
is_range = true is_range = true
if it.has_low { if index.has_low {
c.expr(it.low) c.expr(index.low)
} }
if it.has_high { if index.has_high {
c.expr(it.high) c.expr(index.high)
} }
} }
else {} else {}
@ -2856,35 +2855,35 @@ fn (c &Checker) fetch_and_verify_orm_fields(info table.Struct, pos token.Positio
return fields return fields
} }
fn (mut c Checker) fn_decl(it ast.FnDecl) { fn (mut c Checker) fn_decl(node ast.FnDecl) {
if it.is_generic && c.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion if node.is_generic && c.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion
// loop thru each generic type and generate a function // loop thru each generic type and generate a function
for gen_type in c.table.fn_gen_types[it.name] { for gen_type in c.table.fn_gen_types[node.name] {
c.cur_generic_type = gen_type c.cur_generic_type = gen_type
// sym:=c.table.get_type_symbol(gen_type) // sym:=c.table.get_type_symbol(gen_type)
// println('\ncalling check for $it.name for type $sym.name') // println('\ncalling check for $node.name for type $sym.name')
c.fn_decl(it) c.fn_decl(node)
} }
c.cur_generic_type = 0 c.cur_generic_type = 0
return return
} }
if it.language == .v && !c.is_builtin_mod { if node.language == .v && !c.is_builtin_mod {
c.check_valid_snake_case(it.name, 'function name', it.pos) c.check_valid_snake_case(node.name, 'function name', node.pos)
} }
if it.is_method { if node.is_method {
sym := c.table.get_type_symbol(it.receiver.typ) sym := c.table.get_type_symbol(node.receiver.typ)
if sym.kind == .interface_ { if sym.kind == .interface_ {
c.error('interfaces cannot be used as method receiver', it.receiver_pos) c.error('interfaces cannot be used as method receiver', node.receiver_pos)
} }
// if sym.has_method(it.name) { // if sym.has_method(node.name) {
// c.warn('duplicate method `$it.name`', it.pos) // c.warn('duplicate method `$node.name`', node.pos)
// } // }
// Do not allow to modify types from other modules // Do not allow to modify types from other modules
if sym.mod != c.mod && !c.is_builtin_mod && sym.mod != '' { // TODO remove != '' if sym.mod != c.mod && !c.is_builtin_mod && sym.mod != '' { // TODO remove != ''
// remove the method to hide other related errors (`method is private` etc) // remove the method to hide other related errors (`method is private` etc)
mut idx := 0 mut idx := 0
for i, m in sym.methods { for i, m in sym.methods {
if m.name == it.name { if m.name == node.name {
println('got it') println('got it')
idx = i idx = i
break break
@ -2893,25 +2892,25 @@ fn (mut c Checker) fn_decl(it ast.FnDecl) {
sym.methods.delete(idx) sym.methods.delete(idx)
// //
c.error('cannot define new methods on non-local `$sym.name` (' + c.error('cannot define new methods on non-local `$sym.name` (' +
'current module is `$c.mod`, `$sym.name` is from `$sym.mod`)', it.pos) 'current module is `$c.mod`, `$sym.name` is from `$sym.mod`)', node.pos)
} }
} }
if it.language == .v { if node.language == .v {
// Make sure all types are valid // Make sure all types are valid
for arg in it.args { for arg in node.args {
sym := c.table.get_type_symbol(arg.typ) sym := c.table.get_type_symbol(arg.typ)
if sym.kind == .placeholder { if sym.kind == .placeholder {
c.error('unknown type `$sym.name`', it.pos) c.error('unknown type `$sym.name`', node.pos)
} }
} }
} }
c.expected_type = table.void_type c.expected_type = table.void_type
c.cur_fn = &it c.cur_fn = &node
c.stmts(it.stmts) c.stmts(node.stmts)
if it.language == .v && !it.no_body && if node.language == .v && !node.no_body &&
it.return_type != table.void_type && !c.returns && node.return_type != table.void_type && !c.returns &&
it.name !in ['panic', 'exit'] { node.name !in ['panic', 'exit'] {
c.error('missing return at end of function `$it.name`', it.pos) c.error('missing return at end of function `$node.name`', node.pos)
} }
c.returns = false c.returns = false
} }