From 651c7e8de1631797f8452a6f1c65f292b4c2d00b Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 28 Dec 2019 11:02:06 +0100 Subject: [PATCH] cgen tests --- vlib/builtin/builtin.v | 14 ++++++++++++ vlib/v/ast/ast.v | 2 +- vlib/v/cgen/cgen.v | 42 ++++++++++++++++++++-------------- vlib/v/cgen/cgen_test.v | 50 +++++++++++++++++++++++++++++++++++++++++ vlib/v/cgen/tests/1.c | 4 ++++ vlib/v/cgen/tests/1.v | 4 ++++ vlib/v/cgen/tests/2.c | 11 +++++++++ vlib/v/cgen/tests/2.v | 12 ++++++++++ vlib/v/parser/parser.v | 35 ++++++++++++++++++++--------- 9 files changed, 145 insertions(+), 29 deletions(-) create mode 100644 vlib/v/cgen/cgen_test.v create mode 100644 vlib/v/cgen/tests/1.c create mode 100644 vlib/v/cgen/tests/1.v create mode 100644 vlib/v/cgen/tests/2.c create mode 100644 vlib/v/cgen/tests/2.v diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index 789dc2f2a4..718858d553 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -96,6 +96,20 @@ pub fn eprintln(s string) { println(s) } +pub fn eprint(s string) { + if isnil(s.str) { + panic('eprint(NIL)') + } + $if !windows { + C.fflush(stdout) + C.fflush(stderr) + C.fprintf(stderr, '%.*s', s.len, s.str) + C.fflush(stderr) + return + } + print(s) +} + pub fn print(s string) { $if windows { C.wprintf(s.to_wide()) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index c830e13e0b..649dcc9dac 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -30,7 +30,7 @@ pub: val string } -// module decleration +// module declaration pub struct Module { pub: name string diff --git a/vlib/v/cgen/cgen.v b/vlib/v/cgen/cgen.v index 77d9e5ae96..b54abff8cb 100644 --- a/vlib/v/cgen/cgen.v +++ b/vlib/v/cgen/cgen.v @@ -7,11 +7,12 @@ import ( struct Gen { out strings.Builder - } pub fn gen(program ast.Program) string { - mut g := Gen{out:strings.new_builder(100)} + mut g := Gen{ + out: strings.new_builder(100) + } for expr in program.exprs { g.expr(expr) g.writeln('') @@ -19,9 +20,7 @@ pub fn gen(program ast.Program) string { return (g.out.str()) } -pub fn (g &Gen) save() { - -} +pub fn (g &Gen) save() {} pub fn (g mut Gen) write(s string) { g.out.write(s) @@ -32,7 +31,7 @@ pub fn (g mut Gen) writeln(s string) { } fn (g mut Gen) expr(node ast.Expr) { - //println('cgen expr()') + // println('cgen expr()') match node { ast.IntegerLiteral { g.write(it.val.str()) @@ -48,7 +47,7 @@ fn (g mut Gen) expr(node ast.Expr) { g.write('tos3("$it.val")') } ast.FnDecl { - g.writeln('$it.typ.name $it.name () { ') + g.writeln('$it.typ.name ${it.name}() { ') for expr in it.exprs { g.expr(expr) } @@ -62,17 +61,27 @@ fn (g mut Gen) expr(node ast.Expr) { ast.BinaryExpr { g.expr(it.left) match it.op { - .plus { g.write(' + ') } - .minus { g.write(' - ') } - .mul { g.write(' * ') } - .div { g.write(' / ') } - .plus_assign { g.write(' += ') } + .plus { + g.write(' + ') + } + .minus { + g.write(' - ') + } + .mul { + g.write(' * ') + } + .div { + g.write(' / ') + } + .plus_assign { + g.write(' += ') + } else {} - } + } g.expr(it.right) - // if typ.name != typ2.name { - //verror('bad types $typ.name $typ2.name') - //} + // if typ.name != typ2.name { + // verror('bad types $typ.name $typ2.name') + // } } ast.VarDecl { g.write('$it.typ.name $it.name = ') @@ -89,4 +98,3 @@ fn verror(s string) { println(s) exit(1) } - diff --git a/vlib/v/cgen/cgen_test.v b/vlib/v/cgen/cgen_test.v new file mode 100644 index 0000000000..4c04d26cc5 --- /dev/null +++ b/vlib/v/cgen/cgen_test.v @@ -0,0 +1,50 @@ +import ( + os + v.parser + v.ast + v.cgen + v.table +) + +const ( + nr_tests = 2 +) + +fn test_c_files() { + println('Running V => C tests') + for i in 1 .. nr_tests + 1 { + text := os.read_file('tests/${i}.v') or { + panic(err) + } + ctext := os.read_file('tests/${i}.c') or { + panic(err) + } + table := &table.Table{} + program := parser.parse_file(text, table) + res := cgen.gen(program) + if compare_texts(res, ctext) { + eprintln('${i}... OK') + } + else { + eprintln('${i}... FAIL') + eprintln('expected:\n$ctext\ngot:\n$res') + } + } +} + +fn compare_texts(a, b string) bool { + lines_a := a.trim_space().split_into_lines() + lines_b := b.trim_space().split_into_lines() + if lines_a.len != lines_b.len { + println('different len') + return false + } + for i, line_a in lines_a { + line_b := lines_b[i] + if line_a.trim_space() != line_b.trim_space() { + println('!' + line_a) + return false + } + } + return true +} diff --git a/vlib/v/cgen/tests/1.c b/vlib/v/cgen/tests/1.c new file mode 100644 index 0000000000..2d3020b2b4 --- /dev/null +++ b/vlib/v/cgen/tests/1.c @@ -0,0 +1,4 @@ +int main() { +int a = 10; +return 0; +} diff --git a/vlib/v/cgen/tests/1.v b/vlib/v/cgen/tests/1.v new file mode 100644 index 0000000000..1252c41344 --- /dev/null +++ b/vlib/v/cgen/tests/1.v @@ -0,0 +1,4 @@ +fn main() int { + a := 10 + return 0 +} diff --git a/vlib/v/cgen/tests/2.c b/vlib/v/cgen/tests/2.c new file mode 100644 index 0000000000..55f6ec6e67 --- /dev/null +++ b/vlib/v/cgen/tests/2.c @@ -0,0 +1,11 @@ +int function1() { + int a = 10 + 1; + return 0; +} + +void function2() { + int x = 0; + f64 f = 10.1; + string s = tos3("hi"); + int m = 10; +} diff --git a/vlib/v/cgen/tests/2.v b/vlib/v/cgen/tests/2.v new file mode 100644 index 0000000000..55c4a859d7 --- /dev/null +++ b/vlib/v/cgen/tests/2.v @@ -0,0 +1,12 @@ +fn function1() int { + a := 10 + 1 + return 0 +} + +// comment +fn function2() { + x := 0 + f := 10.1 + s := 'hi' + mut m := 10 +} diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index caeca1c9d3..d69dcadba9 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -72,7 +72,7 @@ pub fn parse_file(text string, table &table.Table) ast.Program { expr,_ := p.expr(token.lowest_prec) exprs << expr } - println('nr exprs = $exprs.len') + // println('nr exprs = $exprs.len') println(exprs[0]) return ast.Program{ exprs} @@ -90,7 +90,7 @@ pub fn (p mut Parser) parse_block() []ast.Expr { exprs << expr } p.next() - println('nr exprs in block = $exprs.len') + // println('nr exprs in block = $exprs.len') return exprs } @@ -146,6 +146,9 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { .key_return { return p.return_stmt() } + .key_mut { + return p.var_decl() + } .name { if p.peek_tok.kind == .decl_assign { return p.var_decl() @@ -159,9 +162,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { } .lpar { node,typ = p.expr(0) - if p.tok.kind != .rpar { - panic('Parse Error: expected )') - } + p.check(.rpar) } else { p.next() @@ -173,6 +174,9 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { op: p.tok.kind } } + else { + verror('!unknown token ' + p.tok.str()) + } } } // left binding power @@ -256,7 +260,7 @@ fn (p mut Parser) parse_number_literal() (ast.Expr,types.Type) { // val: lit.f64() val: lit } - typ = types.int_type + typ = types.f64_type } else { node = ast.IntegerLiteral{ @@ -283,7 +287,7 @@ fn (p mut Parser) import_stmt() (ast.Expr,types.Type) { fn (p mut Parser) fn_decl() (ast.Expr,types.Type) { p.check(.key_fn) name := p.tok.lit - println('fn decl $name') + // println('fn decl $name') p.check(.name) p.check(.lpar) p.check(.rpar) @@ -295,7 +299,6 @@ fn (p mut Parser) fn_decl() (ast.Expr,types.Type) { } p.check(.lcbr) // p.check(.rcbr) - println('OK!') exprs := p.parse_block() mut node := ast.Expr{} node = ast.FnDecl{ @@ -307,7 +310,7 @@ fn (p mut Parser) fn_decl() (ast.Expr,types.Type) { } fn (p mut Parser) return_stmt() (ast.Expr,types.Type) { - println('return st') + // println('return st') p.next() expr,t := p.expr(0) if !types.check(p.return_type, t) { @@ -321,6 +324,16 @@ fn (p mut Parser) return_stmt() (ast.Expr,types.Type) { } fn (p mut Parser) var_decl() (ast.Expr,types.Type) { + is_mut := p.tok.kind == .key_mut // || p.prev_tok == .key_for + is_static := p.tok.kind == .key_static + if p.tok.kind == .key_mut { + p.check(.key_mut) + // p.fspace() + } + if p.tok.kind == .key_static { + p.check(.key_static) + // p.fspace() + } name := p.tok.lit p.next() p.next() @@ -329,8 +342,8 @@ fn (p mut Parser) var_decl() (ast.Expr,types.Type) { verror('redefinition of `$name`') } p.table.names << name - println(p.table.names) - println('added $name') + // println(p.table.names) + // println('added $name') mut node := ast.Expr{} // TODO can't return VarDecl{} node = ast.VarDecl{