for loop; struct decl; struct init; < > <= >=

pull/3271/head
Alexander Medvednikov 2019-12-30 06:16:59 +01:00
parent 8a4bce667c
commit 806691c1db
8 changed files with 197 additions and 46 deletions

12
v2.v
View File

@ -7,6 +7,15 @@ import (
os os
) )
const (
cdefs = '
#define true 1
#define false 0
typedef struct { char* str; } string;
typedef double f64;
string tos3(char* s) { return (string){ .str = s }; }
')
fn main() { fn main() {
path := os.args[1] path := os.args[1]
println('V2 $path') println('V2 $path')
@ -15,6 +24,9 @@ fn main() {
program := parser.parse_file(text, table) program := parser.parse_file(text, table)
res := cgen.gen(program) res := cgen.gen(program)
mut out := os.create('out.c')? mut out := os.create('out.c')?
out.writeln(cdefs)
out.writeln(res) out.writeln(res)
out.close() out.close()
println('out.c generated')
os.system('cc out.c')
} }

View File

@ -9,9 +9,10 @@ import (
) )
pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral | pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral |
FloatLiteral | Ident | CallExpr | BoolLiteral FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit
pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | AssignStmt pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | AssignStmt |
ForStmt | StructDecl
// Stand-alone expression in a statement list. // Stand-alone expression in a statement list.
pub struct ExprStmt { pub struct ExprStmt {
pub: pub:
@ -47,6 +48,25 @@ pub:
expr Expr expr Expr
} }
pub struct Field {
pub:
name string
typ types.Type
}
pub struct StructDecl {
pub:
name string
fields []Field
}
pub struct StructInit {
pub:
typ types.Type
fields []string
exprs []Expr
}
// import statement // import statement
pub struct Import { pub struct Import {
pub: pub:
@ -143,6 +163,12 @@ pub:
else_ []Stmt else_ []Stmt
} }
pub struct ForStmt {
pub:
cond Expr
stmts []Stmt
}
pub struct ReturnStmt { pub struct ReturnStmt {
tok_kind token.TokenKind // or pos tok_kind token.TokenKind // or pos
results []Expr results []Expr

View File

@ -60,6 +60,22 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.expr(it.expr) g.expr(it.expr)
g.writeln(';') g.writeln(';')
} }
ast.ForStmt {
g.write('while (')
g.expr(it.cond)
g.writeln(') {')
for stmt in it.stmts {
g.stmt(stmt)
}
g.writeln('}')
}
ast.StructDecl {
g.writeln('typedef struct {')
for field in it.fields {
g.writeln('\t$field.typ.name $field.name;')
}
g.writeln('} $it.name;')
}
ast.ExprStmt { ast.ExprStmt {
g.expr(it.expr) g.expr(it.expr)
match it.expr { match it.expr {
@ -71,7 +87,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
} }
} }
else { else {
verror('stmt bad node') verror('cgen.stmt(): bad node')
} }
} }
} }
@ -94,32 +110,22 @@ fn (g mut Gen) expr(node ast.Expr) {
} }
ast.BinaryExpr { ast.BinaryExpr {
g.expr(it.left) g.expr(it.left)
match it.op { g.write(' $it.op.str() ')
.plus {
g.write(' + ')
}
.minus {
g.write(' - ')
}
.mul {
g.write(' * ')
}
.div {
g.write(' / ')
}
.plus_assign {
g.write(' += ')
}
else {}
}
g.expr(it.right) g.expr(it.right)
// if it.op in [.plus_assign] {
// g.writeln(';')
// }
// if typ.name != typ2.name { // if typ.name != typ2.name {
// verror('bad types $typ.name $typ2.name') // verror('bad types $typ.name $typ2.name')
// } // }
} }
// `user := User{name: 'Bob'}`
ast.StructInit {
g.writeln('($it.typ.name){')
for i, field in it.fields {
g.write('\t.$field = ')
g.expr(it.exprs[i])
g.writeln(', ')
}
g.write('}')
}
ast.CallExpr { ast.CallExpr {
g.write('${it.name}(') g.write('${it.name}(')
for i, expr in it.args { for i, expr in it.args {

View File

@ -7,6 +7,10 @@ int function1() {
void foo(int a) { void foo(int a) {
} }
typedef struct {
string name;
} User;
void function2() { void function2() {
int x = 0; int x = 0;
f64 f = 10.1; f64 f = 10.1;
@ -20,6 +24,25 @@ void function2() {
foo(10); foo(10);
x += 8; x += 8;
} }
if (false) {
foo(1);
}
while (true) {
foo(0);
}
int e = 1 + 2 > 0;
int e2 = 1 + 2 < 0;
int j = 0; int j = 0;
} }
void init_user() {
User user = (User){
.name = tos3("Bob"),
};
}
int main() {
return 0;
}

View File

@ -8,6 +8,10 @@ fn foo(a int) {
} }
struct User {
name string
}
// comment // comment
fn function2() { fn function2() {
mut x := 0 mut x := 0
@ -24,7 +28,28 @@ fn function2() {
foo(10) foo(10)
x += 8 x += 8
} }
if false {
foo(1)
}
for true {
foo(0)
}
e := 1 + 2 > 0
e2 := 1 + 2 < 0
////x += 1
//}
j := 0 j := 0
} }
fn init_user() {
user := User{
name: 'Bob'
}
}
fn main() int {
return 0
}

View File

@ -48,8 +48,12 @@ pub fn (p mut Parser) get_type() types.Type {
return types.string_type return types.string_type
} }
else { else {
p.error('bad type lit') typ := p.table.types[p.tok.lit]
exit(0) if isnil(typ.name.str) || typ.name == '' {
p.error('undefined type `$p.tok.lit`')
}
println('RET Typ $typ.name')
return typ
} }
} }
} }
@ -99,20 +103,6 @@ pub fn (p mut Parser) parse_block() []ast.Stmt {
return stmts return stmts
} }
/*
pub fn parse_stmt(text string) ast.Stmt {
mut s := scanner.new_scanner(text)
res := s.scan()
mut p := Parser{
scanner: s
tok: res.tok
lit: res.lit
}
return p.stmt()
}
*/
fn (p mut Parser) next() { fn (p mut Parser) next() {
p.tok = p.peek_tok p.tok = p.peek_tok
p.peek_tok = p.scanner.scan() p.peek_tok = p.scanner.scan()
@ -154,12 +144,18 @@ pub fn (p mut Parser) stmt() ast.Stmt {
.key_fn { .key_fn {
return p.fn_decl() return p.fn_decl()
} }
.key_struct {
return p.struct_decl()
}
.key_return { .key_return {
return p.return_stmt() return p.return_stmt()
} }
.key_mut { .key_mut {
return p.var_decl() return p.var_decl()
} }
.key_for {
return p.for_statement()
}
else { else {
expr,_ := p.expr(0) expr,_ := p.expr(0)
return ast.ExprStmt{ return ast.ExprStmt{
@ -251,6 +247,26 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
node = x node = x
typ = typ2 typ = typ2
} }
// struct init
else if p.peek_tok.kind == .lcbr {
typ = p.get_type()
p.check(.lcbr)
mut field_names := []string
mut exprs := []ast.Expr
for p.tok.kind != .rcbr {
field_name := p.check_name()
field_names << field_name
p.check(.colon)
expr,field_type := p.expr(0)
exprs << expr
}
node = ast.StructInit{
typ: typ
exprs: exprs
fields: field_names
}
p.check(.rcbr)
}
else { else {
// name expr // name expr
node = ast.Ident{ node = ast.Ident{
@ -260,9 +276,9 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
p.next() p.next()
} }
} }
.key_true { .key_true, .key_false {
node = ast.BoolLiteral{ node = ast.BoolLiteral{
val: true val: p.tok.kind == .key_true
} }
typ = types.bool_type typ = types.bool_type
p.next() p.next()
@ -309,6 +325,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
op: prev_tok.kind op: prev_tok.kind
right: expr right: expr
} }
// println(t2.name + 'OOO')
if !types.check(&typ, &t2) { if !types.check(&typ, &t2) {
p.error('cannot convert `$t2.name` to `$typ.name`') p.error('cannot convert `$t2.name` to `$typ.name`')
} }
@ -316,6 +333,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
else if prev_tok.is_left_assoc() { else if prev_tok.is_left_assoc() {
mut expr := ast.Expr{} mut expr := ast.Expr{}
expr,t2 = p.expr(prev_tok.precedence()) expr,t2 = p.expr(prev_tok.precedence())
// println(t2.name + '222')
node = ast.BinaryExpr{ node = ast.BinaryExpr{
left: node left: node
op: prev_tok.kind op: prev_tok.kind
@ -326,6 +344,20 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
return node,typ return node,typ
} }
fn (p mut Parser) for_statement() ast.ForStmt {
p.check(.key_for)
cond,typ := p.expr(0)
if !types.check(types.bool_type, typ) {
p.error('non-bool used as for condition')
}
p.check(.lcbr)
stmts := p.parse_block()
return ast.ForStmt{
cond: cond
stmts: stmts
}
}
fn (p mut Parser) if_expr() (ast.Expr,types.Type) { fn (p mut Parser) if_expr() (ast.Expr,types.Type) {
mut node := ast.Expr{} mut node := ast.Expr{}
p.check(.key_if) p.check(.key_if)
@ -384,12 +416,34 @@ fn (p mut Parser) import_stmt() ast.Import {
return ast.Import{} return ast.Import{}
} }
fn (p mut Parser) struct_decl() ast.StructDecl {
p.check(.key_struct)
name := p.check_name()
p.check(.lcbr)
mut fields := []ast.Field
for p.tok.kind != .rcbr {
field_name := p.check_name()
typ := p.get_type()
fields << ast.Field{
name: field_name
typ: typ
}
}
p.check(.rcbr)
p.table.register_type(types.Type{
name: name
})
return ast.StructDecl{
name: name
fields: fields
}
}
fn (p mut Parser) fn_decl() ast.FnDecl { fn (p mut Parser) fn_decl() ast.FnDecl {
p.table.clear_vars() p.table.clear_vars()
p.check(.key_fn) p.check(.key_fn)
name := p.tok.lit name := p.check_name()
// println('fn decl $name') // println('fn decl $name')
p.check(.name)
p.check(.lpar) p.check(.lpar)
// Args // Args
mut args := []table.Var mut args := []table.Var

View File

@ -9,6 +9,7 @@ pub mut:
local_vars []Var local_vars []Var
// fns Hashmap // fns Hashmap
fns map[string]Fn fns map[string]Fn
types map[string]types.Type
} }
pub struct Var { pub struct Var {
@ -90,3 +91,7 @@ pub fn (t mut Table) register_fn(new_fn Fn) {
// println('reg fn $new_fn.name nr_args=$new_fn.args.len') // println('reg fn $new_fn.name nr_args=$new_fn.args.len')
t.fns[new_fn.name] = new_fn t.fns[new_fn.name] = new_fn
} }
pub fn (t mut Table) register_type(typ types.Type) {
t.types[typ.name] = typ
}

View File

@ -360,8 +360,8 @@ pub fn (tok Token) is_left_assoc() bool {
// .number, // .number,
// `*` | `/` | `%` // `*` | `/` | `%`
.mul, .div, .mod, .mul, .div, .mod,
// `^` | `||` | `&` // `^` | `||` | `&` < > <= >=
.xor, .logical_or, .and, .xor, .logical_or, .and, .gt, .lt, .le, .ge,
// `,` // `,`
.comma] .comma]
} }