v2: type sys - store type idx/ptr in int & add helpers

pull/3713/head
joe-conigliaro 2020-02-10 18:32:08 +11:00 committed by GitHub
parent 9845fd1cf5
commit e274c5c485
11 changed files with 515 additions and 426 deletions

View File

@ -240,19 +240,23 @@ fn C.RegQueryValueEx() voidptr
fn C.RemoveDirectory() int 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.wprintf()
fn C.setbuf() //fn C.setbuf()
fn C.setbuf(voidptr, charptr)
fn C.SymCleanup() fn C.SymCleanup()

View File

@ -20,7 +20,7 @@ HashStmt | AssignStmt
pub struct ExprStmt { pub struct ExprStmt {
pub: pub:
expr Expr expr Expr
typ table.TypeRef typ table.Type
} }
pub struct IntegerLiteral { pub struct IntegerLiteral {
@ -69,7 +69,7 @@ pub struct Field {
pub: pub:
name string name string
// type_idx int // type_idx int
typ table.TypeRef typ table.Type
} }
pub struct ConstDecl { pub struct ConstDecl {
@ -89,7 +89,7 @@ pub:
pub struct StructInit { pub struct StructInit {
pub: pub:
pos token.Position pos token.Position
typ table.TypeRef typ table.Type
fields []string fields []string
exprs []Expr exprs []Expr
} }
@ -105,7 +105,7 @@ pub:
pub struct Arg { pub struct Arg {
pub: pub:
typ table.TypeRef typ table.Type
name string name string
} }
@ -113,7 +113,7 @@ pub struct FnDecl {
pub: pub:
name string name string
stmts []Stmt stmts []Stmt
typ table.TypeRef typ table.Type
args []Arg args []Arg
is_pub bool is_pub bool
is_variadic bool is_variadic bool
@ -147,7 +147,7 @@ pub:
pub struct Return { pub struct Return {
pub: pub:
pos token.Position pos token.Position
expected_type table.TypeRef // TODO: remove once checker updated expected_type table.Type // TODO: remove once checker updated
exprs []Expr exprs []Expr
} }
@ -173,7 +173,7 @@ pub:
expr Expr expr Expr
is_mut bool is_mut bool
mut: mut:
typ table.TypeRef typ table.Type
pos token.Position pos token.Position
} }
@ -182,7 +182,7 @@ pub:
name string name string
expr Expr expr Expr
mut: mut:
typ table.TypeRef typ table.Type
} }
pub struct StmtBlock { pub struct StmtBlock {
@ -201,7 +201,7 @@ pub:
pub struct IdentVar { pub struct IdentVar {
pub mut: pub mut:
typ table.TypeRef typ table.Type
is_mut bool is_mut bool
// name string // name string
} }
@ -219,9 +219,10 @@ pub enum IdentKind {
pub struct Ident { pub struct Ident {
pub: pub:
name string name string
value string
is_c bool
tok_kind token.Kind tok_kind token.Kind
pos token.Position pos token.Position
value string
mut: mut:
kind IdentKind kind IdentKind
info IdentInfo info IdentInfo
@ -245,9 +246,9 @@ pub:
op token.Kind op token.Kind
pos token.Position pos token.Position
left Expr left Expr
left_type table.TypeRef left_type table.Type
right Expr right Expr
right_type table.TypeRef right_type table.Type
} }
/* /*
@ -290,7 +291,7 @@ pub:
cond Expr cond Expr
stmts []Stmt stmts []Stmt
else_stmts []Stmt else_stmts []Stmt
typ table.TypeRef typ table.Type
left Expr // `a` in `a := if ...` left Expr // `a` in `a := if ...`
pos token.Position pos token.Position
} }
@ -301,7 +302,7 @@ pub:
cond Expr cond Expr
blocks []StmtBlock blocks []StmtBlock
match_exprs []Expr match_exprs []Expr
typ table.TypeRef typ table.Type
pos token.Position pos token.Position
} }
@ -372,7 +373,7 @@ pub:
pos token.Position pos token.Position
exprs []Expr exprs []Expr
mut: mut:
typ table.TypeRef typ table.Type
} }
// s[10..20] // s[10..20]

View File

@ -14,7 +14,7 @@ pub struct Checker {
table &table.Table table &table.Table
mut: mut:
file_name string file_name string
resolved []table.TypeRef resolved []table.Type
} }
pub fn new_checker(table &table.Table) Checker { pub fn new_checker(table &table.Table) Checker {
@ -63,27 +63,30 @@ fn (c &Checker) complete_types() {
// println('Resolve type: $t.name') // println('Resolve type: $t.name')
if t.kind == .array { if t.kind == .array {
mut info := t.array_info() mut info := t.array_info()
if info.elem_type.typ.kind == .unresolved { if table.type_is_unresolved(info.elem_type) {
info.elem_type = c.resolved[info.elem_type.idx] 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] 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 t1.info = info
} }
} }
else if t.kind == .map { else if t.kind == .map {
mut info := t.map_info() mut info := t.map_info()
mut updated := false mut updated := false
if info.key_type.typ.kind == .unresolved { if table.type_is_unresolved(info.key_type) {
info.key_type = c.resolved[info.key_type.idx] info.key_type = c.resolve(info.key_type)
updated = true updated = true
} }
if info.value_type.typ.kind == .unresolved { if table.type_is_unresolved(info.value_type) {
info.value_type = c.resolved[info.value_type.idx] info.value_type = c.resolve(info.value_type)
updated = true updated = true
} }
if updated { if updated {
mut t1 := &c.table.types[idx] 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 t1.info = info
} }
} }
@ -92,8 +95,8 @@ fn (c &Checker) complete_types() {
mut types := info.types mut types := info.types
mut updated := false mut updated := false
for i, ut in types { for i, ut in types {
if ut.typ.kind == .unresolved { if table.type_is_unresolved(ut) {
types[i] = c.resolved[ut.idx] types[i] = c.resolve(ut)
updated = true updated = true
} }
} }
@ -106,22 +109,30 @@ fn (c &Checker) complete_types() {
} }
} }
pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.TypeRef { // return the resolved Type from unresovled Type
typ := c.table.find_type(struct_init.typ.typ.name) or { pub fn (c &Checker) resolve(unresolved table.Type) table.Type {
c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos) return c.resolved[-table.type_idx(unresolved)-1]
panic('') }
}
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 { match typ.kind {
.placeholder { .placeholder {
c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos) c.error('unknown struct: $typ.name', struct_init.pos)
} }
.struct_ { .struct_ {
info := typ.info as table.Struct info := typ.info as table.Struct
for i, expr in struct_init.exprs { for i, expr in struct_init.exprs {
field := info.fields[i] field := info.fields[i]
field_type := c.expr(expr) expr_type := c.expr(expr)
if !c.table.check(field_type, field.typ) { expr_type_sym := c.table.get_type_symbol(expr_type)
c.error('cannot assign $field_type.typ.name as $field.typ.typ.name for field $field.name', struct_init.pos) 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 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) left_type := c.expr(infix_expr.left)
right_type := c.expr(infix_expr.right) 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) { // 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 `$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() { if infix_expr.op.is_relational() {
return c.table.type_ref(table.bool_type_idx) return table.bool_type
} }
return left_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) left_type := c.expr(assign_expr.left)
right_type := c.expr(assign_expr.val) right_type := c.expr(assign_expr.val)
if !c.table.check(right_type, left_type) { 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 fn_name := call_expr.name
if f := c.table.find_fn(fn_name) { if f := c.table.find_fn(fn_name) {
// return_ti := f.return_ti // return_ti := f.return_ti
if !f.is_c { if /*TODO:*/!f.is_c {
if call_expr.args.len < f.args.len { if call_expr.args.len < f.args.len {
c.error('too few arguments in call to `$fn_name`', call_expr.pos) 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) 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 /*TODO:*/!f.is_c {
if f.name == 'backtrace_symbols_fd' { for i, arg_expr in call_expr.args {
println('ARGS FOR: backtrace_symbols_fd:') arg := if f.is_variadic && i >= f.args.len-1 {
for i, arg_expr in call_expr.args { f.args[f.args.len-1]
typ := c.expr(arg_expr) } else {
println(' -- $i - $typ.typ.name') 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) typ := c.expr(arg_expr)
if !c.table.check(&typ, &arg.typ) { typ_sym := c.table.get_type_symbol(typ)
c.error('!cannot use type `$typ.typ.name` as type `$arg.typ.typ.name` in argument to `$fn_name`', call_expr.pos) 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) 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) 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 return method.return_type
} }
// check parent // check parent
if !isnil(typ.typ.parent) { if !isnil(typ_sym.parent) {
if method := typ.typ.parent.find_method(method_call_expr.name) { if method := typ_sym.parent.find_method(method_call_expr.name) {
return method.return_type 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) 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 := c.expr(selector_expr.expr)
typ_sym := c.table.get_type_symbol(typ)
field_name := selector_expr.field field_name := selector_expr.field
if field := typ.typ.find_field(field_name) { if field := typ_sym.find_field(field_name) {
return field.typ return field.typ
} }
// types with parent struct (array/maps) handled here // check parent
if !isnil(typ.typ.parent) { if !isnil(typ_sym.parent) {
if field := typ.typ.parent.find_field(field_name) { if field := typ_sym.parent.find_field(field_name) {
if field.typ.typ.kind == .unresolved { if table.type_is_unresolved(field.typ) {
return c.resolved[field.typ.idx] return c.resolved[field.typ]
} }
return field.typ return field.typ
} }
} }
if typ.typ.kind != .struct_ { if typ_sym.kind != .struct_ {
c.error('`$typ.typ.name` is not a struct', selector_expr.pos) c.error('`$typ_sym.name` is not a struct', selector_expr.pos)
} }
else { 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) exit(0)
} }
// TODO: non deferred // TODO: non deferred
pub fn (c &Checker) return_stmt(return_stmt ast.Return) { 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 { if return_stmt.exprs.len == 0 {
return return
} }
@ -238,9 +252,10 @@ pub fn (c &Checker) return_stmt(return_stmt ast.Return) {
got_types << typ got_types << typ
} }
expected_type := return_stmt.expected_type expected_type := return_stmt.expected_type
expected_type_sym := c.table.get_type_symbol(expected_type)
mut expected_types := [expected_type] mut expected_types := [expected_type]
if expected_type.typ.kind == .multi_return { if expected_type_sym.kind == .multi_return {
mr_info := expected_type.typ.info as table.MultiReturn mr_info := expected_type_sym.info as table.MultiReturn
expected_types = mr_info.types expected_types = mr_info.types
} }
if expected_types.len > 0 && expected_types.len != got_types.len { 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 { for i, exp_typ in expected_types {
got_typ := got_types[i] got_typ := got_types[i]
if !c.table.check(got_typ, exp_typ) { 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) assign_stmt(assign_stmt ast.AssignStmt) {}
pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.TypeRef { pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.Type {
mut elem_type := c.table.type_ref(table.void_type_idx) mut elem_type := table.void_type
for i, expr in array_init.exprs { for i, expr in array_init.exprs {
c.expr(expr) c.expr(expr)
typ := c.expr(expr) typ := c.expr(expr)
@ -267,7 +284,8 @@ pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.TypeRef {
continue continue
} }
if !c.table.check(elem_type, typ) { 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 return array_init.typ
@ -289,13 +307,16 @@ fn (c &Checker) stmt(node ast.Stmt) {
ast.VarDecl { ast.VarDecl {
typ := c.expr(it.expr) typ := c.expr(it.expr)
// println('checker: var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr') // 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 it.typ = typ
} }
} }
ast.ForStmt { ast.ForStmt {
typ := c.expr(it.cond) 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) c.error('non-bool used as for condition', it.pos)
} }
for stmt in it.stmts { 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 { match mut node {
ast.AssignExpr { ast.AssignExpr {
c.check_assign_expr(it) c.check_assign_expr(it)
} }
ast.IntegerLiteral { ast.IntegerLiteral {
return c.table.type_ref(table.int_type_idx) return table.int_type
} }
// ast.FloatLiteral {} // ast.FloatLiteral {}
ast.PostfixExpr { ast.PostfixExpr {
@ -337,7 +358,7 @@ pub fn (c &Checker) expr(node ast.Expr) table.TypeRef {
*/ */
ast.StringLiteral { ast.StringLiteral {
return c.table.type_ref(table.string_type_idx) return table.string_type
} }
ast.PrefixExpr { ast.PrefixExpr {
return c.expr(it.right) return c.expr(it.right)
@ -360,18 +381,18 @@ pub fn (c &Checker) expr(node ast.Expr) table.TypeRef {
ast.Ident { ast.Ident {
if it.kind == .variable { if it.kind == .variable {
mut info := it.info as ast.IdentVar mut info := it.info as ast.IdentVar
if info.typ.typ.kind == .unresolved { if table.type_is_unresolved(info.typ) {
typ := c.resolved[info.typ.idx] typ := c.resolve(info.typ)
info.typ = typ info.typ = typ
it.info = info it.info = info
return typ return typ
} }
return info.typ return info.typ
} }
return c.table.type_ref(table.void_type_idx) return table.void_type
} }
ast.BoolLiteral { ast.BoolLiteral {
return c.table.type_ref(table.bool_type_idx) return table.bool_type
} }
ast.SelectorExpr { ast.SelectorExpr {
return c.selector_expr(it) return c.selector_expr(it)
@ -381,8 +402,10 @@ pub fn (c &Checker) expr(node ast.Expr) table.TypeRef {
} }
ast.IfExpr { ast.IfExpr {
typ := c.expr(it.cond) typ := c.expr(it.cond)
if typ.typ.kind != .bool { typ_sym := c.table.get_type_symbol(typ)
c.error('non-bool (`$typ.typ.name`) used as if condition', it.pos) // 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 { for i, stmt in it.stmts {
c.stmt(stmt) c.stmt(stmt)
@ -395,10 +418,10 @@ pub fn (c &Checker) expr(node ast.Expr) table.TypeRef {
} }
else {} 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 { match node.expr {
ast.IdentVar { ast.IdentVar {
@ -408,13 +431,15 @@ pub fn (c &Checker) postfix_expr(node ast.PostfixExpr) table.TypeRef {
} }
*/ */
typ := c.expr(node.expr) typ := c.expr(node.expr)
if typ.typ.kind != .int { // if typ.typ.kind != .int {
c.error('invalid operation: $node.op.str() (non-numeric type `$typ.typ.name`)', node.pos) 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 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 typ := c.expr(node.left)
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 {
@ -423,20 +448,23 @@ pub fn (c &Checker) index_expr(node ast.IndexExpr) table.TypeRef {
} }
else {} 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` if is_range {} // `x[start..end]` has the same type as `x`
else { else {
// Check index type // Check index type
index_type := c.expr(node.index) index_type := c.expr(node.index)
if index_type.typ.kind != .int { // if index_type.typ.kind != .int {
c.error('non-integer index (type `$index_type.typ.name`)', node.pos) 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 return info.elem_type
} }
} }
else { else {
typ = c.table.type_ref(table.int_type_idx) typ = table.int_type
} }
return typ return typ
// c.expr(it.index) // c.expr(it.index)
@ -452,8 +480,6 @@ pub fn (c &Checker) error(s string, pos token.Position) {
path = path.replace(workdir, '') path = path.replace(workdir, '')
} }
final_msg_line := '$path:$pos.line_nr: checker error: $s' final_msg_line := '$path:$pos.line_nr: checker error: $s'
// sometimes eprintln wasnt working?
println(final_msg_line)
eprintln(final_msg_line) eprintln(final_msg_line)
/* /*
if colored_output { if colored_output {

View File

@ -56,7 +56,8 @@ fn (g mut Gen) stmt(node ast.Stmt) {
ast.Import {} ast.Import {}
ast.ConstDecl { ast.ConstDecl {
for i, field in it.fields { 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.expr(it.exprs[i])
g.writeln(';') g.writeln(';')
} }
@ -68,16 +69,18 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.write('int ${it.name}(') g.write('int ${it.name}(')
} }
else { else {
g.write('$it.typ.typ.name ${it.name}(') type_sym := g.table.get_type_symbol(it.typ)
g.definitions.write('$it.typ.typ.name ${it.name}(') g.write('$type_sym.name ${it.name}(')
g.definitions.write('$type_sym.name ${it.name}(')
} }
for i, arg in it.args { 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 { 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.write(arg_type_name + ' ' + arg.name)
g.definitions.write(arg_type + ' ' + arg.name) g.definitions.write(arg_type_name + ' ' + arg.name)
if i < it.args.len - 1 { if i < it.args.len - 1 {
g.write(', ') g.write(', ')
g.definitions.write(', ') g.definitions.write(', ')
@ -100,7 +103,8 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.write('return') g.write('return')
// multiple returns // multiple returns
if it.exprs.len > 1 { 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 { for i, expr in it.exprs {
g.write('.arg$i=') g.write('.arg$i=')
g.expr(expr) g.expr(expr)
@ -136,7 +140,8 @@ fn (g mut Gen) stmt(node ast.Stmt) {
println('assign') println('assign')
} }
ast.VarDecl { 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.expr(it.expr)
g.writeln(';') g.writeln(';')
} }
@ -165,7 +170,8 @@ fn (g mut Gen) stmt(node ast.Stmt) {
ast.StructDecl { ast.StructDecl {
g.writeln('typedef struct {') g.writeln('typedef struct {')
for field in it.fields { 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;') g.writeln('} $it.name;')
} }
@ -237,7 +243,8 @@ fn (g mut Gen) expr(node ast.Expr) {
} }
// `user := User{name: 'Bob'}` // `user := User{name: 'Bob'}`
ast.StructInit { 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 { for i, field in it.fields {
g.write('\t.$field = ') g.write('\t.$field = ')
g.expr(it.exprs[i]) g.expr(it.exprs[i])
@ -257,7 +264,8 @@ fn (g mut Gen) expr(node ast.Expr) {
} }
ast.MethodCallExpr {} ast.MethodCallExpr {}
ast.ArrayInit { 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 { for expr in it.exprs {
g.expr(expr) g.expr(expr)
g.write(', ') g.write(', ')
@ -287,8 +295,9 @@ fn (g mut Gen) expr(node ast.Expr) {
// If expression? Assign the value to a temp var. // If expression? Assign the value to a temp var.
// Previously ?: was used, but it's too unreliable. // Previously ?: was used, but it's too unreliable.
// ti := g.table.refresh_ti(it.ti) // ti := g.table.refresh_ti(it.ti)
type_sym := g.table.get_type_symbol(it.typ)
mut tmp := '' mut tmp := ''
if it.typ.typ.kind != .void { if type_sym.kind != .void {
tmp = g.table.new_tmp_var() tmp = g.table.new_tmp_var()
// g.writeln('$ti.name $tmp;') // g.writeln('$ti.name $tmp;')
} }
@ -297,7 +306,7 @@ fn (g mut Gen) expr(node ast.Expr) {
g.writeln(') {') g.writeln(') {')
for i, stmt in it.stmts { for i, stmt in it.stmts {
// Assign ret value // 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 =') // g.writeln('$tmp =')
println(1) println(1)
} }
@ -313,11 +322,12 @@ fn (g mut Gen) expr(node ast.Expr) {
} }
} }
ast.MatchExpr { ast.MatchExpr {
type_sym := g.table.get_type_symbol(it.typ)
mut tmp := '' mut tmp := ''
if it.typ.typ.kind != .void { if type_sym.kind != .void {
tmp = g.table.new_tmp_var() tmp = g.table.new_tmp_var()
} }
g.write('$it.typ.typ.name $tmp = ') g.write('$type_sym.name $tmp = ')
g.expr(it.cond) g.expr(it.cond)
g.writeln(';') // $it.blocks.len') g.writeln(';') // $it.blocks.len')
for i, block in it.blocks { for i, block in it.blocks {

View File

@ -37,9 +37,11 @@ pub fn (g mut JsGen) writeln(s string) {
fn (g mut JsGen) stmt(node ast.Stmt) { fn (g mut JsGen) stmt(node ast.Stmt) {
match node { match node {
ast.FnDecl { 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 { 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(') { ') g.writeln(') { ')
for stmt in it.stmts { for stmt in it.stmts {
@ -57,7 +59,8 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
} }
ast.AssignStmt {} ast.AssignStmt {}
ast.VarDecl { 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.expr(it.expr)
g.writeln(';') g.writeln(';')
} }
@ -119,7 +122,8 @@ fn (g mut JsGen) expr(node ast.Expr) {
} }
// `user := User{name: 'Bob'}` // `user := User{name: 'Bob'}`
ast.StructInit { 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 { for i, field in it.fields {
g.write('\t$field : ') g.write('\t$field : ')
g.expr(it.exprs[i]) g.expr(it.exprs[i])

View File

@ -8,7 +8,7 @@ import (
v.table 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 tok := p.tok
fn_name := p.check_name() fn_name := p.check_name()
p.check(.lpar) p.check(.lpar)
@ -64,7 +64,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
// Receiver? // Receiver?
mut rec_name := '' mut rec_name := ''
mut is_method := false 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 { if p.tok.kind == .lpar {
is_method = true is_method = true
p.next() p.next()
@ -168,7 +168,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
} }
p.check(.rpar) p.check(.rpar)
// Return type // 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] { if p.tok.kind in [.name, .lpar, .amp, .lsbr, .question] {
typ = p.parse_type() typ = p.parse_type()
p.return_type = typ p.return_type = typ
@ -178,7 +178,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
p.return_type = typ p.return_type = typ
} }
if is_method { 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 name: name
args: args args: args
return_type: typ return_type: typ

View File

@ -6,7 +6,7 @@ import (
v.table 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) p.check(.lsbr)
// fixed array // fixed array
if p.tok.kind == .number { 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(.rsbr)
p.check_name() p.check_name()
idx := p.table.find_or_register_array_fixed(elem_ti, size, 1) 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 // array
p.check(.rsbr) p.check(.rsbr)
@ -27,28 +27,30 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.TypeRef {
nr_dims++ nr_dims++
} }
idx := p.table.find_or_register_array(elem_ti, 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() p.next()
if p.tok.kind != .lsbr { 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) p.check(.lsbr)
key_type := p.parse_type() 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.error('maps can only have string keys for now')
} }
p.check(.rsbr) p.check(.rsbr)
value_type := p.parse_type() value_type := p.parse_type()
idx := p.table.find_or_register_map(key_type, value_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) p.check(.lpar)
mut mr_types := []table.TypeRef mut mr_types := []table.Type
for { for {
mr_type := p.parse_type() mr_type := p.parse_type()
mr_types << mr_type mr_types << mr_type
@ -61,16 +63,16 @@ pub fn (p mut Parser) parse_multi_return_ti() table.TypeRef {
} }
p.check(.rpar) p.check(.rpar)
idx := p.table.find_or_register_multi_return(mr_types) 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.check(.key_fn)
p.fn_decl() 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 mut nr_muls := 0
for p.tok.kind == .amp { for p.tok.kind == .amp {
p.check(.amp) p.check(.amp)
@ -91,14 +93,14 @@ pub fn (p mut Parser) parse_type() table.TypeRef {
} }
// array // array
.lsbr { .lsbr {
return p.parse_array_ti(nr_muls) return p.parse_array_type(nr_muls)
} }
// multiple return // multiple return
.lpar { .lpar {
if nr_muls > 0 { 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 { else {
// no defer // no defer
@ -110,64 +112,64 @@ pub fn (p mut Parser) parse_type() table.TypeRef {
} }
match name { match name {
'voidptr' { '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' { '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' { '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' { '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' { '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' { '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' { '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' { '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' { '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' { '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' { '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' { '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' { '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' { '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' { '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' { '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 // struct / enum / placeholder
else { else {
// struct / enum // struct / enum
mut idx := p.table.find_type_idx(name) mut idx := p.table.find_type_idx(name)
if idx > 0 { if idx > 0 {
return p.table.type_ref_ptr(idx, nr_muls) return table.new_type_ptr(idx, nr_muls)
} }
// not found - add placeholder // not found - add placeholder
idx = p.table.add_placeholder_type(name) idx = p.table.add_placeholder_type(name)
println('NOT FOUND: $name - adding placeholder - $idx') println('NOT FOUND: $name - adding placeholder - $idx')
return p.table.type_ref_ptr(idx, nr_muls) return table.new_type_ptr(idx, nr_muls)
} }
} }
} }

View File

@ -33,7 +33,7 @@ mut:
peek_tok token.Token peek_tok token.Token
// vars []string // vars []string
table &table.Table table &table.Table
return_type table.TypeRef // current function's return type return_type table.Type // current function's return type
// scope_level int // scope_level int
// var_idx int // var_idx int
is_c bool is_c bool
@ -71,6 +71,7 @@ pub fn parse_file(path string, table &table.Table) ast.File {
table: table table: table
file_name: path file_name: path
pref: &pref.Preferences{} pref: &pref.Preferences{}
unresolved_offset: table.unresolved_idxs.size
} }
p.read_first_token() p.read_first_token()
// module decl // 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 node := ast.Ident{}
mut typ := p.table.type_ref(table.void_type_idx) mut typ := table.void_type
// p.warn('name ') // p.warn('name ')
// left := p.parse_ident() // left := p.parse_ident()
name := p.check_name() name := p.check_name()
mut ident := ast.Ident{ mut ident := ast.Ident{
name: name name: name
is_c: is_c
} }
mut known_var := false mut known_var := false
if var := p.table.find_var(name) { 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 { else {
if is_c { if is_c {
typ = p.table.type_ref(table.int_type_idx) typ = table.int_type
ident.info = ast.IdentVar{ ident.info = ast.IdentVar{
typ: typ typ: typ
// name: ident.name // name: ident.name
@ -444,9 +446,9 @@ pub fn (p mut Parser) parse_ident(is_c bool) (ast.Ident,table.TypeRef) {
return node,typ 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 node := ast.Expr{}
mut typ := p.table.type_ref(table.void_type_idx) mut typ := table.void_type
// mut typ := table.unresolved_type // mut typ := table.unresolved_type
is_c := p.tok.lit == 'C' && p.peek_tok.kind == .dot is_c := p.tok.lit == 'C' && p.peek_tok.kind == .dot
if is_c { if is_c {
@ -521,9 +523,9 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) {
return node,typ 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()') // println('\n\nparser.expr()')
mut typ := p.table.type_ref(table.void_type_idx) mut typ := table.void_type
mut node := ast.Expr{} mut node := ast.Expr{}
// Prefix // Prefix
match p.tok.kind { 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() node,typ = p.string_expr()
} }
.chartoken { .chartoken {
typ = p.table.type_ref(table.byte_type_idx) typ = table.byte_type
node = ast.CharLiteral{ node = ast.CharLiteral{
val: p.tok.lit val: p.tok.lit
} }
@ -551,7 +553,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.TypeRef) {
node = ast.BoolLiteral{ node = ast.BoolLiteral{
val: p.tok.kind == .key_true val: p.tok.kind == .key_true
} }
typ = p.table.type_ref(table.bool_type_idx) typ = table.bool_type
p.next() p.next()
} }
.key_match { .key_match {
@ -579,7 +581,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.TypeRef) {
p.check(.lpar) p.check(.lpar)
p.next() p.next()
p.check(.rpar) p.check(.rpar)
typ = p.table.type_ref(table.int_type_idx) typ = table.int_type
} }
else { else {
p.error('pexpr(): bad token `$p.tok.str()`') 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 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 op := p.tok.kind
p.next() p.next()
right,typ := p.expr(1) right,typ := p.expr(1)
@ -663,7 +665,7 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.Expr {
// return node,typ // 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() p.next()
field_name := p.check_name() field_name := p.check_name()
// Method call // 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{} mut node := ast.Expr{}
node = mcall_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 return node,typ
} }
sel_expr := ast.SelectorExpr{ 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 field: field_name
pos: p.tok.position() 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{} mut node := ast.Expr{}
node = sel_expr node = sel_expr
return node,typ 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 op := p.tok.kind
// mut typ := p. // mut typ := p.
// println('infix op=$op.str()') // println('infix op=$op.str()')
@ -704,7 +708,7 @@ fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,table.TypeRef) {
p.next() p.next()
right,mut typ := p.expr(precedence) right,mut typ := p.expr(precedence)
if op.is_relational() { if op.is_relational() {
typ = p.table.type_ref(table.bool_type_idx) typ = table.bool_type
} }
mut expr := ast.Expr{} mut expr := ast.Expr{}
expr = ast.InfixExpr{ expr = ast.InfixExpr{
@ -763,9 +767,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
} }
p.check(.semicolon) p.check(.semicolon)
if p.tok.kind != .semicolon { if p.tok.kind != .semicolon {
mut typ := table.TypeRef{ mut typ := table.void_type
typ: 0
}
cond,typ = p.expr(0) cond,typ = p.expr(0)
} }
p.check(.semicolon) p.check(.semicolon)
@ -789,7 +791,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
val_name := p.check_name() val_name := p.check_name()
p.table.register_var(table.Var{ p.table.register_var(table.Var{
name: val_name name: val_name
typ: p.table.type_ref(table.int_type_idx) typ: table.int_type
}) })
} }
p.check(.key_in) p.check(.key_in)
@ -801,7 +803,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
} }
p.table.register_var(table.Var{ p.table.register_var(table.Var{
name: var_name name: var_name
typ: p.table.type_ref(table.int_type_idx) typ: table.int_type
}) })
stmts := p.parse_block() stmts := p.parse_block()
// println('nr stmts=$stmts.len') // 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 p.inside_if = true
// defer { // defer {
// } // }
@ -841,13 +843,14 @@ fn (p mut Parser) if_expr() (ast.Expr,table.TypeRef) {
else_stmts = p.parse_block() else_stmts = p.parse_block()
} }
} }
mut typ := p.table.type_ref(table.void_type_idx) mut typ := table.void_type
// mut left := ast.Expr{} // mut left := ast.Expr{}
// If the last statement is an expression, return its type // If the last statement is an expression, return its type
if stmts.len > 0 { if stmts.len > 0 {
match stmts[stmts.len - 1] { match stmts[stmts.len - 1] {
ast.ExprStmt { 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 typ = it.typ
// return node,it.ti // return node,it.ti
// left = // left =
@ -867,14 +870,14 @@ fn (p mut Parser) if_expr() (ast.Expr,table.TypeRef) {
return node,typ 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{} mut node := ast.Expr{}
node = ast.StringLiteral{ node = ast.StringLiteral{
val: p.tok.lit val: p.tok.lit
} }
if p.peek_tok.kind != .str_dollar { if p.peek_tok.kind != .str_dollar {
p.next() p.next()
return node,p.table.type_ref(table.string_type_idx) return node,table.string_type
} }
// Handle $ interpolation // Handle $ interpolation
for p.tok.kind == .str { for p.tok.kind == .str {
@ -888,13 +891,13 @@ fn (p mut Parser) string_expr() (ast.Expr,table.TypeRef) {
p.next() 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{} mut node := ast.Expr{}
p.check(.lsbr) p.check(.lsbr)
mut val_type := p.table.type_ref(table.void_type_idx) mut val_type := table.void_type
mut exprs := []ast.Expr mut exprs := []ast.Expr
for i := 0; p.tok.kind != .rsbr; i++ { for i := 0; p.tok.kind != .rsbr; i++ {
expr,typ := p.expr(0) 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) // array_type := table.new_type(.array, type_name, type_idx, 0)
idx := p.table.find_or_register_array(val_type, 1) 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{ node = ast.ArrayInit{
typ: array_type typ: array_type
exprs: exprs exprs: exprs
@ -926,16 +929,16 @@ fn (p mut Parser) array_init() (ast.Expr,table.TypeRef) {
return node,array_type 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 lit := p.tok.lit
mut node := ast.Expr{} mut node := ast.Expr{}
mut ti := p.table.type_ref(table.int_type_idx) mut ti := table.int_type
if lit.contains('.') { if lit.contains('.') {
node = ast.FloatLiteral{ node = ast.FloatLiteral{
// val: lit.f64() // val: lit.f64()
val: lit val: lit
} }
ti = p.table.type_ref(table.f64_type_idx) ti = table.f64_type
} }
else { else {
node = ast.IntegerLiteral{ node = ast.IntegerLiteral{
@ -1053,7 +1056,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
// println('struct field $ti.name $field_name') // println('struct field $ti.name $field_name')
} }
p.check(.rcbr) p.check(.rcbr)
t := table.Type{ t := table.TypeSymbol{
parent: 0 parent: 0
kind: .struct_ kind: .struct_
name: name 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 { if p.builtin_mod && t.name in table.builtin_type_names {
// this allows overiding the builtins type // this allows overiding the builtins type
// with the real struct type info parsed from builtin // 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 { } else {
ret = p.table.register_type(t) ret = p.table.register_type_symbol(t)
} }
if ret == -1 { if ret == -1 {
p.error('cannot register type `$name`, another type with this name exists') 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 mut exprs := []ast.Expr
// return type idents // return type idents
// mut got_tis := []table.Type // 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{ return ast.Return{
pos: p.tok.position() pos: p.tok.position()
} }
@ -1154,7 +1157,8 @@ fn (p mut Parser) var_decl() ast.VarDecl {
is_mut: is_mut is_mut: is_mut
typ: typ 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) // println(p.table.names)
node := ast.VarDecl{ node := ast.VarDecl{
name: name 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) p.check(.key_match)
cond,typ := p.expr(0) cond,typ := p.expr(0)
p.check(.lcbr) p.check(.lcbr)
@ -1240,10 +1244,10 @@ fn (p mut Parser) match_expr() (ast.Expr,table.TypeRef) {
typ: typ typ: typ
cond: cond 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 mut idx := p.unresolved_offset + p.unresolved.len
if key in p.table.unresolved_idxs { if key in p.table.unresolved_idxs {
idx = p.table.unresolved_idxs[key] 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.table.unresolved_idxs[key] = idx
p.unresolved << expr p.unresolved << expr
} }
t := table.TypeRef{ return table.new_type((-idx)-1)
idx: idx
typ: &table.Type{
parent: 0
kind: .unresolved
name: 'unresolved-$idx'
}
}
return t
} }
fn verror(s string) { fn verror(s string) {

View File

@ -5,9 +5,9 @@ module table
pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn
pub struct Type { pub struct TypeSymbol {
pub: pub:
parent &Type parent &TypeSymbol
mut: mut:
info TypeInfo info TypeInfo
kind Kind kind Kind
@ -15,33 +15,26 @@ mut:
methods []Fn methods []Fn
} }
pub struct TypeRef {
pub:
idx int
typ &Type
nr_muls int
}
pub const ( pub const (
// primitive types // primitive types
void_type_idx = 1 void_type_idx = 1
voidptr_type_idx = 2 voidptr_type_idx = 2
charptr_type_idx = 3 byteptr_type_idx = 3
byteptr_type_idx = 4 charptr_type_idx = 4
i8_type_idx = 5 i8_type_idx = 5
i16_type_idx = 6 i16_type_idx = 6
int_type_idx = 7 int_type_idx = 7
i64_type_idx = 8 i64_type_idx = 8
u16_type_idx = 9 byte_type_idx = 9
u32_type_idx = 10 u16_type_idx = 10
u64_type_idx = 11 u32_type_idx = 11
f32_type_idx = 12 u64_type_idx = 12
f64_type_idx = 13 f32_type_idx = 13
bool_type_idx = 14 f64_type_idx = 14
char_type_idx = 15
bool_type_idx = 16
// advanced / defined from v structs // advanced / defined from v structs
string_type_idx = 15 string_type_idx = 17
char_type_idx = 16
byte_type_idx = 17
array_type_idx = 18 array_type_idx = 18
map_type_idx = 19 map_type_idx = 19
) )
@ -57,23 +50,21 @@ pub enum Kind {
placeholder placeholder
void void
voidptr voidptr
charptr
byteptr byteptr
charptr
i8 i8
i16 i16
int int
i64 i64
byte
u16 u16
u32 u32
u64 u64
f32 f32
f64 f64
string
char char
byte
bool bool
//const_ string
//enum_
struct_ struct_
array array
array_fixed array_fixed
@ -83,198 +74,173 @@ pub enum Kind {
} }
[inline] [inline]
pub fn(t &Type) mr_info() MultiReturn { pub fn(t &TypeSymbol) mr_info() MultiReturn {
match t.info { match t.info {
MultiReturn { MultiReturn {
return it return it
} }
else { else {
panic('Type.mr_info(): no multi return info') panic('TypeSymbol.mr_info(): no multi return info')
} }
} }
} }
[inline] [inline]
pub fn(t &Type) array_info() Array { pub fn(t &TypeSymbol) array_info() Array {
match t.info { match t.info {
Array { Array {
return it return it
} }
else { else {
panic('Type.array_info(): no array info') panic('TypeSymbol.array_info(): no array info')
} }
} }
} }
[inline] [inline]
pub fn(t &Type) array_fixed_info() ArrayFixed { pub fn(t &TypeSymbol) array_fixed_info() ArrayFixed {
match t.info { match t.info {
ArrayFixed { ArrayFixed {
return it return it
} }
else { else {
panic('Type.array_fixed(): no array fixed info') panic('TypeSymbol.array_fixed(): no array fixed info')
} }
} }
} }
[inline] [inline]
pub fn(t &Type) map_info() Map { pub fn(t &TypeSymbol) map_info() Map {
match t.info { match t.info {
Map { Map {
return it return it
} }
else { 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 return t.name
} }
*/ */
pub fn (t &TypeRef) str() string { [inline]
mut muls := '' pub fn array_name(elem_type &TypeSymbol, nr_dims int) string {
for _ in 0 .. t.nr_muls { return 'array_${elem_type.name}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' }
muls += '&'
}
return '$muls$t.typ.name'
} }
[inline] [inline]
pub fn (t &Table) type_ref(idx int) TypeRef { pub fn array_fixed_name(elem_type &TypeSymbol, size int, nr_dims int) string {
return TypeRef{ return 'array_fixed_${elem_type.name}_${size}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' }
idx: idx
typ: &t.types[idx]
}
} }
[inline] [inline]
pub fn (t &Table) type_ref_ptr(idx int, nr_muls int) TypeRef { pub fn map_name(key_type &TypeSymbol, value_type &TypeSymbol) string {
return TypeRef{ return 'map_${key_type.name}_${value_type.name}'
idx: idx
nr_muls: nr_muls
typ: &t.types[idx]
}
} }
[inline] pub fn (t mut Table) register_builtin_type_symbols() {
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() {
// reserve index 0 so nothing can go there // reserve index 0 so nothing can go there
// save index check, 0 will mean not found // save index check, 0 will mean not found
t.register_type(Type{ t.register_type_symbol(TypeSymbol{
parent: 0 parent: 0
kind: .placeholder kind: .placeholder
name: 'reserved_0' name: 'reserved_0'
}) })
t.register_type(Type{ t.register_type_symbol(TypeSymbol{
parent: 0 parent: 0
kind: .void kind: .void
name: 'void' name: 'void'
}) })
t.register_type(Type{ t.register_type_symbol(TypeSymbol{
parent: 0 parent: 0
kind: .voidptr kind: .voidptr
name: 'voidptr' name: 'voidptr'
}) })
t.register_type(Type{ t.register_type_symbol(TypeSymbol{
parent: 0
kind: .charptr
name: 'charptr'
})
t.register_type(Type{
parent: 0 parent: 0
kind: .byteptr kind: .byteptr
name: '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 parent: 0
kind: .i8 kind: .i8
name: 'i8' name: 'i8'
}) })
t.register_type(Type{ t.register_type_symbol(TypeSymbol{
parent: 0 parent: 0
kind: .i16 kind: .i16
name: 'i16' name: 'i16'
}) })
t.register_type(Type{ t.register_type_symbol(TypeSymbol{
parent: 0 parent: 0
kind: .int kind: .int
name: 'int' name: 'int'
}) })
t.register_type(Type{ t.register_type_symbol(TypeSymbol{
parent: 0 parent: 0
kind: .i64 kind: .i64
name: 'i64' name: 'i64'
}) })
t.register_type(Type{ t.register_type_symbol(TypeSymbol{
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{
parent: 0 parent: 0
kind: .byte kind: .byte
name: '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 parent: 0
kind: .array kind: .array
name: 'array' name: 'array'
}) })
t.register_type(Type{ t.register_type_symbol(TypeSymbol{
parent: 0 parent: 0
kind: .map kind: .map
name: 'map' name: 'map'
@ -282,22 +248,17 @@ pub fn (t mut Table) register_builtin_types() {
} }
[inline] [inline]
pub fn (t &TypeRef) is_ptr() bool { pub fn (t &TypeSymbol) is_int() bool {
return t.nr_muls > 0
}
[inline]
pub fn (t &Type) is_int() bool {
return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64] return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64]
} }
[inline] [inline]
pub fn (t &Type) is_float() bool { pub fn (t &TypeSymbol) is_float() bool {
return t.kind in [.f32, .f64] return t.kind in [.f32, .f64]
} }
[inline] [inline]
pub fn (t &Type) is_number() bool { pub fn (t &TypeSymbol) is_number() bool {
return t.is_int() || t.is_float() return t.is_int() || t.is_float()
} }
@ -321,12 +282,6 @@ pub fn (k Kind) str() string {
.byteptr{ .byteptr{
'byteptr' 'byteptr'
} }
// .const_{
// 'const'
// }
// .enum_{
// 'enum'
// }
.struct_{ .struct_{
'struct' 'struct'
} }
@ -398,14 +353,6 @@ pub fn (kinds []Kind) str() string {
return kinds_str return kinds_str
} }
// pub struct Const {
// pub:
// name string
// }
// pub struct Enum {
// pub:
// name string
// }
pub struct Struct { pub struct Struct {
pub mut: pub mut:
fields []Field fields []Field
@ -415,23 +362,14 @@ pub struct Field {
pub: pub:
name string name string
mut: mut:
typ TypeRef typ Type
// type_idx int
} }
// pub struct Int {
// pub:
// bit_size u32
// is_unsigned bool
// }
// pub struct Float {
// pub:
// bit_size u32
// }
pub struct Array { pub struct Array {
pub: pub:
nr_dims int nr_dims int
mut: mut:
elem_type TypeRef elem_type Type
} }
pub struct ArrayFixed { pub struct ArrayFixed {
@ -439,26 +377,18 @@ pub:
nr_dims int nr_dims int
size int size int
mut: mut:
elem_type TypeRef elem_type Type
} }
pub struct Map { pub struct Map {
pub mut: pub mut:
key_type TypeRef key_type Type
value_type TypeRef value_type Type
} }
pub struct MultiReturn { pub struct MultiReturn {
pub: pub:
name string name string
mut: mut:
types []TypeRef types []Type
}
[inline]
pub fn (t &Table) get_type(idx int) &Type {
if idx == 0 {
panic('get_type: idx 0')
}
return &t.types[idx]
} }

View File

@ -8,7 +8,7 @@ module table
pub struct Table { pub struct Table {
// struct_fields map[string][]string // struct_fields map[string][]string
pub mut: pub mut:
types []Type types []TypeSymbol
// type_idxs Hashmap // type_idxs Hashmap
type_idxs map[string]int type_idxs map[string]int
unresolved_idxs map[string]int unresolved_idxs map[string]int
@ -26,7 +26,7 @@ pub struct Fn {
pub: pub:
name string name string
args []Var args []Var
return_type TypeRef return_type Type
is_variadic bool is_variadic bool
is_c bool is_c bool
} }
@ -40,14 +40,14 @@ pub:
is_global bool is_global bool
scope_level int scope_level int
mut: mut:
typ TypeRef typ Type
} }
pub fn new_table() &Table { pub fn new_table() &Table {
mut t := &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 return t
} }
@ -82,7 +82,7 @@ pub fn (t mut Table) register_const(v Var) {
t.consts[v.name] = v 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{ t.consts[name] = Var{
name: name name: name
typ: typ 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) { 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 := { new_var := {
v | v |
idx:t.var_idx, 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 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 idx=$typ.idx')
println('register method `$new_fn.name` type=$typ.name') println('register method `$new_fn.name` type=$typ.name')
mut t1 := typ mut t1 := typ
@ -207,14 +208,14 @@ pub fn (t mut Table) new_tmp_var() string {
return 'tmp$t.tmp_cnt' 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 { t.find_method(name) or {
return false return false
} }
return true 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 { for method in t.methods {
if method.name == name { if method.name == name {
return method 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 { s.find_field(name) or {
return false return false
} }
return true return true
} }
pub fn (s &Type) find_field(name string) ?Field { pub fn (s &TypeSymbol) find_field(name string) ?Field {
match s.info { match s.info {
Struct { Struct {
for field in it.fields { for field in it.fields {
@ -245,7 +246,7 @@ pub fn (s &Type) find_field(name string) ?Field {
return none 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) { if !isnil(s.parent) {
println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name') 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 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) { if !isnil(s.parent) {
println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name') 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] [inline]
pub fn (t &Table) find_type(name string) ?Type { pub fn (t &Table) find_type(name string) ?TypeSymbol {
idx := t.type_idxs[name] idx := t.type_idxs[name]
if idx > 0 { if idx > 0 {
return t.types[idx] return t.types[idx]
@ -291,11 +292,28 @@ pub fn (t &Table) find_type(name string) ?Type {
return none 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 // this will override or register builtin type
// allows prexisitng types added in register_builtins // allows prexisitng types added in register_builtins
// to be overriden with their real type info // to be overriden with their real type info
[inline] [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] existing_idx := t.type_idxs[typ.name]
if existing_idx > 0 { if existing_idx > 0 {
if existing_idx >= string_type_idx { 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 existing_idx
} }
return t.register_type(typ) return t.register_type_symbol(typ)
} }
[inline] [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] existing_idx := t.type_idxs[typ.name]
if existing_idx > 0 { if existing_idx > 0 {
ex_type := t.types[existing_idx] ex_type := t.types[existing_idx]
@ -344,15 +362,17 @@ pub fn (t &Table) known_type(name string) bool {
return true return true
} }
pub fn (t mut Table) find_or_register_map(key_type TypeRef, value_type TypeRef) int { pub fn (t mut Table) find_or_register_map(key_type, value_type Type) int {
name := map_name(&key_type, &value_type) 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
existing_idx := t.type_idxs[name] existing_idx := t.type_idxs[name]
if existing_idx > 0 { if existing_idx > 0 {
return existing_idx return existing_idx
} }
// register // register
map_type := Type{ map_typ := TypeSymbol{
parent: &t.types[map_type_idx] parent: &t.types[map_type_idx]
kind: .map kind: .map
name: name 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 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 { pub fn (t mut Table) find_or_register_array(elem_type Type, nr_dims int) int {
name := array_name(&elem_type, nr_dims) elem_type_sym := t.get_type_symbol(elem_type)
name := array_name(elem_type_sym, nr_dims)
// existing // existing
existing_idx := t.type_idxs[name] existing_idx := t.type_idxs[name]
if existing_idx > 0 { if existing_idx > 0 {
return existing_idx return existing_idx
} }
// register // register
array_type := Type{ array_type := TypeSymbol{
parent: &t.types[array_type_idx] parent: &t.types[array_type_idx]
kind: .array kind: .array
name: name 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 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 { pub fn (t mut Table) find_or_register_array_fixed(elem_type Type, size int, nr_dims int) int {
name := array_fixed_name(&elem_type, size, nr_dims) elem_type_sym := t.get_type_symbol(elem_type)
name := array_fixed_name(elem_type_sym, size, nr_dims)
// existing // existing
existing_idx := t.type_idxs[name] existing_idx := t.type_idxs[name]
if existing_idx > 0 { if existing_idx > 0 {
return existing_idx return existing_idx
} }
// register // register
array_fixed_type := Type{ array_fixed_type := TypeSymbol{
parent: 0 parent: 0
kind: .array_fixed kind: .array_fixed
name: name 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 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' mut name := 'multi_return'
for mr_typ in mr_typs { 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
existing_idx := t.type_idxs[name] 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 return existing_idx
} }
// register // register
mr_type := Type{ mr_type := TypeSymbol{
parent: 0 parent: 0
kind: .multi_return kind: .multi_return
name: name name: name
@ -424,34 +447,39 @@ pub fn (t mut Table) find_or_register_multi_return(mr_typs []TypeRef) int {
types: mr_typs 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 { pub fn (t mut Table) add_placeholder_type(name string) int {
ph_type := Type{ ph_type := TypeSymbol{
parent: 0 parent: 0
kind: .placeholder kind: .placeholder
name: name name: name
} }
// println('added placeholder: $name - $ph_type.idx') // 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 { pub fn (t &Table) check(got, expected Type) bool {
println('check: $got.typ.name, $expected.typ.name') got_type_sym := t.get_type_symbol(got)
if expected.typ.kind == .voidptr { 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 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 return true
} }
if expected.typ.kind == .byteptr && got.typ.kind == .voidptr { if got_type_sym.is_int() && exp_type_sym.is_int() {
return true return true
} }
// if expected.name == 'array' { // if expected.name == 'array' {
// return true // 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 false
} }
return true return true
@ -459,7 +487,7 @@ pub fn (t &Table) check(got, expected &TypeRef) bool {
/* /*
[inline] [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 { match expr {
ast.ArrayInit { ast.ArrayInit {
return it.typ return it.typ

View File

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