mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v2: resolve unresolved call expression types & add test
This commit is contained in:
parent
83f0c228e9
commit
85e4e4cb40
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -13,7 +13,8 @@ pub struct Checker {
|
||||
table &table.Table
|
||||
mut:
|
||||
file_name string
|
||||
// TODO: resolved
|
||||
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
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
nr_tests = 3
|
||||
nr_tests = 4
|
||||
)
|
||||
|
||||
fn test_c_files() {
|
||||
|
62
vlib/v/gen/tests/4.c
Normal file
62
vlib/v/gen/tests/4.c
Normal 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;
|
72
vlib/v/gen/tests/4.vv
Normal file
72
vlib/v/gen/tests/4.vv
Normal 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
|
||||
}
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -32,7 +32,6 @@ pub:
|
||||
is_mut bool
|
||||
is_const bool
|
||||
is_global bool
|
||||
// expr ast.Expr
|
||||
mut:
|
||||
typ Type
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user