v2: type checker + lots of other changes
parent
8c1b03c731
commit
09d1eb7c55
|
@ -8,11 +8,7 @@ import (
|
||||||
os.cmdline
|
os.cmdline
|
||||||
strings
|
strings
|
||||||
filepath
|
filepath
|
||||||
v.gen.x64
|
v.builder
|
||||||
v.table
|
|
||||||
v.parser
|
|
||||||
v.gen
|
|
||||||
time
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
|
@ -390,29 +386,15 @@ pub fn (v mut V) compile2() {
|
||||||
println('all .v files before:')
|
println('all .v files before:')
|
||||||
println(v.files)
|
println(v.files)
|
||||||
}
|
}
|
||||||
v.add_v_files_to_compile()
|
// v.add_v_files_to_compile()
|
||||||
|
v.files << v.dir
|
||||||
if v.pref.is_verbose {
|
if v.pref.is_verbose {
|
||||||
println('all .v files:')
|
println('all .v files:')
|
||||||
println(v.files)
|
println(v.files)
|
||||||
}
|
}
|
||||||
table := table.new_table()
|
mut b := builder.new_builder()
|
||||||
files := parser.parse_files(v.files, table)
|
b.build_c(v.files, v.out_name)
|
||||||
c := gen.cgen(files, table)
|
|
||||||
println('out: $v.out_name_c')
|
|
||||||
os.write_file(v.out_name_c, c)
|
|
||||||
/*
|
|
||||||
cgen.genln(c_builtin_types)
|
|
||||||
|
|
||||||
if !v.pref.is_bare {
|
|
||||||
cgen.genln(c_headers)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cgen.genln(bare_c_headers)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
v.cc()
|
v.cc()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (v mut V) compile_x64() {
|
pub fn (v mut V) compile_x64() {
|
||||||
|
@ -423,12 +405,8 @@ pub fn (v mut V) compile_x64() {
|
||||||
//v.files << v.v_files_from_dir(filepath.join(v.pref.vlib_path,'builtin','bare'))
|
//v.files << v.v_files_from_dir(filepath.join(v.pref.vlib_path,'builtin','bare'))
|
||||||
v.files << v.dir
|
v.files << v.dir
|
||||||
|
|
||||||
table := &table.new_table()
|
mut b := builder.new_builder()
|
||||||
ticks := time.ticks()
|
b.build_x64(v.files, v.out_name)
|
||||||
files := parser.parse_files(v.files, table)
|
|
||||||
println('PARSE: ${time.ticks() - ticks}ms')
|
|
||||||
x64.gen(files, v.out_name)
|
|
||||||
println('x64 GEN: ${time.ticks() - ticks}ms')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v mut V) generate_init() {
|
fn (v mut V) generate_init() {
|
||||||
|
|
|
@ -45,6 +45,7 @@ pub:
|
||||||
// `foo.bar`
|
// `foo.bar`
|
||||||
pub struct SelectorExpr {
|
pub struct SelectorExpr {
|
||||||
pub:
|
pub:
|
||||||
|
pos token.Position
|
||||||
expr Expr
|
expr Expr
|
||||||
field string
|
field string
|
||||||
}
|
}
|
||||||
|
@ -60,11 +61,13 @@ pub:
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
|
// type_idx int
|
||||||
ti types.TypeIdent
|
ti types.TypeIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StructDecl {
|
pub struct StructDecl {
|
||||||
pub:
|
pub:
|
||||||
|
pos token.Position
|
||||||
name string
|
name string
|
||||||
fields []Field
|
fields []Field
|
||||||
is_pub bool
|
is_pub bool
|
||||||
|
@ -72,7 +75,7 @@ pub:
|
||||||
|
|
||||||
pub struct StructInit {
|
pub struct StructInit {
|
||||||
pub:
|
pub:
|
||||||
// typ types.TypeIdent
|
pos token.Position
|
||||||
ti types.TypeIdent
|
ti types.TypeIdent
|
||||||
fields []string
|
fields []string
|
||||||
exprs []Expr
|
exprs []Expr
|
||||||
|
@ -81,7 +84,9 @@ pub:
|
||||||
// import statement
|
// import statement
|
||||||
pub struct Import {
|
pub struct Import {
|
||||||
pub:
|
pub:
|
||||||
mods map[string]string // alias -> module
|
pos token.Position
|
||||||
|
mod string
|
||||||
|
alias string
|
||||||
// expr Expr
|
// expr Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,24 +108,27 @@ pub:
|
||||||
|
|
||||||
pub struct CallExpr {
|
pub struct CallExpr {
|
||||||
pub:
|
pub:
|
||||||
// func Expr
|
// tok token.Token
|
||||||
|
pos token.Position
|
||||||
|
mut:
|
||||||
|
// func Expr
|
||||||
name string
|
name string
|
||||||
args []Expr
|
args []Expr
|
||||||
is_unknown bool
|
|
||||||
tok token.Token
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MethodCallExpr {
|
pub struct MethodCallExpr {
|
||||||
pub:
|
pub:
|
||||||
|
// tok token.Token
|
||||||
|
pos token.Position
|
||||||
expr Expr
|
expr Expr
|
||||||
name string
|
name string
|
||||||
args []Expr
|
args []Expr
|
||||||
is_unknown bool
|
|
||||||
tok token.Token
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Return {
|
pub struct Return {
|
||||||
pub:
|
pub:
|
||||||
|
pos token.Position
|
||||||
|
expected_ti types.TypeIdent // TODO: remove once checker updated
|
||||||
exprs []Expr
|
exprs []Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,12 +152,30 @@ pub struct VarDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
expr Expr
|
expr Expr
|
||||||
|
is_mut bool
|
||||||
|
mut:
|
||||||
ti types.TypeIdent
|
ti types.TypeIdent
|
||||||
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
pub:
|
pub:
|
||||||
stmts []Stmt
|
mod Module
|
||||||
|
imports []Import
|
||||||
|
stmts []Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IdentVar {
|
||||||
|
pub:
|
||||||
|
expr Expr
|
||||||
|
ti types.TypeIdent
|
||||||
|
}
|
||||||
|
|
||||||
|
type IdentInfo = IdentVar
|
||||||
|
|
||||||
|
pub enum IdentKind {
|
||||||
|
blank_ident
|
||||||
|
variable
|
||||||
}
|
}
|
||||||
|
|
||||||
// A single identifier
|
// A single identifier
|
||||||
|
@ -157,14 +183,18 @@ pub struct Ident {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
tok_kind token.Kind
|
tok_kind token.Kind
|
||||||
|
pos token.Position
|
||||||
value string
|
value string
|
||||||
|
mut:
|
||||||
|
kind IdentKind
|
||||||
|
info IdentInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BinaryExpr {
|
pub struct BinaryExpr {
|
||||||
pub:
|
pub:
|
||||||
// tok_kind token.Kind
|
|
||||||
// op BinaryOp
|
// op BinaryOp
|
||||||
op token.Kind
|
op token.Kind
|
||||||
|
pos token.Position
|
||||||
left Expr
|
left Expr
|
||||||
// left_ti types.TypeIdent
|
// left_ti types.TypeIdent
|
||||||
right Expr
|
right Expr
|
||||||
|
@ -231,6 +261,7 @@ pub:
|
||||||
|
|
||||||
pub struct ReturnStmt {
|
pub struct ReturnStmt {
|
||||||
tok_kind token.Kind // or pos
|
tok_kind token.Kind // or pos
|
||||||
|
pos token.Position
|
||||||
results []Expr
|
results []Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,9 +277,10 @@ pub:
|
||||||
|
|
||||||
pub struct AssignExpr {
|
pub struct AssignExpr {
|
||||||
pub:
|
pub:
|
||||||
|
op token.Kind
|
||||||
|
pos token.Position
|
||||||
left Expr
|
left Expr
|
||||||
val Expr
|
val Expr
|
||||||
op token.Kind
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ArrayInit {
|
pub struct ArrayInit {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
module builder
|
||||||
|
|
||||||
|
import (
|
||||||
|
os
|
||||||
|
time
|
||||||
|
v.table
|
||||||
|
v.checker
|
||||||
|
v.parser
|
||||||
|
v.gen
|
||||||
|
v.gen.x64
|
||||||
|
)
|
||||||
|
|
||||||
|
pub struct Builder {
|
||||||
|
pub:
|
||||||
|
table &table.Table
|
||||||
|
checker checker.Checker
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_builder() Builder {
|
||||||
|
table := table.new_table()
|
||||||
|
return Builder{
|
||||||
|
table: table
|
||||||
|
checker: checker.new_checker(table)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (b mut Builder) gen_c(v_files []string) string {
|
||||||
|
ast_files := parser.parse_files(v_files, b.table)
|
||||||
|
b.checker.check_files(v_files, ast_files)
|
||||||
|
return gen.cgen(ast_files, b.table)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (b mut Builder) build_c(v_files []string, out_file string) {
|
||||||
|
os.write_file(out_file, b.gen_c(v_files))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (b mut Builder) build_x64(v_files []string, out_file string) {
|
||||||
|
ticks := time.ticks()
|
||||||
|
ast_files := parser.parse_files(v_files, b.table)
|
||||||
|
println('PARSE: ${time.ticks() - ticks}ms')
|
||||||
|
b.checker.check_files(v_files, ast_files)
|
||||||
|
println('CHECK: ${time.ticks() - ticks}ms')
|
||||||
|
x64.gen(ast_files, out_file)
|
||||||
|
println('x64 GEN: ${time.ticks() - ticks}ms')
|
||||||
|
}
|
|
@ -0,0 +1,258 @@
|
||||||
|
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
module checker
|
||||||
|
|
||||||
|
import (
|
||||||
|
v.ast
|
||||||
|
v.table
|
||||||
|
v.types
|
||||||
|
v.token
|
||||||
|
)
|
||||||
|
|
||||||
|
pub struct Checker {
|
||||||
|
table &table.Table
|
||||||
|
mut:
|
||||||
|
file_name string
|
||||||
|
// TODO: resolved
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_checker(table &table.Table) Checker {
|
||||||
|
return Checker{
|
||||||
|
table: table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c &Checker) check(ast_file ast.File) {
|
||||||
|
for stmt in ast_file.stmts {
|
||||||
|
c.stmt(stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c mut Checker) check_files(v_files []string, ast_files []ast.File) {
|
||||||
|
for i, file in ast_files {
|
||||||
|
c.file_name = v_files[i]
|
||||||
|
c.check(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) {
|
||||||
|
typ := c.table.find_type(struct_init.ti.name) or {
|
||||||
|
c.error('unknown struct: $struct_init.ti.name', struct_init.pos)
|
||||||
|
panic('')
|
||||||
|
}
|
||||||
|
match typ.kind {
|
||||||
|
.placeholder {
|
||||||
|
c.error('unknown struct: $struct_init.ti.name', struct_init.pos)
|
||||||
|
}
|
||||||
|
.struct_ {
|
||||||
|
info := typ.info as types.Struct
|
||||||
|
for i, expr in struct_init.exprs {
|
||||||
|
field := info.fields[i]
|
||||||
|
expr_ti := c.table.get_expr_ti(expr)
|
||||||
|
if !c.table.check(expr_ti, field.ti) {
|
||||||
|
c.error('cannot assign $expr_ti.name as $field.ti.name for field $field.name', struct_init.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c &Checker) check_binary_expr(binary_expr ast.BinaryExpr) {
|
||||||
|
left_ti := c.table.get_expr_ti(binary_expr.left)
|
||||||
|
right_ti := c.table.get_expr_ti(binary_expr.right)
|
||||||
|
if !c.table.check(&right_ti, &left_ti) {
|
||||||
|
c.error('binary expr: cannot use $right_ti.name as $left_ti.name', binary_expr.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c &Checker) check_assign_expr(assign_expr ast.AssignExpr) {
|
||||||
|
left_ti := c.table.get_expr_ti(assign_expr.left)
|
||||||
|
right_ti := c.table.get_expr_ti(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c &Checker) check_call_expr(call_expr ast.CallExpr) {
|
||||||
|
fn_name := call_expr.name
|
||||||
|
if f := c.table.find_fn(fn_name) {
|
||||||
|
// return_ti := f.return_ti
|
||||||
|
if call_expr.args.len < f.args.len {
|
||||||
|
c.error('too few arguments in call to `$fn_name`', call_expr.pos)
|
||||||
|
} else if call_expr.args.len > f.args.len {
|
||||||
|
c.error('too many arguments in call to `$fn_name`', call_expr.pos)
|
||||||
|
}
|
||||||
|
for i, arg in f.args {
|
||||||
|
arg_expr := call_expr.args[i]
|
||||||
|
ti := c.table.get_expr_ti(arg_expr)
|
||||||
|
if !c.table.check(&ti, &arg.ti) {
|
||||||
|
c.error('cannot use type `$ti.name` as type `$arg.ti.name` in argument to `$fn_name`', call_expr.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.error('unknown fn: $fn_name', call_expr.pos)
|
||||||
|
// c.warn('unknown function `$fn_name`')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) {
|
||||||
|
ti := c.table.get_expr_ti(method_call_expr.expr)
|
||||||
|
if !c.table.has_method(ti.idx, method_call_expr.name) {
|
||||||
|
c.error('type `$ti.name` has no method `$method_call_expr.name`', method_call_expr.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c &Checker) check_selector_expr(selector_expr ast.SelectorExpr) {
|
||||||
|
ti := c.table.get_expr_ti(selector_expr.expr)
|
||||||
|
field_name := selector_expr.field
|
||||||
|
// struct_ := c.table.types[ti.idx] as types.Struct
|
||||||
|
typ := c.table.types[ti.idx]
|
||||||
|
match typ.kind {
|
||||||
|
.struct_ {
|
||||||
|
// if !c.table.struct_has_field(it, field) {
|
||||||
|
// c.error('AAA unknown field `${it.name}.$field`')
|
||||||
|
// }
|
||||||
|
// TODO: fix bug
|
||||||
|
c.table.struct_find_field(typ, field_name) or {
|
||||||
|
c.error('unknown field `${typ.name}.$field_name`', selector_expr.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c.error('$ti.name is not a struct', selector_expr.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: non deferred
|
||||||
|
pub fn (c &Checker) check_return_stmt(return_stmt ast.Return) {
|
||||||
|
mut got_tis := []types.TypeIdent
|
||||||
|
for expr in return_stmt.exprs {
|
||||||
|
ti := c.table.get_expr_ti(expr)
|
||||||
|
got_tis << ti
|
||||||
|
}
|
||||||
|
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 types.MultiReturn
|
||||||
|
expected_tis = mr_info.tis
|
||||||
|
}
|
||||||
|
if 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)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c &Checker) stmt(node ast.Stmt) {
|
||||||
|
match node {
|
||||||
|
ast.FnDecl {
|
||||||
|
for stmt in it.stmts {
|
||||||
|
c.stmt(stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.Return {
|
||||||
|
c.check_return_stmt(it)
|
||||||
|
}
|
||||||
|
ast.VarDecl {
|
||||||
|
c.expr(it.expr)
|
||||||
|
}
|
||||||
|
ast.ForStmt {
|
||||||
|
c.expr(it.cond)
|
||||||
|
for stmt in it.stmts {
|
||||||
|
c.stmt(stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.ForCStmt {
|
||||||
|
c.stmt(it.init)
|
||||||
|
c.expr(it.cond)
|
||||||
|
c.stmt(it.inc)
|
||||||
|
for stmt in it.stmts {
|
||||||
|
c.stmt(stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ast.StructDecl {}
|
||||||
|
ast.ExprStmt {
|
||||||
|
c.expr(it.expr)
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c &Checker) expr(node ast.Expr) {
|
||||||
|
match node {
|
||||||
|
ast.AssignExpr {
|
||||||
|
c.check_assign_expr(it)
|
||||||
|
}
|
||||||
|
// ast.IntegerLiteral {}
|
||||||
|
// ast.FloatLiteral {}
|
||||||
|
ast.PostfixExpr {
|
||||||
|
c.expr(it.expr)
|
||||||
|
}
|
||||||
|
ast.UnaryExpr {
|
||||||
|
c.expr(it.left)
|
||||||
|
}
|
||||||
|
// ast.StringLiteral {}
|
||||||
|
ast.PrefixExpr {
|
||||||
|
c.expr(it.right)
|
||||||
|
}
|
||||||
|
ast.BinaryExpr {
|
||||||
|
c.check_binary_expr(it)
|
||||||
|
}
|
||||||
|
ast.StructInit {
|
||||||
|
c.check_struct_init(it)
|
||||||
|
}
|
||||||
|
ast.CallExpr {
|
||||||
|
c.check_call_expr(it)
|
||||||
|
}
|
||||||
|
ast.MethodCallExpr {
|
||||||
|
c.check_method_call_expr(it)
|
||||||
|
}
|
||||||
|
ast.ArrayInit {
|
||||||
|
for expr in it.exprs {
|
||||||
|
c.expr(expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ast.Ident {}
|
||||||
|
// ast.BoolLiteral {}
|
||||||
|
ast.SelectorExpr {
|
||||||
|
c.check_selector_expr(it)
|
||||||
|
}
|
||||||
|
ast.IndexExpr {
|
||||||
|
c.expr(it.left)
|
||||||
|
c.expr(it.index)
|
||||||
|
}
|
||||||
|
ast.IfExpr {
|
||||||
|
c.expr(it.cond)
|
||||||
|
for i, stmt in it.stmts {
|
||||||
|
c.stmt(stmt)
|
||||||
|
}
|
||||||
|
if it.else_stmts.len > 0 {
|
||||||
|
for stmt in it.else_stmts {
|
||||||
|
c.stmt(stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c &Checker) error(s string, pos token.Position) {
|
||||||
|
print_backtrace()
|
||||||
|
final_msg_line := '$c.file_name:$pos.line_nr: error: $s'
|
||||||
|
eprintln(final_msg_line)
|
||||||
|
/*
|
||||||
|
if colored_output {
|
||||||
|
eprintln(term.bold(term.red(final_msg_line)))
|
||||||
|
}else{
|
||||||
|
eprintln(final_msg_line)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
exit(1)
|
||||||
|
}
|
|
@ -55,15 +55,18 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
g.write('int ${it.name}(')
|
g.write('int ${it.name}(')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('$it.ti.name ${it.name}(')
|
ti := g.table.refresh_ti(it.ti)
|
||||||
g.definitions.write('$it.ti.name ${it.name}(')
|
g.write('$ti.name ${it.name}(')
|
||||||
|
g.definitions.write('$ti.name ${it.name}(')
|
||||||
}
|
}
|
||||||
for i, arg in it.args {
|
for i, arg in it.args {
|
||||||
g.write(arg.ti.name + ' ' + arg.name)
|
// t := g.table.get_type(arg.ti.idx)
|
||||||
|
ti := g.table.refresh_ti(arg.ti)
|
||||||
|
g.write(ti.name + ' ' + arg.name)
|
||||||
if i < it.args.len - 1 {
|
if i < it.args.len - 1 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
g.definitions.write(arg.ti.name + ' ' + arg.name)
|
g.definitions.write(ti.name + ' ' + arg.name)
|
||||||
}
|
}
|
||||||
g.writeln(') { ')
|
g.writeln(') { ')
|
||||||
if !is_main {
|
if !is_main {
|
||||||
|
@ -82,7 +85,9 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
g.write('return ')
|
g.write('return ')
|
||||||
// multiple returns
|
// multiple returns
|
||||||
if it.exprs.len > 1 {
|
if it.exprs.len > 1 {
|
||||||
g.write('($g.fn_decl.ti.name){')
|
// t := g.table.get_type(g.fn_decl.ti.idx)
|
||||||
|
ti := g.table.refresh_ti(g.fn_decl.ti)
|
||||||
|
g.write('($ti.name){')
|
||||||
for i, expr in it.exprs {
|
for i, expr in it.exprs {
|
||||||
g.write('.arg$i=')
|
g.write('.arg$i=')
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
|
@ -99,7 +104,14 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('$it.ti.name $it.name = ')
|
mut ti := it.ti
|
||||||
|
if ti.kind == .unresolved {
|
||||||
|
ti = g.table.get_expr_ti(it.expr)
|
||||||
|
// println('A $it.ti.name')
|
||||||
|
// println('B $ti.name')
|
||||||
|
// panic("############# UNRESOLVED")
|
||||||
|
}
|
||||||
|
g.write('$ti.name $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
@ -128,7 +140,9 @@ 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.ti.name $field.name;')
|
// t := g.table.get_type(field.ti.idx)
|
||||||
|
ti := g.table.refresh_ti(field.ti)
|
||||||
|
g.writeln('\t$ti.name $field.name;')
|
||||||
}
|
}
|
||||||
g.writeln('} $it.name;')
|
g.writeln('} $it.name;')
|
||||||
}
|
}
|
||||||
|
@ -197,7 +211,9 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
// `user := User{name: 'Bob'}`
|
// `user := User{name: 'Bob'}`
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
g.writeln('($it.ti.name){')
|
// t := g.table.get_type(it.ti.idx)
|
||||||
|
ti := g.table.refresh_ti(it.ti)
|
||||||
|
g.writeln('($ti.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])
|
||||||
|
@ -215,8 +231,11 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
ast.MethodCallExpr {}
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.ti.name), {\t')
|
// 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')
|
||||||
for expr in it.exprs {
|
for expr in it.exprs {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
|
@ -248,17 +267,18 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
ast.IfExpr {
|
ast.IfExpr {
|
||||||
// If expression? Assign the value to a temp var.
|
// If expression? Assign the value to a temp var.
|
||||||
// Previously ?: was used, but it's too unreliable.
|
// Previously ?: was used, but it's too unreliable.
|
||||||
|
ti := g.table.refresh_ti(it.ti)
|
||||||
mut tmp := ''
|
mut tmp := ''
|
||||||
if it.ti.kind != .void {
|
if ti.kind != .void {
|
||||||
tmp = g.table.new_tmp_var()
|
tmp = g.table.new_tmp_var()
|
||||||
// g.writeln('$it.ti.name $tmp;')
|
// g.writeln('$ti.name $tmp;')
|
||||||
}
|
}
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
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.ti.kind != .void {
|
if i == it.stmts.len - 1 && ti.kind != .void {
|
||||||
// g.writeln('$tmp =')
|
// g.writeln('$tmp =')
|
||||||
println(1)
|
println(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import (
|
import (
|
||||||
os
|
os
|
||||||
filepath
|
filepath
|
||||||
v.parser
|
v.builder
|
||||||
v.ast
|
|
||||||
v.gen
|
|
||||||
v.table
|
|
||||||
term
|
term
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,9 +23,8 @@ fn test_c_files() {
|
||||||
ctext := os.read_file('$vroot/vlib/v/gen/tests/${i}.c') or {
|
ctext := os.read_file('$vroot/vlib/v/gen/tests/${i}.c') or {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
table := &table.new_table()
|
mut b := builder.new_builder()
|
||||||
program := parser.parse_file(path, table)
|
res := b.gen_c([path])
|
||||||
res := gen.cgen([program], table)
|
|
||||||
if compare_texts(res, ctext) {
|
if compare_texts(res, ctext) {
|
||||||
eprintln('${term_ok} ${i}')
|
eprintln('${term_ok} ${i}')
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,19 @@ module gen
|
||||||
import (
|
import (
|
||||||
strings
|
strings
|
||||||
v.ast
|
v.ast
|
||||||
|
v.table
|
||||||
term
|
term
|
||||||
)
|
)
|
||||||
|
|
||||||
struct JsGen {
|
struct JsGen {
|
||||||
out strings.Builder
|
out strings.Builder
|
||||||
|
table &table.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jsgen(program ast.File) string {
|
pub fn jsgen(program ast.File, table &table.Table) string {
|
||||||
mut g := JsGen{
|
mut g := JsGen{
|
||||||
out: strings.new_builder(100)
|
out: strings.new_builder(100)
|
||||||
|
table: table
|
||||||
}
|
}
|
||||||
for stmt in program.stmts {
|
for stmt in program.stmts {
|
||||||
g.stmt(stmt)
|
g.stmt(stmt)
|
||||||
|
@ -34,9 +37,11 @@ pub fn (g mut JsGen) writeln(s string) {
|
||||||
fn (g mut JsGen) stmt(node ast.Stmt) {
|
fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||||
match node {
|
match node {
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
g.write('/** @return { $it.ti.name } **/\nfunction ${it.name}(')
|
ti := g.table.refresh_ti(it.ti)
|
||||||
|
g.write('/** @return { $ti.name } **/\nfunction ${it.name}(')
|
||||||
for arg in it.args {
|
for arg in it.args {
|
||||||
g.write(' /** @type { arg.ti.name } **/ $arg.name')
|
arg_ti := g.table.refresh_ti(arg.ti)
|
||||||
|
g.write(' /** @type { $arg_ti.name } **/ $arg.name')
|
||||||
}
|
}
|
||||||
g.writeln(') { ')
|
g.writeln(') { ')
|
||||||
for stmt in it.stmts {
|
for stmt in it.stmts {
|
||||||
|
@ -55,7 +60,8 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('var /* $it.ti.name */ $it.name = ')
|
ti := g.table.refresh_ti(it.ti)
|
||||||
|
g.write('var /* $ti.name */ $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
@ -114,7 +120,8 @@ fn (g mut JsGen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
// `user := User{name: 'Bob'}`
|
// `user := User{name: 'Bob'}`
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
g.writeln('/*$it.ti.name*/{')
|
ti := g.table.refresh_ti(it.ti)
|
||||||
|
g.writeln('/*$ti.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])
|
||||||
|
|
|
@ -31,7 +31,7 @@ i < 10; i++;
|
||||||
1, 2, 3,
|
1, 2, 3,
|
||||||
});
|
});
|
||||||
int number = nums[0];
|
int number = nums[0];
|
||||||
void n = get_int2();
|
int n = get_int2();
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_int(string a) {
|
int get_int(string a) {
|
||||||
|
|
|
@ -149,10 +149,11 @@ pub fn (p mut Parser) parse_ti() types.TypeIdent {
|
||||||
else {
|
else {
|
||||||
// struct / enum
|
// struct / enum
|
||||||
mut idx := p.table.find_type_idx(name)
|
mut idx := p.table.find_type_idx(name)
|
||||||
// add placeholder
|
if idx > 0 {
|
||||||
if idx == 0 {
|
return types.new_ti(p.table.types[idx].kind, name, idx, nr_muls)
|
||||||
idx = p.table.add_placeholder_type(name)
|
|
||||||
}
|
}
|
||||||
|
// not found - add placeholder
|
||||||
|
idx = p.table.add_placeholder_type(name)
|
||||||
return types.new_ti(.placeholder, name, idx, nr_muls)
|
return types.new_ti(.placeholder, name, idx, nr_muls)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,50 +13,30 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.TypeIdent) {
|
||||||
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
|
|
||||||
is_unknown = false
|
|
||||||
mut args := []ast.Expr
|
mut args := []ast.Expr
|
||||||
mut return_ti := types.void_ti
|
// mut return_ti := types.void_ti
|
||||||
if f := p.table.find_fn(fn_name) {
|
for p.tok.kind != .rpar {
|
||||||
// println('found fn $fn_name')
|
e,_ := p.expr(0)
|
||||||
return_ti = f.return_ti
|
args << e
|
||||||
for i, arg in f.args {
|
if p.tok.kind != .rpar {
|
||||||
e,ti := p.expr(0)
|
p.check(.comma)
|
||||||
if !types.check(&arg.ti, &ti) {
|
|
||||||
p.error('cannot use type `$ti.name` as type `$arg.ti.name` in argument to `$fn_name`')
|
|
||||||
}
|
|
||||||
args << e
|
|
||||||
if i < f.args.len - 1 {
|
|
||||||
p.check(.comma)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if p.tok.kind == .comma {
|
|
||||||
p.error('too many arguments in call to `$fn_name`')
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
is_unknown = true
|
|
||||||
p.warn('unknown function `$fn_name`')
|
|
||||||
for p.tok.kind != .rpar {
|
|
||||||
e,_ := p.expr(0)
|
|
||||||
args << e
|
|
||||||
if p.tok.kind != .rpar {
|
|
||||||
p.check(.comma)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
node := ast.CallExpr{
|
node := ast.CallExpr{
|
||||||
name: fn_name
|
name: fn_name
|
||||||
args: args
|
args: args
|
||||||
is_unknown: is_unknown
|
// tok: tok
|
||||||
tok: tok
|
pos: tok.position()
|
||||||
// typ: return_ti
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if is_unknown {
|
mut ti := types.unresolved_ti
|
||||||
p.table.unknown_calls << node
|
if f := p.table.find_fn(fn_name) {
|
||||||
|
ti = f.return_ti
|
||||||
}
|
}
|
||||||
return node,return_ti
|
println('adding call_expr check $fn_name')
|
||||||
|
|
||||||
|
return node, ti
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) call_args() []ast.Expr {
|
pub fn (p mut Parser) call_args() []ast.Expr {
|
||||||
|
@ -170,6 +150,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
|
|
||||||
pub fn (p &Parser) check_fn_calls() {
|
pub fn (p &Parser) check_fn_calls() {
|
||||||
println('check fn calls2')
|
println('check fn calls2')
|
||||||
|
/*
|
||||||
for call in p.table.unknown_calls {
|
for call in p.table.unknown_calls {
|
||||||
f := p.table.find_fn(call.name) or {
|
f := p.table.find_fn(call.name) or {
|
||||||
p.error_at_line('unknown function `$call.name`', call.tok.line_nr)
|
p.error_at_line('unknown function `$call.name`', call.tok.line_nr)
|
||||||
|
@ -179,4 +160,5 @@ pub fn (p &Parser) check_fn_calls() {
|
||||||
// println(f.return_ti.name)
|
// println(f.return_ti.name)
|
||||||
// println('IN AST typ=' + call.typ.name)
|
// println('IN AST typ=' + call.typ.name)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
module parser
|
|
@ -60,6 +60,22 @@ pub fn parse_file(path string, table &table.Table) ast.File {
|
||||||
file_name: path
|
file_name: path
|
||||||
}
|
}
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
|
|
||||||
|
// module decl
|
||||||
|
module_decl := if p.tok.kind == .key_module {
|
||||||
|
p.module_decl()
|
||||||
|
} else {
|
||||||
|
ast.Module{
|
||||||
|
name: 'main'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// imports
|
||||||
|
mut imports := []ast.Import
|
||||||
|
for p.tok.kind == .key_import {
|
||||||
|
imports << p.import_stmt()
|
||||||
|
}
|
||||||
|
// TODO: import only mode
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// res := s.scan()
|
// res := s.scan()
|
||||||
if p.tok.kind == .eof {
|
if p.tok.kind == .eof {
|
||||||
|
@ -69,11 +85,12 @@ pub fn parse_file(path string, table &table.Table) ast.File {
|
||||||
// println('stmt at ' + p.tok.str())
|
// println('stmt at ' + p.tok.str())
|
||||||
stmts << p.top_stmt()
|
stmts << p.top_stmt()
|
||||||
}
|
}
|
||||||
p.check_fn_calls()
|
|
||||||
// println('nr stmts = $stmts.len')
|
// println('nr stmts = $stmts.len')
|
||||||
// println(stmts[0])
|
// println(stmts[0])
|
||||||
return ast.File{
|
return ast.File{
|
||||||
stmts: stmts
|
mod: module_decl
|
||||||
|
imports: imports
|
||||||
|
stmts: stmts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,14 +153,11 @@ fn (p mut Parser) check_name() string {
|
||||||
|
|
||||||
pub fn (p mut Parser) top_stmt() ast.Stmt {
|
pub fn (p mut Parser) top_stmt() ast.Stmt {
|
||||||
match p.tok.kind {
|
match p.tok.kind {
|
||||||
.key_module {
|
|
||||||
return p.module_decl()
|
|
||||||
}
|
|
||||||
.key_import {
|
|
||||||
return p.import_stmt()
|
|
||||||
}
|
|
||||||
.key_pub {
|
.key_pub {
|
||||||
match p.peek_tok.kind {
|
match p.peek_tok.kind {
|
||||||
|
.key_const {
|
||||||
|
return p.const_decl()
|
||||||
|
}
|
||||||
.key_fn {
|
.key_fn {
|
||||||
return p.fn_decl()
|
return p.fn_decl()
|
||||||
}
|
}
|
||||||
|
@ -154,16 +168,16 @@ pub fn (p mut Parser) top_stmt() ast.Stmt {
|
||||||
p.error('wrong pub keyword usage')
|
p.error('wrong pub keyword usage')
|
||||||
return ast.Stmt{}
|
return ast.Stmt{}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// .key_const {
|
|
||||||
// return p.const_decl()
|
|
||||||
// }
|
|
||||||
// .key_enum {
|
// .key_enum {
|
||||||
// return p.enum_decl()
|
// return p.enum_decl()
|
||||||
// }
|
// }
|
||||||
// .key_type {
|
// .key_type {
|
||||||
// return p.type_decl()
|
// return p.type_decl()
|
||||||
// }
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.key_const {
|
||||||
|
return p.const_decl()
|
||||||
}
|
}
|
||||||
.key_fn {
|
.key_fn {
|
||||||
return p.fn_decl()
|
return p.fn_decl()
|
||||||
|
@ -213,11 +227,12 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
||||||
pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr {
|
pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr {
|
||||||
op := p.tok.kind
|
op := p.tok.kind
|
||||||
p.next()
|
p.next()
|
||||||
val,_ := p.expr(0)
|
val, _ := p.expr(0)
|
||||||
node := ast.AssignExpr{
|
node := ast.AssignExpr{
|
||||||
left: left
|
left: left
|
||||||
op: op
|
|
||||||
val: val
|
val: val
|
||||||
|
op: op
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
@ -238,7 +253,7 @@ pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
|
||||||
// println('assignn_stmt() ' + op.str())
|
// println('assignn_stmt() ' + op.str())
|
||||||
p.next()
|
p.next()
|
||||||
right_expr,right_type := p.expr(0)
|
right_expr,right_type := p.expr(0)
|
||||||
if !types.check(left_type, right_type) {
|
if !p.table.check(left_type, right_type) {
|
||||||
p.error('oops')
|
p.error('oops')
|
||||||
}
|
}
|
||||||
return ast.AssignStmt{
|
return ast.AssignStmt{
|
||||||
|
@ -282,7 +297,8 @@ pub fn (p &Parser) warn(s string) {
|
||||||
|
|
||||||
pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) {
|
pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) {
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
mut ti := types.void_ti
|
// mut ti := types.void_ti
|
||||||
|
mut ti := types.unresolved_ti
|
||||||
if p.tok.lit == 'C' {
|
if p.tok.lit == 'C' {
|
||||||
p.next()
|
p.next()
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
|
@ -293,7 +309,8 @@ pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) {
|
||||||
}
|
}
|
||||||
// fn call
|
// fn call
|
||||||
if p.peek_tok.kind == .lpar {
|
if p.peek_tok.kind == .lpar {
|
||||||
x,ti2 := p.call_expr() // TODO `node,typ :=` should work
|
println('calling $p.tok.lit')
|
||||||
|
x, ti2 := p.call_expr() // TODO `node,typ :=` should work
|
||||||
node = x
|
node = x
|
||||||
ti = ti2
|
ti = ti2
|
||||||
}
|
}
|
||||||
|
@ -308,22 +325,21 @@ pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) {
|
||||||
field_name := p.check_name()
|
field_name := p.check_name()
|
||||||
field_names << field_name
|
field_names << field_name
|
||||||
p.check(.colon)
|
p.check(.colon)
|
||||||
// expr,field_type := p.expr(0)
|
|
||||||
expr,_ := p.expr(0)
|
expr,_ := p.expr(0)
|
||||||
// if !types.check( ,field_type
|
|
||||||
exprs << expr
|
exprs << expr
|
||||||
}
|
}
|
||||||
node = ast.StructInit{
|
node = ast.StructInit{
|
||||||
ti: ti
|
ti: ti
|
||||||
exprs: exprs
|
exprs: exprs
|
||||||
fields: field_names
|
fields: field_names
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// p.warn('name ')
|
// p.warn('name ')
|
||||||
// left := p.parse_ident()
|
// left := p.parse_ident()
|
||||||
node = ast.Ident{
|
mut ident := ast.Ident{
|
||||||
name: p.tok.lit
|
name: p.tok.lit
|
||||||
}
|
}
|
||||||
var := p.table.find_var(p.tok.lit) or {
|
var := p.table.find_var(p.tok.lit) or {
|
||||||
|
@ -331,6 +347,13 @@ pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) {
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
ti = var.ti
|
ti = var.ti
|
||||||
|
ident.kind = .variable
|
||||||
|
ident.info = ast.IdentVar {
|
||||||
|
ti: ti
|
||||||
|
expr: var.expr
|
||||||
|
}
|
||||||
|
// ident.ti = ti
|
||||||
|
node = ident
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
return node,ti
|
return node,ti
|
||||||
|
@ -438,59 +461,33 @@ fn (p mut Parser) index_expr(left ast.Expr) (ast.Expr,types.TypeIdent) {
|
||||||
return node,ti
|
return node,ti
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) dot_expr(left ast.Expr, ti types.TypeIdent) (ast.Expr,types.TypeIdent) {
|
fn (p mut Parser) dot_expr(left ast.Expr, left_ti &types.TypeIdent) (ast.Expr,types.TypeIdent) {
|
||||||
p.next()
|
p.next()
|
||||||
field_name := p.check_name()
|
field_name := p.check_name()
|
||||||
println('# $ti.name $ti.idx - $field_name')
|
ti := types.unresolved_ti
|
||||||
if ti.kind != .void {
|
|
||||||
p.warn('#### void type in dot_expr - field: $field_name')
|
|
||||||
}
|
|
||||||
struc := p.table.types[ti.idx] as types.Struct
|
|
||||||
// Method call
|
// Method call
|
||||||
if p.tok.kind == .lpar {
|
if p.tok.kind == .lpar {
|
||||||
if !p.table.struct_has_method(struc, field_name) {
|
|
||||||
p.error('type `$struc.name` has no method `$field_name`')
|
|
||||||
}
|
|
||||||
p.next()
|
p.next()
|
||||||
args := p.call_args()
|
args := p.call_args()
|
||||||
println('method call $field_name')
|
mcall_expr := ast.MethodCallExpr{
|
||||||
mut node := ast.Expr{}
|
|
||||||
node = ast.MethodCallExpr{
|
|
||||||
expr: left
|
expr: left
|
||||||
name: field_name
|
name: field_name
|
||||||
args: args
|
args: args
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
return node,types.int_ti
|
mut node := ast.Expr{}
|
||||||
|
node = mcall_expr
|
||||||
|
return node, ti
|
||||||
}
|
}
|
||||||
if !p.table.struct_has_field(struc, field_name) {
|
|
||||||
// t :=
|
|
||||||
p.error('type `$struc.name` has no field `$field_name`')
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
// p.next()
|
|
||||||
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
|
|
||||||
for f in typ.fields {
|
|
||||||
if f.name == field {
|
|
||||||
ok = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
p.error('unknown field `${typ.name}.$field`')
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
mut node := ast.Expr{}
|
sel_expr := ast.SelectorExpr{
|
||||||
node = ast.SelectorExpr{
|
|
||||||
expr: left
|
expr: left
|
||||||
field: field_name
|
field: field_name
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
return node,types.int_ti
|
mut node := ast.Expr{}
|
||||||
|
node = sel_expr
|
||||||
|
return node, ti
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,types.TypeIdent) {
|
fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,types.TypeIdent) {
|
||||||
|
@ -505,9 +502,10 @@ fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,types.TypeIdent) {
|
||||||
}
|
}
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.Expr{}
|
||||||
expr = ast.BinaryExpr{
|
expr = ast.BinaryExpr{
|
||||||
op: op
|
|
||||||
left: left
|
left: left
|
||||||
right: right
|
right: right
|
||||||
|
op: op
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
return expr,ti
|
return expr,ti
|
||||||
}
|
}
|
||||||
|
@ -587,7 +585,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||||
}
|
}
|
||||||
// `for cond {`
|
// `for cond {`
|
||||||
cond,ti := p.expr(0)
|
cond,ti := p.expr(0)
|
||||||
if !types.check(types.bool_ti, ti) {
|
if !p.table.check(types.bool_ti, ti) {
|
||||||
p.error('non-bool used as for condition')
|
p.error('non-bool used as for condition')
|
||||||
}
|
}
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
|
@ -604,7 +602,7 @@ 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_ti := p.expr(0)
|
cond,cond_ti := p.expr(0)
|
||||||
// if !types.check(types.bool_ti, cond_ti) {
|
// if !p.table.check(types.bool_ti, cond_ti) {
|
||||||
if cond_ti.kind != .bool {
|
if cond_ti.kind != .bool {
|
||||||
p.error('non-bool used as if condition')
|
p.error('non-bool used as if condition')
|
||||||
}
|
}
|
||||||
|
@ -670,7 +668,7 @@ fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
val_ti = ti
|
val_ti = ti
|
||||||
}
|
}
|
||||||
else if !types.check(val_ti, ti) {
|
else if !p.table.check(val_ti, ti) {
|
||||||
p.error('expected array element with type `$val_ti.name`')
|
p.error('expected array element with type `$val_ti.name`')
|
||||||
}
|
}
|
||||||
exprs << expr
|
exprs << expr
|
||||||
|
@ -714,25 +712,57 @@ fn (p mut Parser) parse_number_literal() (ast.Expr,types.TypeIdent) {
|
||||||
|
|
||||||
fn (p mut Parser) module_decl() ast.Module {
|
fn (p mut Parser) module_decl() ast.Module {
|
||||||
p.check(.key_module)
|
p.check(.key_module)
|
||||||
p.next()
|
name := p.check_name()
|
||||||
return ast.Module{}
|
return ast.Module{
|
||||||
|
name: name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) import_stmt() ast.Import {
|
fn (p mut Parser) parse_import() ast.Import {
|
||||||
p.check(.key_import)
|
mod_name := p.check_name()
|
||||||
name := p.check_name()
|
mut mod_alias := mod_name
|
||||||
mut alias := name
|
|
||||||
if p.tok.kind == .key_as {
|
if p.tok.kind == .key_as {
|
||||||
p.check(.key_as)
|
p.check(.key_as)
|
||||||
alias = p.check_name()
|
mod_alias = p.check_name()
|
||||||
}
|
}
|
||||||
mut mods := map[string]string
|
|
||||||
mods[alias] = name
|
|
||||||
return ast.Import{
|
return ast.Import{
|
||||||
mods: mods
|
mod: mod_name
|
||||||
|
alias: mod_alias
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (p mut Parser) import_stmt() []ast.Import {
|
||||||
|
p.check(.key_import)
|
||||||
|
mut imports := []ast.Import
|
||||||
|
if p.tok.kind == .lpar {
|
||||||
|
p.check(.lpar)
|
||||||
|
for p.tok.kind != .rpar {
|
||||||
|
imports << p.parse_import()
|
||||||
|
}
|
||||||
|
p.check(.rpar)
|
||||||
|
} else {
|
||||||
|
imports << p.parse_import()
|
||||||
|
}
|
||||||
|
return imports
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
//fn (p mut Parser) const_decl() ast... {
|
||||||
|
fn (p mut Parser) const_decl() ast.Stmt {
|
||||||
|
p.check(.key_const)
|
||||||
|
p.check(.lpar)
|
||||||
|
for p.tok.kind != .rpar {
|
||||||
|
name := p.check_name()
|
||||||
|
println('const: $name')
|
||||||
|
p.check(.assign)
|
||||||
|
_, _ := p.expr(0)
|
||||||
|
// expr, ti := p.expr(0)
|
||||||
|
}
|
||||||
|
p.check(.rpar)
|
||||||
|
return ast.Stmt{}
|
||||||
|
}
|
||||||
|
|
||||||
fn (p mut Parser) struct_decl() ast.StructDecl {
|
fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
is_pub := p.tok.kind == .key_pub
|
is_pub := p.tok.kind == .key_pub
|
||||||
if is_pub {
|
if is_pub {
|
||||||
|
@ -756,18 +786,23 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
}
|
}
|
||||||
fields << types.Field{
|
fields << types.Field{
|
||||||
name: field_name
|
name: field_name
|
||||||
type_idx: ti.idx
|
// type_idx: ti.idx
|
||||||
|
ti: ti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
p.table.register_struct(types.Struct{
|
p.table.register_type(table.Type{
|
||||||
|
kind: .struct_
|
||||||
name: name
|
name: name
|
||||||
fields: fields
|
info: types.Struct{
|
||||||
|
fields: fields
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return ast.StructDecl{
|
return ast.StructDecl{
|
||||||
name: name
|
name: name
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
fields: ast_fields
|
fields: ast_fields
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,11 +811,12 @@ fn (p mut Parser) return_stmt() ast.Return {
|
||||||
// return expressions
|
// return expressions
|
||||||
mut exprs := []ast.Expr
|
mut exprs := []ast.Expr
|
||||||
// return type idents
|
// return type idents
|
||||||
mut got_tis := []types.TypeIdent
|
// mut got_tis := []types.TypeIdent
|
||||||
for {
|
for {
|
||||||
expr,ti := p.expr(0)
|
// expr,ti := p.expr(0)
|
||||||
|
expr, _ := p.expr(0)
|
||||||
exprs << expr
|
exprs << expr
|
||||||
got_tis << ti
|
// got_tis << ti
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
}
|
}
|
||||||
|
@ -788,23 +824,13 @@ fn (p mut Parser) return_stmt() ast.Return {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut expected_tis := [p.return_ti]
|
// TODO: consider non deferred
|
||||||
if p.return_ti.kind == .multi_return {
|
stmt := ast.Return{
|
||||||
mr_type := p.table.types[p.return_ti.idx] as types.MultiReturn
|
expected_ti: p.return_ti
|
||||||
expected_tis = mr_type.tis
|
|
||||||
}
|
|
||||||
if expected_tis.len != got_tis.len {
|
|
||||||
p.error('wrong number of return arguments:\n\texpected: $expected_tis.str()\n\tgot: $got_tis.str()')
|
|
||||||
}
|
|
||||||
for i, exp_ti in expected_tis {
|
|
||||||
got_ti := got_tis[i]
|
|
||||||
if !types.check(got_ti, exp_ti) {
|
|
||||||
p.error('cannot use `$got_ti.name` as type `$exp_ti.name` in return argument')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ast.Return{
|
|
||||||
exprs: exprs
|
exprs: exprs
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
|
return stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) var_decl() ast.VarDecl {
|
fn (p mut Parser) var_decl() ast.VarDecl {
|
||||||
|
@ -820,25 +846,29 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
||||||
}
|
}
|
||||||
name := p.tok.lit
|
name := p.tok.lit
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
expr,ti := p.expr(token.lowest_prec)
|
expr, ti := p.expr(token.lowest_prec)
|
||||||
if _ := p.table.find_var(name) {
|
if _ := p.table.find_var(name) {
|
||||||
p.error('redefinition of `$name`')
|
p.error('redefinition of `$name`')
|
||||||
}
|
}
|
||||||
p.table.register_var(table.Var{
|
p.table.register_var(table.Var{
|
||||||
name: name
|
name: name
|
||||||
ti: ti
|
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
|
expr: expr
|
||||||
|
ti: ti
|
||||||
})
|
})
|
||||||
// println(p.table.names)
|
// println(p.table.names)
|
||||||
// println('added var `$name` with type $t.name')
|
node := ast.VarDecl{
|
||||||
return ast.VarDecl{
|
|
||||||
name: name
|
name: name
|
||||||
expr: expr // p.expr(token.lowest_prec)
|
expr: expr // p.expr(token.lowest_prec)
|
||||||
|
is_mut: is_mut
|
||||||
ti: ti
|
ti: ti
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn verror(s string) {
|
fn verror(s string) {
|
||||||
println(s)
|
println(s)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
v.ast
|
v.ast
|
||||||
v.gen
|
v.gen
|
||||||
v.table
|
v.table
|
||||||
|
v.checker
|
||||||
term
|
term
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ fn test_one() {
|
||||||
//
|
//
|
||||||
]
|
]
|
||||||
expected := 'int a = 10;int b = -a;int c = 20;'
|
expected := 'int a = 10;int b = -a;int c = 20;'
|
||||||
table := &table.Table{}
|
table := table.new_table()
|
||||||
mut e := []ast.Stmt
|
mut e := []ast.Stmt
|
||||||
for line in input {
|
for line in input {
|
||||||
e << parse_stmt(line, table)
|
e << parse_stmt(line, table)
|
||||||
|
@ -118,7 +119,8 @@ fn test_parse_expr() {
|
||||||
'-a;',
|
'-a;',
|
||||||
]
|
]
|
||||||
mut e := []ast.Stmt
|
mut e := []ast.Stmt
|
||||||
table := &table.Table{}
|
table := table.new_table()
|
||||||
|
mut checker := checker.new_checker(table)
|
||||||
for s in input {
|
for s in input {
|
||||||
// println('\n\nst="$s"')
|
// println('\n\nst="$s"')
|
||||||
e << parse_stmt(s, table)
|
e << parse_stmt(s, table)
|
||||||
|
@ -126,6 +128,7 @@ fn test_parse_expr() {
|
||||||
program := ast.File{
|
program := ast.File{
|
||||||
stmts: e
|
stmts: e
|
||||||
}
|
}
|
||||||
|
checker.check(program)
|
||||||
res := gen.cgen([program], table)
|
res := gen.cgen([program], table)
|
||||||
println('========')
|
println('========')
|
||||||
println(res)
|
println(res)
|
||||||
|
|
|
@ -1,30 +1,21 @@
|
||||||
module table
|
module table
|
||||||
|
|
||||||
import (
|
import (
|
||||||
v.types
|
|
||||||
v.ast
|
v.ast
|
||||||
|
v.types
|
||||||
)
|
)
|
||||||
|
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
// struct_fields map[string][]string
|
// struct_fields map[string][]string
|
||||||
pub mut:
|
pub mut:
|
||||||
types []types.Type
|
types []Type
|
||||||
// type_idxs Hashmap
|
// type_idxs Hashmap
|
||||||
type_idxs map[string]int
|
type_idxs map[string]int
|
||||||
local_vars []Var
|
local_vars []Var
|
||||||
// fns Hashmap
|
// fns Hashmap
|
||||||
fns map[string]Fn
|
fns map[string]Fn
|
||||||
methods [][]Fn
|
|
||||||
//
|
|
||||||
unknown_calls []ast.CallExpr
|
|
||||||
tmp_cnt int
|
tmp_cnt int
|
||||||
}
|
imports []string
|
||||||
|
|
||||||
pub struct Var {
|
|
||||||
pub:
|
|
||||||
name string
|
|
||||||
ti types.TypeIdent
|
|
||||||
is_mut bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Fn {
|
pub struct Fn {
|
||||||
|
@ -34,6 +25,29 @@ pub:
|
||||||
return_ti types.TypeIdent
|
return_ti types.TypeIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Var {
|
||||||
|
pub:
|
||||||
|
name string
|
||||||
|
is_mut bool
|
||||||
|
expr ast.Expr
|
||||||
|
mut:
|
||||||
|
ti types.TypeIdent
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Type {
|
||||||
|
pub:
|
||||||
|
parent_idx int
|
||||||
|
mut:
|
||||||
|
info types.TypeInfo
|
||||||
|
kind types.Kind
|
||||||
|
name string
|
||||||
|
methods []Fn
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t Type) str() string {
|
||||||
|
return t.name
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_table() &Table {
|
pub fn new_table() &Table {
|
||||||
mut t := &Table{}
|
mut t := &Table{}
|
||||||
t.register_builtin_types()
|
t.register_builtin_types()
|
||||||
|
@ -41,55 +55,56 @@ pub fn new_table() &Table {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t mut Table) register_builtin_types() {
|
pub fn (t mut Table) register_builtin_types() {
|
||||||
// add dummy type at 0 so nothing can go there
|
// reserve index 0 so nothing can go there
|
||||||
// save index check, 0 will mean not found
|
// save index check, 0 will mean not found
|
||||||
t.register_type(types.Type{}, 'dymmy_type_at_idx_0', 0)
|
t.register_type(Type{kind: .placeholder, name: 'reserved_0'})
|
||||||
t.register_type(types.Primitive{
|
t.register_type(Type{kind: .void, name: 'void'})
|
||||||
idx: types.void_type_idx
|
t.register_type(Type{kind: .voidptr, name: 'voidptr'})
|
||||||
kind: .void
|
t.register_type(Type{kind: .charptr, name: 'charptr'})
|
||||||
}, 'void', types.void_type_idx)
|
t.register_type(Type{kind: .byteptr, name: 'byteptr'})
|
||||||
t.register_type(types.Primitive{
|
t.register_type(Type{kind: .i8, name: 'i8'})
|
||||||
idx: types.voidptr_type_idx
|
t.register_type(Type{kind: .i16, name: 'i16'})
|
||||||
kind: .voidptr
|
t.register_type(Type{kind: .int, name: 'int'})
|
||||||
}, 'voidptr', types.voidptr_type_idx)
|
t.register_type(Type{kind: .i64, name: 'i64'})
|
||||||
t.register_type(types.Primitive{
|
t.register_type(Type{kind: .u16, name: 'u16'})
|
||||||
idx: types.charptr_type_idx
|
t.register_type(Type{kind: .u32, name: 'u32'})
|
||||||
kind: .charptr
|
t.register_type(Type{kind: .u64, name: 'u64'})
|
||||||
}, 'charptr', types.charptr_type_idx)
|
t.register_type(Type{kind: .f32, name: 'f32'})
|
||||||
t.register_type(types.Primitive{
|
t.register_type(Type{kind: .f64, name: 'f64'})
|
||||||
idx: types.byteptr_type_idx
|
t.register_type(Type{kind: .string, name: 'string'})
|
||||||
kind: .byteptr
|
t.register_type(Type{kind: .char, name: 'char'})
|
||||||
}, 'byteptr', types.byteptr_type_idx)
|
t.register_type(Type{kind: .byte, name: 'byte'})
|
||||||
t.register_type(types.Int{
|
t.register_type(Type{kind: .bool, name: 'bool'})
|
||||||
types.i8_type_idx,8,false}, 'i8', types.i8_type_idx)
|
}
|
||||||
t.register_type(types.Int{
|
|
||||||
types.i16_type_idx,16,false}, 'i16', types.i16_type_idx)
|
pub fn (t &Table) refresh_ti(ti types.TypeIdent) types.TypeIdent {
|
||||||
t.register_type(types.Int{
|
if ti.idx == 0 {
|
||||||
types.i64_type_idx,32,false}, 'int', types.int_type_idx)
|
return ti
|
||||||
t.register_type(types.Int{
|
}
|
||||||
types.i64_type_idx,64,false}, 'i64', types.i64_type_idx)
|
if ti.kind in [.placeholder, .unresolved] {
|
||||||
t.register_type(types.Int{
|
typ := t.types[ti.idx]
|
||||||
types.u16_type_idx,16,true}, 'u16', types.u16_type_idx)
|
return { ti|
|
||||||
t.register_type(types.Int{
|
kind: typ.kind,
|
||||||
types.u32_type_idx,32,true}, 'u32', types.u32_type_idx)
|
name: typ.name
|
||||||
t.register_type(types.Int{
|
}
|
||||||
types.u64_type_idx,64,true}, 'u64', types.u64_type_idx)
|
}
|
||||||
t.register_type(types.Float{
|
return ti
|
||||||
types.f64_type_idx,32}, 'f32', types.f32_type_idx)
|
}
|
||||||
t.register_type(types.Float{
|
|
||||||
types.f64_type_idx,64}, 'f64', types.f64_type_idx)
|
pub fn (t &Table) get_type(idx int) Type {
|
||||||
t.register_type(types.String{
|
if idx == 0 {
|
||||||
types.string_type_idx}, 'string', types.string_type_idx)
|
panic('get_type: idx 0')
|
||||||
t.register_type(types.Primitive{
|
}
|
||||||
idx: types.char_type_idx
|
return t.types[idx]
|
||||||
kind: .char
|
}
|
||||||
}, 'char', types.char_type_idx)
|
|
||||||
t.register_type(types.Primitive{
|
pub fn (t &Table) find_var_idx(name string) int {
|
||||||
idx: types.byte_type_idx
|
for i,var in t.local_vars {
|
||||||
kind: .byte
|
if var.name == name {
|
||||||
}, 'byte', types.byte_type_idx)
|
return i
|
||||||
t.register_type(types.Bool{
|
}
|
||||||
types.bool_type_idx}, 'bool', types.bool_type_idx)
|
}
|
||||||
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t &Table) find_var(name string) ?Var {
|
pub fn (t &Table) find_var(name string) ?Var {
|
||||||
|
@ -122,6 +137,7 @@ pub fn (t mut Table) clear_vars() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t mut Table) register_var(v Var) {
|
pub fn (t mut Table) register_var(v Var) {
|
||||||
|
println('register_var: $v.name - $v.ti.name')
|
||||||
t.local_vars << v
|
t.local_vars << v
|
||||||
/*
|
/*
|
||||||
mut new_var := {
|
mut new_var := {
|
||||||
|
@ -159,68 +175,66 @@ 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_method(ti types.TypeIdent, new_fn Fn) bool {
|
pub fn (t mut Table) register_method(ti &types.TypeIdent, new_fn Fn) bool {
|
||||||
println('register method `$new_fn.name` tiname=$ti.name ')
|
idx := ti.idx
|
||||||
/*
|
println('register method `$new_fn.name` type=$ti.name idx=$ti.idx')
|
||||||
match t.types[ti.idx] {
|
mut methods := t.types[idx].methods
|
||||||
types.Struct {
|
methods << new_fn
|
||||||
println('got struct')
|
t.types[idx].methods = methods
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mut struc := t.types[ti.idx] as types.Struct
|
|
||||||
if struc.methods.len == 0 {
|
|
||||||
struc.methods = make(0, 0, sizeof(types.Field))
|
|
||||||
}
|
|
||||||
println('register method `$new_fn.name` struct=$struc.name ')
|
|
||||||
struc.methods << types.Field{
|
|
||||||
name: new_fn.name
|
|
||||||
}
|
|
||||||
t.types[ti.idx] = struc
|
|
||||||
*/
|
|
||||||
|
|
||||||
println('register method `$new_fn.name` struct=$ti.name ')
|
|
||||||
println('##### $ti.idx - $t.methods.len')
|
|
||||||
t.methods[ti.idx] << new_fn
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (t &Table) has_method(type_idx int, name string) bool {
|
||||||
|
t.find_method(type_idx, 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 {
|
||||||
|
if method.name == name {
|
||||||
|
return method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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'
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t &Table) struct_has_field(s &types.Struct, name string) bool {
|
pub fn (t &Table) struct_has_field(s &Type, name string) bool {
|
||||||
println('struct_has_field($s.name, $name) s.idx=$s.idx types.len=$t.types.len s.parent_idx=$s.parent_idx')
|
println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
|
||||||
// for typ in t.types {
|
// for typ in t.types {
|
||||||
// println('$typ.idx $typ.name')
|
// println('$typ.idx $typ.name')
|
||||||
// }
|
// }
|
||||||
for field in s.fields {
|
if _ := t.struct_find_field(s, name) {
|
||||||
if field.name == name {
|
return true
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if s.parent_idx != 0 {
|
|
||||||
parent := t.types[s.parent_idx] as types.Struct
|
|
||||||
println('got parent $parent.name')
|
|
||||||
for field in parent.fields {
|
|
||||||
if field.name == name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t &Table) struct_has_method(s &types.Struct, name string) bool {
|
pub fn (t &Table) struct_find_field(s &Type, name string) ?types.Field {
|
||||||
for field in t.methods[s.idx] {
|
println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
|
||||||
|
info := s.info as types.Struct
|
||||||
|
for field in info.fields {
|
||||||
if field.name == name {
|
if field.name == name {
|
||||||
return true
|
return field
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
if s.parent_idx != 0 {
|
||||||
|
parent := t.types[s.parent_idx]
|
||||||
|
parent_info := s.info as types.Struct
|
||||||
|
println('got parent $parent.name')
|
||||||
|
for field in parent_info.fields {
|
||||||
|
if field.name == name {
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -229,7 +243,7 @@ pub fn (t &Table) find_type_idx(name string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &Table) find_type(name string) ?types.Type {
|
pub fn (t &Table) find_type(name string) ?Type {
|
||||||
idx := t.type_idxs[name]
|
idx := t.type_idxs[name]
|
||||||
if idx > 0 {
|
if idx > 0 {
|
||||||
return t.types[idx]
|
return t.types[idx]
|
||||||
|
@ -238,52 +252,30 @@ pub fn (t &Table) find_type(name string) ?types.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t mut Table) register_type(typ types.Type, name string, idx int) {
|
pub fn (t mut Table) register_type(typ Type) int {
|
||||||
// sanity check
|
|
||||||
if idx != t.types.len {
|
|
||||||
panic('error registering type $name, type.idx must = table.types.len (got `$idx` expected `$t.types.len`')
|
|
||||||
}
|
|
||||||
t.type_idxs[name] = idx
|
|
||||||
t.types << typ
|
|
||||||
e := []Fn
|
|
||||||
t.methods << e // TODO [] breaks V
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (t mut Table) register_struct(typ types.Struct) int {
|
|
||||||
println('register_struct($typ.name)')
|
|
||||||
// existing
|
|
||||||
existing_idx := t.type_idxs[typ.name]
|
existing_idx := t.type_idxs[typ.name]
|
||||||
if existing_idx > 0 {
|
if existing_idx > 0 {
|
||||||
ex_type := t.types[existing_idx]
|
ex_type := t.types[existing_idx]
|
||||||
match ex_type {
|
match ex_type.kind {
|
||||||
types.Placeholder {
|
.placeholder {
|
||||||
// override placeholder
|
// override placeholder
|
||||||
println('overriding type placeholder `$it.name` with struct')
|
println('overriding type placeholder `$typ.name`')
|
||||||
mut struct_type := types.Type{}
|
t.types[existing_idx] = {typ|
|
||||||
struct_type = {
|
methods: ex_type.methods
|
||||||
typ |
|
|
||||||
idx:existing_idx
|
|
||||||
}
|
}
|
||||||
t.types[existing_idx] = struct_type
|
|
||||||
return existing_idx
|
|
||||||
}
|
|
||||||
types.Struct {
|
|
||||||
return existing_idx
|
return existing_idx
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if ex_type.kind == typ.kind {
|
||||||
|
return existing_idx
|
||||||
|
}
|
||||||
panic('cannot register type `$typ.name`, another type with this name exists')
|
panic('cannot register type `$typ.name`, another type with this name exists')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// register
|
|
||||||
println('registering: $typ.name')
|
|
||||||
idx := t.types.len
|
idx := t.types.len
|
||||||
struct_type := {
|
t.types << typ
|
||||||
typ |
|
t.type_idxs[typ.name] = idx
|
||||||
idx:idx,
|
|
||||||
parent_idx:0,
|
|
||||||
}
|
|
||||||
t.register_type(struct_type, typ.name, idx)
|
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,13 +287,15 @@ pub fn (t mut Table) find_or_register_map(key_ti &types.TypeIdent, value_ti &typ
|
||||||
return existing_idx,name
|
return existing_idx,name
|
||||||
}
|
}
|
||||||
// register
|
// register
|
||||||
idx := t.types.len
|
map_type := Type{
|
||||||
map_type := types.Map{
|
kind: .map
|
||||||
name: name
|
name: name
|
||||||
key_type_idx: key_ti.idx
|
info: types.Map{
|
||||||
value_type_idx: value_ti.idx
|
key_type_idx: key_ti.idx
|
||||||
|
value_type_idx: value_ti.idx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.register_type(map_type, name, idx)
|
idx := t.register_type(map_type)
|
||||||
return idx,name
|
return idx,name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,16 +308,17 @@ pub fn (t mut Table) find_or_register_array(elem_ti &types.TypeIdent, nr_dims in
|
||||||
}
|
}
|
||||||
// register
|
// register
|
||||||
parent_idx := t.type_idxs['array']
|
parent_idx := t.type_idxs['array']
|
||||||
idx := t.types.len
|
array_type := Type{
|
||||||
array_type := types.Array{
|
|
||||||
idx: idx
|
|
||||||
parent_idx: parent_idx
|
parent_idx: parent_idx
|
||||||
|
kind: .array
|
||||||
name: name
|
name: name
|
||||||
elem_type_idx: elem_ti.idx
|
info: types.Array{
|
||||||
elem_is_ptr: elem_ti.is_ptr()
|
elem_type_idx: elem_ti.idx
|
||||||
nr_dims: nr_dims
|
elem_is_ptr: elem_ti.is_ptr()
|
||||||
|
nr_dims: nr_dims
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.register_type(array_type, name, idx)
|
idx := t.register_type(array_type)
|
||||||
return idx,name
|
return idx,name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,16 +330,17 @@ pub fn (t mut Table) find_or_register_array_fixed(elem_ti &types.TypeIdent, size
|
||||||
return existing_idx,name
|
return existing_idx,name
|
||||||
}
|
}
|
||||||
// register
|
// register
|
||||||
idx := t.types.len
|
array_fixed_type := Type{
|
||||||
array_fixed_type := types.ArrayFixed{
|
kind: .array_fixed
|
||||||
idx: idx
|
|
||||||
name: name
|
name: name
|
||||||
elem_type_idx: elem_ti.idx
|
info: types.ArrayFixed{
|
||||||
elem_is_ptr: elem_ti.is_ptr()
|
elem_type_idx: elem_ti.idx
|
||||||
size: size
|
elem_is_ptr: elem_ti.is_ptr()
|
||||||
nr_dims: nr_dims
|
size: size
|
||||||
|
nr_dims: nr_dims
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.register_type(array_fixed_type, name, idx)
|
idx := t.register_type(array_fixed_type)
|
||||||
return idx,name
|
return idx,name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,13 +355,14 @@ pub fn (t mut Table) find_or_register_multi_return(mr_tis []types.TypeIdent) (in
|
||||||
return existing_idx,name
|
return existing_idx,name
|
||||||
}
|
}
|
||||||
// register
|
// register
|
||||||
idx := t.types.len
|
mr_type := Type{
|
||||||
mr_type := types.MultiReturn{
|
kind: .multi_return
|
||||||
idx: idx
|
|
||||||
name: name
|
name: name
|
||||||
tis: mr_tis
|
info: types.MultiReturn{
|
||||||
|
tis: mr_tis
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.register_type(mr_type, name, idx)
|
idx := t.register_type(mr_type)
|
||||||
return idx,name
|
return idx,name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,22 +374,121 @@ pub fn (t mut Table) find_or_register_variadic(variadic_ti &types.TypeIdent) (in
|
||||||
return existing_idx,name
|
return existing_idx,name
|
||||||
}
|
}
|
||||||
// register
|
// register
|
||||||
idx := t.types.len
|
variadic_type := Type{
|
||||||
variadic_type := types.Variadic{
|
kind: .variadic
|
||||||
idx: idx
|
name: name
|
||||||
ti: variadic_ti
|
info: types.Variadic{
|
||||||
|
ti: variadic_ti
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.register_type(variadic_type, name, idx)
|
idx := t.register_type(variadic_type)
|
||||||
return idx,name
|
return idx,name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t mut Table) add_placeholder_type(name string) int {
|
pub fn (t mut Table) add_placeholder_type(name string) int {
|
||||||
idx := t.types.len
|
ph_type := Type{
|
||||||
ph_type := types.Placeholder{
|
kind: .placeholder
|
||||||
idx: idx
|
|
||||||
name: name
|
name: name
|
||||||
}
|
}
|
||||||
println('added placeholder: $name - $idx ')
|
idx := t.register_type(ph_type)
|
||||||
t.register_type(ph_type, name, idx)
|
println('added placeholder: $name - $idx')
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [inline]
|
||||||
|
// pub fn (t &Table) update_ti(ti &types.TypeIdent) types.TypeIdent {
|
||||||
|
// if ti.kind == .unresolved {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn (t &Table) check(got, expected &types.TypeIdent) bool {
|
||||||
|
println('check: $got.name, $expected.name')
|
||||||
|
if expected.kind == .voidptr {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
//if expected.name == 'array' {
|
||||||
|
// return true
|
||||||
|
//}
|
||||||
|
if got.idx != expected.idx {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (t &Table) get_expr_ti(expr ast.Expr) types.TypeIdent {
|
||||||
|
match expr {
|
||||||
|
ast.ArrayInit{
|
||||||
|
return it.ti
|
||||||
|
}
|
||||||
|
ast.IndexExpr{
|
||||||
|
return t.get_expr_ti(it.left)
|
||||||
|
}
|
||||||
|
ast.CallExpr {
|
||||||
|
func := t.find_fn(it.name) or {
|
||||||
|
return types.void_ti
|
||||||
|
}
|
||||||
|
return func.return_ti
|
||||||
|
}
|
||||||
|
ast.MethodCallExpr {
|
||||||
|
ti := t.get_expr_ti(it.expr)
|
||||||
|
func := t.find_method(ti.idx, it.name) or {
|
||||||
|
return types.void_ti
|
||||||
|
}
|
||||||
|
return func.return_ti
|
||||||
|
}
|
||||||
|
ast.Ident {
|
||||||
|
if it.kind == .variable {
|
||||||
|
info := it.info as ast.IdentVar
|
||||||
|
if info.ti.kind != .unresolved {
|
||||||
|
return info.ti
|
||||||
|
}
|
||||||
|
return t.get_expr_ti(info.expr)
|
||||||
|
}
|
||||||
|
return types.void_ti
|
||||||
|
}
|
||||||
|
ast.StructInit {
|
||||||
|
return it.ti
|
||||||
|
}
|
||||||
|
ast.StringLiteral {
|
||||||
|
return types.string_ti
|
||||||
|
}
|
||||||
|
ast.IntegerLiteral {
|
||||||
|
return types.int_ti
|
||||||
|
}
|
||||||
|
ast.SelectorExpr {
|
||||||
|
ti := t.get_expr_ti(it.expr)
|
||||||
|
kind := t.types[ti.idx].kind
|
||||||
|
if ti.kind == .placeholder {
|
||||||
|
println(' ##### PH $ti.name')
|
||||||
|
}
|
||||||
|
if !(kind in [.placeholder, .struct_]) {
|
||||||
|
return types.void_ti
|
||||||
|
}
|
||||||
|
struct_ := t.types[ti.idx]
|
||||||
|
struct_info := struct_.info as types.Struct
|
||||||
|
for field in struct_info.fields {
|
||||||
|
if field.name == it.field {
|
||||||
|
return field.ti
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if struct_.parent_idx != 0 {
|
||||||
|
parent := t.types[struct_.parent_idx]
|
||||||
|
parent_info := parent.info as types.Struct
|
||||||
|
for field in parent_info.fields {
|
||||||
|
if field.name == it.field {
|
||||||
|
return field.ti
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types.void_ti
|
||||||
|
}
|
||||||
|
ast.BinaryExpr {
|
||||||
|
return t.get_expr_ti(it.left)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return types.void_ti
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
module token
|
||||||
|
|
||||||
|
pub struct Position {
|
||||||
|
pub:
|
||||||
|
line_nr int // the line number in the source where the token occured
|
||||||
|
// pos int // the position of the token in scanner text
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (tok &Token) position() Position {
|
||||||
|
return Position{
|
||||||
|
line_nr: tok.line_nr
|
||||||
|
// pos: tok.pos
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,14 +29,10 @@ pub enum Kind {
|
||||||
voidptr
|
voidptr
|
||||||
charptr
|
charptr
|
||||||
byteptr
|
byteptr
|
||||||
const_
|
|
||||||
enum_
|
|
||||||
struct_
|
|
||||||
int
|
|
||||||
i8
|
i8
|
||||||
i16
|
i16
|
||||||
|
int
|
||||||
i64
|
i64
|
||||||
byte
|
|
||||||
u16
|
u16
|
||||||
u32
|
u32
|
||||||
u64
|
u64
|
||||||
|
@ -44,20 +40,25 @@ pub enum Kind {
|
||||||
f64
|
f64
|
||||||
string
|
string
|
||||||
char
|
char
|
||||||
|
byte
|
||||||
bool
|
bool
|
||||||
|
const_
|
||||||
|
enum_
|
||||||
|
struct_
|
||||||
array
|
array
|
||||||
array_fixed
|
array_fixed
|
||||||
map
|
map
|
||||||
multi_return
|
multi_return
|
||||||
variadic
|
variadic
|
||||||
|
unresolved
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Type = Placeholder | Primitive | Const | Enum | Struct | Int | Float |
|
pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn | Variadic
|
||||||
String | Bool | Array | ArrayFixed | Map | MultiReturn | Variadic
|
|
||||||
|
|
||||||
pub struct TypeIdent {
|
pub struct TypeIdent {
|
||||||
pub:
|
pub:
|
||||||
idx int
|
idx int
|
||||||
|
mut:
|
||||||
kind Kind
|
kind Kind
|
||||||
name string
|
name string
|
||||||
nr_muls int
|
nr_muls int
|
||||||
|
@ -73,17 +74,18 @@ pub fn new_ti(kind Kind, name string, idx int, nr_muls int) TypeIdent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
// [inline]
|
||||||
pub fn new_builtin_ti(kind Kind, nr_muls int) TypeIdent {
|
// pub fn new_builtin_ti(kind Kind, nr_muls int) TypeIdent {
|
||||||
return TypeIdent{
|
// return TypeIdent{
|
||||||
idx: -int(kind) - 1
|
// idx: -int(kind) - 1
|
||||||
kind: kind
|
// kind: kind
|
||||||
name: kind.str()
|
// name: kind.str()
|
||||||
nr_muls: nr_muls
|
// nr_muls: nr_muls
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
|
unresolved_ti = new_ti(.unresolved, 'unresolved', 0, 0)
|
||||||
void_ti = new_ti(.void, 'void', void_type_idx, 0)
|
void_ti = new_ti(.void, 'void', void_type_idx, 0)
|
||||||
int_ti = new_ti(.int, 'int', int_type_idx, 0)
|
int_ti = new_ti(.int, 'int', int_type_idx, 0)
|
||||||
string_ti = new_ti(.string, 'string', string_type_idx, 0)
|
string_ti = new_ti(.string, 'string', string_type_idx, 0)
|
||||||
|
@ -115,24 +117,15 @@ pub fn (ti &TypeIdent) str() string {
|
||||||
for _ in 0 .. ti.nr_muls {
|
for _ in 0 .. ti.nr_muls {
|
||||||
muls += '&'
|
muls += '&'
|
||||||
}
|
}
|
||||||
return '$muls$ti.name'
|
// return '$muls$ti.name'
|
||||||
}
|
return '$muls$ti.idx'
|
||||||
|
|
||||||
pub fn check(got, expected &TypeIdent) bool {
|
|
||||||
if expected.kind == .voidptr {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if expected.name == 'array' {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if got.idx != expected.idx {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (k Kind) str() string {
|
pub fn (k Kind) str() string {
|
||||||
k_str := match k {
|
k_str := match k {
|
||||||
|
.unresolved{
|
||||||
|
'unresolved'
|
||||||
|
}
|
||||||
.placeholder{
|
.placeholder{
|
||||||
'placeholder'
|
'placeholder'
|
||||||
}
|
}
|
||||||
|
@ -148,12 +141,12 @@ pub fn (k Kind) str() string {
|
||||||
.byteptr{
|
.byteptr{
|
||||||
'byteptr'
|
'byteptr'
|
||||||
}
|
}
|
||||||
.const_{
|
// .const_{
|
||||||
'const'
|
// 'const'
|
||||||
}
|
// }
|
||||||
.enum_{
|
// .enum_{
|
||||||
'enum'
|
// 'enum'
|
||||||
}
|
// }
|
||||||
.struct_{
|
.struct_{
|
||||||
'struct'
|
'struct'
|
||||||
}
|
}
|
||||||
|
@ -222,75 +215,42 @@ pub fn (kinds []Kind) str() string {
|
||||||
return kinds_str
|
return kinds_str
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Placeholder {
|
// pub struct Const {
|
||||||
pub:
|
// pub:
|
||||||
idx int
|
// name string
|
||||||
name string
|
// }
|
||||||
// kind Kind
|
|
||||||
}
|
|
||||||
// Void | Voidptr | Charptr | Byteptr
|
|
||||||
pub struct Primitive {
|
|
||||||
pub:
|
|
||||||
idx int
|
|
||||||
kind Kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Const {
|
// pub struct Enum {
|
||||||
pub:
|
// pub:
|
||||||
idx int
|
// name string
|
||||||
name string
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Enum {
|
|
||||||
pub:
|
|
||||||
idx int
|
|
||||||
name string
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Struct {
|
pub struct Struct {
|
||||||
pub:
|
|
||||||
idx int
|
|
||||||
parent_idx int
|
|
||||||
name string
|
|
||||||
pub mut:
|
pub mut:
|
||||||
fields []Field
|
fields []Field
|
||||||
methods []Field // TODO Method
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
type_idx int
|
ti TypeIdent
|
||||||
|
// type_idx int
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Int {
|
// pub struct Int {
|
||||||
pub:
|
// pub:
|
||||||
idx int
|
// bit_size u32
|
||||||
bit_size u32
|
// is_unsigned bool
|
||||||
is_unsigned bool
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Float {
|
// pub struct Float {
|
||||||
pub:
|
// pub:
|
||||||
idx int
|
// bit_size u32
|
||||||
bit_size u32
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
pub struct String {
|
|
||||||
pub:
|
|
||||||
idx int
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Bool {
|
|
||||||
pub:
|
|
||||||
idx int
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Array {
|
pub struct Array {
|
||||||
pub:
|
pub:
|
||||||
idx int
|
|
||||||
parent_idx int
|
|
||||||
name string
|
|
||||||
elem_type_kind Kind
|
elem_type_kind Kind
|
||||||
elem_type_idx int
|
elem_type_idx int
|
||||||
elem_is_ptr bool
|
elem_is_ptr bool
|
||||||
|
@ -299,9 +259,6 @@ pub:
|
||||||
|
|
||||||
pub struct ArrayFixed {
|
pub struct ArrayFixed {
|
||||||
pub:
|
pub:
|
||||||
idx int
|
|
||||||
parent_idx int
|
|
||||||
name string
|
|
||||||
elem_type_kind Kind
|
elem_type_kind Kind
|
||||||
elem_type_idx int
|
elem_type_idx int
|
||||||
elem_is_ptr bool
|
elem_is_ptr bool
|
||||||
|
@ -311,8 +268,6 @@ pub:
|
||||||
|
|
||||||
pub struct Map {
|
pub struct Map {
|
||||||
pub:
|
pub:
|
||||||
idx int
|
|
||||||
name string
|
|
||||||
key_type_kind Kind
|
key_type_kind Kind
|
||||||
key_type_idx int
|
key_type_idx int
|
||||||
value_type_kind Kind
|
value_type_kind Kind
|
||||||
|
@ -321,89 +276,11 @@ pub:
|
||||||
|
|
||||||
pub struct MultiReturn {
|
pub struct MultiReturn {
|
||||||
pub:
|
pub:
|
||||||
idx int
|
|
||||||
name string
|
name string
|
||||||
tis []TypeIdent
|
tis []TypeIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Variadic {
|
pub struct Variadic {
|
||||||
pub:
|
pub:
|
||||||
idx int
|
|
||||||
ti TypeIdent
|
ti TypeIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t Primitive) str() string {
|
|
||||||
s := match t.kind {
|
|
||||||
.void{
|
|
||||||
'void'
|
|
||||||
}
|
|
||||||
.voidptr{
|
|
||||||
'voidptr'
|
|
||||||
}
|
|
||||||
.charptr{
|
|
||||||
'charptr'
|
|
||||||
}
|
|
||||||
.byteptr{
|
|
||||||
'byteptr'
|
|
||||||
}
|
|
||||||
.char{
|
|
||||||
'char'
|
|
||||||
}
|
|
||||||
.byte{
|
|
||||||
'byte'
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
'unknown'}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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 t.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (t Variadic) str() string {
|
|
||||||
return 'variadic_$t.ti.kind.str()'
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
pub fn (s &Struct) has_field(name string) bool {
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
Loading…
Reference in New Issue