v2: resolve unresolved call expression types & add test

pull/3647/head
joe-conigliaro 2020-02-04 22:03:12 +11:00 committed by GitHub
parent 83f0c228e9
commit 85e4e4cb40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 186 additions and 30 deletions

View File

@ -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)
}

View File

@ -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

View File

@ -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
}

View File

@ -7,7 +7,7 @@ import (
)
const (
nr_tests = 3
nr_tests = 4
)
fn test_c_files() {

View File

@ -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;

View File

@ -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
}

View File

@ -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 {

View File

@ -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)

View File

@ -32,7 +32,6 @@ pub:
is_mut bool
is_const bool
is_global bool
// expr ast.Expr
mut:
typ Type
}