From 48ea1153a5709ef45f9233504298f27ea86efb97 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 7 Jan 2020 00:14:19 +0100 Subject: [PATCH] for ;; syntax --- .github/workflows/ci.yml | 3 +- vlib/builtin/array.v | 2 +- vlib/v/ast/ast.v | 18 ++++++++++-- vlib/v/gen/cgen.v | 17 +++++++++--- vlib/v/gen/cgen_test.v | 1 + vlib/v/gen/tests/1.c | 8 ++++++ vlib/v/gen/tests/1.vv | 8 +++++- vlib/v/gen/x64/gen.v | 29 ++++++++----------- vlib/v/parser/parser.v | 60 +++++++++++++++++++++++++++++++++++++--- 9 files changed, 116 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a804dab3f..8341fdbf6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -126,8 +126,9 @@ jobs: echo "Generating a 1m line V file..." ../vprod run gen1m.v > 1m.v echo "Building it..." - ../vprod -x64 1m.v + ../vprod -x64 -o 1m 1m.v echo "Running it..." + ls ./1m #run: echo "TODO" #cd examples/x64 && ../../v -x64 hello_world.v && ./hello_world diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index 558a9f5a12..fab9d620c9 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -78,7 +78,7 @@ fn (a mut array) ensure_cap(required int) { // repeated `nr_repeat` times pub fn (a array) repeat(nr_repeats int) array { if nr_repeats < 0 { - panic('array.repeat: count is negative (count == $nr_repeats)') + panic('array.repeat: count is negative (count == nr_repeats)') } mut size := nr_repeats * a.len * a.element_size if size == 0 { diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 36a4eabd88..ddbd5a0613 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -12,7 +12,7 @@ pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | AssignExpr | PrefixExpr pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | -ForStmt | StructDecl +ForStmt | StructDecl | ForCStmt | ForInStmt // | IncDecStmt k // Stand-alone expression in a statement list. pub struct ExprStmt { @@ -195,7 +195,21 @@ pub struct ForStmt { pub: cond Expr stmts []Stmt - is_in bool +} + +pub struct ForInStmt { +pub: + var string + cond Expr + stmts []Stmt +} + +pub struct ForCStmt { +pub: + init Stmt // i := 0; + cond Expr // i < 10; + inc Stmt // i++; + stmts []Stmt } pub struct ReturnStmt { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 5a4940260c..1879087f0e 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -81,11 +81,20 @@ fn (g mut Gen) stmt(node ast.Stmt) { } ast.ForStmt { g.write('while (') - if !it.is_in { - // `for in` loops don't have a condition - println('it cond') - g.expr(it.cond) + g.expr(it.cond) + g.writeln(') {') + for stmt in it.stmts { + g.stmt(stmt) } + g.writeln('}') + } + ast.ForCStmt { + g.write('for (') + g.stmt(it.init) + // g.write('; ') + g.expr(it.cond) + g.write('; ') + g.stmt(it.inc) g.writeln(') {') for stmt in it.stmts { g.stmt(stmt) diff --git a/vlib/v/gen/cgen_test.v b/vlib/v/gen/cgen_test.v index e55842a8a0..b7da665950 100644 --- a/vlib/v/gen/cgen_test.v +++ b/vlib/v/gen/cgen_test.v @@ -31,6 +31,7 @@ fn test_c_files() { eprintln('${i}... ' + term.red('FAIL')) eprintln(path) eprintln('got:\n$res') + assert false } } } diff --git a/vlib/v/gen/tests/1.c b/vlib/v/gen/tests/1.c index 0c2a38340c..0d320bc0c6 100644 --- a/vlib/v/gen/tests/1.c +++ b/vlib/v/gen/tests/1.c @@ -2,6 +2,7 @@ void foo(int a); int get_int(string a); int get_int2(); void myuser(); +void variadic(variadic_int a); typedef struct { int age; @@ -18,6 +19,13 @@ return 0; } void foo(int a) { + while (true) { + + } + for (int i = 0; +i < 10; i++; +) { + } void n = get_int2(); } diff --git a/vlib/v/gen/tests/1.vv b/vlib/v/gen/tests/1.vv index 4c16cee197..b206d8d027 100644 --- a/vlib/v/gen/tests/1.vv +++ b/vlib/v/gen/tests/1.vv @@ -24,6 +24,12 @@ fn main() { */ fn foo(a int) { + for true { + + } + for i := 0; i < 10; i++ { + + } n := get_int2() } @@ -45,5 +51,5 @@ fn myuser() { b2 := user.age > 0 } -fn variadic(a ...int) { +fn variadic(a ...int) { } diff --git a/vlib/v/gen/x64/gen.v b/vlib/v/gen/x64/gen.v index ba6d6a0e8d..748c6f9c9e 100644 --- a/vlib/v/gen/x64/gen.v +++ b/vlib/v/gen/x64/gen.v @@ -5,7 +5,7 @@ module x64 import ( v.ast - term + // term ) pub struct Gen { @@ -325,15 +325,10 @@ fn (g mut Gen) stmt(node ast.Stmt) { } g.ret() } - ast.Return { - } - ast.VarDecl { - } - ast.ForStmt { - if it.is_in {} - } - ast.StructDecl { - } + ast.Return {} + ast.VarDecl {} + ast.ForStmt {} + ast.StructDecl {} ast.ExprStmt { g.expr(it.expr) } @@ -378,12 +373,12 @@ fn (g mut Gen) expr(node ast.Expr) { ast.BoolLiteral {} ast.IfExpr {} else { - //println(term.red('x64.expr(): bad node')) - } + // println(term.red('x64.expr(): bad node')) + } + } } -} -fn verror(s string) { - println(s) - exit(1) -} + fn verror(s string) { + println(s) + exit(1) + } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index d11b2bb57f..f00887751d 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -149,7 +149,7 @@ pub fn (p mut Parser) top_stmt() ast.Stmt { p.error('wrong pub keyword usage') return ast.Stmt{} } - } + } // .key_const { // return p.const_decl() // } @@ -256,6 +256,10 @@ pub fn (p &Parser) warn(s string) { pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) { mut node := ast.Expr{} mut ti := types.void_ti + if p.tok.lit == 'C' { + p.next() + p.check(.dot) + } // fn call if p.peek_tok.kind == .lpar { x,ti2 := p.call_expr() // TODO `node,typ :=` should work @@ -435,10 +439,59 @@ fn (p &Parser) is_addative() bool { return p.tok.kind in [.plus, .minus] && p.peek_tok.kind in [.number, .name] } -fn (p mut Parser) for_statement() ast.ForStmt { +fn (p mut Parser) for_statement() ast.Stmt { p.check(.key_for) + // Infinite loop + if p.tok.kind == .lcbr { + stmts := p.parse_block() + return ast.ForStmt{ + stmts: stmts + } + } + else if p.tok.kind == .key_mut { + p.error('`mut` is not required in for loops') + } + // for i := 0; i < 10; i++ { + else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon] { + mut init := ast.Stmt{} + mut cond := ast.Expr{} + mut inc := ast.Stmt{} + if p.peek_tok.kind == .decl_assign { + init = p.var_decl() + } + else if p.tok.kind != .semicolon { + // allow `for ;; i++ {` + // Allow `for i = 0; i < ...` + /* + cond, typ = p.expr(0) + if typ.kind != _bool { + p.error('non-bool used as for condition') + } + */ + println(1) + } + p.check(.semicolon) + if p.tok.kind != .semicolon { + mut typ := types.TypeIdent{} + cond,typ = p.expr(0) + if typ.kind != ._bool { + p.error('non-bool used as for condition') + } + } + p.check(.semicolon) + if p.tok.kind != .lcbr { + inc = p.stmt() + } + stmts := p.parse_block() + return ast.ForCStmt{ + stmts: stmts + init: init + cond: cond + inc: inc + } + } // `for i in start .. end` - if p.peek_tok.kind == .key_in { + else if p.peek_tok.kind == .key_in { var := p.check_name() p.check(.key_in) start := p.tok.lit.int() @@ -451,7 +504,6 @@ fn (p mut Parser) for_statement() ast.ForStmt { // println('nr stmts=$stmts.len') return ast.ForStmt{ stmts: stmts - is_in: true } } // `for cond {`