diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index aafe94c566..f0d81195b3 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -23,6 +23,9 @@ mut: errors []string expected_type table.Type fn_return_type table.Type // current function's return type + // TODO: remove once all exprs/stmts are handled + unhandled_exprs []string + unhandled_stmts []string } pub fn new_checker(table &table.Table) Checker { @@ -42,10 +45,6 @@ pub fn (c mut Checker) check(ast_file ast.File) { println(t.name + ' - ' + t.kind.str()) } */ - - if c.nr_errors > 0 { - exit(1) - } } pub fn (c mut Checker) check2(ast_file ast.File) []string { @@ -72,6 +71,8 @@ pub fn (c mut Checker) check_files(ast_files []ast.File) { for file in ast_files { c.check(file) } + + c.print_unhandled_nodes() } pub fn (c mut Checker) check_struct_init(struct_init ast.StructInit) table.Type { @@ -370,18 +371,11 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { fn (c mut Checker) stmt(node ast.Stmt) { // c.expected_type = table.void_type match mut node { - ast.FnDecl { - c.fn_return_type = it.typ - for stmt in it.stmts { - c.stmt(stmt) - } - } - ast.Return { - c.return_stmt(it) - } ast.AssignStmt { c.assign_stmt(it) } + // ast.Attr {} + // ast.CompIf {} ast.ConstDecl { for i, expr in it.exprs { mut field := it.fields[i] @@ -395,14 +389,14 @@ fn (c mut Checker) stmt(node ast.Stmt) { it.fields[i] = field } } - ast.VarDecl { - typ := c.expr(it.expr) - // typ_sym := c.table.get_type_symbol(typ) - // println('var $it.name - $typ - $it.typ - $typ_sym.name') - // if it.typ == 0 { - // it.typ = typ - // } - it.typ = typ + ast.ExprStmt { + c.expr(it.expr) + } + ast.FnDecl { + c.fn_return_type = it.typ + for stmt in it.stmts { + c.stmt(stmt) + } } ast.ForStmt { typ := c.expr(it.cond) @@ -423,11 +417,27 @@ fn (c mut Checker) stmt(node ast.Stmt) { c.stmt(stmt) } } - // ast.StructDecl {} - ast.ExprStmt { - c.expr(it.expr) + // ast.ForInStmt {} + // ast.GlobalDecl {} + // ast.HashStmt {} + ast.Import {} + ast.Return { + c.return_stmt(it) + } + // ast.StructDecl {} + ast.VarDecl { + typ := c.expr(it.expr) + // typ_sym := c.table.get_type_symbol(typ) + // println('var $it.name - $typ - $it.typ - $typ_sym.name') + // if it.typ == 0 { + // it.typ = typ + // } + it.typ = typ + } + else { + node_name := typeof(node) + if !(node_name) in c.unhandled_stmts { c.unhandled_stmts << node_name } } - else {} } } @@ -439,6 +449,9 @@ fn (c mut Checker) stmts(stmts []ast.Stmt) { pub fn (c mut Checker) expr(node ast.Expr) table.Type { match mut node { + ast.ArrayInit { + return c.array_init(mut it) + } ast.AssignExpr { c.check_assign_expr(it) } @@ -451,82 +464,85 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type { } return var.typ } + ast.BoolLiteral { + return table.bool_type + } + ast.CastExpr { + return it.typ + } + ast.CallExpr { + return c.call_expr(it) + } + ast.CharLiteral { + return table.byte_type + } ast.EnumVal { return c.enum_val(it) } ast.FloatLiteral { return table.f64_type } + ast.Ident { + return c.ident(mut it) + } + ast.IfExpr { + return c.if_expr(mut it) + } + ast.IfGuardExpr { + return table.bool_type + } + ast.IndexExpr { + return c.index_expr(it) + } + ast.InfixExpr { + return c.infix_expr(it) + } ast.IntegerLiteral { return table.int_type } + ast.MapInit { + return c.map_init(it) + } + ast.MatchExpr { + return c.match_expr(mut it) + } + ast.MethodCallExpr { + return c.check_method_call_expr(it) + } ast.PostfixExpr { return c.postfix_expr(it) } - /* - ast.UnaryExpr { - c.expr(it.left) + ast.PrefixExpr { + return c.expr(it.right) + } + ast.None { + return table.none_type + } + ast.ParExpr { + return c.expr(it.expr) + } + ast.SelectorExpr { + return c.selector_expr(it) } - */ - ast.SizeOf { return table.int_type } ast.StringLiteral { return table.string_type } - ast.CharLiteral { - return table.byte_type - } - ast.PrefixExpr { - return c.expr(it.right) - } - ast.InfixExpr { - return c.infix_expr(it) - } ast.StructInit { return c.check_struct_init(it) } - ast.CallExpr { - return c.call_expr(it) + /* + ast.UnaryExpr { + c.expr(it.left) } - ast.MethodCallExpr { - return c.check_method_call_expr(it) + */ + else { + // TODO: find nil string bug triggered with typeof + // node_name := typeof(node) + // if !(node_name) in c.unhandled_exprs { c.unhandled_exprs << node_name } } - ast.ArrayInit { - return c.array_init(mut it) - } - ast.Ident { - return c.ident(mut it) - } - ast.BoolLiteral { - return table.bool_type - } - ast.SelectorExpr { - return c.selector_expr(it) - } - ast.IndexExpr { - return c.index_expr(it) - } - ast.IfExpr { - return c.if_expr(mut it) - } - ast.MatchExpr { - return c.match_expr(mut it) - } - ast.CastExpr { - return it.typ - } - ast.ParExpr { - return c.expr(it.expr) - } - ast.None { - return table.none_type - } - ast.IfGuardExpr { - return table.bool_type - } - else {} } return table.void_type } @@ -775,6 +791,40 @@ pub fn (c mut Checker) enum_val(node ast.EnumVal) table.Type { return typ_idx } +pub fn (c mut Checker) map_init(node ast.MapInit) table.Type { + key0_type := c.expr(node.keys[0]) + val0_type := c.expr(node.vals[0]) + for i, key in node.keys { + if i == 0 { + continue + } + val := node.vals[i] + key_type := c.expr(key) + val_type := c.expr(val) + if !c.table.check(key_type, key0_type) { + key0_type_sym := c.table.get_type_symbol(key0_type) + key_type_sym := c.table.get_type_symbol(key_type) + c.error('map init: cannot use `$key_type_sym.name` as `$key0_type_sym` for map key', node.pos) + } + if !c.table.check(val_type, val0_type) { + val0_type_sym := c.table.get_type_symbol(val0_type) + val_type_sym := c.table.get_type_symbol(val_type) + c.error('map init: cannot use `$val_type_sym.name` as `$val0_type_sym` for map value', node.pos) + } + } + return c.table.find_or_register_map(key0_type, val0_type) +} + +// TODO: remove once all exprs/stmts are handled +pub fn (c &Checker) print_unhandled_nodes() { + if c.unhandled_exprs.len > 0 { + eprintln(' # unhandled Expr nodes:\n\t * ' + c.unhandled_exprs.join(', ') + '\n') + } + if c.unhandled_stmts.len > 0 { + eprintln(' # unhandled Stmt nodes:\n\t * ' + c.unhandled_stmts.join(', ') + '\n') + } +} + pub fn (c mut Checker) error(s string, pos token.Position) { c.nr_errors++ print_backtrace() @@ -797,6 +847,7 @@ pub fn (c mut Checker) error(s string, pos token.Position) { println('\n\n') if c.nr_errors >= max_nr_errors { + c.print_unhandled_nodes() exit(1) } } diff --git a/vlib/v/table/atype_symbols.v b/vlib/v/table/atype_symbols.v index 556e58a57f..a72d186788 100644 --- a/vlib/v/table/atype_symbols.v +++ b/vlib/v/table/atype_symbols.v @@ -96,7 +96,7 @@ pub fn (t &TypeSymbol) enum_info() Enum { return it } else { - panic('TypeSymbol.enum_info(): no enum info') + panic('TypeSymbol.enum_info(): no enum info for type: $t.name') } } } @@ -108,7 +108,7 @@ pub fn (t &TypeSymbol) mr_info() MultiReturn { return it } else { - panic('TypeSymbol.mr_info(): no multi return info') + panic('TypeSymbol.mr_info(): no multi return info for type: $t.name') } } } @@ -120,7 +120,7 @@ pub fn (t &TypeSymbol) array_info() Array { return it } else { - panic('TypeSymbol.array_info(): no array info') + panic('TypeSymbol.array_info(): no array info for type: $t.name') } } } @@ -132,7 +132,7 @@ pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed { return it } else { - panic('TypeSymbol.array_fixed(): no array fixed info') + panic('TypeSymbol.array_fixed(): no array fixed info for type: $t.name') } } } @@ -144,7 +144,7 @@ pub fn (t &TypeSymbol) map_info() Map { return it } else { - panic('TypeSymbol.map_info(): no map info') + panic('TypeSymbol.map_info(): no map info for type: $t.name') } } } @@ -155,22 +155,6 @@ pub fn (t TypeSymbol) str() string { } */ - -[inline] -pub fn array_name(elem_type &TypeSymbol, nr_dims int) string { - return 'array_${elem_type.name}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' } -} - -[inline] -pub fn array_fixed_name(elem_type &TypeSymbol, size int, nr_dims int) string { - return 'array_fixed_${elem_type.name}_${size}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' } -} - -[inline] -pub fn map_name(key_type &TypeSymbol, value_type &TypeSymbol) string { - return 'map_${key_type.name}_${value_type.name}' -} - pub fn (t mut Table) register_builtin_type_symbols() { // reserve index 0 so nothing can go there // save index check, 0 will mean not found diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 832ed0122f..9f89f720a3 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -252,10 +252,32 @@ pub fn (t &Table) known_type(name string) bool { return true } -pub fn (t mut Table) find_or_register_map(key_type, value_type Type) int { +[inline] +pub fn (t &Table) array_name(elem_type Type, nr_dims int) string { + elem_type_sym := t.get_type_symbol(elem_type) + return 'array_${elem_type_sym.name}' + + if type_is_ptr(elem_type) { '_ptr' } else { '' } + + if nr_dims > 1 { '_${nr_dims}d' } else { '' } +} + +[inline] +pub fn (t &Table) array_fixed_name(elem_type Type, size int, nr_dims int) string { + elem_type_sym := t.get_type_symbol(elem_type) + return 'array_fixed_${elem_type_sym.name}_${size}' + + if type_is_ptr(elem_type) { '_ptr' } else { '' } + + if nr_dims > 1 { '_${nr_dims}d' } else { '' } +} + +[inline] +pub fn (t &Table) map_name(key_type Type, value_type Type) string { key_type_sym := t.get_type_symbol(key_type) - val_type_sym := t.get_type_symbol(value_type) - name := map_name(key_type_sym, val_type_sym) + value_type_sym := t.get_type_symbol(value_type) + return 'map_${key_type_sym.name}_${value_type_sym.name}' + + if type_is_ptr(value_type) { '_ptr' } else { '' } +} + +pub fn (t mut Table) find_or_register_map(key_type, value_type Type) int { + name := t.map_name(key_type, value_type) // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { @@ -275,8 +297,7 @@ pub fn (t mut Table) find_or_register_map(key_type, value_type Type) int { } pub fn (t mut Table) find_or_register_array(elem_type Type, nr_dims int) int { - elem_type_sym := t.get_type_symbol(elem_type) - name := array_name(elem_type_sym, nr_dims) + name := t.array_name(elem_type, nr_dims) // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { @@ -296,8 +317,7 @@ pub fn (t mut Table) find_or_register_array(elem_type Type, nr_dims int) int { } pub fn (t mut Table) find_or_register_array_fixed(elem_type Type, size int, nr_dims int) int { - elem_type_sym := t.get_type_symbol(elem_type) - name := array_fixed_name(elem_type_sym, size, nr_dims) + name := t.array_fixed_name(elem_type, size, nr_dims) // existing existing_idx := t.type_idxs[name] if existing_idx > 0 {