v: initial impl of new type sys w/ pointer & placeholder support (#3323)
parent
778a1cc34a
commit
2061394ad7
|
@ -17,7 +17,7 @@ ForStmt | StructDecl
|
||||||
pub struct ExprStmt {
|
pub struct ExprStmt {
|
||||||
pub:
|
pub:
|
||||||
expr Expr
|
expr Expr
|
||||||
typ types.Type
|
ti types.TypeIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IntegerLiteral {
|
pub struct IntegerLiteral {
|
||||||
|
@ -59,7 +59,7 @@ pub:
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
typ types.Type
|
ti types.TypeIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StructDecl {
|
pub struct StructDecl {
|
||||||
|
@ -71,7 +71,8 @@ pub:
|
||||||
|
|
||||||
pub struct StructInit {
|
pub struct StructInit {
|
||||||
pub:
|
pub:
|
||||||
typ types.Type
|
ti types.TypeIdent
|
||||||
|
// typ types.Type
|
||||||
fields []string
|
fields []string
|
||||||
exprs []Expr
|
exprs []Expr
|
||||||
}
|
}
|
||||||
|
@ -86,7 +87,8 @@ pub:
|
||||||
|
|
||||||
pub struct Arg {
|
pub struct Arg {
|
||||||
pub:
|
pub:
|
||||||
typ types.Type
|
ti types.TypeIdent
|
||||||
|
// typ types.Type
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +96,8 @@ pub struct FnDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
typ types.Type
|
ti types.TypeIdent
|
||||||
|
// typ types.Type
|
||||||
args []Arg
|
args []Arg
|
||||||
is_pub bool
|
is_pub bool
|
||||||
receiver Field
|
receiver Field
|
||||||
|
@ -133,7 +136,8 @@ pub struct VarDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
expr Expr
|
expr Expr
|
||||||
typ types.Type
|
ti types.TypeIdent
|
||||||
|
// typ types.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
|
@ -174,7 +178,8 @@ pub:
|
||||||
cond Expr
|
cond Expr
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
else_stmts []Stmt
|
else_stmts []Stmt
|
||||||
typ types.Type
|
ti types.TypeIdent
|
||||||
|
// typ types.Type
|
||||||
left Expr // `a` in `a := if ...`
|
left Expr // `a` in `a := if ...`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +205,8 @@ pub:
|
||||||
pub struct ArrayInit {
|
pub struct ArrayInit {
|
||||||
pub:
|
pub:
|
||||||
exprs []Expr
|
exprs []Expr
|
||||||
typ types.Type
|
ti types.TypeIdent
|
||||||
|
// typ types.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// string representaiton of expr
|
// string representaiton of expr
|
||||||
|
|
|
@ -53,12 +53,12 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
g.write('int ${it.name}(')
|
g.write('int ${it.name}(')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('$it.typ.name ${it.name}(')
|
g.write('$it.ti.type_name ${it.name}(')
|
||||||
g.definitions.write('$it.typ.name ${it.name}(')
|
g.definitions.write('$it.ti.type_name ${it.name}(')
|
||||||
}
|
}
|
||||||
for arg in it.args {
|
for arg in it.args {
|
||||||
g.write(arg.typ.name + ' ' + arg.name)
|
g.write(arg.ti.type_name + ' ' + arg.name)
|
||||||
g.definitions.write(arg.typ.name + ' ' + arg.name)
|
g.definitions.write(arg.ti.type_name + ' ' + arg.name)
|
||||||
}
|
}
|
||||||
g.writeln(') { ')
|
g.writeln(') { ')
|
||||||
if !is_main {
|
if !is_main {
|
||||||
|
@ -78,7 +78,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('$it.typ.name $it.name = ')
|
g.write('$it.ti.type_name $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
g.writeln('typedef struct {')
|
g.writeln('typedef struct {')
|
||||||
for field in it.fields {
|
for field in it.fields {
|
||||||
g.writeln('\t$field.typ.name $field.name;')
|
g.writeln('\t$field.ti.type_name $field.name;')
|
||||||
}
|
}
|
||||||
g.writeln('} $it.name;')
|
g.writeln('} $it.name;')
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
// `user := User{name: 'Bob'}`
|
// `user := User{name: 'Bob'}`
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
g.writeln('($it.typ.name){')
|
g.writeln('($it.ti.type_name){')
|
||||||
for i, field in it.fields {
|
for i, field in it.fields {
|
||||||
g.write('\t.$field = ')
|
g.write('\t.$field = ')
|
||||||
g.expr(it.exprs[i])
|
g.expr(it.exprs[i])
|
||||||
|
@ -173,7 +173,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.typ.name), {\t')
|
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.ti.type_name), {\t')
|
||||||
for expr in it.exprs {
|
for expr in it.exprs {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
|
@ -200,7 +200,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
// If expression? Assign the value to a temp var.
|
// If expression? Assign the value to a temp var.
|
||||||
// Previously ?: was used, but it's too unreliable.
|
// Previously ?: was used, but it's too unreliable.
|
||||||
mut tmp := ''
|
mut tmp := ''
|
||||||
if it.typ.idx != types.void_type.idx {
|
if it.ti.type_kind != ._void {
|
||||||
tmp = g.table.new_tmp_var()
|
tmp = g.table.new_tmp_var()
|
||||||
// g.writeln('$it.typ.name $tmp;')
|
// g.writeln('$it.typ.name $tmp;')
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
for i, stmt in it.stmts {
|
for i, stmt in it.stmts {
|
||||||
// Assign ret value
|
// Assign ret value
|
||||||
if i == it.stmts.len - 1 && it.typ.idx != types.void_type.idx {
|
if i == it.stmts.len - 1 && it.ti.type_kind != ._void {
|
||||||
// g.writeln('$tmp =')
|
// g.writeln('$tmp =')
|
||||||
println(1)
|
println(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,9 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
g.write('/** @return { $it.typ.name } **/\nfunction ${it.name}(')
|
g.write('/** @return { $it.ti.type_name } **/\nfunction ${it.name}(')
|
||||||
for arg in it.args {
|
for arg in it.args {
|
||||||
g.write(' /** @type { arg.typ.name } **/ $arg.name')
|
g.write(' /** @type { arg.ti.type_name } **/ $arg.name')
|
||||||
}
|
}
|
||||||
g.writeln(') { ')
|
g.writeln(') { ')
|
||||||
for stmt in it.stmts {
|
for stmt in it.stmts {
|
||||||
|
@ -56,7 +56,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('var /* $it.typ.name */ $it.name = ')
|
g.write('var /* $it.ti.type_name */ $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
// g.writeln('typedef struct {')
|
// g.writeln('typedef struct {')
|
||||||
// for field in it.fields {
|
// for field in it.fields {
|
||||||
// g.writeln('\t$field.typ.name $field.name;')
|
// g.writeln('\t$field.ti.type_name $field.name;')
|
||||||
// }
|
// }
|
||||||
g.writeln('var $it.name = function() {};')
|
g.writeln('var $it.name = function() {};')
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ fn (g mut JsGen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
// `user := User{name: 'Bob'}`
|
// `user := User{name: 'Bob'}`
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
g.writeln('/*$it.typ.name*/{')
|
g.writeln('/*$it.ti.type_name*/{')
|
||||||
for i, field in it.fields {
|
for i, field in it.fields {
|
||||||
g.write('\t$field : ')
|
g.write('\t$field : ')
|
||||||
g.expr(it.exprs[i])
|
g.expr(it.exprs[i])
|
||||||
|
|
|
@ -337,7 +337,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('$it.typ.name $it.name = ')
|
g.write('$it.ti.type_name $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
@ -354,7 +354,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
g.writeln('typedef struct {')
|
g.writeln('typedef struct {')
|
||||||
for field in it.fields {
|
for field in it.fields {
|
||||||
g.writeln('\t$field.typ.name $field.name;')
|
g.writeln('\t$field.ti.type_name $field.name;')
|
||||||
}
|
}
|
||||||
g.writeln('} $it.name;')
|
g.writeln('} $it.name;')
|
||||||
}
|
}
|
||||||
|
@ -394,13 +394,13 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
g.write(' $it.op.str() ')
|
g.write(' $it.op.str() ')
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
// if typ.name != typ2.name {
|
// if ti.type_name != typ2.name {
|
||||||
// verror('bad types $typ.name $typ2.name')
|
// verror('bad types $ti.type_name $typ2.name')
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
// `user := User{name: 'Bob'}`
|
// `user := User{name: 'Bob'}`
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
g.writeln('($it.typ.name){')
|
g.writeln('($it.ti.type_name){')
|
||||||
for i, field in it.fields {
|
for i, field in it.fields {
|
||||||
g.write('\t.$field = ')
|
g.write('\t.$field = ')
|
||||||
g.expr(it.exprs[i])
|
g.expr(it.exprs[i])
|
||||||
|
@ -426,7 +426,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
|
|
||||||
}
|
}
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.typ.name), {\t')
|
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.ti.type_name), {\t')
|
||||||
for expr in it.exprs {
|
for expr in it.exprs {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
|
|
|
@ -13,20 +13,20 @@ import (
|
||||||
os
|
os
|
||||||
)
|
)
|
||||||
|
|
||||||
pub fn (p mut Parser) call_expr() (ast.CallExpr,types.Type) {
|
pub fn (p mut Parser) call_expr() (ast.CallExpr,types.TypeIdent) {
|
||||||
// println('got fn call')
|
// println('got fn call')
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
fn_name := p.check_name()
|
fn_name := p.check_name()
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
mut is_unknown := false
|
mut is_unknown := false
|
||||||
mut args := []ast.Expr
|
mut args := []ast.Expr
|
||||||
mut return_type := types.void_type
|
mut return_ti := types.new_base_ti(._void, 0)
|
||||||
if f := p.table.find_fn(fn_name) {
|
if f := p.table.find_fn(fn_name) {
|
||||||
return_type = f.return_type
|
return_ti = f.return_ti
|
||||||
for i, arg in f.args {
|
for i, arg in f.args {
|
||||||
e,typ := p.expr(0)
|
e,ti := p.expr(0)
|
||||||
if !types.check(arg.typ, typ) {
|
if !types.check(arg.ti, ti) {
|
||||||
p.error('cannot use type `$typ.name` as type `$arg.typ.name` in argument to `$fn_name`')
|
p.error('cannot use type `$ti.type_name` as type `$arg.ti.type_name` in argument to `$fn_name`')
|
||||||
}
|
}
|
||||||
args << e
|
args << e
|
||||||
if i < f.args.len - 1 {
|
if i < f.args.len - 1 {
|
||||||
|
@ -59,7 +59,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.Type) {
|
||||||
if is_unknown {
|
if is_unknown {
|
||||||
p.table.unknown_calls << node
|
p.table.unknown_calls << node
|
||||||
}
|
}
|
||||||
return node,return_type
|
return node,return_ti
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) fn_decl() ast.FnDecl {
|
fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
|
@ -71,17 +71,17 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
p.check(.key_fn)
|
p.check(.key_fn)
|
||||||
// Receiver?
|
// Receiver?
|
||||||
mut rec_name := ''
|
mut rec_name := ''
|
||||||
mut rec_type := types.void_type
|
mut rec_ti := types.new_base_ti(._void, 0)
|
||||||
if p.tok.kind == .lpar {
|
if p.tok.kind == .lpar {
|
||||||
p.next()
|
p.next()
|
||||||
rec_name = p.check_name()
|
rec_name = p.check_name()
|
||||||
if p.tok.kind == .key_mut {
|
if p.tok.kind == .key_mut {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
rec_type = p.parse_type()
|
rec_ti = p.parse_ti()
|
||||||
p.table.register_var(table.Var{
|
p.table.register_var(table.Var{
|
||||||
name: rec_name
|
name: rec_name
|
||||||
typ: rec_type
|
ti: rec_ti
|
||||||
})
|
})
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
}
|
}
|
||||||
|
@ -98,16 +98,16 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
arg_names << p.check_name()
|
arg_names << p.check_name()
|
||||||
}
|
}
|
||||||
typ := p.parse_type()
|
ti := p.parse_ti()
|
||||||
for arg_name in arg_names {
|
for arg_name in arg_names {
|
||||||
arg := table.Var{
|
arg := table.Var{
|
||||||
name: arg_name
|
name: arg_name
|
||||||
typ: typ
|
ti: ti
|
||||||
}
|
}
|
||||||
args << arg
|
args << arg
|
||||||
p.table.register_var(arg)
|
p.table.register_var(arg)
|
||||||
ast_args << ast.Arg{
|
ast_args << ast.Arg{
|
||||||
typ: typ
|
ti: ti
|
||||||
name: arg_name
|
name: arg_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,26 +117,26 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
}
|
}
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
// Return type
|
// Return type
|
||||||
mut typ := types.void_type
|
mut ti := types.new_base_ti(._void, 0)
|
||||||
if p.tok.kind == .name {
|
if p.tok.kind in [.amp, .name] {
|
||||||
typ = p.parse_type()
|
ti = p.parse_ti()
|
||||||
p.return_type = typ
|
p.return_ti = ti
|
||||||
}
|
}
|
||||||
p.table.register_fn(table.Fn{
|
p.table.register_fn(table.Fn{
|
||||||
name: name
|
name: name
|
||||||
args: args
|
args: args
|
||||||
return_type: typ
|
return_ti: ti
|
||||||
})
|
})
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
return ast.FnDecl{
|
return ast.FnDecl{
|
||||||
name: name
|
name: name
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
typ: typ
|
ti: ti
|
||||||
args: ast_args
|
args: ast_args
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
receiver: ast.Field{
|
receiver: ast.Field{
|
||||||
name: rec_name
|
name: rec_name
|
||||||
typ: rec_type
|
ti: rec_ti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ mut:
|
||||||
peek_tok token.Token
|
peek_tok token.Token
|
||||||
// vars []string
|
// vars []string
|
||||||
table &table.Table
|
table &table.Table
|
||||||
return_type types.Type
|
return_ti types.TypeIdent
|
||||||
is_c bool
|
is_c bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,126 @@ pub fn parse_stmt(text string, table &table.Table) ast.Stmt {
|
||||||
return p.stmt()
|
return p.stmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Parser) parse_ti() types.TypeIdent {
|
||||||
|
defer {
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
|
mut nr_muls := 0
|
||||||
|
if p.tok.kind == .amp {
|
||||||
|
p.check(.amp)
|
||||||
|
nr_muls = 1
|
||||||
|
}
|
||||||
|
name := p.tok.lit
|
||||||
|
if nr_muls > 0 {
|
||||||
|
println('## POINTER: $name')
|
||||||
|
}
|
||||||
|
match name {
|
||||||
|
'voidptr' {
|
||||||
|
return types.new_base_ti(._voidptr, nr_muls)
|
||||||
|
}
|
||||||
|
'byteptr' {
|
||||||
|
return types.new_base_ti(._byteptr, nr_muls)
|
||||||
|
}
|
||||||
|
'charptr' {
|
||||||
|
return types.new_base_ti(._charptr, nr_muls)
|
||||||
|
}
|
||||||
|
'164' {
|
||||||
|
return types.new_base_ti(._i16, nr_muls)
|
||||||
|
}
|
||||||
|
'int' {
|
||||||
|
return types.new_base_ti(._int, nr_muls)
|
||||||
|
}
|
||||||
|
'i64' {
|
||||||
|
return types.new_base_ti(._i64, nr_muls)
|
||||||
|
}
|
||||||
|
'byte' {
|
||||||
|
return types.new_base_ti(._byte, nr_muls)
|
||||||
|
}
|
||||||
|
'u16' {
|
||||||
|
return types.new_base_ti(._u16, nr_muls)
|
||||||
|
}
|
||||||
|
'u32' {
|
||||||
|
return types.new_base_ti(._u32, nr_muls)
|
||||||
|
}
|
||||||
|
'u64' {
|
||||||
|
return types.new_base_ti(._u64, nr_muls)
|
||||||
|
}
|
||||||
|
'f32' {
|
||||||
|
return types.new_base_ti(._f32, nr_muls)
|
||||||
|
}
|
||||||
|
'f64' {
|
||||||
|
return types.new_base_ti(._f64, nr_muls)
|
||||||
|
}
|
||||||
|
'string' {
|
||||||
|
return types.new_base_ti(._string, nr_muls)
|
||||||
|
}
|
||||||
|
'char' {
|
||||||
|
return types.new_base_ti(._char, nr_muls)
|
||||||
|
}
|
||||||
|
'bool' {
|
||||||
|
return types.new_base_ti(._bool, nr_muls)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// array
|
||||||
|
if p.tok.kind == .lsbr {
|
||||||
|
p.check(.lsbr)
|
||||||
|
// fixed array
|
||||||
|
if p.tok.kind == .number {
|
||||||
|
fixed_size := p.tok.lit.int()
|
||||||
|
p.check(.rsbr)
|
||||||
|
elem_ti := p.parse_ti()
|
||||||
|
array_fixed_type := types.ArrayFixed{
|
||||||
|
name: 'array_fixed_$elem_ti.type_name'
|
||||||
|
size: fixed_size
|
||||||
|
elem_type_idx: elem_ti.type_idx
|
||||||
|
}
|
||||||
|
idx := p.table.find_or_register_array_fixed(array_fixed_type)
|
||||||
|
return types.new_ti(._array_fixed, array_fixed_type.name, idx, nr_muls)
|
||||||
|
}
|
||||||
|
p.check(.rsbr)
|
||||||
|
// array
|
||||||
|
elem_ti := p.parse_ti()
|
||||||
|
array_type := types.Array{
|
||||||
|
name: 'array_$elem_ti.type_name'
|
||||||
|
elem_type_idx: elem_ti.type_idx
|
||||||
|
}
|
||||||
|
idx := p.table.find_or_register_array(array_type)
|
||||||
|
return types.new_ti(._array, array_type.name, idx, nr_muls)
|
||||||
|
}
|
||||||
|
// map
|
||||||
|
else if name == 'map' {
|
||||||
|
p.next()
|
||||||
|
p.check(.lsbr)
|
||||||
|
key_ti := p.parse_ti()
|
||||||
|
p.check(.rsbr)
|
||||||
|
value_ti := p.parse_ti()
|
||||||
|
map_type := types.Map{
|
||||||
|
name: 'map_${key_ti.type_name}_${value_ti.type_name}'
|
||||||
|
key_type_idx: key_ti.type_idx,
|
||||||
|
value_type_idx: value_ti.type_idx
|
||||||
|
}
|
||||||
|
idx := p.table.find_or_register_map(map_type)
|
||||||
|
return types.new_ti(._map, map_type.name, idx, nr_muls)
|
||||||
|
} else {
|
||||||
|
// struct / enum
|
||||||
|
mut idx := p.table.find_type_idx(name)
|
||||||
|
// add placeholder
|
||||||
|
if idx == 0 {
|
||||||
|
idx = p.table.add_placeholder_type(name)
|
||||||
|
}
|
||||||
|
return types.new_ti(._placeholder, name, idx, nr_muls)
|
||||||
|
}
|
||||||
|
|
||||||
|
// typ := p.table.types[p.tok.lit]
|
||||||
|
// if isnil(typ.name.str) || typ.name == '' {
|
||||||
|
// p.error('undefined type `$p.tok.lit`')
|
||||||
|
// }
|
||||||
|
// println('RET Typ $typ.name')
|
||||||
|
// typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_file(path string, table &table.Table) ast.File {
|
pub fn parse_file(path string, table &table.Table) ast.File {
|
||||||
println('parse file "$path"')
|
println('parse file "$path"')
|
||||||
text := os.read_file(path) or {
|
text := os.read_file(path) or {
|
||||||
|
@ -74,16 +194,16 @@ pub fn parse_files(paths []string, table &table.Table) []ast.File {
|
||||||
}
|
}
|
||||||
|
|
||||||
// former get_type()
|
// former get_type()
|
||||||
pub fn (p mut Parser) parse_type() types.Type {
|
// pub fn (p mut Parser) parse_ti() types.Type {
|
||||||
typ := p.table.find_type(p.tok.lit) or {
|
// typ := p.table.find_type(p.tok.lit) or {
|
||||||
// typ := p.table.types[p.tok.lit]
|
// // typ := p.table.types[p.tok.lit]
|
||||||
// if isnil(typ.name.str) || typ.name == '' {
|
// // if isnil(typ.name.str) || typ.name == '' {
|
||||||
p.error('undefined type `$p.tok.lit`')
|
// p.error('undefined type `$p.tok.lit`')
|
||||||
exit(0)
|
// exit(0)
|
||||||
}
|
// }
|
||||||
p.next()
|
// p.next()
|
||||||
return typ
|
// return typ
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn (p mut Parser) read_first_token() {
|
pub fn (p mut Parser) read_first_token() {
|
||||||
// need to call next() twice to get peek token and current token
|
// need to call next() twice to get peek token and current token
|
||||||
|
@ -184,10 +304,10 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
||||||
return p.for_statement()
|
return p.for_statement()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
expr,typ := p.expr(0)
|
expr,ti := p.expr(0)
|
||||||
return ast.ExprStmt{
|
return ast.ExprStmt{
|
||||||
expr: expr
|
expr: expr
|
||||||
typ: typ
|
ti: ti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,11 +353,12 @@ pub fn (p &Parser) warn(s string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of Pratt Precedence
|
// Implementation of Pratt Precedence
|
||||||
pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.TypeIdent) {
|
||||||
// println('expr at ' + p.tok.str())
|
// println('expr at ' + p.tok.str())
|
||||||
// null denotation (prefix)
|
// null denotation (prefix)
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
mut typ := types.void_type
|
// mut typ := types.void_type
|
||||||
|
mut ti := types.new_base_ti(._void, 0)
|
||||||
match p.tok.kind {
|
match p.tok.kind {
|
||||||
.name {
|
.name {
|
||||||
/*
|
/*
|
||||||
|
@ -254,13 +375,13 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
}
|
}
|
||||||
// fn call
|
// fn call
|
||||||
if p.peek_tok.kind == .lpar {
|
if p.peek_tok.kind == .lpar {
|
||||||
x,typ2 := p.call_expr() // TODO `node,typ :=` should work
|
x,ti2 := p.call_expr() // TODO `node,typ :=` should work
|
||||||
node = x
|
node = x
|
||||||
typ = typ2
|
ti = ti2
|
||||||
}
|
}
|
||||||
// struct init
|
// struct init
|
||||||
else if p.peek_tok.kind == .lcbr {
|
else if p.peek_tok.kind == .lcbr {
|
||||||
typ = p.parse_type()
|
ti = p.parse_ti()
|
||||||
// println('sturct init typ=$typ.name')
|
// println('sturct init typ=$typ.name')
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
mut field_names := []string
|
mut field_names := []string
|
||||||
|
@ -275,7 +396,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
exprs << expr
|
exprs << expr
|
||||||
}
|
}
|
||||||
node = ast.StructInit{
|
node = ast.StructInit{
|
||||||
typ: typ
|
ti: ti
|
||||||
exprs: exprs
|
exprs: exprs
|
||||||
fields: field_names
|
fields: field_names
|
||||||
}
|
}
|
||||||
|
@ -290,46 +411,46 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
p.error('unknown variable `$p.tok.lit`')
|
p.error('unknown variable `$p.tok.lit`')
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
typ = var.typ
|
ti = var.ti
|
||||||
// ///typ = types.int_type
|
// ///typ = types.int_type
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.lsbr {
|
.lsbr {
|
||||||
node,typ = p.array_init()
|
node,ti = p.array_init()
|
||||||
}
|
}
|
||||||
.key_true, .key_false {
|
.key_true, .key_false {
|
||||||
node = ast.BoolLiteral{
|
node = ast.BoolLiteral{
|
||||||
val: p.tok.kind == .key_true
|
val: p.tok.kind == .key_true
|
||||||
}
|
}
|
||||||
typ = types.bool_type
|
ti = types.new_base_ti(._bool, 0)
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
.str {
|
.str {
|
||||||
node,typ = p.parse_string_literal()
|
node,ti = p.parse_string_literal()
|
||||||
}
|
}
|
||||||
.number {
|
.number {
|
||||||
node,typ = p.parse_number_literal()
|
node,ti = p.parse_number_literal()
|
||||||
}
|
}
|
||||||
.key_if {
|
.key_if {
|
||||||
node,typ = p.if_expr()
|
node,ti = p.if_expr()
|
||||||
}
|
}
|
||||||
.lpar {
|
.lpar {
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
p.next()
|
p.next()
|
||||||
node,typ = p.expr(token.lowest_prec)
|
node,ti = p.expr(token.lowest_prec)
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if p.tok.is_unary() {
|
if p.tok.is_unary() {
|
||||||
pt := p.tok
|
pt := p.tok
|
||||||
p.next()
|
p.next()
|
||||||
expr,t2 := p.expr(token.lowest_prec)
|
expr,ti2 := p.expr(token.lowest_prec)
|
||||||
node = ast.UnaryExpr{
|
node = ast.UnaryExpr{
|
||||||
left: expr
|
left: expr
|
||||||
op: pt.kind
|
op: pt.kind
|
||||||
}
|
}
|
||||||
typ = t2
|
ti = ti2
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.error('expr(): unknown token ' + p.tok.str() + ' kind=$p.tok.kind')
|
p.error('expr(): unknown token ' + p.tok.str() + ' kind=$p.tok.kind')
|
||||||
|
@ -340,30 +461,36 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
for rbp < p.tok.precedence() {
|
for rbp < p.tok.precedence() {
|
||||||
prev_tok := p.tok
|
prev_tok := p.tok
|
||||||
p.next()
|
p.next()
|
||||||
mut t2 := types.Type{}
|
// mut t2 := types.Type{}
|
||||||
|
mut ti2 := types.new_base_ti(._void, 0)
|
||||||
// left denotation (infix / postfix)
|
// left denotation (infix / postfix)
|
||||||
if prev_tok.is_right_assoc() && !p.tok.kind in [.plus, .minus] && // think of better way to handle this
|
if prev_tok.is_right_assoc() && !p.tok.kind in [.plus, .minus] && // think of better way to handle this
|
||||||
!p.peek_tok.kind in [.number, .name] {
|
!p.peek_tok.kind in [.number, .name] {
|
||||||
// supposed to be only unary, additive handled in left asssoc
|
// supposed to be only unary, additive handled in left asssoc
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.Expr{}
|
||||||
expr,t2 = p.expr(prev_tok.precedence() - 1)
|
expr,ti2 = p.expr(prev_tok.precedence() - 1)
|
||||||
node = ast.BinaryExpr{
|
node = ast.BinaryExpr{
|
||||||
left: node
|
left: node
|
||||||
op: prev_tok.kind
|
op: prev_tok.kind
|
||||||
right: expr
|
right: expr
|
||||||
}
|
}
|
||||||
// println(t2.name + 'OOO')
|
// println(t2.name + 'OOO')
|
||||||
if !types.check(&typ, &t2) {
|
if !types.check(&ti, &ti2) {
|
||||||
println('tok: $prev_tok.str()')
|
println('tok: $prev_tok.str()')
|
||||||
p.error('cannot convert `$t2.name` to `$typ.name`')
|
p.error('cannot convert `$ti2.type_name` to `$ti.type_name`')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if prev_tok.is_left_assoc() {
|
else if prev_tok.is_left_assoc() {
|
||||||
// postfix `.`
|
// postfix `.`
|
||||||
if prev_tok.kind == .dot {
|
if prev_tok.kind == .dot {
|
||||||
p.warn('dot prev_tok = $prev_tok.str() typ=$typ.name')
|
p.warn('dot prev_tok = $prev_tok.str() typ=$ti.type_name')
|
||||||
// p.next()
|
// p.next()
|
||||||
field := p.check_name()
|
field := p.check_name()
|
||||||
|
if !ti.type_kind in [._placeholder, ._struct] {
|
||||||
|
println('kind: $ti.str()')
|
||||||
|
p.error('cannot access field, `$ti.type_name` is not a struct')
|
||||||
|
}
|
||||||
|
typ := p.table.types[ti.type_idx] as types.Struct
|
||||||
mut ok := false
|
mut ok := false
|
||||||
for f in typ.fields {
|
for f in typ.fields {
|
||||||
if f.name == field {
|
if f.name == field {
|
||||||
|
@ -388,14 +515,15 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.Expr{}
|
||||||
expr,t2 = p.expr(prev_tok.precedence() - 1)
|
expr,ti2 = p.expr(prev_tok.precedence() - 1)
|
||||||
if prev_tok.is_relational() {
|
if prev_tok.is_relational() {
|
||||||
typ = types.bool_type
|
// typ = types.bool_type
|
||||||
|
ti = types.new_base_ti(._bool, 0)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
typ = t2
|
ti = ti2
|
||||||
}
|
}
|
||||||
// println(t2.name + '222')
|
// println(ti2.type_name + '222')
|
||||||
node = ast.BinaryExpr{
|
node = ast.BinaryExpr{
|
||||||
left: node
|
left: node
|
||||||
op: prev_tok.kind
|
op: prev_tok.kind
|
||||||
|
@ -404,7 +532,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node,typ
|
return node,ti
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -432,8 +560,9 @@ fn (p mut Parser) for_statement() ast.ForStmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `for cond {`
|
// `for cond {`
|
||||||
cond,typ := p.expr(0)
|
cond,ti := p.expr(0)
|
||||||
if !types.check(types.bool_type, typ) {
|
// if !types.check(types.bool_type, ti) {
|
||||||
|
if ti.type_kind != ._bool {
|
||||||
p.error('non-bool used as for condition')
|
p.error('non-bool used as for condition')
|
||||||
}
|
}
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
|
@ -443,11 +572,12 @@ fn (p mut Parser) for_statement() ast.ForStmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) if_expr() (ast.Expr,types.Type) {
|
fn (p mut Parser) if_expr() (ast.Expr,types.TypeIdent) {
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
p.check(.key_if)
|
p.check(.key_if)
|
||||||
cond,cond_type := p.expr(0)
|
cond,cond_type := p.expr(0)
|
||||||
if !types.check(types.bool_type, cond_type) {
|
// if !types.check(types.bool_type, cond_type) {
|
||||||
|
if cond_type.type_kind != ._bool {
|
||||||
p.error('non-bool used as if condition')
|
p.error('non-bool used as if condition')
|
||||||
}
|
}
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
|
@ -457,13 +587,14 @@ fn (p mut Parser) if_expr() (ast.Expr,types.Type) {
|
||||||
p.check(.key_else)
|
p.check(.key_else)
|
||||||
else_stmts = p.parse_block()
|
else_stmts = p.parse_block()
|
||||||
}
|
}
|
||||||
mut typ := types.void_type
|
// mut typ := types.void_type
|
||||||
|
mut ti := types.new_base_ti(._void, 0)
|
||||||
// mut left := ast.Expr{}
|
// mut left := ast.Expr{}
|
||||||
// If the last statement is an expression, return its type
|
// If the last statement is an expression, return its type
|
||||||
match stmts[stmts.len - 1] {
|
match stmts[stmts.len - 1] {
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
p.warn('if expr ret $it.typ.name')
|
p.warn('if expr ret $it.ti.type_name')
|
||||||
typ = it.typ
|
ti = it.ti
|
||||||
// return node,it.typ
|
// return node,it.typ
|
||||||
// left =
|
// left =
|
||||||
}
|
}
|
||||||
|
@ -473,35 +604,37 @@ fn (p mut Parser) if_expr() (ast.Expr,types.Type) {
|
||||||
cond: cond
|
cond: cond
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
else_stmts: else_stmts
|
else_stmts: else_stmts
|
||||||
typ: typ
|
ti: ti
|
||||||
// left: left
|
// left: left
|
||||||
|
|
||||||
}
|
}
|
||||||
return node,typ
|
return node,ti
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) parse_string_literal() (ast.Expr,types.Type) {
|
fn (p mut Parser) parse_string_literal() (ast.Expr,types.TypeIdent) {
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
node = ast.StringLiteral{
|
node = ast.StringLiteral{
|
||||||
val: p.tok.lit
|
val: p.tok.lit
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
return node,types.string_type
|
// return node,types.string_type
|
||||||
|
return node, types.new_base_ti(._string, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) array_init() (ast.Expr,types.Type) {
|
fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) {
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
mut val_type := types.void_type
|
// mut val_type := types.void_type
|
||||||
|
mut val_ti := types.new_base_ti(._void, 0)
|
||||||
mut exprs := []ast.Expr
|
mut exprs := []ast.Expr
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for p.tok.kind != .rsbr {
|
for p.tok.kind != .rsbr {
|
||||||
expr,typ := p.expr(0)
|
expr,ti := p.expr(0)
|
||||||
// The first element's type
|
// The first element's type
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
val_type = typ
|
val_ti = ti
|
||||||
}
|
}
|
||||||
else if !types.check(val_type, typ) {
|
else if !types.check(val_ti, ti) {
|
||||||
p.error('expected array element with type `$val_type.name`')
|
p.error('expected array element with type `$val_ti.type_name`')
|
||||||
}
|
}
|
||||||
exprs << expr
|
exprs << expr
|
||||||
i++
|
i++
|
||||||
|
@ -511,32 +644,32 @@ fn (p mut Parser) array_init() (ast.Expr,types.Type) {
|
||||||
}
|
}
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
node = ast.ArrayInit{
|
node = ast.ArrayInit{
|
||||||
typ: val_type
|
ti: val_ti
|
||||||
exprs: exprs
|
exprs: exprs
|
||||||
}
|
}
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
return node,val_type
|
return node,val_ti
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) parse_number_literal() (ast.Expr,types.Type) {
|
fn (p mut Parser) parse_number_literal() (ast.Expr,types.TypeIdent) {
|
||||||
lit := p.tok.lit
|
lit := p.tok.lit
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
mut typ := types.int_type
|
mut ti := types.new_base_ti(._int, 0)
|
||||||
if lit.contains('.') {
|
if lit.contains('.') {
|
||||||
node = ast.FloatLiteral{
|
node = ast.FloatLiteral{
|
||||||
// val: lit.f64()
|
// val: lit.f64()
|
||||||
val: lit
|
val: lit
|
||||||
}
|
}
|
||||||
typ = types.f64_type
|
ti = types.new_base_ti(._f64, 0)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
node = ast.IntegerLiteral{
|
node = ast.IntegerLiteral{
|
||||||
val: lit.int()
|
val: lit.int()
|
||||||
}
|
}
|
||||||
typ = types.int_type
|
// ti = types.new_base_ti(._int, 0)
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
return node,typ
|
return node,ti
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) module_decl() ast.Module {
|
fn (p mut Parser) module_decl() ast.Module {
|
||||||
|
@ -569,18 +702,22 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
p.check(.colon)
|
p.check(.colon)
|
||||||
}
|
}
|
||||||
field_name := p.check_name()
|
field_name := p.check_name()
|
||||||
typ := p.parse_type()
|
ti := p.parse_ti()
|
||||||
ast_fields << ast.Field{
|
ast_fields << ast.Field{
|
||||||
name: field_name
|
name: field_name
|
||||||
typ: typ
|
ti: ti
|
||||||
}
|
}
|
||||||
fields << types.Field{
|
fields << types.Field{
|
||||||
name: field_name
|
name: field_name
|
||||||
type_idx: typ.idx
|
type_idx: ti.type_idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
p.table.register_type(types.Type{
|
if name in p.table.type_idxs {
|
||||||
|
println('placeholder exists: $name')
|
||||||
|
}
|
||||||
|
println('about to register: $name')
|
||||||
|
p.table.register_struct(types.Struct{
|
||||||
name: name
|
name: name
|
||||||
fields: fields
|
fields: fields
|
||||||
})
|
})
|
||||||
|
@ -594,8 +731,8 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
fn (p mut Parser) return_stmt() ast.Return {
|
fn (p mut Parser) return_stmt() ast.Return {
|
||||||
p.next()
|
p.next()
|
||||||
expr,t := p.expr(0)
|
expr,t := p.expr(0)
|
||||||
if !types.check(p.return_type, t) {
|
if !types.check(p.return_ti, t) {
|
||||||
p.error('cannot use `$t.name` as type `$p.return_type.name` in return argument')
|
p.error('cannot use `$t.type_name` as type `$p.return_ti.type_name` in return argument')
|
||||||
}
|
}
|
||||||
return ast.Return{
|
return ast.Return{
|
||||||
expr: expr
|
expr: expr
|
||||||
|
@ -621,7 +758,7 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
||||||
}
|
}
|
||||||
p.table.register_var(table.Var{
|
p.table.register_var(table.Var{
|
||||||
name: name
|
name: name
|
||||||
typ: t
|
ti: t
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
})
|
})
|
||||||
// println(p.table.names)
|
// println(p.table.names)
|
||||||
|
@ -630,7 +767,7 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
||||||
name: name
|
name: name
|
||||||
expr: expr // p.expr(token.lowest_prec)
|
expr: expr // p.expr(token.lowest_prec)
|
||||||
|
|
||||||
typ: t
|
ti: t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,9 @@ import (
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
// struct_fields map[string][]string
|
// struct_fields map[string][]string
|
||||||
pub mut:
|
pub mut:
|
||||||
types map[string]types.Type
|
// types map[string]types.Type
|
||||||
|
types []types.Type
|
||||||
|
type_idxs map[string]int
|
||||||
local_vars []Var
|
local_vars []Var
|
||||||
// fns Hashmap
|
// fns Hashmap
|
||||||
fns map[string]Fn
|
fns map[string]Fn
|
||||||
|
@ -20,7 +22,7 @@ pub mut:
|
||||||
pub struct Var {
|
pub struct Var {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
typ types.Type
|
ti types.TypeIdent
|
||||||
is_mut bool
|
is_mut bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,17 +30,23 @@ pub struct Fn {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
args []Var
|
args []Var
|
||||||
return_type types.Type
|
return_ti types.TypeIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_table() &Table {
|
pub fn new_table() &Table {
|
||||||
|
// mut t := &Table{}
|
||||||
|
// t.register_type(types.void_type)
|
||||||
|
// t.register_type(types.int_type)
|
||||||
|
// t.register_type(types.string_type)
|
||||||
|
// t.register_type(types.f64_type)
|
||||||
|
// t.register_type(types.bool_type)
|
||||||
|
// t.register_type(types.voidptr_type)
|
||||||
mut t := &Table{}
|
mut t := &Table{}
|
||||||
t.register_type(types.void_type)
|
// add dummy type at 0 so nothing can go there
|
||||||
t.register_type(types.int_type)
|
// save index check, 0 will mean not found
|
||||||
t.register_type(types.string_type)
|
t.types << types.Type{}
|
||||||
t.register_type(types.f64_type)
|
t.type_idxs['dymmy_type_at_idx_0'] = 0
|
||||||
t.register_type(types.bool_type)
|
|
||||||
t.register_type(types.voidptr_type)
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,19 +117,106 @@ pub fn (t mut Table) register_fn(new_fn Fn) {
|
||||||
t.fns[new_fn.name] = new_fn
|
t.fns[new_fn.name] = new_fn
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t mut Table) register_type(typ types.Type) {
|
pub fn (t mut Table) register_struct(typ types.Struct) int {
|
||||||
t.types[typ.name] = typ
|
mut t2 := types.Type{}
|
||||||
|
// existing
|
||||||
|
existing_idx := t.type_idxs[typ.name]
|
||||||
|
if existing_idx > 0 {
|
||||||
|
ex_type := t.types[existing_idx]
|
||||||
|
match ex_type {
|
||||||
|
types.Placeholder {
|
||||||
|
// override placeholder
|
||||||
|
println('placeholder exists: $it.name overidding')
|
||||||
|
t2 = {typ| idx: existing_idx}
|
||||||
|
t.types[existing_idx] = t2
|
||||||
|
return existing_idx
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// register
|
||||||
|
println('registering: $typ.name')
|
||||||
|
idx := t.types.len
|
||||||
|
t.type_idxs[typ.name] = idx
|
||||||
|
t2 = {typ| idx: idx}
|
||||||
|
t.types << t2
|
||||||
|
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t mut Table) find_or_register_map(typ types.Map) int {
|
||||||
|
// existing
|
||||||
|
existing_idx := t.type_idxs[typ.name]
|
||||||
|
if existing_idx > 0 {
|
||||||
|
return existing_idx
|
||||||
|
}
|
||||||
|
// register
|
||||||
|
idx := t.types.len
|
||||||
|
mut t2 := types.Type{}
|
||||||
|
t2 = {typ| idx: idx}
|
||||||
|
t.type_idxs[typ.name] = idx
|
||||||
|
t.types << t2
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t mut Table) find_or_register_array(typ types.Array) int {
|
||||||
|
// existing
|
||||||
|
existing_idx := t.type_idxs[typ.name]
|
||||||
|
if existing_idx > 0 {
|
||||||
|
return existing_idx
|
||||||
|
}
|
||||||
|
// register
|
||||||
|
idx := t.types.len
|
||||||
|
mut t2 := types.Type{}
|
||||||
|
t2 = {typ| idx: idx}
|
||||||
|
t.type_idxs[typ.name] = idx
|
||||||
|
t.types << t2
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t mut Table) find_or_register_array_fixed(typ types.ArrayFixed) int {
|
||||||
|
// existing
|
||||||
|
existing_idx := t.type_idxs[typ.name]
|
||||||
|
if existing_idx > 0 {
|
||||||
|
return existing_idx
|
||||||
|
}
|
||||||
|
// register
|
||||||
|
idx := t.types.len
|
||||||
|
mut t2 := types.Type{}
|
||||||
|
t2 = {typ| idx: idx}
|
||||||
|
t.type_idxs[typ.name] = idx
|
||||||
|
t.types << t2
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (t &Table) find_type_idx(name string) int {
|
||||||
|
return t.type_idxs[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t mut Table) add_placeholder_type(name string) int {
|
||||||
|
idx := t.types.len
|
||||||
|
t.type_idxs[name] = t.types.len
|
||||||
|
mut pt := types.Type{}
|
||||||
|
pt = types.Placeholder{
|
||||||
|
idx: idx
|
||||||
|
name: name
|
||||||
|
}
|
||||||
|
println('added placeholder: $name - $idx ')
|
||||||
|
t.types << pt
|
||||||
|
return idx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t &Table) find_type(name string) ?types.Type {
|
pub fn (t &Table) find_type(name string) ?types.Type {
|
||||||
typ := t.types[name]
|
idx := t.type_idxs[name]
|
||||||
if isnil(typ.name.str) || typ.name == '' {
|
if idx > 0 {
|
||||||
return none
|
return t.types[idx]
|
||||||
}
|
}
|
||||||
return typ
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t mut Table) new_tmp_var() string {
|
pub fn (t mut Table) new_tmp_var() string {
|
||||||
t.tmp_cnt++
|
t.tmp_cnt++
|
||||||
return 'tmp$t.tmp_cnt'
|
return 'tmp$t.tmp_cnt'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,208 @@
|
||||||
module types
|
module types
|
||||||
|
|
||||||
pub enum Kind {
|
pub enum Kind {
|
||||||
struct_
|
_placeholder,
|
||||||
builtin
|
_void,
|
||||||
enum_
|
_voidptr,
|
||||||
|
_charptr,
|
||||||
|
_byteptr,
|
||||||
|
_const,
|
||||||
|
_enum,
|
||||||
|
_struct,
|
||||||
|
_int,
|
||||||
|
_i8,
|
||||||
|
_i16,
|
||||||
|
_i64,
|
||||||
|
_byte,
|
||||||
|
_u16,
|
||||||
|
_u32,
|
||||||
|
_u64,
|
||||||
|
_f32,
|
||||||
|
_f64,
|
||||||
|
_string,
|
||||||
|
_char,
|
||||||
|
_bool,
|
||||||
|
_array,
|
||||||
|
_array_fixed,
|
||||||
|
_map,
|
||||||
|
_multi_return,
|
||||||
|
_variadic
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Type {
|
pub struct TypeIdent {
|
||||||
|
pub:
|
||||||
|
type_idx int
|
||||||
|
type_kind Kind
|
||||||
|
type_name string
|
||||||
|
nr_muls int
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn new_ti(type_kind Kind, type_name string, type_idx int, nr_muls int) TypeIdent {
|
||||||
|
return TypeIdent{
|
||||||
|
type_idx: type_idx
|
||||||
|
type_kind: type_kind
|
||||||
|
type_name: type_name
|
||||||
|
nr_muls: nr_muls
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn new_base_ti(type_kind Kind, nr_muls int) TypeIdent {
|
||||||
|
return TypeIdent{
|
||||||
|
type_kind: type_kind
|
||||||
|
type_name: type_kind.str()
|
||||||
|
nr_muls: nr_muls
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (ti &TypeIdent) is_ptr() bool {
|
||||||
|
return ti.nr_muls > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (ti &TypeIdent) is_int() bool {
|
||||||
|
return ti.type_kind in [._i8, ._i16, ._int, ._i64, ._byte, ._u16, ._u32, ._u64]
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (ti &TypeIdent) is_float() bool {
|
||||||
|
return ti.type_kind in [._f32, ._f64]
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (ti &TypeIdent) is_number() bool {
|
||||||
|
return ti.is_int() || ti.is_float()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ti &TypeIdent) str() string {
|
||||||
|
return '$ti.type_kind.str() $ti.type_idx: $ti.type_name ($ti.nr_muls)'
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check(got, expected &TypeIdent) bool {
|
||||||
|
if got.type_idx != expected.type_idx {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t Kind) str() string {
|
||||||
|
t_str := match t {
|
||||||
|
._placeholder {
|
||||||
|
'placeholder'
|
||||||
|
}
|
||||||
|
._void {
|
||||||
|
'void'
|
||||||
|
}
|
||||||
|
._voidptr {
|
||||||
|
'voidptr'
|
||||||
|
}
|
||||||
|
._charptr {
|
||||||
|
'charptr'
|
||||||
|
}
|
||||||
|
._byteptr {
|
||||||
|
'byteptr'
|
||||||
|
}
|
||||||
|
._const {
|
||||||
|
'const'
|
||||||
|
}
|
||||||
|
._enum {
|
||||||
|
'enum'
|
||||||
|
}
|
||||||
|
._struct {
|
||||||
|
'struct'
|
||||||
|
}
|
||||||
|
._int {
|
||||||
|
'int'
|
||||||
|
}
|
||||||
|
._i8 {
|
||||||
|
'i8'
|
||||||
|
}
|
||||||
|
._i16 {
|
||||||
|
'i16'
|
||||||
|
}
|
||||||
|
._i64 {
|
||||||
|
'i64'
|
||||||
|
}
|
||||||
|
._byte {
|
||||||
|
'byte'
|
||||||
|
}
|
||||||
|
._u16 {
|
||||||
|
'u18'
|
||||||
|
}
|
||||||
|
._f32 {
|
||||||
|
'f32'
|
||||||
|
}
|
||||||
|
._f64 {
|
||||||
|
'f64'
|
||||||
|
}
|
||||||
|
._string {
|
||||||
|
'string'
|
||||||
|
}
|
||||||
|
._char {
|
||||||
|
'char'
|
||||||
|
}
|
||||||
|
._bool {
|
||||||
|
'bool'
|
||||||
|
}
|
||||||
|
._array {
|
||||||
|
'array'
|
||||||
|
}
|
||||||
|
._array_fixed {
|
||||||
|
'array_fixed'
|
||||||
|
}
|
||||||
|
._map {
|
||||||
|
'map'
|
||||||
|
}
|
||||||
|
._multi_return {
|
||||||
|
'multi_return'
|
||||||
|
}
|
||||||
|
._variadic {
|
||||||
|
'variadic'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
'unknown'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t_str
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Type = Placeholder | Void | Voidptr | Charptr | Byteptr | Const | Enum | Struct |
|
||||||
|
Int | Float | String | Char | Byte | Bool | Array | ArrayFixed | Map | MultiReturn | Variadic
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Placeholder {
|
||||||
pub:
|
pub:
|
||||||
name string
|
|
||||||
idx int
|
idx int
|
||||||
// kind Kind
|
name string
|
||||||
|
kind Kind
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Void {}
|
||||||
|
|
||||||
|
pub struct Voidptr {}
|
||||||
|
|
||||||
|
pub struct Charptr {}
|
||||||
|
|
||||||
|
pub struct Byteptr {}
|
||||||
|
|
||||||
|
pub struct Const {
|
||||||
|
pub:
|
||||||
|
idx int
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Enum {
|
||||||
|
pub:
|
||||||
|
idx int
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Struct {
|
||||||
|
pub:
|
||||||
|
idx int
|
||||||
|
name string
|
||||||
fields []Field
|
fields []Field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,36 +215,95 @@ pub:
|
||||||
type_idx int
|
type_idx int
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const (
|
pub struct Int {
|
||||||
void_type = Type{
|
pub:
|
||||||
name: 'void'
|
bit_size u32
|
||||||
idx: 0
|
is_unsigned bool
|
||||||
}
|
|
||||||
int_type = Type{
|
|
||||||
name: 'int'
|
|
||||||
idx: 1
|
|
||||||
}
|
|
||||||
string_type = Type{
|
|
||||||
name: 'string'
|
|
||||||
idx: 2
|
|
||||||
}
|
|
||||||
f64_type = Type{
|
|
||||||
name: 'f64'
|
|
||||||
idx: 3
|
|
||||||
}
|
|
||||||
bool_type = Type{
|
|
||||||
name: 'bool'
|
|
||||||
idx: 4
|
|
||||||
}
|
|
||||||
voidptr_type = Type{
|
|
||||||
name: 'voidptr'
|
|
||||||
idx: 5
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
pub fn check(got, expected &Type) bool {
|
|
||||||
if got.idx != expected.idx {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Float {
|
||||||
|
bit_size u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct String {}
|
||||||
|
|
||||||
|
pub struct Char {}
|
||||||
|
|
||||||
|
pub struct Byte {}
|
||||||
|
|
||||||
|
pub struct Bool {}
|
||||||
|
|
||||||
|
pub struct Array {
|
||||||
|
pub:
|
||||||
|
idx int
|
||||||
|
name string
|
||||||
|
elem_type_kind Kind
|
||||||
|
elem_type_idx int
|
||||||
|
nr_dims int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ArrayFixed {
|
||||||
|
pub:
|
||||||
|
idx int
|
||||||
|
name string
|
||||||
|
elem_type_kind Kind
|
||||||
|
elem_type_idx int
|
||||||
|
size int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Map {
|
||||||
|
pub:
|
||||||
|
idx int
|
||||||
|
name string
|
||||||
|
key_type_kind Kind
|
||||||
|
key_type_idx int
|
||||||
|
value_type_kind Kind
|
||||||
|
value_type_idx int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MultiReturn {
|
||||||
|
pub:
|
||||||
|
elem_type_kinds []Kind
|
||||||
|
elem_type_idxs []int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Variadic {
|
||||||
|
pub:
|
||||||
|
elem_type_kind Kind
|
||||||
|
elem_type_idx int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t Void) str() string { return 'void' }
|
||||||
|
pub fn (t Voidptr) str() string { return 'voidptr' }
|
||||||
|
pub fn (t Charptr) str() string { return 'charptr' }
|
||||||
|
pub fn (t Byteptr) str() string { return 'Byteptr' }
|
||||||
|
pub fn (t Const) str() string { return t.name }
|
||||||
|
pub fn (t Enum) str() string { return t.name }
|
||||||
|
pub fn (t Struct) str() string { return t.name }
|
||||||
|
pub fn (t Int) str() string { return if t.is_unsigned {'u$t.bit_size' } else { 'i$t.bit_size' } }
|
||||||
|
pub fn (t Float) str() string { return 'f$t.bit_size' }
|
||||||
|
pub fn (t String) str() string { return 'string' }
|
||||||
|
pub fn (t Char) str() string { return 'char' }
|
||||||
|
pub fn (t Byte) str() string { return 'byte' }
|
||||||
|
pub fn (t Array) str() string { return t.name }
|
||||||
|
pub fn (t ArrayFixed) str() string { return t.name }
|
||||||
|
pub fn (t Map) str() string { return t.name }
|
||||||
|
pub fn (t MultiReturn) str() string { return 'multi_return_$t.elem_type_kinds.str()' }
|
||||||
|
pub fn (t Variadic) str() string { return 'variadic_$t.elem_type_kind.str()' }
|
||||||
|
|
||||||
|
pub const (
|
||||||
|
void_type = Void{}
|
||||||
|
voidptr_type = Voidptr{}
|
||||||
|
charptr_type = Charptr{}
|
||||||
|
byteptr_type = Byteptr{}
|
||||||
|
int_type = Int{32, false}
|
||||||
|
i64_type = Int{64, false}
|
||||||
|
byte_type = Int{8, true}
|
||||||
|
u32_type = Int{32, true}
|
||||||
|
u64_type = Int{64, true}
|
||||||
|
f32_type = Float{32}
|
||||||
|
f64_type = Float{64}
|
||||||
|
string_type = String{}
|
||||||
|
char_type = Char{}
|
||||||
|
bool_type = Bool{}
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
module types
|
||||||
|
|
||||||
|
fn test_types() {
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue