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.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()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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