From e274c5c485fd8b5cde4920b7b89acd9ed5b474d4 Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Mon, 10 Feb 2020 18:32:08 +1100 Subject: [PATCH] v2: type sys - store type idx/ptr in int & add helpers --- vlib/builtin/cfns.v | 12 +- vlib/v/ast/ast.v | 31 +-- vlib/v/checker/checker.v | 198 ++++++++------- vlib/v/gen/cgen.v | 42 ++-- vlib/v/gen/jsgen.v | 12 +- vlib/v/parser/fn.v | 9 +- vlib/v/parser/parse_type.v | 70 +++--- vlib/v/parser/parser.v | 98 ++++---- vlib/v/table/{atypes.v => atype_symbols.v} | 268 ++++++++------------- vlib/v/table/table.v | 114 +++++---- vlib/v/table/types.v | 87 +++++++ 11 files changed, 515 insertions(+), 426 deletions(-) rename vlib/v/table/{atypes.v => atype_symbols.v} (57%) create mode 100644 vlib/v/table/types.v diff --git a/vlib/builtin/cfns.v b/vlib/builtin/cfns.v index 581030afeb..83334f36b5 100644 --- a/vlib/builtin/cfns.v +++ b/vlib/builtin/cfns.v @@ -240,19 +240,23 @@ fn C.RegQueryValueEx() voidptr fn C.RemoveDirectory() int -fn C.GetStdHandle() voidptr +//fn C.GetStdHandle() voidptr +fn C.GetStdHandle(u32) voidptr -fn C.SetConsoleMode() +//fn C.SetConsoleMode() +fn C.SetConsoleMode(voidptr, u32) -fn C.GetConsoleMode() int +//fn C.GetConsoleMode() int +fn C.GetConsoleMode(voidptr, &u32) int fn C.wprintf() -fn C.setbuf() +//fn C.setbuf() +fn C.setbuf(voidptr, charptr) fn C.SymCleanup() diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 65db7d0583..b36ee1ed9e 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -20,7 +20,7 @@ HashStmt | AssignStmt pub struct ExprStmt { pub: expr Expr - typ table.TypeRef + typ table.Type } pub struct IntegerLiteral { @@ -69,7 +69,7 @@ pub struct Field { pub: name string // type_idx int - typ table.TypeRef + typ table.Type } pub struct ConstDecl { @@ -89,7 +89,7 @@ pub: pub struct StructInit { pub: pos token.Position - typ table.TypeRef + typ table.Type fields []string exprs []Expr } @@ -105,7 +105,7 @@ pub: pub struct Arg { pub: - typ table.TypeRef + typ table.Type name string } @@ -113,7 +113,7 @@ pub struct FnDecl { pub: name string stmts []Stmt - typ table.TypeRef + typ table.Type args []Arg is_pub bool is_variadic bool @@ -147,7 +147,7 @@ pub: pub struct Return { pub: pos token.Position - expected_type table.TypeRef // TODO: remove once checker updated + expected_type table.Type // TODO: remove once checker updated exprs []Expr } @@ -173,7 +173,7 @@ pub: expr Expr is_mut bool mut: - typ table.TypeRef + typ table.Type pos token.Position } @@ -182,7 +182,7 @@ pub: name string expr Expr mut: - typ table.TypeRef + typ table.Type } pub struct StmtBlock { @@ -201,7 +201,7 @@ pub: pub struct IdentVar { pub mut: - typ table.TypeRef + typ table.Type is_mut bool // name string } @@ -219,9 +219,10 @@ pub enum IdentKind { pub struct Ident { pub: name string + value string + is_c bool tok_kind token.Kind pos token.Position - value string mut: kind IdentKind info IdentInfo @@ -245,9 +246,9 @@ pub: op token.Kind pos token.Position left Expr - left_type table.TypeRef + left_type table.Type right Expr - right_type table.TypeRef + right_type table.Type } /* @@ -290,7 +291,7 @@ pub: cond Expr stmts []Stmt else_stmts []Stmt - typ table.TypeRef + typ table.Type left Expr // `a` in `a := if ...` pos token.Position } @@ -301,7 +302,7 @@ pub: cond Expr blocks []StmtBlock match_exprs []Expr - typ table.TypeRef + typ table.Type pos token.Position } @@ -372,7 +373,7 @@ pub: pos token.Position exprs []Expr mut: - typ table.TypeRef + typ table.Type } // s[10..20] diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index d07b200168..afbd75d936 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -14,7 +14,7 @@ pub struct Checker { table &table.Table mut: file_name string - resolved []table.TypeRef + resolved []table.Type } pub fn new_checker(table &table.Table) Checker { @@ -63,27 +63,30 @@ fn (c &Checker) complete_types() { // println('Resolve type: $t.name') if t.kind == .array { mut info := t.array_info() - if info.elem_type.typ.kind == .unresolved { - info.elem_type = c.resolved[info.elem_type.idx] + if table.type_is_unresolved(info.elem_type) { + info.elem_type = c.resolve(info.elem_type) + elem_type_sym := c.table.get_type_symbol(info.elem_type) mut t1 := &c.table.types[idx] - t1.name = table.array_name(&info.elem_type, info.nr_dims) + t1.name = table.array_name(elem_type_sym, info.nr_dims) t1.info = info } } else if t.kind == .map { mut info := t.map_info() mut updated := false - if info.key_type.typ.kind == .unresolved { - info.key_type = c.resolved[info.key_type.idx] + if table.type_is_unresolved(info.key_type) { + info.key_type = c.resolve(info.key_type) updated = true } - if info.value_type.typ.kind == .unresolved { - info.value_type = c.resolved[info.value_type.idx] + if table.type_is_unresolved(info.value_type) { + info.value_type = c.resolve(info.value_type) updated = true } if updated { mut t1 := &c.table.types[idx] - t1.name = table.map_name(&info.key_type, &info.value_type) + key_type_sym := c.table.get_type_symbol(info.key_type) + value_type_sym := c.table.get_type_symbol(info.value_type) + t1.name = table.map_name(key_type_sym, value_type_sym) t1.info = info } } @@ -92,8 +95,8 @@ fn (c &Checker) complete_types() { mut types := info.types mut updated := false for i, ut in types { - if ut.typ.kind == .unresolved { - types[i] = c.resolved[ut.idx] + if table.type_is_unresolved(ut) { + types[i] = c.resolve(ut) updated = true } } @@ -106,22 +109,30 @@ fn (c &Checker) complete_types() { } } -pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.TypeRef { - typ := c.table.find_type(struct_init.typ.typ.name) or { - c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos) - panic('') - } +// return the resolved Type from unresovled Type +pub fn (c &Checker) resolve(unresolved table.Type) table.Type { + return c.resolved[-table.type_idx(unresolved)-1] +} + +pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.Type { + // typ := c.table.find_type(struct_init.typ.typ.name) or { + // c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos) + // panic('') + // } + typ := c.table.get_type_symbol(struct_init.typ) match typ.kind { .placeholder { - c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos) + c.error('unknown struct: $typ.name', struct_init.pos) } .struct_ { info := typ.info as table.Struct for i, expr in struct_init.exprs { field := info.fields[i] - field_type := c.expr(expr) - if !c.table.check(field_type, field.typ) { - c.error('cannot assign $field_type.typ.name as $field.typ.typ.name for field $field.name', struct_init.pos) + expr_type := c.expr(expr) + expr_type_sym := c.table.get_type_symbol(expr_type) + field_type_sym := c.table.get_type_symbol(field.typ) + if !c.table.check(expr_type, field.typ) { + c.error('cannot assign $expr_type_sym.name as $field_type_sym.name for field $field.name', struct_init.pos) } } } @@ -130,16 +141,18 @@ pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.TypeRef return struct_init.typ } -pub fn (c &Checker) infix_expr(infix_expr ast.InfixExpr) table.TypeRef { +pub fn (c &Checker) infix_expr(infix_expr ast.InfixExpr) table.Type { left_type := c.expr(infix_expr.left) right_type := c.expr(infix_expr.right) - if !c.table.check(&right_type, &left_type) { + if !c.table.check(right_type, left_type) { + left_type_sym := c.table.get_type_symbol(left_type) + right_type_sym := c.table.get_type_symbol(right_type) // if !c.table.check(&infix_expr.right_type, &infix_expr.right_type) { // c.error('infix expr: cannot use `$infix_expr.right_type.name` as `$infix_expr.left_type.name`', infix_expr.pos) - c.error('infix expr: cannot use `$left_type.typ.name` as `$right_type.typ.name`', infix_expr.pos) + c.error('infix expr: cannot use `$right_type_sym.name` as `$left_type_sym.name`', infix_expr.pos) } if infix_expr.op.is_relational() { - return c.table.type_ref(table.bool_type_idx) + return table.bool_type } return left_type } @@ -148,37 +161,36 @@ fn (c &Checker) check_assign_expr(assign_expr ast.AssignExpr) { left_type := c.expr(assign_expr.left) right_type := c.expr(assign_expr.val) if !c.table.check(right_type, left_type) { - c.error('cannot assign $right_type.typ.name to $left_type.typ.name', assign_expr.pos) + left_type_sym := c.table.get_type_symbol(left_type) + right_type_sym := c.table.get_type_symbol(right_type) + c.error('cannot assign $right_type_sym.name to $left_type_sym.name', assign_expr.pos) } } -pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.TypeRef { +pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.Type { fn_name := call_expr.name if f := c.table.find_fn(fn_name) { // return_ti := f.return_ti - if !f.is_c { + if /*TODO:*/!f.is_c { if call_expr.args.len < f.args.len { c.error('too few arguments in call to `$fn_name`', call_expr.pos) } - else if call_expr.args.len > f.args.len { + else if !f.is_variadic && call_expr.args.len > f.args.len { c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)', call_expr.pos) } } - // for debugging - if f.name == 'backtrace_symbols_fd' { - println('ARGS FOR: backtrace_symbols_fd:') - for i, arg_expr in call_expr.args { - typ := c.expr(arg_expr) - println(' -- $i - $typ.typ.name') + if /*TODO:*/!f.is_c { + for i, arg_expr in call_expr.args { + arg := if f.is_variadic && i >= f.args.len-1 { + f.args[f.args.len-1] + } else { + f.args[i] } - } - // TODO: variadic - if fn_name != 'printf' && f.args.len > 0 { - for i, arg in f.args { - arg_expr := call_expr.args[i] typ := c.expr(arg_expr) - if !c.table.check(&typ, &arg.typ) { - c.error('!cannot use type `$typ.typ.name` as type `$arg.typ.typ.name` in argument to `$fn_name`', call_expr.pos) + typ_sym := c.table.get_type_symbol(typ) + arg_typ_sym := c.table.get_type_symbol(arg.typ) + if /*TODO:*/!f.is_c && !c.table.check(typ, arg.typ) { + c.error('!cannot use type `$typ_sym.name` as type `$arg_typ_sym.name` in argument ${i+1} to `$fn_name`', call_expr.pos) } } } @@ -188,48 +200,50 @@ pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.TypeRef { exit(1) } -pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.TypeRef { +pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type { typ := c.expr(method_call_expr.expr) - if method := typ.typ.find_method(method_call_expr.name) { + typ_sym := c.table.get_type_symbol(typ) + if method := typ_sym.find_method(method_call_expr.name) { return method.return_type } // check parent - if !isnil(typ.typ.parent) { - if method := typ.typ.parent.find_method(method_call_expr.name) { + if !isnil(typ_sym.parent) { + if method := typ_sym.parent.find_method(method_call_expr.name) { return method.return_type } } - c.error('type `$typ.typ.name` has no method `$method_call_expr.name`', method_call_expr.pos) + c.error('type `$typ_sym.name` has no method `$method_call_expr.name`', method_call_expr.pos) exit(1) } -pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.TypeRef { +pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.Type { typ := c.expr(selector_expr.expr) + typ_sym := c.table.get_type_symbol(typ) field_name := selector_expr.field - if field := typ.typ.find_field(field_name) { + if field := typ_sym.find_field(field_name) { return field.typ } - // types with parent struct (array/maps) handled here - if !isnil(typ.typ.parent) { - if field := typ.typ.parent.find_field(field_name) { - if field.typ.typ.kind == .unresolved { - return c.resolved[field.typ.idx] + // check parent + if !isnil(typ_sym.parent) { + if field := typ_sym.parent.find_field(field_name) { + if table.type_is_unresolved(field.typ) { + return c.resolved[field.typ] } return field.typ } } - if typ.typ.kind != .struct_ { - c.error('`$typ.typ.name` is not a struct', selector_expr.pos) + if typ_sym.kind != .struct_ { + c.error('`$typ_sym.name` is not a struct', selector_expr.pos) } else { - c.error('unknown field `${typ.typ.name}.$field_name`', selector_expr.pos) + c.error('unknown field `${typ_sym.name}.$field_name`', selector_expr.pos) } exit(0) } // TODO: non deferred pub fn (c &Checker) return_stmt(return_stmt ast.Return) { - mut got_types := []table.TypeRef + mut got_types := []table.Type if return_stmt.exprs.len == 0 { return } @@ -238,9 +252,10 @@ pub fn (c &Checker) return_stmt(return_stmt ast.Return) { got_types << typ } expected_type := return_stmt.expected_type + expected_type_sym := c.table.get_type_symbol(expected_type) mut expected_types := [expected_type] - if expected_type.typ.kind == .multi_return { - mr_info := expected_type.typ.info as table.MultiReturn + if expected_type_sym.kind == .multi_return { + mr_info := expected_type_sym.info as table.MultiReturn expected_types = mr_info.types } if expected_types.len > 0 && expected_types.len != got_types.len { @@ -249,15 +264,17 @@ pub fn (c &Checker) return_stmt(return_stmt ast.Return) { for i, exp_typ in expected_types { got_typ := got_types[i] if !c.table.check(got_typ, exp_typ) { - c.error('cannot use `$got_typ.typ.name` as type `$exp_typ.typ.name` in return argument', return_stmt.pos) + got_typ_sym := c.table.get_type_symbol(got_typ) + exp_typ_sym := c.table.get_type_symbol(exp_typ) + c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument', return_stmt.pos) } } } pub fn (c &Checker) assign_stmt(assign_stmt ast.AssignStmt) {} -pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.TypeRef { - mut elem_type := c.table.type_ref(table.void_type_idx) +pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.Type { + mut elem_type := table.void_type for i, expr in array_init.exprs { c.expr(expr) typ := c.expr(expr) @@ -267,7 +284,8 @@ pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.TypeRef { continue } if !c.table.check(elem_type, typ) { - c.error('expected array element with type `$elem_type.typ.name`', array_init.pos) + elem_type_sym := c.table.get_type_symbol(elem_type) + c.error('expected array element with type `$elem_type_sym.name`', array_init.pos) } } return array_init.typ @@ -289,13 +307,16 @@ fn (c &Checker) stmt(node ast.Stmt) { ast.VarDecl { typ := c.expr(it.expr) // println('checker: var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr') - if typ.typ.kind != .void { + // if typ.typ.kind != .void { + if table.type_idx(typ) != table.void_type_idx { it.typ = typ } } ast.ForStmt { typ := c.expr(it.cond) - if typ.typ.kind != .bool { + // typ_sym := c.table.get_type_symbol(typ) + // if typ_sym.kind != .bool { + if table.type_idx(typ) != table.bool_type_idx { c.error('non-bool used as for condition', it.pos) } for stmt in it.stmts { @@ -318,13 +339,13 @@ fn (c &Checker) stmt(node ast.Stmt) { } } -pub fn (c &Checker) expr(node ast.Expr) table.TypeRef { +pub fn (c &Checker) expr(node ast.Expr) table.Type { match mut node { ast.AssignExpr { c.check_assign_expr(it) } ast.IntegerLiteral { - return c.table.type_ref(table.int_type_idx) + return table.int_type } // ast.FloatLiteral {} ast.PostfixExpr { @@ -337,7 +358,7 @@ pub fn (c &Checker) expr(node ast.Expr) table.TypeRef { */ ast.StringLiteral { - return c.table.type_ref(table.string_type_idx) + return table.string_type } ast.PrefixExpr { return c.expr(it.right) @@ -360,18 +381,18 @@ pub fn (c &Checker) expr(node ast.Expr) table.TypeRef { ast.Ident { if it.kind == .variable { mut info := it.info as ast.IdentVar - if info.typ.typ.kind == .unresolved { - typ := c.resolved[info.typ.idx] + if table.type_is_unresolved(info.typ) { + typ := c.resolve(info.typ) info.typ = typ it.info = info return typ } return info.typ } - return c.table.type_ref(table.void_type_idx) + return table.void_type } ast.BoolLiteral { - return c.table.type_ref(table.bool_type_idx) + return table.bool_type } ast.SelectorExpr { return c.selector_expr(it) @@ -381,8 +402,10 @@ pub fn (c &Checker) expr(node ast.Expr) table.TypeRef { } ast.IfExpr { typ := c.expr(it.cond) - if typ.typ.kind != .bool { - c.error('non-bool (`$typ.typ.name`) used as if condition', it.pos) + typ_sym := c.table.get_type_symbol(typ) + // if typ_sym.kind != .bool { + if table.type_idx(typ) != table.bool_type_idx { + c.error('non-bool (`$typ_sym.name`) used as if condition', it.pos) } for i, stmt in it.stmts { c.stmt(stmt) @@ -395,10 +418,10 @@ pub fn (c &Checker) expr(node ast.Expr) table.TypeRef { } else {} } - return c.table.type_ref(table.void_type_idx) + return table.void_type } -pub fn (c &Checker) postfix_expr(node ast.PostfixExpr) table.TypeRef { +pub fn (c &Checker) postfix_expr(node ast.PostfixExpr) table.Type { /* match node.expr { ast.IdentVar { @@ -408,13 +431,15 @@ pub fn (c &Checker) postfix_expr(node ast.PostfixExpr) table.TypeRef { } */ typ := c.expr(node.expr) - if typ.typ.kind != .int { - c.error('invalid operation: $node.op.str() (non-numeric type `$typ.typ.name`)', node.pos) + // if typ.typ.kind != .int { + if table.type_idx(typ) != table.int_type_idx { + typ_sym := c.table.get_type_symbol(typ) + c.error('invalid operation: $node.op.str() (non-numeric type `$typ_sym.name`)', node.pos) } return typ } -pub fn (c &Checker) index_expr(node ast.IndexExpr) table.TypeRef { +pub fn (c &Checker) index_expr(node ast.IndexExpr) table.Type { mut typ := c.expr(node.left) mut is_range := false // TODO is_range := node.index is ast.RangeExpr match node.index { @@ -423,20 +448,23 @@ pub fn (c &Checker) index_expr(node ast.IndexExpr) table.TypeRef { } else {} } - if typ.typ.kind == .array { + typ_sym := c.table.get_type_symbol(typ) + if typ_sym.kind == .array { if is_range {} // `x[start..end]` has the same type as `x` else { // Check index type index_type := c.expr(node.index) - if index_type.typ.kind != .int { - c.error('non-integer index (type `$index_type.typ.name`)', node.pos) + // if index_type.typ.kind != .int { + if table.type_idx(index_type) != table.int_type_idx { + index_type_sym := c.table.get_type_symbol(index_type) + c.error('non-integer index (type `$index_type_sym.name`)', node.pos) } - info := typ.typ.info as table.Array + info := typ_sym.info as table.Array return info.elem_type } } else { - typ = c.table.type_ref(table.int_type_idx) + typ = table.int_type } return typ // c.expr(it.index) @@ -452,8 +480,6 @@ pub fn (c &Checker) error(s string, pos token.Position) { path = path.replace(workdir, '') } final_msg_line := '$path:$pos.line_nr: checker error: $s' - // sometimes eprintln wasnt working? - println(final_msg_line) eprintln(final_msg_line) /* if colored_output { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 91b023f8df..8ddb329034 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -56,7 +56,8 @@ fn (g mut Gen) stmt(node ast.Stmt) { ast.Import {} ast.ConstDecl { for i, field in it.fields { - g.write('$field.typ.typ.name $field.name = ') + field_type_sym := g.table.get_type_symbol(field.typ) + g.write('$field_type_sym.name $field.name = ') g.expr(it.exprs[i]) g.writeln(';') } @@ -68,16 +69,18 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.write('int ${it.name}(') } else { - g.write('$it.typ.typ.name ${it.name}(') - g.definitions.write('$it.typ.typ.name ${it.name}(') + type_sym := g.table.get_type_symbol(it.typ) + g.write('$type_sym.name ${it.name}(') + g.definitions.write('$type_sym.name ${it.name}(') } for i, arg in it.args { - mut arg_type := arg.typ.typ.name + arg_type_sym := g.table.get_type_symbol(arg.typ) + mut arg_type_name := arg_type_sym.name if i == it.args.len-1 && it.is_variadic { - arg_type = 'variadic_$arg.typ.typ.name' + arg_type_name = 'variadic_$arg_type_sym.name' } - g.write(arg_type + ' ' + arg.name) - g.definitions.write(arg_type + ' ' + arg.name) + g.write(arg_type_name + ' ' + arg.name) + g.definitions.write(arg_type_name + ' ' + arg.name) if i < it.args.len - 1 { g.write(', ') g.definitions.write(', ') @@ -100,7 +103,8 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.write('return') // multiple returns if it.exprs.len > 1 { - g.write(' ($g.fn_decl.typ.typ.name){') + type_sym := g.table.get_type_symbol(g.fn_decl.typ) + g.write(' ($type_sym.name){') for i, expr in it.exprs { g.write('.arg$i=') g.expr(expr) @@ -136,7 +140,8 @@ fn (g mut Gen) stmt(node ast.Stmt) { println('assign') } ast.VarDecl { - g.write('$it.typ.typ.name $it.name = ') + type_sym := g.table.get_type_symbol(it.typ) + g.write('$type_sym.name $it.name = ') g.expr(it.expr) g.writeln(';') } @@ -165,7 +170,8 @@ fn (g mut Gen) stmt(node ast.Stmt) { ast.StructDecl { g.writeln('typedef struct {') for field in it.fields { - g.writeln('\t$field.typ.typ.name $field.name;') + field_type_sym := g.table.get_type_symbol(field.typ) + g.writeln('\t$field_type_sym.name $field.name;') } g.writeln('} $it.name;') } @@ -237,7 +243,8 @@ fn (g mut Gen) expr(node ast.Expr) { } // `user := User{name: 'Bob'}` ast.StructInit { - g.writeln('($it.typ.typ.name){') + type_sym := g.table.get_type_symbol(it.typ) + g.writeln('($type_sym.name){') for i, field in it.fields { g.write('\t.$field = ') g.expr(it.exprs[i]) @@ -257,7 +264,8 @@ fn (g mut Gen) expr(node ast.Expr) { } ast.MethodCallExpr {} ast.ArrayInit { - g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.typ.typ.name), {\t') + type_sym := g.table.get_type_symbol(it.typ) + g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($type_sym.name), {\t') for expr in it.exprs { g.expr(expr) g.write(', ') @@ -287,8 +295,9 @@ fn (g mut Gen) expr(node ast.Expr) { // If expression? Assign the value to a temp var. // Previously ?: was used, but it's too unreliable. // ti := g.table.refresh_ti(it.ti) + type_sym := g.table.get_type_symbol(it.typ) mut tmp := '' - if it.typ.typ.kind != .void { + if type_sym.kind != .void { tmp = g.table.new_tmp_var() // g.writeln('$ti.name $tmp;') } @@ -297,7 +306,7 @@ fn (g mut Gen) expr(node ast.Expr) { g.writeln(') {') for i, stmt in it.stmts { // Assign ret value - if i == it.stmts.len - 1 && it.typ.typ.kind != .void { + if i == it.stmts.len - 1 && type_sym.kind != .void { // g.writeln('$tmp =') println(1) } @@ -313,11 +322,12 @@ fn (g mut Gen) expr(node ast.Expr) { } } ast.MatchExpr { + type_sym := g.table.get_type_symbol(it.typ) mut tmp := '' - if it.typ.typ.kind != .void { + if type_sym.kind != .void { tmp = g.table.new_tmp_var() } - g.write('$it.typ.typ.name $tmp = ') + g.write('$type_sym.name $tmp = ') g.expr(it.cond) g.writeln(';') // $it.blocks.len') for i, block in it.blocks { diff --git a/vlib/v/gen/jsgen.v b/vlib/v/gen/jsgen.v index 714dcfb436..9fb38b8b68 100644 --- a/vlib/v/gen/jsgen.v +++ b/vlib/v/gen/jsgen.v @@ -37,9 +37,11 @@ pub fn (g mut JsGen) writeln(s string) { fn (g mut JsGen) stmt(node ast.Stmt) { match node { ast.FnDecl { - g.write('/** @return { $it.typ.typ.name } **/\nfunction ${it.name}(') + type_sym := g.table.get_type_symbol(it.typ) + g.write('/** @return { $type_sym.name } **/\nfunction ${it.name}(') for arg in it.args { - g.write(' /** @type { $arg.typ.typ.name } **/ $arg.name') + arg_type_sym := g.table.get_type_symbol(arg.typ) + g.write(' /** @type { $arg_type_sym.name } **/ $arg.name') } g.writeln(') { ') for stmt in it.stmts { @@ -57,7 +59,8 @@ fn (g mut JsGen) stmt(node ast.Stmt) { } ast.AssignStmt {} ast.VarDecl { - g.write('var /* $it.typ.typ.name */ $it.name = ') + type_sym := g.table.get_type_symbol(it.typ) + g.write('var /* $type_sym.name */ $it.name = ') g.expr(it.expr) g.writeln(';') } @@ -119,7 +122,8 @@ fn (g mut JsGen) expr(node ast.Expr) { } // `user := User{name: 'Bob'}` ast.StructInit { - g.writeln('/*$it.typ.typ.name*/{') + type_sym := g.table.get_type_symbol(it.typ) + g.writeln('/*$type_sym.name*/{') for i, field in it.fields { g.write('\t$field : ') g.expr(it.exprs[i]) diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 528b9345e9..2afc9d5d90 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -8,7 +8,7 @@ import ( v.table ) -pub fn (p mut Parser) call_expr() (ast.CallExpr,table.TypeRef) { +pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) { tok := p.tok fn_name := p.check_name() p.check(.lpar) @@ -64,7 +64,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { // Receiver? mut rec_name := '' mut is_method := false - mut rec_type := p.table.type_ref(table.void_type_idx) + mut rec_type := table.void_type if p.tok.kind == .lpar { is_method = true p.next() @@ -168,7 +168,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { } p.check(.rpar) // Return type - mut typ := p.table.type_ref(table.void_type_idx) + mut typ := table.void_type if p.tok.kind in [.name, .lpar, .amp, .lsbr, .question] { typ = p.parse_type() p.return_type = typ @@ -178,7 +178,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl { p.return_type = typ } if is_method { - ok := p.table.register_method(rec_type.typ, table.Fn{ + type_sym := p.table.get_type_symbol(rec_type) + ok := p.table.register_method(type_sym, table.Fn{ name: name args: args return_type: typ diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 073d8b6c2c..35b496b419 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -6,7 +6,7 @@ import ( v.table ) -pub fn (p mut Parser) parse_array_ti(nr_muls int) table.TypeRef { +pub fn (p mut Parser) parse_array_type(nr_muls int) table.Type { p.check(.lsbr) // fixed array if p.tok.kind == .number { @@ -15,7 +15,7 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.TypeRef { p.check(.rsbr) p.check_name() idx := p.table.find_or_register_array_fixed(elem_ti, size, 1) - return p.table.type_ref_ptr(idx, nr_muls) + return table.new_type_ptr(idx, nr_muls) } // array p.check(.rsbr) @@ -27,28 +27,30 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.TypeRef { nr_dims++ } idx := p.table.find_or_register_array(elem_ti, nr_dims) - return p.table.type_ref_ptr(idx, nr_muls) + return table.new_type_ptr(idx, nr_muls) } -pub fn (p mut Parser) parse_map_type(nr_muls int) table.TypeRef { +pub fn (p mut Parser) parse_map_type(nr_muls int) table.Type { p.next() if p.tok.kind != .lsbr { - return p.table.type_ref(table.map_type_idx) + return table.new_type(table.map_type_idx) } p.check(.lsbr) key_type := p.parse_type() - if key_type.typ.kind != .string { + // key_type_sym := p.get_type_symbol(key_type) + // if key_type_sym.kind != .string { + if table.type_idx(key_type) != table.string_type_idx { p.error('maps can only have string keys for now') } p.check(.rsbr) value_type := p.parse_type() idx := p.table.find_or_register_map(key_type, value_type) - return p.table.type_ref_ptr(idx, nr_muls) + return table.new_type_ptr(idx, nr_muls) } -pub fn (p mut Parser) parse_multi_return_ti() table.TypeRef { +pub fn (p mut Parser) parse_multi_return_type() table.Type { p.check(.lpar) - mut mr_types := []table.TypeRef + mut mr_types := []table.Type for { mr_type := p.parse_type() mr_types << mr_type @@ -61,16 +63,16 @@ pub fn (p mut Parser) parse_multi_return_ti() table.TypeRef { } p.check(.rpar) idx := p.table.find_or_register_multi_return(mr_types) - return p.table.type_ref(idx) + return table.new_type(idx) } -pub fn (p mut Parser) parse_fn_type() table.TypeRef { +pub fn (p mut Parser) parse_fn_type() table.Type { // p.check(.key_fn) p.fn_decl() - return p.table.type_ref(table.int_type_idx) + return table.int_type } -pub fn (p mut Parser) parse_type() table.TypeRef { +pub fn (p mut Parser) parse_type() table.Type { mut nr_muls := 0 for p.tok.kind == .amp { p.check(.amp) @@ -91,14 +93,14 @@ pub fn (p mut Parser) parse_type() table.TypeRef { } // array .lsbr { - return p.parse_array_ti(nr_muls) + return p.parse_array_type(nr_muls) } // multiple return .lpar { if nr_muls > 0 { - p.error('parse_ti: unexpected `&` before multiple returns') + p.error('parse_type: unexpected `&` before multiple returns') } - return p.parse_multi_return_ti() + return p.parse_multi_return_type() } else { // no defer @@ -110,64 +112,64 @@ pub fn (p mut Parser) parse_type() table.TypeRef { } match name { 'voidptr' { - return p.table.type_ref_ptr(table.voidptr_type_idx, nr_muls) + return table.new_type_ptr(table.voidptr_type_idx, nr_muls) } 'byteptr' { - return p.table.type_ref_ptr(table.byteptr_type_idx, nr_muls) + return table.new_type_ptr(table.byteptr_type_idx, nr_muls) } 'charptr' { - return p.table.type_ref_ptr(table.charptr_type_idx, nr_muls) + return table.new_type_ptr(table.charptr_type_idx, nr_muls) } 'i8' { - return p.table.type_ref_ptr(table.i8_type_idx, nr_muls) + return table.new_type_ptr(table.i8_type_idx, nr_muls) } 'i16' { - return p.table.type_ref_ptr(table.i16_type_idx, nr_muls) + return table.new_type_ptr(table.i16_type_idx, nr_muls) } 'int' { - return p.table.type_ref_ptr(table.int_type_idx, nr_muls) + return table.new_type_ptr(table.int_type_idx, nr_muls) } 'i64' { - return p.table.type_ref_ptr(table.i64_type_idx, nr_muls) + return table.new_type_ptr(table.i64_type_idx, nr_muls) } 'byte' { - return p.table.type_ref_ptr(table.byte_type_idx, nr_muls) + return table.new_type_ptr(table.byte_type_idx, nr_muls) } 'u16' { - return p.table.type_ref_ptr(table.u16_type_idx, nr_muls) + return table.new_type_ptr(table.u16_type_idx, nr_muls) } 'u32' { - return p.table.type_ref_ptr(table.u32_type_idx, nr_muls) + return table.new_type_ptr(table.u32_type_idx, nr_muls) } 'u64' { - return p.table.type_ref_ptr(table.u64_type_idx, nr_muls) + return table.new_type_ptr(table.u64_type_idx, nr_muls) } 'f32' { - return p.table.type_ref_ptr(table.f32_type_idx, nr_muls) + return table.new_type_ptr(table.f32_type_idx, nr_muls) } 'f64' { - return p.table.type_ref_ptr(table.f64_type_idx, nr_muls) + return table.new_type_ptr(table.f64_type_idx, nr_muls) } 'string' { - return p.table.type_ref_ptr(table.string_type_idx, nr_muls) + return table.new_type_ptr(table.string_type_idx, nr_muls) } 'char' { - return p.table.type_ref_ptr(table.charptr_type_idx, nr_muls) + return table.new_type_ptr(table.char_type_idx, nr_muls) } 'bool' { - return p.table.type_ref_ptr(table.bool_type_idx, nr_muls) + return table.new_type_ptr(table.bool_type_idx, nr_muls) } // struct / enum / placeholder else { // struct / enum mut idx := p.table.find_type_idx(name) if idx > 0 { - return p.table.type_ref_ptr(idx, nr_muls) + return table.new_type_ptr(idx, nr_muls) } // not found - add placeholder idx = p.table.add_placeholder_type(name) println('NOT FOUND: $name - adding placeholder - $idx') - return p.table.type_ref_ptr(idx, nr_muls) + return table.new_type_ptr(idx, nr_muls) } } } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 1a78a364a9..73037358a1 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -33,7 +33,7 @@ mut: peek_tok token.Token // vars []string table &table.Table - return_type table.TypeRef // current function's return type + return_type table.Type // current function's return type // scope_level int // var_idx int is_c bool @@ -71,6 +71,7 @@ pub fn parse_file(path string, table &table.Table) ast.File { table: table file_name: path pref: &pref.Preferences{} + unresolved_offset: table.unresolved_idxs.size } p.read_first_token() // module decl @@ -385,14 +386,15 @@ pub fn (p &Parser) warn(s string) { } } -pub fn (p mut Parser) parse_ident(is_c bool) (ast.Ident,table.TypeRef) { +pub fn (p mut Parser) parse_ident(is_c bool) (ast.Ident,table.Type) { mut node := ast.Ident{} - mut typ := p.table.type_ref(table.void_type_idx) + mut typ := table.void_type // p.warn('name ') // left := p.parse_ident() name := p.check_name() mut ident := ast.Ident{ name: name + is_c: is_c } mut known_var := false if var := p.table.find_var(name) { @@ -413,7 +415,7 @@ pub fn (p mut Parser) parse_ident(is_c bool) (ast.Ident,table.TypeRef) { } else { if is_c { - typ = p.table.type_ref(table.int_type_idx) + typ = table.int_type ident.info = ast.IdentVar{ typ: typ // name: ident.name @@ -444,9 +446,9 @@ pub fn (p mut Parser) parse_ident(is_c bool) (ast.Ident,table.TypeRef) { return node,typ } -pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) { +pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) { mut node := ast.Expr{} - mut typ := p.table.type_ref(table.void_type_idx) + mut typ := table.void_type // mut typ := table.unresolved_type is_c := p.tok.lit == 'C' && p.peek_tok.kind == .dot if is_c { @@ -521,9 +523,9 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) { return node,typ } -pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.TypeRef) { +pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) { // println('\n\nparser.expr()') - mut typ := p.table.type_ref(table.void_type_idx) + mut typ := table.void_type mut node := ast.Expr{} // Prefix match p.tok.kind { @@ -534,7 +536,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.TypeRef) { node,typ = p.string_expr() } .chartoken { - typ = p.table.type_ref(table.byte_type_idx) + typ = table.byte_type node = ast.CharLiteral{ val: p.tok.lit } @@ -551,7 +553,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.TypeRef) { node = ast.BoolLiteral{ val: p.tok.kind == .key_true } - typ = p.table.type_ref(table.bool_type_idx) + typ = table.bool_type p.next() } .key_match { @@ -579,7 +581,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.TypeRef) { p.check(.lpar) p.next() p.check(.rpar) - typ = p.table.type_ref(table.int_type_idx) + typ = table.int_type } else { p.error('pexpr(): bad token `$p.tok.str()`') @@ -619,7 +621,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.TypeRef) { return node,typ } -fn (p mut Parser) prefix_expr() (ast.Expr,table.TypeRef) { +fn (p mut Parser) prefix_expr() (ast.Expr,table.Type) { op := p.tok.kind p.next() right,typ := p.expr(1) @@ -663,7 +665,7 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.Expr { // return node,typ } -fn (p mut Parser) dot_expr(left ast.Expr, left_type &table.TypeRef) (ast.Expr,table.TypeRef) { +fn (p mut Parser) dot_expr(left ast.Expr, left_type table.Type) (ast.Expr,table.Type) { p.next() field_name := p.check_name() // Method call @@ -682,7 +684,8 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_type &table.TypeRef) (ast.Expr,ta } mut node := ast.Expr{} node = mcall_expr - typ := p.add_unresolved('${left_type.typ.name}.${field_name}()', mcall_expr) + // typ := p.add_unresolved('${left_type.typ.name}.${field_name}()', mcall_expr) + typ := p.add_unresolved('${table.type_idx(left_type)}.${field_name}()', mcall_expr) return node,typ } sel_expr := ast.SelectorExpr{ @@ -690,13 +693,14 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_type &table.TypeRef) (ast.Expr,ta field: field_name pos: p.tok.position() } - typ := p.add_unresolved('${left_type.typ.name}.$field_name', sel_expr) + // typ := p.add_unresolved('${left_type.typ.name}.$field_name', sel_expr) + typ := p.add_unresolved('${table.type_idx(left_type)}.$field_name', sel_expr) mut node := ast.Expr{} node = sel_expr return node,typ } -fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,table.TypeRef) { +fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,table.Type) { op := p.tok.kind // mut typ := p. // println('infix op=$op.str()') @@ -704,7 +708,7 @@ fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,table.TypeRef) { p.next() right,mut typ := p.expr(precedence) if op.is_relational() { - typ = p.table.type_ref(table.bool_type_idx) + typ = table.bool_type } mut expr := ast.Expr{} expr = ast.InfixExpr{ @@ -763,9 +767,7 @@ fn (p mut Parser) for_statement() ast.Stmt { } p.check(.semicolon) if p.tok.kind != .semicolon { - mut typ := table.TypeRef{ - typ: 0 - } + mut typ := table.void_type cond,typ = p.expr(0) } p.check(.semicolon) @@ -789,7 +791,7 @@ fn (p mut Parser) for_statement() ast.Stmt { val_name := p.check_name() p.table.register_var(table.Var{ name: val_name - typ: p.table.type_ref(table.int_type_idx) + typ: table.int_type }) } p.check(.key_in) @@ -801,7 +803,7 @@ fn (p mut Parser) for_statement() ast.Stmt { } p.table.register_var(table.Var{ name: var_name - typ: p.table.type_ref(table.int_type_idx) + typ: table.int_type }) stmts := p.parse_block() // println('nr stmts=$stmts.len') @@ -822,7 +824,7 @@ fn (p mut Parser) for_statement() ast.Stmt { } } -fn (p mut Parser) if_expr() (ast.Expr,table.TypeRef) { +fn (p mut Parser) if_expr() (ast.Expr,table.Type) { p.inside_if = true // defer { // } @@ -841,13 +843,14 @@ fn (p mut Parser) if_expr() (ast.Expr,table.TypeRef) { else_stmts = p.parse_block() } } - mut typ := p.table.type_ref(table.void_type_idx) + mut typ := table.void_type // mut left := ast.Expr{} // If the last statement is an expression, return its type if stmts.len > 0 { match stmts[stmts.len - 1] { ast.ExprStmt { - p.warn('if expr ret $it.typ.typ.name') + type_sym := p.table.get_type_symbol(it.typ) + p.warn('if expr ret $type_sym.name') typ = it.typ // return node,it.ti // left = @@ -867,14 +870,14 @@ fn (p mut Parser) if_expr() (ast.Expr,table.TypeRef) { return node,typ } -fn (p mut Parser) string_expr() (ast.Expr,table.TypeRef) { +fn (p mut Parser) string_expr() (ast.Expr,table.Type) { mut node := ast.Expr{} node = ast.StringLiteral{ val: p.tok.lit } if p.peek_tok.kind != .str_dollar { p.next() - return node,p.table.type_ref(table.string_type_idx) + return node,table.string_type } // Handle $ interpolation for p.tok.kind == .str { @@ -888,13 +891,13 @@ fn (p mut Parser) string_expr() (ast.Expr,table.TypeRef) { p.next() } } - return node,p.table.type_ref(table.string_type_idx) + return node,table.string_type } -fn (p mut Parser) array_init() (ast.Expr,table.TypeRef) { +fn (p mut Parser) array_init() (ast.Expr,table.Type) { mut node := ast.Expr{} p.check(.lsbr) - mut val_type := p.table.type_ref(table.void_type_idx) + mut val_type := table.void_type mut exprs := []ast.Expr for i := 0; p.tok.kind != .rsbr; i++ { expr,typ := p.expr(0) @@ -917,7 +920,7 @@ fn (p mut Parser) array_init() (ast.Expr,table.TypeRef) { } // array_type := table.new_type(.array, type_name, type_idx, 0) idx := p.table.find_or_register_array(val_type, 1) - array_type := p.table.type_ref_ptr(idx, 0) + array_type := table.new_type(idx) node = ast.ArrayInit{ typ: array_type exprs: exprs @@ -926,16 +929,16 @@ fn (p mut Parser) array_init() (ast.Expr,table.TypeRef) { return node,array_type } -fn (p mut Parser) parse_number_literal() (ast.Expr,table.TypeRef) { +fn (p mut Parser) parse_number_literal() (ast.Expr,table.Type) { lit := p.tok.lit mut node := ast.Expr{} - mut ti := p.table.type_ref(table.int_type_idx) + mut ti := table.int_type if lit.contains('.') { node = ast.FloatLiteral{ // val: lit.f64() val: lit } - ti = p.table.type_ref(table.f64_type_idx) + ti = table.f64_type } else { node = ast.IntegerLiteral{ @@ -1053,7 +1056,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { // println('struct field $ti.name $field_name') } p.check(.rcbr) - t := table.Type{ + t := table.TypeSymbol{ parent: 0 kind: .struct_ name: name @@ -1065,9 +1068,9 @@ fn (p mut Parser) struct_decl() ast.StructDecl { if p.builtin_mod && t.name in table.builtin_type_names { // this allows overiding the builtins type // with the real struct type info parsed from builtin - ret = p.table.register_builtin_type(t) + ret = p.table.register_builtin_type_symbol(t) } else { - ret = p.table.register_type(t) + ret = p.table.register_type_symbol(t) } if ret == -1 { p.error('cannot register type `$name`, another type with this name exists') @@ -1086,7 +1089,7 @@ fn (p mut Parser) return_stmt() ast.Return { mut exprs := []ast.Expr // return type idents // mut got_tis := []table.Type - if p.return_type.idx == table.void_type_idx { + if table.type_idx(p.return_type) == table.void_type_idx { return ast.Return{ pos: p.tok.position() } @@ -1154,7 +1157,8 @@ fn (p mut Parser) var_decl() ast.VarDecl { is_mut: is_mut typ: typ }) - p.warn('var decl name=$name typ=$typ.typ.name') + typ_sym := p.table.get_type_symbol(typ) + p.warn('var decl name=$name typ=$typ_sym.name') // println(p.table.names) node := ast.VarDecl{ name: name @@ -1208,7 +1212,7 @@ fn (p mut Parser) global_decl() ast.GlobalDecl { } } -fn (p mut Parser) match_expr() (ast.Expr,table.TypeRef) { +fn (p mut Parser) match_expr() (ast.Expr,table.Type) { p.check(.key_match) cond,typ := p.expr(0) p.check(.lcbr) @@ -1240,10 +1244,10 @@ fn (p mut Parser) match_expr() (ast.Expr,table.TypeRef) { typ: typ cond: cond } - return node,p.table.type_ref(table.void_type_idx) + return node,table.void_type } -fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.TypeRef { +fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.Type { mut idx := p.unresolved_offset + p.unresolved.len if key in p.table.unresolved_idxs { idx = p.table.unresolved_idxs[key] @@ -1252,15 +1256,7 @@ fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.TypeRef { p.table.unresolved_idxs[key] = idx p.unresolved << expr } - t := table.TypeRef{ - idx: idx - typ: &table.Type{ - parent: 0 - kind: .unresolved - name: 'unresolved-$idx' - } - } - return t + return table.new_type((-idx)-1) } fn verror(s string) { diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atype_symbols.v similarity index 57% rename from vlib/v/table/atypes.v rename to vlib/v/table/atype_symbols.v index c8cb1ece04..b794866b7c 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atype_symbols.v @@ -5,9 +5,9 @@ module table pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn -pub struct Type { +pub struct TypeSymbol { pub: - parent &Type + parent &TypeSymbol mut: info TypeInfo kind Kind @@ -15,33 +15,26 @@ mut: methods []Fn } -pub struct TypeRef { -pub: - idx int - typ &Type - nr_muls int -} - pub const ( // primitive types void_type_idx = 1 voidptr_type_idx = 2 - charptr_type_idx = 3 - byteptr_type_idx = 4 + byteptr_type_idx = 3 + charptr_type_idx = 4 i8_type_idx = 5 i16_type_idx = 6 int_type_idx = 7 i64_type_idx = 8 - u16_type_idx = 9 - u32_type_idx = 10 - u64_type_idx = 11 - f32_type_idx = 12 - f64_type_idx = 13 - bool_type_idx = 14 + byte_type_idx = 9 + u16_type_idx = 10 + u32_type_idx = 11 + u64_type_idx = 12 + f32_type_idx = 13 + f64_type_idx = 14 + char_type_idx = 15 + bool_type_idx = 16 // advanced / defined from v structs - string_type_idx = 15 - char_type_idx = 16 - byte_type_idx = 17 + string_type_idx = 17 array_type_idx = 18 map_type_idx = 19 ) @@ -57,23 +50,21 @@ pub enum Kind { placeholder void voidptr - charptr byteptr + charptr i8 i16 int i64 + byte u16 u32 u64 f32 f64 - string char - byte bool - //const_ - //enum_ + string struct_ array array_fixed @@ -83,198 +74,173 @@ pub enum Kind { } [inline] -pub fn(t &Type) mr_info() MultiReturn { +pub fn(t &TypeSymbol) mr_info() MultiReturn { match t.info { MultiReturn { return it } else { - panic('Type.mr_info(): no multi return info') + panic('TypeSymbol.mr_info(): no multi return info') } } } [inline] -pub fn(t &Type) array_info() Array { +pub fn(t &TypeSymbol) array_info() Array { match t.info { Array { return it } else { - panic('Type.array_info(): no array info') + panic('TypeSymbol.array_info(): no array info') } } } [inline] -pub fn(t &Type) array_fixed_info() ArrayFixed { +pub fn(t &TypeSymbol) array_fixed_info() ArrayFixed { match t.info { ArrayFixed { return it } else { - panic('Type.array_fixed(): no array fixed info') + panic('TypeSymbol.array_fixed(): no array fixed info') } } } [inline] -pub fn(t &Type) map_info() Map { +pub fn(t &TypeSymbol) map_info() Map { match t.info { Map { return it } else { - panic('Type.map_info(): no map info') + panic('TypeSymbol.map_info(): no map info') } } } /* -pub fn (t Type) str() string { +pub fn (t TypeSymbol) str() string { return t.name } */ -pub fn (t &TypeRef) str() string { - mut muls := '' - for _ in 0 .. t.nr_muls { - muls += '&' - } - return '$muls$t.typ.name' +[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 (t &Table) type_ref(idx int) TypeRef { - return TypeRef{ - idx: idx - typ: &t.types[idx] - } +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 (t &Table) type_ref_ptr(idx int, nr_muls int) TypeRef { - return TypeRef{ - idx: idx - nr_muls: nr_muls - typ: &t.types[idx] - } +pub fn map_name(key_type &TypeSymbol, value_type &TypeSymbol) string { + return 'map_${key_type.name}_${value_type.name}' } -[inline] -pub fn array_name(elem_type &TypeRef, nr_dims int) string { - return 'array_${elem_type.typ.name}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' } -} - -[inline] -pub fn array_fixed_name(elem_type &TypeRef, size int, nr_dims int) string { - return 'array_fixed_${elem_type.typ.name}_${size}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' } -} - -[inline] -pub fn map_name(key_type &TypeRef, value_type &TypeRef) string { - return 'map_${key_type.typ.name}_${value_type.typ.name}' -} - -pub fn (t mut Table) register_builtin_types() { +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 - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .placeholder name: 'reserved_0' }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .void name: 'void' }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .voidptr name: 'voidptr' }) - t.register_type(Type{ - parent: 0 - kind: .charptr - name: 'charptr' - }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .byteptr name: 'byteptr' }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ + parent: 0 + kind: .charptr + name: 'charptr' + }) + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .i8 name: 'i8' }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .i16 name: 'i16' }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .int name: 'int' }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .i64 name: 'i64' }) - t.register_type(Type{ - parent: 0 - kind: .u16 - name: 'u16' - }) - t.register_type(Type{ - parent: 0 - kind: .u32 - name: 'u32' - }) - t.register_type(Type{ - parent: 0 - kind: .u64 - name: 'u64' - }) - t.register_type(Type{ - parent: 0 - kind: .f32 - name: 'f32' - }) - t.register_type(Type{ - parent: 0 - kind: .f64 - name: 'f64' - }) - t.register_type(Type{ - parent: 0 - kind: .bool - name: 'bool' - }) - t.register_type(Type{ - parent: 0 - kind: .string - name: 'string' - }) - t.register_type(Type{ - parent: 0 - kind: .char - name: 'char' - }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .byte name: 'byte' }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ + parent: 0 + kind: .u16 + name: 'u16' + }) + t.register_type_symbol(TypeSymbol{ + parent: 0 + kind: .u32 + name: 'u32' + }) + t.register_type_symbol(TypeSymbol{ + parent: 0 + kind: .u64 + name: 'u64' + }) + t.register_type_symbol(TypeSymbol{ + parent: 0 + kind: .f32 + name: 'f32' + }) + t.register_type_symbol(TypeSymbol{ + parent: 0 + kind: .f64 + name: 'f64' + }) + t.register_type_symbol(TypeSymbol{ + parent: 0 + kind: .char + name: 'char' + }) + t.register_type_symbol(TypeSymbol{ + parent: 0 + kind: .bool + name: 'bool' + }) + t.register_type_symbol(TypeSymbol{ + parent: 0 + kind: .string + name: 'string' + }) + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .array name: 'array' }) - t.register_type(Type{ + t.register_type_symbol(TypeSymbol{ parent: 0 kind: .map name: 'map' @@ -282,22 +248,17 @@ pub fn (t mut Table) register_builtin_types() { } [inline] -pub fn (t &TypeRef) is_ptr() bool { - return t.nr_muls > 0 -} - -[inline] -pub fn (t &Type) is_int() bool { +pub fn (t &TypeSymbol) is_int() bool { return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64] } [inline] -pub fn (t &Type) is_float() bool { +pub fn (t &TypeSymbol) is_float() bool { return t.kind in [.f32, .f64] } [inline] -pub fn (t &Type) is_number() bool { +pub fn (t &TypeSymbol) is_number() bool { return t.is_int() || t.is_float() } @@ -321,12 +282,6 @@ pub fn (k Kind) str() string { .byteptr{ 'byteptr' } - // .const_{ - // 'const' - // } - // .enum_{ - // 'enum' - // } .struct_{ 'struct' } @@ -398,14 +353,6 @@ pub fn (kinds []Kind) str() string { return kinds_str } -// pub struct Const { -// pub: -// name string -// } -// pub struct Enum { -// pub: -// name string -// } pub struct Struct { pub mut: fields []Field @@ -415,23 +362,14 @@ pub struct Field { pub: name string mut: - typ TypeRef - // type_idx int + typ Type } -// pub struct Int { -// pub: -// bit_size u32 -// is_unsigned bool -// } -// pub struct Float { -// pub: -// bit_size u32 -// } + pub struct Array { pub: nr_dims int mut: - elem_type TypeRef + elem_type Type } pub struct ArrayFixed { @@ -439,26 +377,18 @@ pub: nr_dims int size int mut: - elem_type TypeRef + elem_type Type } pub struct Map { pub mut: - key_type TypeRef - value_type TypeRef + key_type Type + value_type Type } pub struct MultiReturn { pub: name string mut: - types []TypeRef -} - -[inline] -pub fn (t &Table) get_type(idx int) &Type { - if idx == 0 { - panic('get_type: idx 0') - } - return &t.types[idx] + types []Type } diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 2260101aa5..41d71d97a1 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -8,7 +8,7 @@ module table pub struct Table { // struct_fields map[string][]string pub mut: - types []Type + types []TypeSymbol // type_idxs Hashmap type_idxs map[string]int unresolved_idxs map[string]int @@ -26,7 +26,7 @@ pub struct Fn { pub: name string args []Var - return_type TypeRef + return_type Type is_variadic bool is_c bool } @@ -40,14 +40,14 @@ pub: is_global bool scope_level int mut: - typ TypeRef + typ Type } pub fn new_table() &Table { mut t := &Table{ - types: make(0, 400, sizeof(Type)) + types: make(0, 400, sizeof(TypeSymbol)) } - t.register_builtin_types() + t.register_builtin_type_symbols() return t } @@ -82,7 +82,7 @@ pub fn (t mut Table) register_const(v Var) { t.consts[v.name] = v } -pub fn (t mut Table) register_global(name string, typ TypeRef) { +pub fn (t mut Table) register_global(name string, typ Type) { t.consts[name] = Var{ name: name typ: typ @@ -96,7 +96,8 @@ pub fn (t mut Table) register_global(name string, typ TypeRef) { } pub fn (t mut Table) register_var(v Var) { - println('register_var: $v.name - $v.typ.typ.name') + typ_sym := t.get_type_symbol(v.typ) + println('register_var: $v.name - $typ_sym.name') new_var := { v | idx:t.var_idx, @@ -192,7 +193,7 @@ pub fn (t mut Table) register_fn(new_fn Fn) { t.fns[new_fn.name] = new_fn } -pub fn (t &Table) register_method(typ &Type, new_fn Fn) bool { +pub fn (t &Table) register_method(typ &TypeSymbol, new_fn Fn) bool { // println('register method `$new_fn.name` type=$typ.name idx=$typ.idx') println('register method `$new_fn.name` type=$typ.name') mut t1 := typ @@ -207,14 +208,14 @@ pub fn (t mut Table) new_tmp_var() string { return 'tmp$t.tmp_cnt' } -pub fn (t &Type) has_method(name string) bool { +pub fn (t &TypeSymbol) has_method(name string) bool { t.find_method(name) or { return false } return true } -pub fn (t &Type) find_method(name string) ?Fn { +pub fn (t &TypeSymbol) find_method(name string) ?Fn { for method in t.methods { if method.name == name { return method @@ -224,14 +225,14 @@ pub fn (t &Type) find_method(name string) ?Fn { } -pub fn (s &Type) has_field(name string) bool { +pub fn (s &TypeSymbol) has_field(name string) bool { s.find_field(name) or { return false } return true } -pub fn (s &Type) find_field(name string) ?Field { +pub fn (s &TypeSymbol) find_field(name string) ?Field { match s.info { Struct { for field in it.fields { @@ -245,7 +246,7 @@ pub fn (s &Type) find_field(name string) ?Field { return none } -pub fn (t &Table) struct_has_field(s &Type, name string) bool { +pub fn (t &Table) struct_has_field(s &TypeSymbol, name string) bool { if !isnil(s.parent) { println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name') } @@ -258,7 +259,7 @@ pub fn (t &Table) struct_has_field(s &Type, name string) bool { return false } -pub fn (t &Table) struct_find_field(s &Type, name string) ?Field { +pub fn (t &Table) struct_find_field(s &TypeSymbol, name string) ?Field { if !isnil(s.parent) { println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name') } @@ -283,7 +284,7 @@ pub fn (t &Table) find_type_idx(name string) int { } [inline] -pub fn (t &Table) find_type(name string) ?Type { +pub fn (t &Table) find_type(name string) ?TypeSymbol { idx := t.type_idxs[name] if idx > 0 { return t.types[idx] @@ -291,11 +292,28 @@ pub fn (t &Table) find_type(name string) ?Type { return none } +[inline] +pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol { + idx := type_idx(typ) + if idx < 0 { + unresolved_idx := -idx + return &TypeSymbol{ + parent: 0 + kind: .unresolved + name: 'unresolved-$unresolved_idx' + } + } else if idx > 0 { + return &t.types[idx] + } + // this should never happen + panic('get_type_symbol: invalid type $idx') +} + // this will override or register builtin type // allows prexisitng types added in register_builtins // to be overriden with their real type info [inline] -pub fn (t mut Table) register_builtin_type(typ Type) int { +pub fn (t mut Table) register_builtin_type_symbol(typ TypeSymbol) int { existing_idx := t.type_idxs[typ.name] if existing_idx > 0 { if existing_idx >= string_type_idx { @@ -304,11 +322,11 @@ pub fn (t mut Table) register_builtin_type(typ Type) int { } return existing_idx } - return t.register_type(typ) + return t.register_type_symbol(typ) } [inline] -pub fn (t mut Table) register_type(typ Type) int { +pub fn (t mut Table) register_type_symbol(typ TypeSymbol) int { existing_idx := t.type_idxs[typ.name] if existing_idx > 0 { ex_type := t.types[existing_idx] @@ -344,15 +362,17 @@ pub fn (t &Table) known_type(name string) bool { return true } -pub fn (t mut Table) find_or_register_map(key_type TypeRef, value_type TypeRef) int { - name := map_name(&key_type, &value_type) +pub fn (t mut Table) find_or_register_map(key_type, value_type Type) int { + 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) // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { return existing_idx } // register - map_type := Type{ + map_typ := TypeSymbol{ parent: &t.types[map_type_idx] kind: .map name: name @@ -361,18 +381,19 @@ pub fn (t mut Table) find_or_register_map(key_type TypeRef, value_type TypeRef) value_type: value_type } } - return t.register_type(map_type) + return t.register_type_symbol(map_typ) } -pub fn (t mut Table) find_or_register_array(elem_type TypeRef, nr_dims int) int { - name := array_name(&elem_type, nr_dims) +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) // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { return existing_idx } // register - array_type := Type{ + array_type := TypeSymbol{ parent: &t.types[array_type_idx] kind: .array name: name @@ -381,18 +402,19 @@ pub fn (t mut Table) find_or_register_array(elem_type TypeRef, nr_dims int) int nr_dims: nr_dims } } - return t.register_type(array_type) + return t.register_type_symbol(array_type) } -pub fn (t mut Table) find_or_register_array_fixed(elem_type TypeRef, size int, nr_dims int) int { - name := array_fixed_name(&elem_type, size, nr_dims) +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) // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { return existing_idx } // register - array_fixed_type := Type{ + array_fixed_type := TypeSymbol{ parent: 0 kind: .array_fixed name: name @@ -402,13 +424,14 @@ pub fn (t mut Table) find_or_register_array_fixed(elem_type TypeRef, size int, n nr_dims: nr_dims } } - return t.register_type(array_fixed_type) + return t.register_type_symbol(array_fixed_type) } -pub fn (t mut Table) find_or_register_multi_return(mr_typs []TypeRef) int { +pub fn (t mut Table) find_or_register_multi_return(mr_typs []Type) int { mut name := 'multi_return' for mr_typ in mr_typs { - name += '_$mr_typ.typ.name' + mr_type_sym := t.get_type_symbol(mr_typ) + name += '_$mr_type_sym.name' } // existing existing_idx := t.type_idxs[name] @@ -416,7 +439,7 @@ pub fn (t mut Table) find_or_register_multi_return(mr_typs []TypeRef) int { return existing_idx } // register - mr_type := Type{ + mr_type := TypeSymbol{ parent: 0 kind: .multi_return name: name @@ -424,34 +447,39 @@ pub fn (t mut Table) find_or_register_multi_return(mr_typs []TypeRef) int { types: mr_typs } } - return t.register_type(mr_type) + return t.register_type_symbol(mr_type) } pub fn (t mut Table) add_placeholder_type(name string) int { - ph_type := Type{ + ph_type := TypeSymbol{ parent: 0 kind: .placeholder name: name } // println('added placeholder: $name - $ph_type.idx') - return t.register_type(ph_type) + return t.register_type_symbol(ph_type) } -pub fn (t &Table) check(got, expected &TypeRef) bool { - println('check: $got.typ.name, $expected.typ.name') - if expected.typ.kind == .voidptr { +pub fn (t &Table) check(got, expected Type) bool { + got_type_sym := t.get_type_symbol(got) + exp_type_sym := t.get_type_symbol(expected) + got_idx := type_idx(got) + exp_idx := type_idx(expected) + println('check: $got_type_sym.name, $exp_type_sym.name') + if exp_type_sym.kind == .voidptr { return true } - if expected.typ.kind in [.voidptr, .byteptr, .charptr] && got.typ.kind == .int { + if got_type_sym.kind in [.voidptr, .byteptr, .charptr, .int] && + exp_type_sym.kind in [.voidptr, .byteptr, .charptr] { return true } - if expected.typ.kind == .byteptr && got.typ.kind == .voidptr { + if got_type_sym.is_int() && exp_type_sym.is_int() { return true } // if expected.name == 'array' { // return true // } - if got.idx != expected.idx && got.typ.name != expected.typ.name { + if got_idx != exp_idx /*&& got.typ.name != expected.typ.name*/ { return false } return true @@ -459,7 +487,7 @@ pub fn (t &Table) check(got, expected &TypeRef) bool { /* [inline] -pub fn (t &Table) get_expr_typ(expr ast.Expr) Type { +pub fn (t &Table) get_expr_typ(expr ast.Expr) TypeSymbol { match expr { ast.ArrayInit { return it.typ diff --git a/vlib/v/table/types.v b/vlib/v/table/types.v new file mode 100644 index 0000000000..1a47adceac --- /dev/null +++ b/vlib/v/table/types.v @@ -0,0 +1,87 @@ +module table + +pub type Type int + +// return underlying TypeSymbol idx +[inline] +pub fn type_idx(t Type) int { + return i16(int(t) >> 16) & 0xffffffff +} + +// return nr_muls +[inline] +pub fn type_nr_muls(t Type) int { + return i16(int(t) & 0xffffffff) +} + +// return true if pointer (nr_muls>0) +[inline] +pub fn type_is_ptr(t Type) bool { + return type_nr_muls(t) > 0 +} + +// increments nr_nuls on Type and return it +[inline] +pub fn type_to_ptr(t Type) Type { + return type_idx(t) << i16(16) | (type_nr_muls(t)+1) +} + +// decrement nr_muls on Type and return it +[inline] +pub fn type_deref(t Type) Type { + idx := type_idx(t) + nr_muls := type_nr_muls(t) + if nr_muls == 0 { + panic('deref: $idx is not a pointer') + } + return idx << i16(16) | (nr_muls+-1) +} + +// new type with idx of TypeSymbol, not pointer (nr_muls=0) +[inline] +pub fn new_type(idx int) Type { + if idx > 32767 || idx < -32767 { + panic('new_type_id: idx must be between -32767 & 32767') + } + return idx << i16(16) +} + +// return Type idx of TypeSymbol & specify if ptr (nr_muls) +[inline] +pub fn new_type_ptr(idx, nr_muls int) Type { + if idx > 32767 || idx < -32767 { + panic('typ_ptr: idx must be between -32767 & 32767') + } + if nr_muls > 32767 || nr_muls < -0 { + panic('typ_ptr: nr_muls must be between 0 & 32767') + } + return idx << i16(16) | nr_muls +} + +// true if the type of unresolved expression +[inline] +pub fn type_is_unresolved(t Type) bool { + return type_idx(t) < 0 +} + +pub const ( + void_type = new_type(void_type_idx) + voidptr_type = new_type(voidptr_type_idx) + byteptr_type = new_type(byteptr_type_idx) + charptr_type = new_type(charptr_type_idx) + i8_type = new_type(i8_type_idx) + int_type = new_type(int_type_idx) + i16_type = new_type(i16_type_idx) + i64_type = new_type(i64_type_idx) + byte_type = new_type(byte_type_idx) + u16_type = new_type(u16_type_idx) + u32_type = new_type(u32_type_idx) + u64_type = new_type(u64_type_idx) + f32_type = new_type(f32_type_idx) + f64_type = new_type(f64_type_idx) + char_type = new_type(char_type_idx) + bool_type = new_type(bool_type_idx) + string_type = new_type(string_type_idx) + array_type = new_type(array_type_idx) + map_type = new_type(map_type_idx) +)