From 85e4e4cb40e1216d11e7131f3e728716806ade91 Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Tue, 4 Feb 2020 22:03:12 +1100 Subject: [PATCH] v2: resolve unresolved call expression types & add test --- vlib/builtin/int.v | 2 +- vlib/v/ast/ast.v | 4 +-- vlib/v/checker/checker.v | 38 ++++++++++++--------- vlib/v/gen/cgen_test.v | 2 +- vlib/v/gen/tests/4.c | 62 ++++++++++++++++++++++++++++++++++ vlib/v/gen/tests/4.vv | 72 ++++++++++++++++++++++++++++++++++++++++ vlib/v/parser/fn.v | 7 ++-- vlib/v/parser/parser.v | 28 ++++++++++++---- vlib/v/table/table.v | 1 - 9 files changed, 186 insertions(+), 30 deletions(-) create mode 100644 vlib/v/gen/tests/4.c create mode 100644 vlib/v/gen/tests/4.vv diff --git a/vlib/builtin/int.v b/vlib/builtin/int.v index 49912dce26..ca4f02929e 100644 --- a/vlib/builtin/int.v +++ b/vlib/builtin/int.v @@ -148,7 +148,7 @@ pub fn (b bool) str() string { pub fn (n int) hex() string { len := if n >= 0 { n.str().len + 3 } else { 11 } hex := malloc(len) // 0x + \n - count := int(C.sprintf(charptr(hex), '0x%x', n)) + count := C.sprintf(charptr(hex), '0x%x', n) return tos(hex, count) } diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index f572fa48db..028d202481 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -190,13 +190,13 @@ pub: mod Module imports []Import stmts []Stmt + unresolved []Expr } pub struct IdentVar { pub: - expr Expr typ table.Type - name string + //name string } type IdentInfo = IdentVar diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 13c3cd04dd..c325388d66 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -10,10 +10,11 @@ import ( ) pub struct Checker { - table &table.Table + table &table.Table mut: - file_name string - // TODO: resolved + file_name string + unresolved []ast.Expr + resolved []table.Type } pub fn new_checker(table &table.Table) Checker { @@ -22,7 +23,10 @@ pub fn new_checker(table &table.Table) Checker { } } -pub fn (c &Checker) check(ast_file ast.File) { +pub fn (c mut Checker) check(ast_file ast.File) { + c.file_name = ast_file.path + c.unresolved = ast_file.unresolved + c.resolve_types() for stmt in ast_file.stmts { c.stmt(stmt) } @@ -30,11 +34,16 @@ pub fn (c &Checker) check(ast_file ast.File) { pub fn (c mut Checker) check_files(ast_files []ast.File) { for file in ast_files { - c.file_name = file.path c.check(file) } } +fn (c mut Checker) resolve_types() { + for x in c.unresolved { + c.resolved << c.expr(x) + } +} + pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.Type { typ := c.table.find_type(struct_init.ti.name) or { c.error('unknown struct: $struct_init.ti.name', struct_init.pos) @@ -100,19 +109,18 @@ pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.Type { } } return f.return_type - }else{ - c.error('unknown fn: $fn_name', call_expr.pos) - exit(0) - // c.warn('unknown function `$fn_name`') } + c.error('unknown fn: $fn_name', call_expr.pos) + exit(1) } pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type { ti := c.expr(method_call_expr.expr) - if !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) + if method := c.table.find_method(ti.idx, method_call_expr.name) { + return method.return_type } - return ti + c.error('type `$ti.name` has no method `$method_call_expr.name`', method_call_expr.pos) + exit(1) } pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.Type { @@ -274,10 +282,10 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type { ast.Ident { if it.kind == .variable { info := it.info as ast.IdentVar - if info.typ.kind != .unresolved { - return info.typ + if info.typ.kind == .unresolved { + return c.resolved[info.typ.idx] } - return c.expr(info.expr) + return info.typ } return table.void_type } diff --git a/vlib/v/gen/cgen_test.v b/vlib/v/gen/cgen_test.v index 65b1903f0d..5e9c1da332 100644 --- a/vlib/v/gen/cgen_test.v +++ b/vlib/v/gen/cgen_test.v @@ -7,7 +7,7 @@ import ( ) const ( - nr_tests = 3 + nr_tests = 4 ) fn test_c_files() { diff --git a/vlib/v/gen/tests/4.c b/vlib/v/gen/tests/4.c new file mode 100644 index 0000000000..d20392ff06 --- /dev/null +++ b/vlib/v/gen/tests/4.c @@ -0,0 +1,62 @@ +int testa(); +string testb(int a); +int testc(int a); +int testa(); +int testb(); +int testa(); +int main() { +Bar b = (Bar){ + .a = 122, +}; +Foo a = (Foo){ + .a = tos3("hello"), + .b = b, +}; +a.a = tos3("da"); +a.b.a = 111; +string a1 = a.a; +int a2 = ; +int c = testa(); +c = 1; +string d = testb(1); +d = tos3("hello"); +string e = tos3("hello"); +e = testb(111); +e = tos3("world"); +return 0; +} + +int testa() { +return testc(1); +} + +string testb(int a) { +return tos3("hello"); +} + +int testc(int a) { +return a; +} + +int testa() { +int a = ; +a = 1; +return 4; +} + +int testb() { +return 4; +} + +int testa() { +return 4; +} + +typedef struct { + int a; +} Bar; + +typedef struct { + string a; + Bar b; +} Foo; diff --git a/vlib/v/gen/tests/4.vv b/vlib/v/gen/tests/4.vv new file mode 100644 index 0000000000..d5b44f0b1d --- /dev/null +++ b/vlib/v/gen/tests/4.vv @@ -0,0 +1,72 @@ +module main + +// import moda + +// import ( +// modb +// modc +// ) + +fn main() { + b := Bar{a: 122} + mut a := Foo{ + a: 'hello' + b: b + } + // a.c = 'sa' + a.a = 'da' + a.b.a = 111 + + a1 := a.a + a2 := b.testa() + + mut c := testa() + c = 1 + mut d := testb(1) + d = 'hello' + + mut e = 'hello' + e = testb(111) + e = 'world' + + //mut f := [testa(),2,3,4] + // f = testa() + // c := 1 + 'string' + // zz := hi + 1 +} + + +fn testa() int { + return testc(1) +} + +fn testb(a int) string { + return 'hello' +} + +fn testc(a int) int { + return a +} + +fn (f &Foo) testa() int { + mut a := f.testb() + a = 1 + return 4 +} + +fn (f &Foo) testb() int { + return 4 +} + +fn (b &Bar) testa() int { + return 4 +} + +struct Bar { + a int +} + +struct Foo{ + a string + b Bar +} diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 3237091152..5618a93702 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -29,12 +29,11 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) { pos: tok.position() } - mut ti := table.unresolved_type if f := p.table.find_fn(fn_name) { - ti = f.return_type + return node,f.return_type } - println('adding call_expr check $fn_name') - return node,ti + typ := p.add_unresolved(node) + return node,typ } pub fn (p mut Parser) call_args() []ast.Expr { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index fa0edc4462..bdff4ce1f2 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -39,6 +39,7 @@ mut: pref &pref.Preferences // Preferences shared from V struct builtin_mod bool mod string + unresolved []ast.Expr } // for tests @@ -92,6 +93,7 @@ pub fn parse_file(path string, table &table.Table) ast.File { mod: module_decl imports: imports stmts: stmts + unresolved: p.unresolved } } @@ -355,8 +357,8 @@ pub fn (p &Parser) warn(s string) { pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) { mut node := ast.Expr{} - // mut typ := table.void_ti - mut typ := table.unresolved_type + mut typ := table.void_type + // mut typ := table.unresolved_type is_c := p.tok.lit == 'C' && p.peek_tok.kind == .dot if is_c { p.next() @@ -403,11 +405,12 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) { } // variable if var := p.table.find_var(p.tok.lit) { + println('#### IDENT: $var.name: $var.typ.name - $var.typ.idx') typ = var.typ ident.kind = .variable ident.info = ast.IdentVar{ typ: typ - name: ident.name + // name: ident.name // expr: p.expr(0)// var.expr } @@ -419,7 +422,8 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) { typ = table.int_type ident.info = ast.IdentVar{ typ: typ - name: ident.name + // name: ident.name + } node = ident p.next() @@ -431,7 +435,8 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) { ident.kind = .constant ident.info = ast.IdentVar{ typ: typ - name: ident.name + // name: ident.name + } node = ident p.next() @@ -582,7 +587,7 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.Expr { fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.Type) { p.next() field_name := p.check_name() - ti := table.unresolved_type + mut ti := table.unresolved_type // Method call if p.tok.kind == .lpar { p.next() @@ -595,6 +600,7 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.T } mut node := ast.Expr{} node = mcall_expr + ti = p.add_unresolved(mcall_expr) return node,ti } sel_expr := ast.SelectorExpr{ @@ -1055,6 +1061,16 @@ fn (p mut Parser) global_decl() ast.GlobalDecl { } } +fn (p mut Parser) add_unresolved(expr ast.Expr) table.Type { + t := table.Type{ + idx: p.unresolved.len + kind: .unresolved + name: 'unresolved' + } + p.unresolved << expr + return t +} + fn verror(s string) { println(s) exit(1) diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 6df0e2f775..24d450a87b 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -32,7 +32,6 @@ pub: is_mut bool is_const bool is_global bool - // expr ast.Expr mut: typ Type }