v2: ArrayInit + all errs & unhandled + arrange nodes + type fix

pull/3890/head
Joe Conigliaro 2020-03-01 15:14:36 +11:00
parent cbffbf3438
commit 00dcaf0e04
3 changed files with 160 additions and 105 deletions

View File

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

View File

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

View File

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