From e7e07be38c72ab9e790c8feb36481ba44b634386 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 1 Jan 2020 23:15:20 +0100 Subject: [PATCH] handle unknown functions; fix var types --- vlib/compiler/expression.v | 2 + vlib/v/ast/ast.v | 5 ++- vlib/v/gen/tests/2.c | 6 +++ vlib/v/gen/tests/2.vv | 7 +++ vlib/v/parser/parser.v | 88 +++++++++++++++++++++++--------------- vlib/v/table/table.v | 9 ++-- 6 files changed, 77 insertions(+), 40 deletions(-) diff --git a/vlib/compiler/expression.v b/vlib/compiler/expression.v index 504f6ce935..80226e69b1 100644 --- a/vlib/compiler/expression.v +++ b/vlib/compiler/expression.v @@ -63,7 +63,9 @@ fn (p mut Parser) bool_expression() string { // `as` cast // TODO remove copypasta if p.tok == .key_as { + p.fspace() p.next() + p.fspace() cast_typ := p.get_type() if typ == cast_typ { p.warn('casting `$typ` to `$cast_typ` is not needed') diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 87a4b0cc9d..37da026a4a 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -92,8 +92,9 @@ pub: pub struct CallExpr { pub: - name string - args []Expr + name string + args []Expr + is_unknown bool } pub struct Return { diff --git a/vlib/v/gen/tests/2.c b/vlib/v/gen/tests/2.c index 47835ab85c..0f03e87129 100644 --- a/vlib/v/gen/tests/2.c +++ b/vlib/v/gen/tests/2.c @@ -17,6 +17,12 @@ void init_user() { }; } +User get_user() { + User user = (User){ + }; + return user; +} + void puts(string s) { } diff --git a/vlib/v/gen/tests/2.vv b/vlib/v/gen/tests/2.vv index 11e721def0..687996aaf2 100644 --- a/vlib/v/gen/tests/2.vv +++ b/vlib/v/gen/tests/2.vv @@ -1,6 +1,7 @@ fn function1() int { a := 10 + 1 b := a + 1 + //return a return 0 } @@ -18,6 +19,12 @@ fn init_user() { } } +fn get_user() User { + user := User{} + return user +} + + fn puts(s string) {} // comment diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 297916406a..8242168764 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -34,34 +34,6 @@ pub fn parse_stmt(text string, table &table.Table) ast.Stmt { return p.stmt() } -pub fn (p mut Parser) get_type() types.Type { - defer { - p.next() - } - match p.tok.lit { - 'int' { - return types.int_type - } - 'f64' { - return types.f64_type - } - 'string' { - return types.string_type - } - 'voidptr' { - return types.voidptr_type - } - else { - typ := p.table.types[p.tok.lit] - if isnil(typ.name.str) || typ.name == '' { - p.error('undefined type `$p.tok.lit`') - } - println('RET Typ $typ.name') - return typ - } - } -} - pub fn parse_file(path string, table &table.Table) ast.File { text := os.read_file(path) or { panic(err) @@ -123,6 +95,33 @@ pub fn parse_files(paths []string, table &table.Table) []ast.File { return files } +pub fn (p mut Parser) parse_type() types.Type { + defer { + p.next() + } + match p.tok.lit { + 'int' { + return types.int_type + } + 'f64' { + return types.f64_type + } + 'string' { + return types.string_type + } + 'voidptr' { + return types.voidptr_type + } + else { + typ := p.table.types[p.tok.lit] + if isnil(typ.name.str) || typ.name == '' { + p.error('undefined type `$p.tok.lit`') + } + return typ + } + } +} + pub fn (p mut Parser) read_first_token() { // need to call next() twice to get peek token and current token p.next() @@ -268,6 +267,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.Type) { // println('got fn call') fn_name := p.check_name() p.check(.lpar) + mut is_unknown := false mut args := []ast.Expr if f := p.table.find_fn(fn_name) { for i, arg in f.args { @@ -284,12 +284,23 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.Type) { p.error('too many arguments in call to `$fn_name`') } }else{ - p.error('unknown function `$fn_name`') + is_unknown = true + p.warn('unknown function `$fn_name`') + for p.tok.kind != .rpar { + p.expr(0) + if p.tok.kind != .rpar { + p.check(.comma) + } + } } p.check(.rpar) node := ast.CallExpr{ name: fn_name args: args + is_unknown: is_unknown + } + if is_unknown { + p.table.unknown_calls << node } return node,types.int_type } @@ -317,7 +328,8 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { } // struct init else if p.peek_tok.kind == .lcbr { - typ = p.get_type() + typ = p.parse_type() + // println('sturct init typ=$typ.name') p.check(.lcbr) mut field_names := []string mut exprs := []ast.Expr @@ -342,7 +354,12 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { node = ast.Ident{ name: p.tok.lit } - typ = types.int_type + var := p.table.find_var(p.tok.lit) or { + p.error('unknown variable `$p.tok.lit`') + exit(0) + } + typ = var.typ + // ///typ = types.int_type p.next() } } @@ -577,7 +594,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { p.check(.colon) } field_name := p.check_name() - typ := p.get_type() + typ := p.parse_type() fields << ast.Field{ name: field_name typ: typ @@ -605,7 +622,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { mut ast_args := []ast.Arg for p.tok.kind != .rpar { arg_name := p.check_name() - typ := p.get_type() + typ := p.parse_type() args << table.Var{ name: arg_name typ: typ @@ -622,7 +639,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { // Return type mut typ := types.void_type if p.tok.kind == .name { - typ = p.get_type() + typ = p.parse_type() p.return_type = typ } p.table.register_fn(table.Fn{ @@ -642,7 +659,7 @@ fn (p mut Parser) return_stmt() ast.Return { p.next() expr,t := p.expr(0) if !types.check(p.return_type, t) { - p.error('bad ret type') + p.error('cannot use `$t.name` as type `$p.return_type.name` in return argument') } return ast.Return{ expr: expr @@ -668,6 +685,7 @@ fn (p mut Parser) var_decl() ast.VarDecl { } p.table.register_var(table.Var{ name: name + typ: t is_mut: is_mut }) // println(p.table.names) diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index b0e19d0558..7905a9cd08 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -2,14 +2,17 @@ module table import ( v.types + v.ast ) pub struct Table { pub mut: - local_vars []Var + local_vars []Var // fns Hashmap - fns map[string]Fn - types map[string]types.Type + fns map[string]Fn + types map[string]types.Type + // + unknown_calls []ast.CallExpr } pub struct Var {