From 349576b5cdcb5c1837806ae7ff4f3529bb166f32 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 29 Dec 2019 07:24:17 +0100 Subject: [PATCH] fn call + fn args --- vlib/v/ast/ast.v | 18 +++++++-- vlib/v/cgen/cgen.v | 9 ++++- vlib/v/cgen/tests/2.c | 5 +++ vlib/v/cgen/tests/2.v | 6 +++ vlib/v/parser/parser.v | 74 +++++++++++++++++++++++++++++++------ vlib/v/parser/parser_test.v | 2 +- vlib/v/table/table.v | 29 ++++++++++++++- 7 files changed, 126 insertions(+), 17 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 3076321bb9..d5066623d3 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -8,8 +8,8 @@ import ( v.types ) -pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral | FloatLiteral | -Ident +pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral | +FloatLiteral | Ident | CallExpr pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | AssignStmt // Stand-alone expression in a statement list. @@ -50,12 +50,24 @@ pub: // imports map[string]string } +pub struct Arg { +pub: + typ types.Type + name string +} + pub struct FnDecl { pub: name string stmts []Stmt - // exprs []Expr typ types.Type + args []Arg +} + +pub struct CallExpr { +pub: + name string + args []Expr } pub struct Return { diff --git a/vlib/v/cgen/cgen.v b/vlib/v/cgen/cgen.v index 2df99c070f..6dc7081b3d 100644 --- a/vlib/v/cgen/cgen.v +++ b/vlib/v/cgen/cgen.v @@ -39,7 +39,11 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.writeln(';') } ast.FnDecl { - g.writeln('$it.typ.name ${it.name}() { ') + g.write('$it.typ.name ${it.name}(') + for arg in it.args { + g.write(arg.typ.name + ' ' + arg.name) + } + g.writeln(') { ') for stmt in it.stmts { g.stmt(stmt) } @@ -109,6 +113,9 @@ fn (g mut Gen) expr(node ast.Expr) { // verror('bad types $typ.name $typ2.name') // } } + ast.CallExpr { + g.write('${it.name}()') + } ast.Ident { g.write('$it.name') } diff --git a/vlib/v/cgen/tests/2.c b/vlib/v/cgen/tests/2.c index ee380abf45..3f948dfad3 100644 --- a/vlib/v/cgen/tests/2.c +++ b/vlib/v/cgen/tests/2.c @@ -4,6 +4,9 @@ int function1() { return 0; } +void foo(int a) { +} + void function2() { int x = 0; f64 f = 10.1; @@ -12,4 +15,6 @@ void function2() { x += 10; x += 1; m += 2; + function1(); } + diff --git a/vlib/v/cgen/tests/2.v b/vlib/v/cgen/tests/2.v index 123c1fd5e4..a8ca700d56 100644 --- a/vlib/v/cgen/tests/2.v +++ b/vlib/v/cgen/tests/2.v @@ -4,6 +4,10 @@ fn function1() int { return 0 } +fn foo(a int) { + +} + // comment fn function2() { mut x := 0 @@ -13,6 +17,8 @@ fn function2() { x += 10 x += 1 m += 2 + function1() //a += 1 //c := 0 } + diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 9ff59eb5d8..1731787839 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -122,7 +122,7 @@ fn (p mut Parser) next() { fn (p mut Parser) check(expected token.TokenKind) { if p.tok.kind != expected { s := 'syntax error: unexpected `${p.tok.kind.str()}`, expecting `${expected.str()}`' - verror(s) + p.error(s) } p.next() } @@ -171,7 +171,7 @@ pub fn (p mut Parser) stmt() ast.Stmt { pub fn (p mut Parser) assign_stmt() ast.AssignStmt { name := p.tok.lit - //println('looking for $name') + // println('looking for $name') var := p.table.find_var(name) or { p.error('unknown variable `$name`') exit(1) @@ -181,7 +181,7 @@ pub fn (p mut Parser) assign_stmt() ast.AssignStmt { } left_expr,left_type := p.expr(0) op := p.tok.kind - //println('assignn_stmt() ' + op.str()) + // println('assignn_stmt() ' + op.str()) p.next() right_expr,right_type := p.expr(0) return ast.AssignStmt{ @@ -204,12 +204,44 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { mut typ := types.void_type match p.tok.kind { .name { - // name expr - node = ast.Ident{ - name: p.tok.lit + /* + sym := p.table.find_symbol(p.tok.lit) + if sym.cat == .function { + return + } + */ + + // fn call + if p.peek_tok.kind == .lpar { + println('got fn call') + fn_name := p.tok.lit + f := p.table.find_fn(fn_name) or { + p.error('unknown fucntion `$p.tok.lit`') + exit(0) + } + p.check(.name) + p.check(.lpar) + mut args := []ast.Expr + for _ in 0 .. f.args.len { + e,_ := p.expr(0) + args << e + p.check(.comma) + } + p.check(.rpar) + node = ast.CallExpr{ + name: fn_name + args: args + } + typ = types.int_type + } + else { + // name expr + node = ast.Ident{ + name: p.tok.lit + } + typ = types.int_type + p.next() } - typ = types.int_type - p.next() } .str { node,typ = p.parse_string_literal() @@ -251,7 +283,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { right: expr } if !types.check(&typ, &t2) { - verror('cannot convert `$t2.name` to `$typ.name`') + p.error('cannot convert `$t2.name` to `$typ.name`') } } else if prev_tok.is_left_assoc() { @@ -316,6 +348,21 @@ fn (p mut Parser) fn_decl() ast.FnDecl { // println('fn decl $name') p.check(.name) p.check(.lpar) + // Args + mut args := []table.Var + mut ast_args := []ast.Arg + for p.tok.kind != .rpar { + arg_name := p.check_name() + typ := p.get_type() + args << table.Var{ + name: arg_name + typ: typ + } + ast_args << ast.Arg{ + typ: typ + name: arg_name + } + } p.check(.rpar) // Return type mut typ := types.void_type @@ -324,12 +371,17 @@ fn (p mut Parser) fn_decl() ast.FnDecl { p.return_type = typ } p.check(.lcbr) + p.table.register_fn(table.Fn{ + name: name + args: args + }) // p.check(.rcbr) stmts := p.parse_block() return ast.FnDecl{ name: name stmts: stmts typ: typ + args: ast_args } } @@ -338,7 +390,7 @@ fn (p mut Parser) return_stmt() ast.Return { p.next() expr,t := p.expr(0) if !types.check(p.return_type, t) { - verror('bad ret type') + p.error('bad ret type') } return ast.Return{ expr: expr @@ -371,7 +423,7 @@ fn (p mut Parser) var_decl() ast.VarDecl { return ast.VarDecl{ name: name expr: expr // p.expr(token.lowest_prec) - + typ: t } } diff --git a/vlib/v/parser/parser_test.v b/vlib/v/parser/parser_test.v index 3c2b9273cd..76d65928b3 100644 --- a/vlib/v/parser/parser_test.v +++ b/vlib/v/parser/parser_test.v @@ -36,7 +36,7 @@ fn test_parse_expr() { '2+2*4', // '(2+2)*4', 'x := 10', - 'a := 12', + 'mut a := 12', 'ab := 10 + 3 * 9', 's := "hi"', // '1 += 2', diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index ee1bc73db9..d03423d4de 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -1,16 +1,29 @@ module table +import ( + v.types +) + pub struct Table { pub mut: local_vars []Var + // fns Hashmap + fns map[string]Fn } pub struct Var { pub: name string + typ types.Type is_mut bool } +pub struct Fn { +pub: + name string + args []Var +} + pub fn (t &Table) find_var(name string) ?Var { /* for i in 0 .. p.var_idx { @@ -40,7 +53,7 @@ pub fn (t mut Table) clear_vars() { } } -fn (t mut Table) register_var(v Var) { +pub fn (t mut Table) register_var(v Var) { t.local_vars << v /* mut new_var := { @@ -63,3 +76,17 @@ fn (t mut Table) register_var(v Var) { */ } + +pub fn (t &Table) find_fn(name string) ?Fn { + f := t.fns[name] + if f.name.str != 0 { + // TODO + return f + } + return none +} + +pub fn (t mut Table) register_fn(new_fn Fn) { + // println('reg fn $new_fn.name nr_args=$new_fn.args.len') + t.fns[new_fn.name] = new_fn +}