v2: use pointer to table.type, fix unresolved array/map sub-types
parent
6c3613407d
commit
d9e92a08cb
|
@ -20,7 +20,7 @@ HashStmt
|
|||
pub struct ExprStmt {
|
||||
pub:
|
||||
expr Expr
|
||||
ti table.Type
|
||||
typ table.TypeRef
|
||||
}
|
||||
|
||||
pub struct IntegerLiteral {
|
||||
|
@ -69,7 +69,7 @@ pub struct Field {
|
|||
pub:
|
||||
name string
|
||||
// type_idx int
|
||||
typ table.Type
|
||||
typ table.TypeRef
|
||||
}
|
||||
|
||||
pub struct ConstDecl {
|
||||
|
@ -89,7 +89,7 @@ pub:
|
|||
pub struct StructInit {
|
||||
pub:
|
||||
pos token.Position
|
||||
ti table.Type
|
||||
typ table.TypeRef
|
||||
fields []string
|
||||
exprs []Expr
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ pub:
|
|||
|
||||
pub struct Arg {
|
||||
pub:
|
||||
ti table.Type
|
||||
typ table.TypeRef
|
||||
name string
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ pub struct FnDecl {
|
|||
pub:
|
||||
name string
|
||||
stmts []Stmt
|
||||
ti table.Type
|
||||
typ table.TypeRef
|
||||
args []Arg
|
||||
is_pub bool
|
||||
receiver Field
|
||||
|
@ -145,9 +145,9 @@ pub:
|
|||
|
||||
pub struct Return {
|
||||
pub:
|
||||
pos token.Position
|
||||
expected_ti table.Type // TODO: remove once checker updated
|
||||
exprs []Expr
|
||||
pos token.Position
|
||||
expected_type table.TypeRef // TODO: remove once checker updated
|
||||
exprs []Expr
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -172,7 +172,7 @@ pub:
|
|||
expr Expr
|
||||
is_mut bool
|
||||
mut:
|
||||
typ table.Type
|
||||
typ table.TypeRef
|
||||
pos token.Position
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ pub:
|
|||
name string
|
||||
expr Expr
|
||||
mut:
|
||||
typ table.Type
|
||||
typ table.TypeRef
|
||||
}
|
||||
|
||||
pub struct File {
|
||||
|
@ -194,9 +194,9 @@ pub:
|
|||
}
|
||||
|
||||
pub struct IdentVar {
|
||||
pub:
|
||||
typ table.Type
|
||||
// name string
|
||||
pub mut:
|
||||
typ table.TypeRef
|
||||
//name string
|
||||
}
|
||||
|
||||
type IdentInfo = IdentVar
|
||||
|
@ -225,9 +225,9 @@ pub:
|
|||
op token.Kind
|
||||
pos token.Position
|
||||
left Expr
|
||||
left_type table.Type
|
||||
left_type table.TypeRef
|
||||
right Expr
|
||||
right_type table.Type
|
||||
right_type table.TypeRef
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -241,7 +241,6 @@ pub:
|
|||
}
|
||||
*/
|
||||
|
||||
|
||||
pub struct PostfixExpr {
|
||||
pub:
|
||||
op token.Kind
|
||||
|
@ -270,7 +269,7 @@ pub:
|
|||
cond Expr
|
||||
stmts []Stmt
|
||||
else_stmts []Stmt
|
||||
ti table.Type
|
||||
typ table.TypeRef
|
||||
left Expr // `a` in `a := if ...`
|
||||
pos token.Position
|
||||
}
|
||||
|
@ -354,7 +353,8 @@ pub struct ArrayInit {
|
|||
pub:
|
||||
pos token.Position
|
||||
exprs []Expr
|
||||
ti table.Type
|
||||
mut:
|
||||
typ table.TypeRef
|
||||
}
|
||||
|
||||
// s[10..20]
|
||||
|
|
|
@ -14,7 +14,7 @@ pub struct Checker {
|
|||
mut:
|
||||
file_name string
|
||||
unresolved []ast.Expr
|
||||
resolved []table.Type
|
||||
resolved []table.TypeRef
|
||||
}
|
||||
|
||||
pub fn new_checker(table &table.Table) Checker {
|
||||
|
@ -39,59 +39,88 @@ pub fn (c mut Checker) check_files(ast_files []ast.File) {
|
|||
}
|
||||
|
||||
fn (c mut Checker) resolve_types() {
|
||||
// resolve type of unresolved expressions
|
||||
for x in c.unresolved {
|
||||
c.resolved << c.expr(x)
|
||||
}
|
||||
// update any types with unresolved sub types
|
||||
for idx, t in c.table.types {
|
||||
if t.kind == .array {
|
||||
mut info := t.info as table.Array
|
||||
if info.elem_type.typ.kind == .unresolved {
|
||||
info.elem_type = c.resolved[info.elem_type.idx]
|
||||
mut t1 := &c.table.types[idx]
|
||||
t1.name = table.array_name(&info.elem_type, info.nr_dims)
|
||||
t1.info = info
|
||||
}
|
||||
}
|
||||
else if t.kind == .map {
|
||||
mut info := t.info as table.Map
|
||||
mut updated := false
|
||||
if info.key_type.typ.kind == .unresolved {
|
||||
info.key_type = c.resolved[info.key_type.idx]
|
||||
updated = true
|
||||
}
|
||||
if info.value_type.typ.kind == .unresolved {
|
||||
info.value_type = c.resolved[info.value_type.idx]
|
||||
updated = true
|
||||
}
|
||||
if updated {
|
||||
mut t1 := &c.table.types[idx]
|
||||
t1.name = table.map_name(&info.key_type, &info.value_type)
|
||||
t1.info = info
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.Type {
|
||||
typ := c.table.find_type(struct_init.ti.name) or {
|
||||
c.error('unknown struct: $struct_init.ti.name', struct_init.pos)
|
||||
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('')
|
||||
}
|
||||
match typ.kind {
|
||||
.placeholder {
|
||||
c.error('unknown struct: $struct_init.ti.name', struct_init.pos)
|
||||
c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos)
|
||||
}
|
||||
.struct_ {
|
||||
info := typ.info as table.Struct
|
||||
for i, expr in struct_init.exprs {
|
||||
field := info.fields[i]
|
||||
// expr_ti := c.expr(expr)
|
||||
field_type := c.expr(expr)
|
||||
if !c.table.check(field_type, field.ti) {
|
||||
c.error('cannot assign $field_type.name as $field.ti.name for field $field.name', struct_init.pos)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
return struct_init.ti
|
||||
return struct_init.typ
|
||||
}
|
||||
|
||||
pub fn (c &Checker) infix_expr(infix_expr ast.InfixExpr) table.Type {
|
||||
left_ti := c.expr(infix_expr.left)
|
||||
right_ti := c.expr(infix_expr.right)
|
||||
if !c.table.check(&right_ti, &left_ti) {
|
||||
pub fn (c &Checker) infix_expr(infix_expr ast.InfixExpr) table.TypeRef {
|
||||
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(&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_ti.name` as `$right_ti.name`', infix_expr.pos)
|
||||
c.error('infix expr: cannot use `$left_type.typ.name` as `$right_type.typ.name`', infix_expr.pos)
|
||||
}
|
||||
if infix_expr.op.is_relational() {
|
||||
return table.bool_type
|
||||
return c.table.type_ref(table.bool_type_idx)
|
||||
}
|
||||
return left_ti
|
||||
return left_type
|
||||
}
|
||||
|
||||
fn (c &Checker) check_assign_expr(assign_expr ast.AssignExpr) {
|
||||
left_ti := c.expr(assign_expr.left)
|
||||
right_ti := c.expr(assign_expr.val)
|
||||
if !c.table.check(right_ti, left_ti) {
|
||||
c.error('cannot assign $right_ti.name to $left_ti.name', assign_expr.pos)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.Type {
|
||||
pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.TypeRef {
|
||||
fn_name := call_expr.name
|
||||
if f := c.table.find_fn(fn_name) {
|
||||
// return_ti := f.return_ti
|
||||
|
@ -103,9 +132,9 @@ pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.Type {
|
|||
}
|
||||
for i, arg in f.args {
|
||||
arg_expr := call_expr.args[i]
|
||||
ti := c.expr(arg_expr)
|
||||
if !c.table.check(&ti, &arg.typ) {
|
||||
c.error('!cannot use type `$ti.name` as type `$arg.typ.name` in argument to `$fn_name`', call_expr.pos)
|
||||
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)
|
||||
}
|
||||
}
|
||||
return f.return_type
|
||||
|
@ -114,83 +143,75 @@ pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.Type {
|
|||
exit(1)
|
||||
}
|
||||
|
||||
pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type {
|
||||
ti := c.expr(method_call_expr.expr)
|
||||
if method := c.table.find_method(ti.idx, method_call_expr.name) {
|
||||
pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.TypeRef {
|
||||
typ := c.expr(method_call_expr.expr)
|
||||
if method := typ.typ.find_method(method_call_expr.name) {
|
||||
return method.return_type
|
||||
}
|
||||
c.error('type `$ti.name` has no method `$method_call_expr.name`', method_call_expr.pos)
|
||||
c.error('type `$typ.typ.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.Type {
|
||||
ti := c.expr(selector_expr.expr)
|
||||
pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.TypeRef {
|
||||
typ := c.expr(selector_expr.expr)
|
||||
field_name := selector_expr.field
|
||||
// struct_ := c.table.types[ti.idx]
|
||||
// struct_info := struct_.info as table.Struct
|
||||
typ := c.table.types[ti.idx]
|
||||
match typ.kind {
|
||||
match typ.typ.kind {
|
||||
.struct_ {
|
||||
// if !c.table.struct_has_field(it, field) {
|
||||
// c.error('AAA unknown field `${it.name}.$field`')
|
||||
// }
|
||||
// TODO: fix bug
|
||||
field := c.table.struct_find_field(typ, field_name) or {
|
||||
c.error('unknown field `${typ.name}.$field_name`', selector_expr.pos)
|
||||
field := c.table.struct_find_field(typ.typ, field_name) or {
|
||||
c.error('unknown field `${typ.typ.name}.$field_name`', selector_expr.pos)
|
||||
exit(0)
|
||||
}
|
||||
return field.ti
|
||||
return field.typ
|
||||
}
|
||||
else {
|
||||
c.error('`$typ.name` is not a struct', selector_expr.pos)
|
||||
c.error('`$typ.typ.name` is not a struct', selector_expr.pos)
|
||||
}
|
||||
}
|
||||
return table.void_type
|
||||
return c.table.type_ref(table.void_type_idx)
|
||||
}
|
||||
|
||||
// TODO: non deferred
|
||||
pub fn (c &Checker) return_stmt(return_stmt ast.Return) {
|
||||
mut got_tis := []table.Type
|
||||
mut got_types := []table.TypeRef
|
||||
if return_stmt.exprs.len == 0 {
|
||||
return
|
||||
}
|
||||
for expr in return_stmt.exprs {
|
||||
ti := c.expr(expr)
|
||||
got_tis << ti
|
||||
typ := c.expr(expr)
|
||||
got_types << typ
|
||||
}
|
||||
expected_ti := return_stmt.expected_ti
|
||||
mut expected_tis := [expected_ti]
|
||||
if expected_ti.kind == .multi_return {
|
||||
mr_type := c.table.types[expected_ti.idx]
|
||||
mr_info := mr_type.info as table.MultiReturn
|
||||
expected_tis = mr_info.tis
|
||||
expected_type := return_stmt.expected_type
|
||||
mut expected_types := [expected_type]
|
||||
if expected_type.typ.kind == .multi_return {
|
||||
mr_info := expected_type.typ.info as table.MultiReturn
|
||||
expected_types = mr_info.types
|
||||
}
|
||||
if expected_tis.len > 0 && expected_tis.len != got_tis.len {
|
||||
c.error('wrong number of return arguments:\n\texpected: $expected_tis.str()\n\tgot: $got_tis.str()', return_stmt.pos)
|
||||
if expected_types.len > 0 && expected_types.len != got_types.len {
|
||||
c.error('wrong number of return arguments:\n\texpected: $expected_types.str()\n\tgot: $got_types.str()', return_stmt.pos)
|
||||
}
|
||||
for i, exp_ti in expected_tis {
|
||||
got_ti := got_tis[i]
|
||||
if !c.table.check(got_ti, exp_ti) {
|
||||
c.error('cannot use `$got_ti.name` as type `$exp_ti.name` in return argument', return_stmt.pos)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.Type {
|
||||
mut val_ti := table.void_type
|
||||
pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.TypeRef {
|
||||
mut elem_type := c.table.type_ref(table.void_type_idx)
|
||||
for i, expr in array_init.exprs {
|
||||
c.expr(expr)
|
||||
ti := c.expr(expr)
|
||||
typ := c.expr(expr)
|
||||
// The first element's type
|
||||
if i == 0 {
|
||||
val_ti = ti
|
||||
elem_type = typ
|
||||
continue
|
||||
}
|
||||
if !c.table.check(val_ti, ti) {
|
||||
c.error('expected array element with type `$val_ti.name`', array_init.pos)
|
||||
if !c.table.check(elem_type, typ) {
|
||||
c.error('expected array element with type `$elem_type.typ.name`', array_init.pos)
|
||||
}
|
||||
}
|
||||
return array_init.ti
|
||||
return array_init.typ
|
||||
}
|
||||
|
||||
fn (c &Checker) stmt(node ast.Stmt) {
|
||||
|
@ -205,19 +226,14 @@ fn (c &Checker) stmt(node ast.Stmt) {
|
|||
}
|
||||
ast.VarDecl {
|
||||
typ := c.expr(it.expr)
|
||||
// it.typ = typ
|
||||
// println('checker: var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr')
|
||||
if typ.kind != .void {
|
||||
if typ.typ.kind != .void {
|
||||
it.typ = typ
|
||||
}
|
||||
// if it.typ.kind == .unresolved {
|
||||
// it.ti = typ
|
||||
// println('unresolved var')
|
||||
// }
|
||||
}
|
||||
ast.ForStmt {
|
||||
typ := c.expr(it.cond)
|
||||
if typ.kind != .bool {
|
||||
if typ.typ.kind != .bool {
|
||||
c.error('non-bool used as for condition', it.pos)
|
||||
}
|
||||
for stmt in it.stmts {
|
||||
|
@ -240,13 +256,13 @@ fn (c &Checker) stmt(node ast.Stmt) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
||||
match node {
|
||||
pub fn (c &Checker) expr(node ast.Expr) table.TypeRef {
|
||||
match mut node {
|
||||
ast.AssignExpr {
|
||||
c.check_assign_expr(it)
|
||||
}
|
||||
ast.IntegerLiteral {
|
||||
return table.int_type
|
||||
return c.table.type_ref(table.int_type_idx)
|
||||
}
|
||||
// ast.FloatLiteral {}
|
||||
ast.PostfixExpr {
|
||||
|
@ -259,7 +275,7 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
|||
*/
|
||||
|
||||
ast.StringLiteral {
|
||||
return table.string_type
|
||||
return c.table.type_ref(table.string_type_idx)
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
return c.expr(it.right)
|
||||
|
@ -281,16 +297,19 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
|||
}
|
||||
ast.Ident {
|
||||
if it.kind == .variable {
|
||||
info := it.info as ast.IdentVar
|
||||
if info.typ.kind == .unresolved {
|
||||
return c.resolved[info.typ.idx]
|
||||
mut info := it.info as ast.IdentVar
|
||||
if info.typ.typ.kind == .unresolved {
|
||||
typ := c.resolved[info.typ.idx]
|
||||
info.typ = typ
|
||||
it.info = info
|
||||
return typ
|
||||
}
|
||||
return info.typ
|
||||
}
|
||||
return table.void_type
|
||||
return c.table.type_ref(table.void_type_idx)
|
||||
}
|
||||
ast.BoolLiteral {
|
||||
return table.bool_type
|
||||
return c.table.type_ref(table.bool_type_idx)
|
||||
}
|
||||
ast.SelectorExpr {
|
||||
return c.selector_expr(it)
|
||||
|
@ -300,8 +319,8 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
|||
}
|
||||
ast.IfExpr {
|
||||
typ := c.expr(it.cond)
|
||||
if typ.kind != .bool {
|
||||
c.error('non-bool (`$typ.name`) used as if condition', it.pos)
|
||||
if typ.typ.kind != .bool {
|
||||
c.error('non-bool (`$typ.typ.name`) used as if condition', it.pos)
|
||||
}
|
||||
for i, stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
|
@ -314,10 +333,10 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
|||
}
|
||||
else {}
|
||||
}
|
||||
return table.void_type
|
||||
return c.table.type_ref(table.void_type_idx)
|
||||
}
|
||||
|
||||
pub fn (c &Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
||||
pub fn (c &Checker) postfix_expr(node ast.PostfixExpr) table.TypeRef {
|
||||
/*
|
||||
match node.expr {
|
||||
ast.IdentVar {
|
||||
|
@ -327,13 +346,13 @@ pub fn (c &Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
|||
}
|
||||
*/
|
||||
typ := c.expr(node.expr)
|
||||
if typ.kind != .int {
|
||||
c.error('invalid operation: $node.op.str() (non-numeric type `$typ.name`)', node.pos)
|
||||
if typ.typ.kind != .int {
|
||||
c.error('invalid operation: $node.op.str() (non-numeric type `$typ.typ.name`)', node.pos)
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
pub fn (c &Checker) index_expr(node ast.IndexExpr) table.Type {
|
||||
pub fn (c &Checker) index_expr(node ast.IndexExpr) table.TypeRef {
|
||||
mut typ := c.expr(node.left)
|
||||
mut is_range := false // TODO is_range := node.index is ast.RangeExpr
|
||||
match node.index {
|
||||
|
@ -342,28 +361,20 @@ pub fn (c &Checker) index_expr(node ast.IndexExpr) table.Type {
|
|||
}
|
||||
else {}
|
||||
}
|
||||
// TODO
|
||||
// info := ti.info as table.Array
|
||||
// ti = p.table.types[info.elem_type_idx]
|
||||
if typ.name.starts_with('array_') {
|
||||
if typ.typ.kind == .array {
|
||||
if is_range {} // `x[start..end]` has the same type as `x`
|
||||
else {
|
||||
elm_typ := typ.name[6..]
|
||||
// TODO `typ = ... or ...`
|
||||
x := c.table.find_type(elm_typ) or {
|
||||
c.error(elm_typ, node.pos)
|
||||
exit(0)
|
||||
}
|
||||
typ = x
|
||||
// Check index type
|
||||
index_type := c.expr(node.index)
|
||||
if index_type.kind != .int {
|
||||
c.error('non-integer index (type `$index_type.name`)', node.pos)
|
||||
if index_type.typ.kind != .int {
|
||||
c.error('non-integer index (type `$index_type.typ.name`)', node.pos)
|
||||
}
|
||||
info := typ.typ.info as table.Array
|
||||
return info.elem_type
|
||||
}
|
||||
}
|
||||
else {
|
||||
typ = table.int_type
|
||||
typ = c.table.type_ref(table.int_type_idx)
|
||||
}
|
||||
return typ
|
||||
// c.expr(it.index)
|
||||
|
|
|
@ -49,7 +49,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
ast.Import {}
|
||||
ast.ConstDecl {
|
||||
for i, field in it.fields {
|
||||
g.write('$field.typ.name $field.name = ')
|
||||
g.write('$field.typ.typ.name $field.name = ')
|
||||
g.expr(it.exprs[i])
|
||||
g.writeln(';')
|
||||
}
|
||||
|
@ -61,15 +61,12 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
g.write('int ${it.name}(')
|
||||
}
|
||||
else {
|
||||
ti := g.table.refresh_ti(it.ti)
|
||||
g.write('$ti.name ${it.name}(')
|
||||
g.definitions.write('$ti.name ${it.name}(')
|
||||
g.write('$it.typ.typ.name ${it.name}(')
|
||||
g.definitions.write('$it.typ.typ.name ${it.name}(')
|
||||
}
|
||||
for i, arg in it.args {
|
||||
// t := g.table.get_type(arg.ti.idx)
|
||||
ti := g.table.refresh_ti(arg.ti)
|
||||
g.write(ti.name + ' ' + arg.name)
|
||||
g.definitions.write(ti.name + ' ' + arg.name)
|
||||
g.write(arg.typ.typ.name + ' ' + arg.name)
|
||||
g.definitions.write(arg.typ.typ.name + ' ' + arg.name)
|
||||
if i < it.args.len - 1 {
|
||||
g.write(', ')
|
||||
g.definitions.write(', ')
|
||||
|
@ -92,9 +89,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
g.write('return')
|
||||
// multiple returns
|
||||
if it.exprs.len > 1 {
|
||||
// ttln( := g.table.get_type(g.fn_decl.ti.idx)
|
||||
ti := g.table.refresh_ti(g.fn_decl.ti)
|
||||
g.write(' ($ti.name){')
|
||||
g.write(' ($g.fn_decl.typ.typ.name){')
|
||||
for i, expr in it.exprs {
|
||||
g.write('.arg$i=')
|
||||
g.expr(expr)
|
||||
|
@ -112,7 +107,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
g.writeln(';')
|
||||
}
|
||||
ast.VarDecl {
|
||||
g.write('$it.typ.name $it.name = ')
|
||||
g.write('$it.typ.typ.name $it.name = ')
|
||||
g.expr(it.expr)
|
||||
g.writeln(';')
|
||||
}
|
||||
|
@ -141,9 +136,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
ast.StructDecl {
|
||||
g.writeln('typedef struct {')
|
||||
for field in it.fields {
|
||||
// t := g.table.get_type(field.ti.idx)
|
||||
ti := g.table.refresh_ti(field.typ)
|
||||
g.writeln('\t$ti.name $field.name;')
|
||||
g.writeln('\t$field.typ.typ.name $field.name;')
|
||||
}
|
||||
g.writeln('} $it.name;')
|
||||
}
|
||||
|
@ -215,9 +208,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
|||
}
|
||||
// `user := User{name: 'Bob'}`
|
||||
ast.StructInit {
|
||||
// t := g.table.get_type(it.ti.idx)
|
||||
ti := g.table.refresh_ti(it.ti)
|
||||
g.writeln('($ti.name){')
|
||||
g.writeln('($it.typ.typ.name){')
|
||||
for i, field in it.fields {
|
||||
g.write('\t.$field = ')
|
||||
g.expr(it.exprs[i])
|
||||
|
@ -237,9 +228,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
|||
}
|
||||
ast.MethodCallExpr {}
|
||||
ast.ArrayInit {
|
||||
// t := g.table.get_type(it.ti.idx)
|
||||
ti := g.table.refresh_ti(it.ti)
|
||||
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($ti.name), {\t')
|
||||
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.typ.typ.name), {\t')
|
||||
for expr in it.exprs {
|
||||
g.expr(expr)
|
||||
g.write(', ')
|
||||
|
@ -268,9 +257,9 @@ fn (g mut Gen) expr(node ast.Expr) {
|
|||
ast.IfExpr {
|
||||
// If expression? Assign the value to a temp var.
|
||||
// Previously ?: was used, but it's too unreliable.
|
||||
ti := g.table.refresh_ti(it.ti)
|
||||
// ti := g.table.refresh_ti(it.ti)
|
||||
mut tmp := ''
|
||||
if ti.kind != .void {
|
||||
if it.typ.typ.kind != .void {
|
||||
tmp = g.table.new_tmp_var()
|
||||
// g.writeln('$ti.name $tmp;')
|
||||
}
|
||||
|
@ -279,7 +268,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 && ti.kind != .void {
|
||||
if i == it.stmts.len - 1 && it.typ.typ.kind != .void {
|
||||
// g.writeln('$tmp =')
|
||||
println(1)
|
||||
}
|
||||
|
|
|
@ -11,9 +11,6 @@ const (
|
|||
)
|
||||
|
||||
fn test_c_files() {
|
||||
$if windows {
|
||||
return
|
||||
}
|
||||
println('Running V => C tests')
|
||||
vexe := os.getenv('VEXE')
|
||||
vroot := filepath.dir(vexe)
|
||||
|
@ -21,9 +18,14 @@ fn test_c_files() {
|
|||
term_fail := term.fail_message('FAIL')
|
||||
for i in 1 .. nr_tests + 1 {
|
||||
path := '$vroot/vlib/v/gen/tests/${i}.vv'
|
||||
ctext := os.read_file('$vroot/vlib/v/gen/tests/${i}.c') or {
|
||||
mut ctext := os.read_file('$vroot/vlib/v/gen/tests/${i}.c') or {
|
||||
panic(err)
|
||||
}
|
||||
ctext = ctext // unused warn
|
||||
// normalise line endings on win
|
||||
$if windows {
|
||||
ctext = ctext.replace('\r', '')
|
||||
}
|
||||
mut b := builder.new_builder(pref.Preferences{})
|
||||
res := b.gen_c([path])
|
||||
if compare_texts(res, ctext) {
|
||||
|
|
|
@ -37,11 +37,9 @@ pub fn (g mut JsGen) writeln(s string) {
|
|||
fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||
match node {
|
||||
ast.FnDecl {
|
||||
ti := g.table.refresh_ti(it.ti)
|
||||
g.write('/** @return { $ti.name } **/\nfunction ${it.name}(')
|
||||
g.write('/** @return { $it.typ.typ.name } **/\nfunction ${it.name}(')
|
||||
for arg in it.args {
|
||||
arg_ti := g.table.refresh_ti(arg.ti)
|
||||
g.write(' /** @type { $arg_ti.name } **/ $arg.name')
|
||||
g.write(' /** @type { $arg.typ.typ.name } **/ $arg.name')
|
||||
}
|
||||
g.writeln(') { ')
|
||||
for stmt in it.stmts {
|
||||
|
@ -58,8 +56,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
|||
g.writeln(';')
|
||||
}
|
||||
ast.VarDecl {
|
||||
typ := g.table.refresh_ti(it.typ)
|
||||
g.write('var /* $typ.name */ $it.name = ')
|
||||
g.write('var /* $it.typ.typ.name */ $it.name = ')
|
||||
g.expr(it.expr)
|
||||
g.writeln(';')
|
||||
}
|
||||
|
@ -121,8 +118,7 @@ fn (g mut JsGen) expr(node ast.Expr) {
|
|||
}
|
||||
// `user := User{name: 'Bob'}`
|
||||
ast.StructInit {
|
||||
ti := g.table.refresh_ti(it.ti)
|
||||
g.writeln('/*$ti.name*/{')
|
||||
g.writeln('/*$it.typ.typ.name*/{')
|
||||
for i, field in it.fields {
|
||||
g.write('\t$field : ')
|
||||
g.expr(it.exprs[i])
|
||||
|
|
|
@ -85,7 +85,7 @@ fn myuser() {
|
|||
x := 1
|
||||
q := x | 0x1004
|
||||
user := User{age:10}
|
||||
age := user.age + 1
|
||||
age := user.age + 1 // crash here
|
||||
boo := 2
|
||||
boo2 := boo+1
|
||||
b := age > 0
|
||||
|
|
|
@ -5,51 +5,57 @@ int testa();
|
|||
int testb();
|
||||
int testa();
|
||||
int main() {
|
||||
Bar b = (Bar){
|
||||
Bar b = (Bar){
|
||||
.a = 122,
|
||||
};
|
||||
Foo a = (Foo){
|
||||
};
|
||||
Foo a = (Foo){
|
||||
.a = tos3("hello"),
|
||||
.b = b,
|
||||
};
|
||||
a.a = tos3("da");
|
||||
a.b.a = 111;
|
||||
string a1 = a.a;
|
||||
int a2 = ;
|
||||
int c = testa();
|
||||
c = 1;
|
||||
string d = testb(1);
|
||||
d = tos3("hello");
|
||||
string e = tos3("hello");
|
||||
e = testb(111);
|
||||
e = tos3("world");
|
||||
return 0;
|
||||
};
|
||||
a.a = tos3("da");
|
||||
a.b.a = 111;
|
||||
string a1 = a.a;
|
||||
int a2 = ;
|
||||
int c = testa();
|
||||
c = 1;
|
||||
string d = testb(1);
|
||||
d = tos3("hello");
|
||||
string e = tos3("hello");
|
||||
e = testb(111);
|
||||
e = tos3("world");
|
||||
array_int f = new_array_from_c_array(4, 4, sizeof(array_int), {
|
||||
testa(), 2, 3, 4,
|
||||
});
|
||||
array_string g = new_array_from_c_array(2, 2, sizeof(array_string), {
|
||||
testb(1), tos3("hello"),
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testa() {
|
||||
return testc(1);
|
||||
return testc(1);
|
||||
}
|
||||
|
||||
string testb(int a) {
|
||||
return tos3("hello");
|
||||
return tos3("hello");
|
||||
}
|
||||
|
||||
int testc(int a) {
|
||||
return a;
|
||||
return a;
|
||||
}
|
||||
|
||||
int testa() {
|
||||
int a = ;
|
||||
a = 1;
|
||||
return 4;
|
||||
int a = ;
|
||||
a = 1;
|
||||
return 4;
|
||||
}
|
||||
|
||||
int testb() {
|
||||
return 4;
|
||||
return 4;
|
||||
}
|
||||
|
||||
int testa() {
|
||||
return 4;
|
||||
return 4;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -13,7 +13,6 @@ fn main() {
|
|||
a: 'hello'
|
||||
b: b
|
||||
}
|
||||
// a.c = 'sa'
|
||||
a.a = 'da'
|
||||
a.b.a = 111
|
||||
|
||||
|
@ -29,10 +28,8 @@ fn main() {
|
|||
e = testb(111)
|
||||
e = 'world'
|
||||
|
||||
//mut f := [testa(),2,3,4]
|
||||
// f = testa()
|
||||
// c := 1 + 'string'
|
||||
// zz := hi + 1
|
||||
mut f := [testa(),2,3,4]
|
||||
mut g := [testb(1),'hello']
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
v.table
|
||||
)
|
||||
|
||||
pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) {
|
||||
pub fn (p mut Parser) call_expr() (ast.CallExpr,table.TypeRef) {
|
||||
tok := p.tok
|
||||
fn_name := p.check_name()
|
||||
p.check(.lpar)
|
||||
|
@ -18,7 +18,6 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) {
|
|||
name: fn_name
|
||||
args: args
|
||||
// tok: tok
|
||||
|
||||
pos: tok.position()
|
||||
}
|
||||
if p.tok.kind == .key_orelse {
|
||||
|
@ -28,7 +27,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) {
|
|||
if f := p.table.find_fn(fn_name) {
|
||||
return node,f.return_type
|
||||
}
|
||||
typ := p.add_unresolved(node)
|
||||
typ := p.add_unresolved('${fn_name}()', node)
|
||||
return node,typ
|
||||
}
|
||||
|
||||
|
@ -65,7 +64,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
|||
// Receiver?
|
||||
mut rec_name := ''
|
||||
mut is_method := false
|
||||
mut rec_ti := table.void_type
|
||||
mut rec_type := p.table.type_ref(table.void_type_idx)
|
||||
if p.tok.kind == .lpar {
|
||||
is_method = true
|
||||
p.next()
|
||||
|
@ -73,10 +72,10 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
|||
if p.tok.kind == .key_mut {
|
||||
p.next()
|
||||
}
|
||||
rec_ti = p.parse_type()
|
||||
rec_type = p.parse_type()
|
||||
p.table.register_var(table.Var{
|
||||
name: rec_name
|
||||
typ: rec_ti
|
||||
typ: rec_type
|
||||
})
|
||||
p.check(.rpar)
|
||||
}
|
||||
|
@ -120,19 +119,19 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
|||
if p.tok.kind == .key_mut {
|
||||
p.check(.key_mut)
|
||||
}
|
||||
ti := p.parse_type()
|
||||
typ := p.parse_type()
|
||||
for arg_name in arg_names {
|
||||
arg := table.Var{
|
||||
name: arg_name
|
||||
typ: ti
|
||||
typ: typ
|
||||
}
|
||||
args << arg
|
||||
p.table.register_var(arg)
|
||||
ast_args << ast.Arg{
|
||||
ti: ti
|
||||
typ: typ
|
||||
name: arg_name
|
||||
}
|
||||
if ti.kind == .variadic && p.tok.kind == .comma {
|
||||
if typ.typ.kind == .variadic && p.tok.kind == .comma {
|
||||
p.error('cannot use ...(variadic) with non-final parameter $arg_name')
|
||||
}
|
||||
}
|
||||
|
@ -143,16 +142,17 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
|||
}
|
||||
p.check(.rpar)
|
||||
// Return type
|
||||
mut typ := table.void_type
|
||||
mut typ := p.table.type_ref(table.void_type_idx)
|
||||
if p.tok.kind in [.name, .lpar, .amp, .lsbr, .question] {
|
||||
typ = p.parse_type()
|
||||
p.return_type = typ
|
||||
}
|
||||
else {
|
||||
p.return_type = table.void_type
|
||||
// p.return_type = table.void_type
|
||||
p.return_type = typ
|
||||
}
|
||||
if is_method {
|
||||
ok := p.table.register_method(rec_ti, table.Fn{
|
||||
ok := p.table.register_method(rec_type.typ, table.Fn{
|
||||
name: name
|
||||
args: args
|
||||
return_type: typ
|
||||
|
@ -175,28 +175,13 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
|||
return ast.FnDecl{
|
||||
name: name
|
||||
stmts: stmts
|
||||
ti: typ
|
||||
typ: typ
|
||||
args: ast_args
|
||||
is_pub: is_pub
|
||||
receiver: ast.Field{
|
||||
name: rec_name
|
||||
typ: rec_ti
|
||||
typ: rec_type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (p &Parser) check_fn_calls() {
|
||||
println('check fn calls2')
|
||||
/*
|
||||
for call in p.table.unknown_calls {
|
||||
f := p.table.find_fn(call.name) or {
|
||||
p.error_at_line('unknown function `$call.name`', call.tok.line_nr)
|
||||
return
|
||||
}
|
||||
println(f.name)
|
||||
// println(f.return_ti.name)
|
||||
// println('IN AST typ=' + call.typ.name)
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
v.table
|
||||
)
|
||||
|
||||
pub fn (p mut Parser) parse_array_ti(nr_muls int) table.Type {
|
||||
pub fn (p mut Parser) parse_array_ti(nr_muls int) table.TypeRef {
|
||||
p.check(.lsbr)
|
||||
// fixed array
|
||||
if p.tok.kind == .number {
|
||||
|
@ -14,8 +14,8 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.Type {
|
|||
elem_ti := p.parse_type()
|
||||
p.check(.rsbr)
|
||||
p.check_name()
|
||||
idx,name := p.table.find_or_register_array_fixed(&elem_ti, size, 1)
|
||||
return table.new_type(.array_fixed, name, idx, nr_muls)
|
||||
idx := p.table.find_or_register_array_fixed(elem_ti, size, 1)
|
||||
return p.table.type_ref_ptr(idx, nr_muls)
|
||||
}
|
||||
// array
|
||||
p.check(.rsbr)
|
||||
|
@ -26,29 +26,30 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.Type {
|
|||
p.check(.rsbr)
|
||||
nr_dims++
|
||||
}
|
||||
idx,name := p.table.find_or_register_array(&elem_ti, nr_dims)
|
||||
return table.new_type(.array, name, idx, nr_muls)
|
||||
idx := p.table.find_or_register_array(elem_ti, nr_dims)
|
||||
return p.table.type_ref_ptr(idx, nr_muls)
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_map_type(nr_muls int) table.Type {
|
||||
pub fn (p mut Parser) parse_map_type(nr_muls int) table.TypeRef {
|
||||
if p.tok.kind != .lsbr {
|
||||
return table.map_type
|
||||
// check notes in table/atypes.v near map_type_idx
|
||||
return p.table.type_ref(p.table.type_idxs['map'])
|
||||
}
|
||||
p.next()
|
||||
p.check(.lsbr)
|
||||
key_ti := p.parse_type()
|
||||
p.check(.rsbr)
|
||||
value_ti := p.parse_type()
|
||||
idx,name := p.table.find_or_register_map(&key_ti, &value_ti)
|
||||
return table.new_type(.map, name, idx, nr_muls)
|
||||
idx := p.table.find_or_register_map(key_ti, value_ti)
|
||||
return p.table.type_ref_ptr(idx, nr_muls)
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_multi_return_ti() table.Type {
|
||||
pub fn (p mut Parser) parse_multi_return_ti() table.TypeRef {
|
||||
p.check(.lpar)
|
||||
mut mr_tis := []table.Type
|
||||
mut mr_types := []table.TypeRef
|
||||
for {
|
||||
mr_ti := p.parse_type()
|
||||
mr_tis << mr_ti
|
||||
mr_type := p.parse_type()
|
||||
mr_types << mr_type
|
||||
if p.tok.kind == .comma {
|
||||
p.check(.comma)
|
||||
}
|
||||
|
@ -57,24 +58,24 @@ pub fn (p mut Parser) parse_multi_return_ti() table.Type {
|
|||
}
|
||||
}
|
||||
p.check(.rpar)
|
||||
idx,name := p.table.find_or_register_multi_return(mr_tis)
|
||||
return table.new_type(.multi_return, name, idx, 0)
|
||||
idx := p.table.find_or_register_multi_return(mr_types)
|
||||
return p.table.type_ref(idx)
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_variadic_ti() table.Type {
|
||||
pub fn (p mut Parser) parse_variadic_ti() table.TypeRef {
|
||||
p.check(.ellipsis)
|
||||
variadic_ti := p.parse_type()
|
||||
idx,name := p.table.find_or_register_variadic(&variadic_ti)
|
||||
return table.new_type(.variadic, name, idx, 0)
|
||||
variadic_type := p.parse_type()
|
||||
idx := p.table.find_or_register_variadic(variadic_type)
|
||||
return p.table.type_ref(idx)
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_fn_type() table.Type {
|
||||
pub fn (p mut Parser) parse_fn_type() table.TypeRef {
|
||||
// p.check(.key_fn)
|
||||
p.fn_decl()
|
||||
return table.int_type
|
||||
return p.table.type_ref(table.int_type_idx)
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_type() table.Type {
|
||||
pub fn (p mut Parser) parse_type() table.TypeRef {
|
||||
mut nr_muls := 0
|
||||
for p.tok.kind == .amp {
|
||||
p.check(.amp)
|
||||
|
@ -120,63 +121,64 @@ pub fn (p mut Parser) parse_type() table.Type {
|
|||
return p.parse_map_type(nr_muls)
|
||||
}
|
||||
'voidptr' {
|
||||
return table.new_type(.voidptr, 'voidptr', table.voidptr_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.voidptr_type_idx, nr_muls)
|
||||
}
|
||||
'byteptr' {
|
||||
return table.new_type(.byteptr, 'byteptr', table.byteptr_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.byteptr_type_idx, nr_muls)
|
||||
}
|
||||
'charptr' {
|
||||
return table.new_type(.charptr, 'charptr', table.charptr_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.charptr_type_idx, nr_muls)
|
||||
}
|
||||
'i8' {
|
||||
return table.new_type(.i8, 'i8', table.i8_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.i8_type_idx, nr_muls)
|
||||
}
|
||||
'i16' {
|
||||
return table.new_type(.i16, 'i16', table.i16_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.i16_type_idx, nr_muls)
|
||||
}
|
||||
'int' {
|
||||
return table.new_type(.int, 'int', table.int_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.int_type_idx, nr_muls)
|
||||
}
|
||||
'i64' {
|
||||
return table.new_type(.i64, 'i64', table.i64_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.i64_type_idx, nr_muls)
|
||||
}
|
||||
'byte' {
|
||||
return table.new_type(.byte, 'byte', table.byte_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.byte_type_idx, nr_muls)
|
||||
}
|
||||
'u16' {
|
||||
return table.new_type(.u16, 'u16', table.u16_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.u16_type_idx, nr_muls)
|
||||
}
|
||||
'u32' {
|
||||
return table.new_type(.u32, 'u32', table.u32_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.u32_type_idx, nr_muls)
|
||||
}
|
||||
'u64' {
|
||||
return table.new_type(.u64, 'u64', table.u64_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.u64_type_idx, nr_muls)
|
||||
}
|
||||
'f32' {
|
||||
return table.new_type(.f32, 'f32', table.f32_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.f32_type_idx, nr_muls)
|
||||
}
|
||||
'f64' {
|
||||
return table.new_type(.f64, 'f64', table.f64_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.f64_type_idx, nr_muls)
|
||||
}
|
||||
'string' {
|
||||
return table.new_type(.string, 'string', table.string_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.string_type_idx, nr_muls)
|
||||
}
|
||||
'char' {
|
||||
return table.new_type(.char, 'char', table.charptr_type_idx, nr_muls)
|
||||
return p.table.type_ref_ptr(table.charptr_type_idx, nr_muls)
|
||||
}
|
||||
'bool' {
|
||||
return table.new_type(.bool, 'bool', table.bool_type_idx, nr_muls)
|
||||
return p.table.type_ref_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 table.new_type(p.table.types[idx].kind, name, idx, nr_muls)
|
||||
return p.table.type_ref_ptr(idx, nr_muls)
|
||||
}
|
||||
// not found - add placeholder
|
||||
idx = p.table.add_placeholder_type(name)
|
||||
return table.new_type(.placeholder, name, idx, nr_muls)
|
||||
println('NOT FOUND: $name - adding placeholder - $idx')
|
||||
return p.table.type_ref_ptr(idx, nr_muls)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ mut:
|
|||
peek_tok token.Token
|
||||
// vars []string
|
||||
table &table.Table
|
||||
return_type table.Type // current function's return type
|
||||
return_type table.TypeRef // current function's return type
|
||||
// scope_level int
|
||||
// var_idx int
|
||||
is_c bool
|
||||
|
@ -44,6 +44,7 @@ mut:
|
|||
builtin_mod bool
|
||||
mod string
|
||||
unresolved []ast.Expr
|
||||
unresolved_idxs map[string]int
|
||||
}
|
||||
|
||||
// for tests
|
||||
|
@ -244,10 +245,10 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
|||
if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] {
|
||||
return p.var_decl()
|
||||
}
|
||||
expr,ti := p.expr(0)
|
||||
expr,typ := p.expr(0)
|
||||
return ast.ExprStmt{
|
||||
expr: expr
|
||||
ti: ti
|
||||
typ: typ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -298,8 +299,8 @@ fn (p mut Parser) range_expr(low ast.Expr) ast.Expr {
|
|||
}
|
||||
p.check(.dotdot)
|
||||
high,typ := p.expr(0)
|
||||
if typ.kind != .int {
|
||||
p.error('non-integer index `$typ.name`')
|
||||
if typ.typ.kind != .int {
|
||||
p.error('non-integer index `$typ.typ.name`')
|
||||
}
|
||||
node := ast.RangeExpr{
|
||||
low: low
|
||||
|
@ -369,9 +370,9 @@ pub fn (p &Parser) warn(s string) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
||||
pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) {
|
||||
mut node := ast.Expr{}
|
||||
mut typ := table.void_type
|
||||
mut typ := p.table.type_ref(table.void_type_idx)
|
||||
// mut typ := table.unresolved_type
|
||||
is_c := p.tok.lit == 'C' && p.peek_tok.kind == .dot
|
||||
if is_c {
|
||||
|
@ -416,7 +417,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||
exprs << expr
|
||||
}
|
||||
node = ast.StructInit{
|
||||
ti: typ
|
||||
typ: typ
|
||||
exprs: exprs
|
||||
fields: field_names
|
||||
pos: p.tok.position()
|
||||
|
@ -431,25 +432,23 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||
}
|
||||
// variable
|
||||
if var := p.table.find_var(p.tok.lit) {
|
||||
// println('#### IDENT: $var.name: $var.typ.name - $var.typ.idx')
|
||||
// println('#### IDENT: $var.name: $var.typ.typ.name - $var.typ.idx')
|
||||
typ = var.typ
|
||||
ident.kind = .variable
|
||||
ident.info = ast.IdentVar{
|
||||
typ: typ
|
||||
// name: ident.name
|
||||
// expr: p.expr(0)// var.expr
|
||||
|
||||
}
|
||||
// ident.ti = ti
|
||||
node = ident
|
||||
p.next()
|
||||
}else{
|
||||
if is_c {
|
||||
typ = table.int_type
|
||||
typ = p.table.type_ref(table.int_type_idx)
|
||||
ident.info = ast.IdentVar{
|
||||
typ: typ
|
||||
// name: ident.name
|
||||
|
||||
}
|
||||
node = ident
|
||||
p.next()
|
||||
|
@ -462,7 +461,6 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||
ident.info = ast.IdentVar{
|
||||
typ: typ
|
||||
// name: ident.name
|
||||
|
||||
}
|
||||
node = ident
|
||||
p.next()
|
||||
|
@ -479,9 +477,9 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||
return node,typ
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
||||
pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.TypeRef) {
|
||||
// println('\n\nparser.expr()')
|
||||
mut typ := table.void_type
|
||||
mut typ := p.table.type_ref(table.void_type_idx)
|
||||
mut node := ast.Expr{}
|
||||
// Prefix
|
||||
match p.tok.kind {
|
||||
|
@ -492,7 +490,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
|||
node,typ = p.string_expr()
|
||||
}
|
||||
.chartoken {
|
||||
typ = table.byte_type
|
||||
typ = p.table.type_ref(table.byte_type_idx)
|
||||
node = ast.CharLiteral{
|
||||
val: p.tok.lit
|
||||
}
|
||||
|
@ -509,7 +507,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
|||
node = ast.BoolLiteral{
|
||||
val: p.tok.kind == .key_true
|
||||
}
|
||||
typ = table.bool_type
|
||||
typ = p.table.type_ref(table.bool_type_idx)
|
||||
p.next()
|
||||
}
|
||||
.key_match {
|
||||
|
@ -537,7 +535,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
|||
p.check(.lpar)
|
||||
p.next()
|
||||
p.check(.rpar)
|
||||
typ = table.int_type
|
||||
typ = p.table.type_ref(table.int_type_idx)
|
||||
}
|
||||
else {
|
||||
p.error('pexpr(): bad token `$p.tok.str()`')
|
||||
|
@ -573,16 +571,16 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
|||
return node,typ
|
||||
}
|
||||
|
||||
fn (p mut Parser) prefix_expr() (ast.Expr,table.Type) {
|
||||
fn (p mut Parser) prefix_expr() (ast.Expr,table.TypeRef) {
|
||||
op := p.tok.kind
|
||||
p.next()
|
||||
right,ti := p.expr(1)
|
||||
right,typ := p.expr(1)
|
||||
mut expr := ast.Expr{}
|
||||
expr = ast.PrefixExpr{
|
||||
op: op
|
||||
right: right
|
||||
}
|
||||
return expr,ti
|
||||
return expr,typ
|
||||
}
|
||||
|
||||
// fn (p mut Parser) index_expr(left ast.Expr, typ_ table.Type) (ast.Expr,table.Type) {
|
||||
|
@ -605,21 +603,20 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.Expr {
|
|||
// println('got ]')
|
||||
// /ti := table.int_type
|
||||
mut node := ast.Expr{}
|
||||
// println('index expr: $typ.typ.name')
|
||||
node = ast.IndexExpr{
|
||||
left: left
|
||||
index: index_expr
|
||||
pos: p.tok.position()
|
||||
// typ: typ
|
||||
|
||||
}
|
||||
return node
|
||||
// return node,typ
|
||||
}
|
||||
|
||||
fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.Type) {
|
||||
fn (p mut Parser) dot_expr(left ast.Expr, left_type &table.TypeRef) (ast.Expr,table.TypeRef) {
|
||||
p.next()
|
||||
field_name := p.check_name()
|
||||
mut ti := table.unresolved_type
|
||||
// Method call
|
||||
if p.tok.kind == .lpar {
|
||||
p.next()
|
||||
|
@ -636,38 +633,39 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.T
|
|||
}
|
||||
mut node := ast.Expr{}
|
||||
node = mcall_expr
|
||||
ti = p.add_unresolved(mcall_expr)
|
||||
return node,ti
|
||||
typ := p.add_unresolved('${left_type.typ.name}.${field_name}()', mcall_expr)
|
||||
return node,typ
|
||||
}
|
||||
sel_expr := ast.SelectorExpr{
|
||||
expr: left
|
||||
field: field_name
|
||||
pos: p.tok.position()
|
||||
}
|
||||
typ := p.add_unresolved('${left_type.typ.name}.$field_name', sel_expr)
|
||||
mut node := ast.Expr{}
|
||||
node = sel_expr
|
||||
return node,ti
|
||||
return node,typ
|
||||
}
|
||||
|
||||
fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,table.Type) {
|
||||
fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,table.TypeRef) {
|
||||
op := p.tok.kind
|
||||
// mut typ := p.
|
||||
// println('infix op=$op.str()')
|
||||
precedence := p.tok.precedence()
|
||||
p.next()
|
||||
right,mut ti := p.expr(precedence)
|
||||
right,mut typ := p.expr(precedence)
|
||||
if op.is_relational() {
|
||||
ti = table.bool_type
|
||||
typ = p.table.type_ref(table.bool_type_idx)
|
||||
}
|
||||
mut expr := ast.Expr{}
|
||||
expr = ast.InfixExpr{
|
||||
left: left
|
||||
right: right
|
||||
right_type: ti
|
||||
right_type: typ
|
||||
op: op
|
||||
pos: p.tok.position()
|
||||
}
|
||||
return expr,ti
|
||||
return expr,typ
|
||||
}
|
||||
|
||||
// Implementation of Pratt Precedence
|
||||
|
@ -716,7 +714,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
|||
}
|
||||
p.check(.semicolon)
|
||||
if p.tok.kind != .semicolon {
|
||||
mut typ := table.Type{}
|
||||
mut typ := table.TypeRef{typ:0}
|
||||
cond,typ = p.expr(0)
|
||||
}
|
||||
p.check(.semicolon)
|
||||
|
@ -740,7 +738,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
|||
val_name := p.check_name()
|
||||
p.table.register_var(table.Var{
|
||||
name: val_name
|
||||
typ: table.int_type
|
||||
typ: p.table.type_ref(table.int_type_idx)
|
||||
})
|
||||
}
|
||||
p.check(.key_in)
|
||||
|
@ -752,7 +750,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
|||
}
|
||||
p.table.register_var(table.Var{
|
||||
name: var_name
|
||||
typ: table.int_type
|
||||
typ: p.table.type_ref(table.int_type_idx)
|
||||
})
|
||||
stmts := p.parse_block()
|
||||
// println('nr stmts=$stmts.len')
|
||||
|
@ -773,7 +771,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
|||
}
|
||||
}
|
||||
|
||||
fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
|
||||
fn (p mut Parser) if_expr() (ast.Expr,table.TypeRef) {
|
||||
p.inside_if = true
|
||||
// defer {
|
||||
// }
|
||||
|
@ -792,14 +790,14 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
|
|||
else_stmts = p.parse_block()
|
||||
}
|
||||
}
|
||||
mut ti := table.void_type
|
||||
mut typ := p.table.type_ref(table.void_type_idx)
|
||||
// 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.ti.name')
|
||||
ti = it.ti
|
||||
p.warn('if expr ret $it.typ.typ.name')
|
||||
typ = it.typ
|
||||
// return node,it.ti
|
||||
// left =
|
||||
}
|
||||
|
@ -810,22 +808,22 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
|
|||
cond: cond
|
||||
stmts: stmts
|
||||
else_stmts: else_stmts
|
||||
ti: ti
|
||||
typ: typ
|
||||
pos: p.tok.position()
|
||||
// left: left
|
||||
|
||||
}
|
||||
return node,ti
|
||||
return node,typ
|
||||
}
|
||||
|
||||
fn (p mut Parser) string_expr() (ast.Expr,table.Type) {
|
||||
fn (p mut Parser) string_expr() (ast.Expr,table.TypeRef) {
|
||||
mut node := ast.Expr{}
|
||||
node = ast.StringLiteral{
|
||||
val: p.tok.lit
|
||||
}
|
||||
if p.peek_tok.kind != .str_dollar {
|
||||
p.next()
|
||||
return node,table.string_type
|
||||
return node, p.table.type_ref(table.string_type_idx)
|
||||
}
|
||||
// Handle $ interpolation
|
||||
for p.tok.kind == .str {
|
||||
|
@ -839,13 +837,13 @@ fn (p mut Parser) string_expr() (ast.Expr,table.Type) {
|
|||
p.next()
|
||||
}
|
||||
}
|
||||
return node,table.string_type
|
||||
return node, p.table.type_ref(table.string_type_idx)
|
||||
}
|
||||
|
||||
fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
||||
fn (p mut Parser) array_init() (ast.Expr,table.TypeRef) {
|
||||
mut node := ast.Expr{}
|
||||
p.check(.lsbr)
|
||||
mut val_type := table.void_type
|
||||
mut val_type := p.table.type_ref(table.void_type_idx)
|
||||
mut exprs := []ast.Expr
|
||||
for i := 0; p.tok.kind != .rsbr; i++ {
|
||||
expr,typ := p.expr(0)
|
||||
|
@ -866,27 +864,27 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
|||
// type_idx,type_name := p.table.find_or_register_array_fixed(val_type, 1)
|
||||
// node =
|
||||
}
|
||||
type_idx,type_name := p.table.find_or_register_array(val_type, 1)
|
||||
array_ti := table.new_type(.array, type_name, type_idx, 0)
|
||||
// array_type := table.new_type(.array, type_name, type_idx, 0)
|
||||
idx := p.table.find_or_register_array(val_type, 1)
|
||||
array_type := p.table.type_ref_ptr(idx, 0)
|
||||
node = ast.ArrayInit{
|
||||
ti: array_ti
|
||||
typ: array_type
|
||||
exprs: exprs
|
||||
pos: p.tok.position()
|
||||
}
|
||||
return node,array_ti
|
||||
return node,array_type
|
||||
}
|
||||
|
||||
fn (p mut Parser) parse_number_literal() (ast.Expr,table.Type) {
|
||||
fn (p mut Parser) parse_number_literal() (ast.Expr,table.TypeRef) {
|
||||
lit := p.tok.lit
|
||||
mut node := ast.Expr{}
|
||||
mut ti := table.int_type
|
||||
mut ti := p.table.type_ref(table.int_type_idx)
|
||||
if lit.contains('.') {
|
||||
node = ast.FloatLiteral{
|
||||
// val: lit.f64()
|
||||
val: lit
|
||||
}
|
||||
// ti = table.new_builtin_ti(.f64, 0)
|
||||
ti = table.new_type(.f64, 'f64', table.f64_type_idx, 0)
|
||||
ti = p.table.type_ref(table.f64_type_idx)
|
||||
}
|
||||
else {
|
||||
node = ast.IntegerLiteral{
|
||||
|
@ -987,7 +985,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
|||
}
|
||||
field_name := p.check_name()
|
||||
// p.warn('field $field_name')
|
||||
ti := p.parse_type()
|
||||
typ := p.parse_type()
|
||||
// Default value
|
||||
if p.tok.kind == .assign {
|
||||
p.next()
|
||||
|
@ -995,19 +993,19 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
|||
}
|
||||
ast_fields << ast.Field{
|
||||
name: field_name
|
||||
typ: ti
|
||||
typ: typ
|
||||
}
|
||||
fields << table.Field{
|
||||
name: field_name
|
||||
// type_idx: ti.idx
|
||||
|
||||
ti: ti
|
||||
typ: typ
|
||||
}
|
||||
// println('struct field $ti.name $field_name')
|
||||
}
|
||||
p.check(.rcbr)
|
||||
if name != 'string' {
|
||||
ret := p.table.register_type(table.Type{
|
||||
parent: 0
|
||||
kind: .struct_
|
||||
name: name
|
||||
info: table.Struct{
|
||||
|
@ -1051,7 +1049,7 @@ fn (p mut Parser) return_stmt() ast.Return {
|
|||
}
|
||||
// TODO: consider non deferred
|
||||
stmt := ast.Return{
|
||||
expected_ti: p.return_type
|
||||
expected_type: p.return_type
|
||||
exprs: exprs
|
||||
pos: p.tok.position()
|
||||
}
|
||||
|
@ -1082,7 +1080,7 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
|||
|
||||
typ: typ
|
||||
})
|
||||
p.warn('var decl name=$name typ=$typ.name')
|
||||
p.warn('var decl name=$name typ=$typ.typ.name')
|
||||
// println(p.table.names)
|
||||
node := ast.VarDecl{
|
||||
name: name
|
||||
|
@ -1136,7 +1134,7 @@ fn (p mut Parser) global_decl() ast.GlobalDecl {
|
|||
}
|
||||
}
|
||||
|
||||
fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
|
||||
fn (p mut Parser) match_expr() (ast.Expr,table.TypeRef) {
|
||||
p.check(.key_match)
|
||||
p.expr(0)
|
||||
p.check(.lcbr)
|
||||
|
@ -1156,16 +1154,25 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
|
|||
p.check(.rcbr)
|
||||
mut node := ast.Expr{}
|
||||
node = ast.MatchExpr{}
|
||||
return node,table.void_type
|
||||
return node,p.table.type_ref(table.void_type_idx)
|
||||
}
|
||||
|
||||
fn (p mut Parser) add_unresolved(expr ast.Expr) table.Type {
|
||||
t := table.Type{
|
||||
idx: p.unresolved.len
|
||||
kind: .unresolved
|
||||
name: 'unresolved'
|
||||
fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.TypeRef {
|
||||
mut idx := p.unresolved.len
|
||||
if key in p.unresolved_idxs {
|
||||
idx = p.unresolved_idxs[key]
|
||||
}
|
||||
else {
|
||||
p.unresolved << expr
|
||||
}
|
||||
t := table.TypeRef{
|
||||
idx: idx
|
||||
typ: &table.Type{
|
||||
parent: 0
|
||||
kind: .unresolved
|
||||
name: 'unresolved $p.unresolved.len'
|
||||
}
|
||||
}
|
||||
p.unresolved << expr
|
||||
return t
|
||||
}
|
||||
|
||||
|
|
|
@ -7,14 +7,19 @@ pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn | Variadic
|
|||
|
||||
pub struct Type {
|
||||
pub:
|
||||
idx int
|
||||
parent_idx int
|
||||
parent &Type
|
||||
mut:
|
||||
info TypeInfo
|
||||
kind Kind
|
||||
name string
|
||||
methods []Fn
|
||||
nr_muls int
|
||||
}
|
||||
|
||||
pub struct TypeRef {
|
||||
pub:
|
||||
idx int
|
||||
typ &Type
|
||||
nr_muls int
|
||||
}
|
||||
|
||||
pub const (
|
||||
|
@ -35,7 +40,11 @@ pub const (
|
|||
char_type_idx = 15
|
||||
byte_type_idx = 16
|
||||
bool_type_idx = 17
|
||||
map_type_idx = 18
|
||||
// currently map is parsed from builtin as a normal struct named `map`
|
||||
// any maps after that are of type map with parent being the struct named `map`
|
||||
// same goes for array. this works since builtin is parsed first.
|
||||
// will probably go back to registering these types manually and add idx here
|
||||
// map_type_idx = 18
|
||||
)
|
||||
|
||||
pub enum Kind {
|
||||
|
@ -68,162 +77,170 @@ pub enum Kind {
|
|||
unresolved
|
||||
}
|
||||
|
||||
pub const (
|
||||
unresolved_type = Type{
|
||||
kind: .unresolved
|
||||
name: 'unresolved'
|
||||
}
|
||||
void_type = Type{
|
||||
kind: .void
|
||||
name: 'void'
|
||||
idx: void_type_idx
|
||||
}
|
||||
int_type = Type{
|
||||
kind: .int
|
||||
name: 'int'
|
||||
idx: int_type_idx
|
||||
}
|
||||
string_type = Type{
|
||||
kind: .string
|
||||
name: 'string'
|
||||
idx: string_type_idx
|
||||
}
|
||||
bool_type = Type{
|
||||
kind: .bool
|
||||
name: 'bool'
|
||||
idx: bool_type_idx
|
||||
}
|
||||
byte_type = Type{
|
||||
kind: .byte
|
||||
name: 'byte'
|
||||
idx: byte_type_idx
|
||||
}
|
||||
map_type = Type{
|
||||
kind: .map
|
||||
name: 'map'
|
||||
idx: map_type_idx
|
||||
}
|
||||
)
|
||||
/*
|
||||
pub fn (t Type) str() string {
|
||||
return t.name
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
pub fn (t &Type) str() string {
|
||||
pub fn (t &TypeRef) str() string {
|
||||
mut muls := ''
|
||||
for _ in 0 .. t.nr_muls {
|
||||
muls += '&'
|
||||
}
|
||||
// return '$muls$ti.name'
|
||||
return '$muls$t.idx'
|
||||
return '$muls$t.typ.name'
|
||||
}
|
||||
|
||||
pub fn new_type(kind Kind, name string, idx int, nr_muls int) Type {
|
||||
return Type{
|
||||
[inline]
|
||||
pub fn (t &Table) type_ref(idx int) TypeRef {
|
||||
return TypeRef{
|
||||
idx: idx
|
||||
kind: kind
|
||||
name: name
|
||||
nr_muls: nr_muls
|
||||
typ: &t.types[idx]
|
||||
}
|
||||
}
|
||||
|
||||
[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]
|
||||
}
|
||||
}
|
||||
|
||||
[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() {
|
||||
// reserve index 0 so nothing can go there
|
||||
// save index check, 0 will mean not found
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .placeholder
|
||||
name: 'reserved_0'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .void
|
||||
name: 'void'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .voidptr
|
||||
name: 'voidptr'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .charptr
|
||||
name: 'charptr'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .byteptr
|
||||
name: 'byteptr'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .i8
|
||||
name: 'i8'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .i16
|
||||
name: 'i16'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .int
|
||||
name: 'int'
|
||||
})
|
||||
t.register_type(Type{
|
||||
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: .string
|
||||
name: 'string'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .char
|
||||
name: 'char'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .byte
|
||||
name: 'byte'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .bool
|
||||
name: 'bool'
|
||||
})
|
||||
t.register_type(Type{
|
||||
parent: 0
|
||||
kind: .unresolved
|
||||
name: 'unresolved'
|
||||
})
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (ti &Type) is_ptr() bool {
|
||||
return ti.nr_muls > 0
|
||||
pub fn (t &TypeRef) is_ptr() bool {
|
||||
return t.nr_muls > 0
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (ti &Type) is_int() bool {
|
||||
return ti.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64]
|
||||
pub fn (t &Type) is_int() bool {
|
||||
return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64]
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (ti &Type) is_float() bool {
|
||||
return ti.kind in [.f32, .f64]
|
||||
pub fn (t &Type) is_float() bool {
|
||||
return t.kind in [.f32, .f64]
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (ti &Type) is_number() bool {
|
||||
return ti.is_int() || ti.is_float()
|
||||
pub fn (t &Type) is_number() bool {
|
||||
return t.is_int() || t.is_float()
|
||||
}
|
||||
|
||||
pub fn (k Kind) str() string {
|
||||
|
@ -271,7 +288,13 @@ pub fn (k Kind) str() string {
|
|||
'byte'
|
||||
}
|
||||
.u16{
|
||||
'u18'
|
||||
'u16'
|
||||
}
|
||||
.u32{
|
||||
'u32'
|
||||
}
|
||||
.u64{
|
||||
'u64'
|
||||
}
|
||||
.f32{
|
||||
'f32'
|
||||
|
@ -336,7 +359,7 @@ pub mut:
|
|||
pub struct Field {
|
||||
pub:
|
||||
name string
|
||||
ti Type
|
||||
typ TypeRef
|
||||
// type_idx int
|
||||
}
|
||||
// pub struct Int {
|
||||
|
@ -350,58 +373,40 @@ pub:
|
|||
// }
|
||||
pub struct Array {
|
||||
pub:
|
||||
elem_type_kind Kind
|
||||
elem_type_idx int
|
||||
elem_is_ptr bool
|
||||
nr_dims int
|
||||
nr_dims int
|
||||
mut:
|
||||
elem_type TypeRef
|
||||
}
|
||||
|
||||
pub struct ArrayFixed {
|
||||
pub:
|
||||
elem_type_kind Kind
|
||||
elem_type_idx int
|
||||
elem_is_ptr bool
|
||||
nr_dims int
|
||||
size int
|
||||
nr_dims int
|
||||
size int
|
||||
mut:
|
||||
elem_type TypeRef
|
||||
}
|
||||
|
||||
pub struct Map {
|
||||
pub:
|
||||
key_type_kind Kind
|
||||
key_type_idx int
|
||||
value_type_kind Kind
|
||||
value_type_idx int
|
||||
pub mut:
|
||||
key_type TypeRef
|
||||
value_type TypeRef
|
||||
}
|
||||
|
||||
pub struct MultiReturn {
|
||||
pub:
|
||||
name string
|
||||
tis []Type
|
||||
name string
|
||||
types []TypeRef
|
||||
}
|
||||
|
||||
pub struct Variadic {
|
||||
pub:
|
||||
ti Type
|
||||
typ TypeRef
|
||||
}
|
||||
|
||||
pub fn (t &Table) refresh_ti(ti Type) Type {
|
||||
if ti.idx == 0 {
|
||||
return ti
|
||||
}
|
||||
if ti.kind in [.placeholder, .unresolved] {
|
||||
typ := t.types[ti.idx]
|
||||
return {
|
||||
ti |
|
||||
kind:typ.kind,
|
||||
name:typ.name
|
||||
}
|
||||
}
|
||||
return ti
|
||||
}
|
||||
|
||||
pub fn (t &Table) get_type(idx int) Type {
|
||||
[inline]
|
||||
pub fn (t &Table) get_type(idx int) &Type {
|
||||
if idx == 0 {
|
||||
panic('get_type: idx 0')
|
||||
}
|
||||
return t.types[idx]
|
||||
return &t.types[idx]
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ pub struct Fn {
|
|||
pub:
|
||||
name string
|
||||
args []Var
|
||||
return_type Type
|
||||
return_type TypeRef
|
||||
}
|
||||
|
||||
pub struct Var {
|
||||
|
@ -37,11 +37,13 @@ pub:
|
|||
is_global bool
|
||||
scope_level int
|
||||
mut:
|
||||
typ Type
|
||||
typ TypeRef
|
||||
}
|
||||
|
||||
pub fn new_table() &Table {
|
||||
mut t := &Table{}
|
||||
mut t := &Table{
|
||||
types: make(0, 400, sizeof(Type))
|
||||
}
|
||||
t.register_builtin_types()
|
||||
return t
|
||||
}
|
||||
|
@ -77,7 +79,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 Type) {
|
||||
pub fn (t mut Table) register_global(name string, typ TypeRef) {
|
||||
t.consts[name] = Var{
|
||||
name: name
|
||||
typ: typ
|
||||
|
@ -86,12 +88,11 @@ pub fn (t mut Table) register_global(name string, typ Type) {
|
|||
// mod: p.mod
|
||||
// is_mut: true
|
||||
// idx: -1
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (t mut Table) register_var(v Var) {
|
||||
println('register_var: $v.name - $v.typ.name')
|
||||
println('register_var: $v.name - $v.typ.typ.name')
|
||||
new_var := {
|
||||
v |
|
||||
idx:t.var_idx,
|
||||
|
@ -187,24 +188,25 @@ pub fn (t mut Table) register_fn(new_fn Fn) {
|
|||
t.fns[new_fn.name] = new_fn
|
||||
}
|
||||
|
||||
pub fn (t mut Table) register_method(typ &Type, new_fn Fn) bool {
|
||||
idx := typ.idx
|
||||
println('register method `$new_fn.name` type=$typ.name idx=$typ.idx')
|
||||
mut methods := t.types[idx].methods
|
||||
pub fn (t &Table) register_method(typ &Type, 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
|
||||
mut methods := typ.methods
|
||||
methods << new_fn
|
||||
t.types[idx].methods = methods
|
||||
t1.methods = methods
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (t &Table) has_method(type_idx int, name string) bool {
|
||||
t.find_method(type_idx, name) or {
|
||||
pub fn (t &Type) has_method(name string) bool {
|
||||
t.find_method(name) or {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (t &Table) find_method(type_idx int, name string) ?Fn {
|
||||
for method in t.types[type_idx].methods {
|
||||
pub fn (t &Type) find_method(name string) ?Fn {
|
||||
for method in t.methods {
|
||||
if method.name == name {
|
||||
return method
|
||||
}
|
||||
|
@ -218,7 +220,11 @@ pub fn (t mut Table) new_tmp_var() string {
|
|||
}
|
||||
|
||||
pub fn (t &Table) struct_has_field(s &Type, name string) bool {
|
||||
println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
|
||||
if !isnil(s.parent) {
|
||||
println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name')
|
||||
} else {
|
||||
println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent=none')
|
||||
}
|
||||
// for typ in t.types {
|
||||
// println('$typ.idx $typ.name')
|
||||
// }
|
||||
|
@ -229,20 +235,25 @@ pub fn (t &Table) struct_has_field(s &Type, name string) bool {
|
|||
}
|
||||
|
||||
pub fn (t &Table) struct_find_field(s &Type, name string) ?Field {
|
||||
println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
|
||||
if !isnil(s.parent) {
|
||||
println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name')
|
||||
} else {
|
||||
println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent=none')
|
||||
}
|
||||
info := s.info as Struct
|
||||
for field in info.fields {
|
||||
if field.name == name {
|
||||
return field
|
||||
}
|
||||
}
|
||||
if s.parent_idx != 0 {
|
||||
parent := t.types[s.parent_idx]
|
||||
parent_info := s.info as Struct
|
||||
println('got parent $parent.name')
|
||||
for field in parent_info.fields {
|
||||
if field.name == name {
|
||||
return field
|
||||
if !isnil(s.parent) {
|
||||
if s.parent.kind == .struct_ {
|
||||
parent_info := s.parent.info as Struct
|
||||
println('got parent $s.parent.name')
|
||||
for field in parent_info.fields {
|
||||
if field.name == name {
|
||||
return field
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -282,14 +293,15 @@ pub fn (t mut Table) register_type(typ Type) int {
|
|||
if ex_type.kind == typ.kind {
|
||||
return existing_idx
|
||||
}
|
||||
// panic('cannot register type `$typ.name`, another type with this name exists')
|
||||
return -1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
idx := t.types.len
|
||||
typ_idx := t.types.len
|
||||
t.types << typ
|
||||
t.type_idxs[typ.name] = idx
|
||||
return idx
|
||||
t.type_idxs[typ.name] = typ_idx
|
||||
return typ_idx
|
||||
}
|
||||
|
||||
pub fn (t &Table) known_type(name string) bool {
|
||||
|
@ -299,136 +311,127 @@ pub fn (t &Table) known_type(name string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_map(key_typ &Type, value_typ &Type) (int,string) {
|
||||
name := 'map_${key_typ.name}_${value_typ.name}'
|
||||
pub fn (t mut Table) find_or_register_map(key_type TypeRef, value_type TypeRef) int {
|
||||
name := map_name(&key_type, &value_type)
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
return existing_idx
|
||||
}
|
||||
// register
|
||||
map_type := Type{
|
||||
parent: &t.types[t.type_idxs['map']]
|
||||
kind: .map
|
||||
name: name
|
||||
info: Map{
|
||||
key_type_idx: key_typ.idx
|
||||
value_type_idx: value_typ.idx
|
||||
key_type: key_type
|
||||
value_type: value_type
|
||||
}
|
||||
}
|
||||
idx := t.register_type(map_type)
|
||||
return idx,name
|
||||
return t.register_type(map_type)
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_array(elem_typ &Type, nr_dims int) (int,string) {
|
||||
name := 'array_${elem_typ.name}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' }
|
||||
pub fn (t mut Table) find_or_register_array(elem_type TypeRef, nr_dims int) int {
|
||||
name := array_name(&elem_type, nr_dims)
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
return existing_idx
|
||||
}
|
||||
// register
|
||||
parent_idx := t.type_idxs['array']
|
||||
array_type := Type{
|
||||
parent_idx: parent_idx
|
||||
parent: &t.types[t.type_idxs['array']]
|
||||
kind: .array
|
||||
name: name
|
||||
info: Array{
|
||||
elem_type_idx: elem_typ.idx
|
||||
elem_is_ptr: elem_typ.is_ptr()
|
||||
elem_type: elem_type
|
||||
nr_dims: nr_dims
|
||||
}
|
||||
}
|
||||
idx := t.register_type(array_type)
|
||||
return idx,name
|
||||
return t.register_type(array_type)
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_array_fixed(elem_typ &Type, size int, nr_dims int) (int,string) {
|
||||
name := 'array_fixed_${elem_typ.name}_${size}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' }
|
||||
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)
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
return existing_idx
|
||||
}
|
||||
// register
|
||||
array_fixed_type := Type{
|
||||
parent: 0
|
||||
kind: .array_fixed
|
||||
name: name
|
||||
info: ArrayFixed{
|
||||
elem_type_idx: elem_typ.idx
|
||||
elem_is_ptr: elem_typ.is_ptr()
|
||||
elem_type: elem_type
|
||||
size: size
|
||||
nr_dims: nr_dims
|
||||
}
|
||||
}
|
||||
idx := t.register_type(array_fixed_type)
|
||||
return idx,name
|
||||
return t.register_type(array_fixed_type)
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_multi_return(mr_typs []Type) (int,string) {
|
||||
pub fn (t mut Table) find_or_register_multi_return(mr_typs []TypeRef) int {
|
||||
mut name := 'multi_return'
|
||||
for mr_typ in mr_typs {
|
||||
name += '_$mr_typ.name'
|
||||
name += '_$mr_typ.typ.name'
|
||||
}
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
return existing_idx
|
||||
}
|
||||
// register
|
||||
mr_type := Type{
|
||||
parent: 0
|
||||
kind: .multi_return
|
||||
name: name
|
||||
info: MultiReturn{
|
||||
tis: mr_typs
|
||||
types: mr_typs
|
||||
}
|
||||
}
|
||||
idx := t.register_type(mr_type)
|
||||
return idx,name
|
||||
return t.register_type(mr_type)
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_variadic(variadic_typ &Type) (int,string) {
|
||||
name := 'variadic_$variadic_typ.name'
|
||||
pub fn (t mut Table) find_or_register_variadic(variadic_typ TypeRef) int {
|
||||
name := 'variadic_$variadic_typ.typ.name'
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
return existing_idx
|
||||
}
|
||||
// register
|
||||
variadic_type := Type{
|
||||
parent: 0
|
||||
kind: .variadic
|
||||
name: name
|
||||
info: Variadic{
|
||||
ti: variadic_typ
|
||||
typ: variadic_typ
|
||||
}
|
||||
}
|
||||
idx := t.register_type(variadic_type)
|
||||
return idx,name
|
||||
return t.register_type(variadic_type)
|
||||
}
|
||||
|
||||
pub fn (t mut Table) add_placeholder_type(name string) int {
|
||||
ph_type := Type{
|
||||
parent: 0
|
||||
kind: .placeholder
|
||||
name: name
|
||||
}
|
||||
idx := t.register_type(ph_type)
|
||||
println('added placeholder: $name - $idx')
|
||||
return idx
|
||||
// println('added placeholder: $name - $ph_type.idx')
|
||||
return t.register_type(ph_type)
|
||||
}
|
||||
|
||||
// [inline]
|
||||
// pub fn (t &Table) update_typ(ti &types.Type) types.Type {
|
||||
// if typ.kind == .unresolved {
|
||||
// }
|
||||
// }
|
||||
pub fn (t &Table) check(got, expected &Type) bool {
|
||||
println('check: $got.name, $expected.name')
|
||||
if expected.kind == .voidptr {
|
||||
pub fn (t &Table) check(got, expected &TypeRef) bool {
|
||||
println('check: $got.typ.name, $expected.typ.name')
|
||||
if expected.typ.kind == .voidptr {
|
||||
return true
|
||||
}
|
||||
// if expected.name == 'array' {
|
||||
// return true
|
||||
// }
|
||||
if got.idx != expected.idx && got.name != expected.name {
|
||||
if got.idx != expected.idx && got.typ.name != expected.typ.name {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
Loading…
Reference in New Issue