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 {
|
pub fn (n int) hex() string {
|
||||||
len := if n >= 0 { n.str().len + 3 } else { 11 }
|
len := if n >= 0 { n.str().len + 3 } else { 11 }
|
||||||
hex := malloc(len) // 0x + \n
|
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)
|
return tos(hex, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,13 +190,13 @@ pub:
|
|||||||
mod Module
|
mod Module
|
||||||
imports []Import
|
imports []Import
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
|
unresolved []Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IdentVar {
|
pub struct IdentVar {
|
||||||
pub:
|
pub:
|
||||||
expr Expr
|
|
||||||
typ table.Type
|
typ table.Type
|
||||||
name string
|
//name string
|
||||||
}
|
}
|
||||||
|
|
||||||
type IdentInfo = IdentVar
|
type IdentInfo = IdentVar
|
||||||
|
@ -10,10 +10,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
pub struct Checker {
|
pub struct Checker {
|
||||||
table &table.Table
|
table &table.Table
|
||||||
mut:
|
mut:
|
||||||
file_name string
|
file_name string
|
||||||
// TODO: resolved
|
unresolved []ast.Expr
|
||||||
|
resolved []table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_checker(table &table.Table) Checker {
|
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 {
|
for stmt in ast_file.stmts {
|
||||||
c.stmt(stmt)
|
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) {
|
pub fn (c mut Checker) check_files(ast_files []ast.File) {
|
||||||
for file in ast_files {
|
for file in ast_files {
|
||||||
c.file_name = file.path
|
|
||||||
c.check(file)
|
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 {
|
pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.Type {
|
||||||
typ := c.table.find_type(struct_init.ti.name) or {
|
typ := c.table.find_type(struct_init.ti.name) or {
|
||||||
c.error('unknown struct: $struct_init.ti.name', struct_init.pos)
|
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
|
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 {
|
pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type {
|
||||||
ti := c.expr(method_call_expr.expr)
|
ti := c.expr(method_call_expr.expr)
|
||||||
if !c.table.has_method(ti.idx, method_call_expr.name) {
|
if method := c.table.find_method(ti.idx, method_call_expr.name) {
|
||||||
c.error('type `$ti.name` has no method `$method_call_expr.name`', method_call_expr.pos)
|
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 {
|
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 {
|
ast.Ident {
|
||||||
if it.kind == .variable {
|
if it.kind == .variable {
|
||||||
info := it.info as ast.IdentVar
|
info := it.info as ast.IdentVar
|
||||||
if info.typ.kind != .unresolved {
|
if info.typ.kind == .unresolved {
|
||||||
return info.typ
|
return c.resolved[info.typ.idx]
|
||||||
}
|
}
|
||||||
return c.expr(info.expr)
|
return info.typ
|
||||||
}
|
}
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
nr_tests = 3
|
nr_tests = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
fn test_c_files() {
|
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()
|
pos: tok.position()
|
||||||
}
|
}
|
||||||
mut ti := table.unresolved_type
|
|
||||||
if f := p.table.find_fn(fn_name) {
|
if f := p.table.find_fn(fn_name) {
|
||||||
ti = f.return_type
|
return node,f.return_type
|
||||||
}
|
}
|
||||||
println('adding call_expr check $fn_name')
|
typ := p.add_unresolved(node)
|
||||||
return node,ti
|
return node,typ
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) call_args() []ast.Expr {
|
pub fn (p mut Parser) call_args() []ast.Expr {
|
||||||
|
@ -39,6 +39,7 @@ mut:
|
|||||||
pref &pref.Preferences // Preferences shared from V struct
|
pref &pref.Preferences // Preferences shared from V struct
|
||||||
builtin_mod bool
|
builtin_mod bool
|
||||||
mod string
|
mod string
|
||||||
|
unresolved []ast.Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
// for tests
|
// for tests
|
||||||
@ -92,6 +93,7 @@ pub fn parse_file(path string, table &table.Table) ast.File {
|
|||||||
mod: module_decl
|
mod: module_decl
|
||||||
imports: imports
|
imports: imports
|
||||||
stmts: stmts
|
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) {
|
pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
// mut typ := table.void_ti
|
mut typ := table.void_type
|
||||||
mut typ := table.unresolved_type
|
// mut typ := table.unresolved_type
|
||||||
is_c := p.tok.lit == 'C' && p.peek_tok.kind == .dot
|
is_c := p.tok.lit == 'C' && p.peek_tok.kind == .dot
|
||||||
if is_c {
|
if is_c {
|
||||||
p.next()
|
p.next()
|
||||||
@ -403,11 +405,12 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||||||
}
|
}
|
||||||
// variable
|
// variable
|
||||||
if var := p.table.find_var(p.tok.lit) {
|
if var := p.table.find_var(p.tok.lit) {
|
||||||
|
println('#### IDENT: $var.name: $var.typ.name - $var.typ.idx')
|
||||||
typ = var.typ
|
typ = var.typ
|
||||||
ident.kind = .variable
|
ident.kind = .variable
|
||||||
ident.info = ast.IdentVar{
|
ident.info = ast.IdentVar{
|
||||||
typ: typ
|
typ: typ
|
||||||
name: ident.name
|
// name: ident.name
|
||||||
// expr: p.expr(0)// var.expr
|
// 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
|
typ = table.int_type
|
||||||
ident.info = ast.IdentVar{
|
ident.info = ast.IdentVar{
|
||||||
typ: typ
|
typ: typ
|
||||||
name: ident.name
|
// name: ident.name
|
||||||
|
|
||||||
}
|
}
|
||||||
node = ident
|
node = ident
|
||||||
p.next()
|
p.next()
|
||||||
@ -431,7 +435,8 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||||||
ident.kind = .constant
|
ident.kind = .constant
|
||||||
ident.info = ast.IdentVar{
|
ident.info = ast.IdentVar{
|
||||||
typ: typ
|
typ: typ
|
||||||
name: ident.name
|
// name: ident.name
|
||||||
|
|
||||||
}
|
}
|
||||||
node = ident
|
node = ident
|
||||||
p.next()
|
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) {
|
fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.Type) {
|
||||||
p.next()
|
p.next()
|
||||||
field_name := p.check_name()
|
field_name := p.check_name()
|
||||||
ti := table.unresolved_type
|
mut ti := table.unresolved_type
|
||||||
// Method call
|
// Method call
|
||||||
if p.tok.kind == .lpar {
|
if p.tok.kind == .lpar {
|
||||||
p.next()
|
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{}
|
mut node := ast.Expr{}
|
||||||
node = mcall_expr
|
node = mcall_expr
|
||||||
|
ti = p.add_unresolved(mcall_expr)
|
||||||
return node,ti
|
return node,ti
|
||||||
}
|
}
|
||||||
sel_expr := ast.SelectorExpr{
|
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) {
|
fn verror(s string) {
|
||||||
println(s)
|
println(s)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
@ -32,7 +32,6 @@ pub:
|
|||||||
is_mut bool
|
is_mut bool
|
||||||
is_const bool
|
is_const bool
|
||||||
is_global bool
|
is_global bool
|
||||||
// expr ast.Expr
|
|
||||||
mut:
|
mut:
|
||||||
typ Type
|
typ Type
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user