v2: type sys - store type idx/ptr in int & add helpers
parent
9845fd1cf5
commit
e274c5c485
|
@ -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()
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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:')
|
||||
if /*TODO:*/!f.is_c {
|
||||
for i, arg_expr in call_expr.args {
|
||||
typ := c.expr(arg_expr)
|
||||
println(' -- $i - $typ.typ.name')
|
||||
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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
)
|
Loading…
Reference in New Issue