for ;; syntax

pull/3354/head
Alexander Medvednikov 2020-01-07 00:14:19 +01:00
parent 1e28c1d4fd
commit 48ea1153a5
9 changed files with 116 additions and 30 deletions

View File

@ -126,8 +126,9 @@ jobs:
echo "Generating a 1m line V file..." echo "Generating a 1m line V file..."
../vprod run gen1m.v > 1m.v ../vprod run gen1m.v > 1m.v
echo "Building it..." echo "Building it..."
../vprod -x64 1m.v ../vprod -x64 -o 1m 1m.v
echo "Running it..." echo "Running it..."
ls
./1m ./1m
#run: echo "TODO" #cd examples/x64 && ../../v -x64 hello_world.v && ./hello_world #run: echo "TODO" #cd examples/x64 && ../../v -x64 hello_world.v && ./hello_world

View File

@ -78,7 +78,7 @@ fn (a mut array) ensure_cap(required int) {
// repeated `nr_repeat` times // repeated `nr_repeat` times
pub fn (a array) repeat(nr_repeats int) array { pub fn (a array) repeat(nr_repeats int) array {
if nr_repeats < 0 { 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 mut size := nr_repeats * a.len * a.element_size
if size == 0 { if size == 0 {

View File

@ -12,7 +12,7 @@ pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | AssignExpr | PrefixExpr FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | AssignExpr | PrefixExpr
pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt |
ForStmt | StructDecl ForStmt | StructDecl | ForCStmt | ForInStmt
// | IncDecStmt k // | IncDecStmt k
// Stand-alone expression in a statement list. // Stand-alone expression in a statement list.
pub struct ExprStmt { pub struct ExprStmt {
@ -195,7 +195,21 @@ pub struct ForStmt {
pub: pub:
cond Expr cond Expr
stmts []Stmt 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 { pub struct ReturnStmt {

View File

@ -81,11 +81,20 @@ fn (g mut Gen) stmt(node ast.Stmt) {
} }
ast.ForStmt { ast.ForStmt {
g.write('while (') g.write('while (')
if !it.is_in { g.expr(it.cond)
// `for in` loops don't have a condition g.writeln(') {')
println('it cond') for stmt in it.stmts {
g.expr(it.cond) 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(') {') g.writeln(') {')
for stmt in it.stmts { for stmt in it.stmts {
g.stmt(stmt) g.stmt(stmt)

View File

@ -31,6 +31,7 @@ fn test_c_files() {
eprintln('${i}... ' + term.red('FAIL')) eprintln('${i}... ' + term.red('FAIL'))
eprintln(path) eprintln(path)
eprintln('got:\n$res') eprintln('got:\n$res')
assert false
} }
} }
} }

View File

@ -2,6 +2,7 @@ void foo(int a);
int get_int(string a); int get_int(string a);
int get_int2(); int get_int2();
void myuser(); void myuser();
void variadic(variadic_int a);
typedef struct { typedef struct {
int age; int age;
@ -18,6 +19,13 @@ return 0;
} }
void foo(int a) { void foo(int a) {
while (true) {
}
for (int i = 0;
i < 10; i++;
) {
}
void n = get_int2(); void n = get_int2();
} }

View File

@ -24,6 +24,12 @@ fn main() {
*/ */
fn foo(a int) { fn foo(a int) {
for true {
}
for i := 0; i < 10; i++ {
}
n := get_int2() n := get_int2()
} }
@ -45,5 +51,5 @@ fn myuser() {
b2 := user.age > 0 b2 := user.age > 0
} }
fn variadic(a ...int) { fn variadic(a ...int) {
} }

View File

@ -5,7 +5,7 @@ module x64
import ( import (
v.ast v.ast
term // term
) )
pub struct Gen { pub struct Gen {
@ -325,15 +325,10 @@ fn (g mut Gen) stmt(node ast.Stmt) {
} }
g.ret() g.ret()
} }
ast.Return { ast.Return {}
} ast.VarDecl {}
ast.VarDecl { ast.ForStmt {}
} ast.StructDecl {}
ast.ForStmt {
if it.is_in {}
}
ast.StructDecl {
}
ast.ExprStmt { ast.ExprStmt {
g.expr(it.expr) g.expr(it.expr)
} }
@ -378,12 +373,12 @@ fn (g mut Gen) expr(node ast.Expr) {
ast.BoolLiteral {} ast.BoolLiteral {}
ast.IfExpr {} ast.IfExpr {}
else { else {
//println(term.red('x64.expr(): bad node')) // println(term.red('x64.expr(): bad node'))
} }
}
} }
}
fn verror(s string) { fn verror(s string) {
println(s) println(s)
exit(1) exit(1)
} }

View File

@ -149,7 +149,7 @@ pub fn (p mut Parser) top_stmt() ast.Stmt {
p.error('wrong pub keyword usage') p.error('wrong pub keyword usage')
return ast.Stmt{} return ast.Stmt{}
} }
} }
// .key_const { // .key_const {
// return p.const_decl() // 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) { pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) {
mut node := ast.Expr{} mut node := ast.Expr{}
mut ti := types.void_ti mut ti := types.void_ti
if p.tok.lit == 'C' {
p.next()
p.check(.dot)
}
// fn call // fn call
if p.peek_tok.kind == .lpar { if p.peek_tok.kind == .lpar {
x,ti2 := p.call_expr() // TODO `node,typ :=` should work 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] 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) 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` // `for i in start .. end`
if p.peek_tok.kind == .key_in { else if p.peek_tok.kind == .key_in {
var := p.check_name() var := p.check_name()
p.check(.key_in) p.check(.key_in)
start := p.tok.lit.int() start := p.tok.lit.int()
@ -451,7 +504,6 @@ fn (p mut Parser) for_statement() ast.ForStmt {
// println('nr stmts=$stmts.len') // println('nr stmts=$stmts.len')
return ast.ForStmt{ return ast.ForStmt{
stmts: stmts stmts: stmts
is_in: true
} }
} }
// `for cond {` // `for cond {`