for loop; struct decl; struct init; < > <= >=
parent
8a4bce667c
commit
806691c1db
12
v2.v
12
v2.v
|
@ -7,6 +7,15 @@ import (
|
|||
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() {
|
||||
path := os.args[1]
|
||||
println('V2 $path')
|
||||
|
@ -15,6 +24,9 @@ fn main() {
|
|||
program := parser.parse_file(text, table)
|
||||
res := cgen.gen(program)
|
||||
mut out := os.create('out.c')?
|
||||
out.writeln(cdefs)
|
||||
out.writeln(res)
|
||||
out.close()
|
||||
println('out.c generated')
|
||||
os.system('cc out.c')
|
||||
}
|
||||
|
|
|
@ -9,9 +9,10 @@ import (
|
|||
)
|
||||
|
||||
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.
|
||||
pub struct ExprStmt {
|
||||
pub:
|
||||
|
@ -47,6 +48,25 @@ pub:
|
|||
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
|
||||
pub struct Import {
|
||||
pub:
|
||||
|
@ -143,6 +163,12 @@ pub:
|
|||
else_ []Stmt
|
||||
}
|
||||
|
||||
pub struct ForStmt {
|
||||
pub:
|
||||
cond Expr
|
||||
stmts []Stmt
|
||||
}
|
||||
|
||||
pub struct ReturnStmt {
|
||||
tok_kind token.TokenKind // or pos
|
||||
results []Expr
|
||||
|
|
|
@ -60,6 +60,22 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
g.expr(it.expr)
|
||||
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 {
|
||||
g.expr(it.expr)
|
||||
match it.expr {
|
||||
|
@ -71,7 +87,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
verror('stmt bad node')
|
||||
verror('cgen.stmt(): bad node')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,32 +110,22 @@ 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(' += ')
|
||||
}
|
||||
else {}
|
||||
}
|
||||
g.write(' $it.op.str() ')
|
||||
g.expr(it.right)
|
||||
// if it.op in [.plus_assign] {
|
||||
// g.writeln(';')
|
||||
// }
|
||||
// if 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 {
|
||||
g.write('${it.name}(')
|
||||
for i, expr in it.args {
|
||||
|
|
|
@ -7,6 +7,10 @@ int function1() {
|
|||
void foo(int a) {
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
string name;
|
||||
} User;
|
||||
|
||||
void function2() {
|
||||
int x = 0;
|
||||
f64 f = 10.1;
|
||||
|
@ -20,6 +24,25 @@ void function2() {
|
|||
foo(10);
|
||||
x += 8;
|
||||
}
|
||||
if (false) {
|
||||
foo(1);
|
||||
}
|
||||
while (true) {
|
||||
foo(0);
|
||||
}
|
||||
int e = 1 + 2 > 0;
|
||||
int e2 = 1 + 2 < 0;
|
||||
int j = 0;
|
||||
}
|
||||
|
||||
void init_user() {
|
||||
User user = (User){
|
||||
.name = tos3("Bob"),
|
||||
};
|
||||
}
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,10 @@ fn foo(a int) {
|
|||
|
||||
}
|
||||
|
||||
struct User {
|
||||
name string
|
||||
}
|
||||
|
||||
// comment
|
||||
fn function2() {
|
||||
mut x := 0
|
||||
|
@ -24,7 +28,28 @@ fn function2() {
|
|||
foo(10)
|
||||
x += 8
|
||||
}
|
||||
if false {
|
||||
foo(1)
|
||||
}
|
||||
for true {
|
||||
foo(0)
|
||||
}
|
||||
e := 1 + 2 > 0
|
||||
e2 := 1 + 2 < 0
|
||||
|
||||
////x += 1
|
||||
//}
|
||||
j := 0
|
||||
}
|
||||
|
||||
fn init_user() {
|
||||
user := User{
|
||||
name: 'Bob'
|
||||
}
|
||||
}
|
||||
|
||||
fn main() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -48,8 +48,12 @@ pub fn (p mut Parser) get_type() types.Type {
|
|||
return types.string_type
|
||||
}
|
||||
else {
|
||||
p.error('bad type lit')
|
||||
exit(0)
|
||||
typ := p.table.types[p.tok.lit]
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
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() {
|
||||
p.tok = p.peek_tok
|
||||
p.peek_tok = p.scanner.scan()
|
||||
|
@ -154,12 +144,18 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
|||
.key_fn {
|
||||
return p.fn_decl()
|
||||
}
|
||||
.key_struct {
|
||||
return p.struct_decl()
|
||||
}
|
||||
.key_return {
|
||||
return p.return_stmt()
|
||||
}
|
||||
.key_mut {
|
||||
return p.var_decl()
|
||||
}
|
||||
.key_for {
|
||||
return p.for_statement()
|
||||
}
|
||||
else {
|
||||
expr,_ := p.expr(0)
|
||||
return ast.ExprStmt{
|
||||
|
@ -251,6 +247,26 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
|||
node = x
|
||||
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 {
|
||||
// name expr
|
||||
node = ast.Ident{
|
||||
|
@ -260,9 +276,9 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
|||
p.next()
|
||||
}
|
||||
}
|
||||
.key_true {
|
||||
.key_true, .key_false {
|
||||
node = ast.BoolLiteral{
|
||||
val: true
|
||||
val: p.tok.kind == .key_true
|
||||
}
|
||||
typ = types.bool_type
|
||||
p.next()
|
||||
|
@ -309,6 +325,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
|||
op: prev_tok.kind
|
||||
right: expr
|
||||
}
|
||||
// println(t2.name + 'OOO')
|
||||
if !types.check(&typ, &t2) {
|
||||
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() {
|
||||
mut expr := ast.Expr{}
|
||||
expr,t2 = p.expr(prev_tok.precedence())
|
||||
// println(t2.name + '222')
|
||||
node = ast.BinaryExpr{
|
||||
left: node
|
||||
op: prev_tok.kind
|
||||
|
@ -326,6 +344,20 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
|||
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) {
|
||||
mut node := ast.Expr{}
|
||||
p.check(.key_if)
|
||||
|
@ -384,12 +416,34 @@ fn (p mut Parser) import_stmt() 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 {
|
||||
p.table.clear_vars()
|
||||
p.check(.key_fn)
|
||||
name := p.tok.lit
|
||||
name := p.check_name()
|
||||
// println('fn decl $name')
|
||||
p.check(.name)
|
||||
p.check(.lpar)
|
||||
// Args
|
||||
mut args := []table.Var
|
||||
|
|
|
@ -9,6 +9,7 @@ pub mut:
|
|||
local_vars []Var
|
||||
// fns Hashmap
|
||||
fns map[string]Fn
|
||||
types map[string]types.Type
|
||||
}
|
||||
|
||||
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')
|
||||
t.fns[new_fn.name] = new_fn
|
||||
}
|
||||
|
||||
pub fn (t mut Table) register_type(typ types.Type) {
|
||||
t.types[typ.name] = typ
|
||||
}
|
||||
|
|
|
@ -360,8 +360,8 @@ pub fn (tok Token) is_left_assoc() bool {
|
|||
// .number,
|
||||
// `*` | `/` | `%`
|
||||
.mul, .div, .mod,
|
||||
// `^` | `||` | `&`
|
||||
.xor, .logical_or, .and,
|
||||
// `^` | `||` | `&` < > <= >=
|
||||
.xor, .logical_or, .and, .gt, .lt, .le, .ge,
|
||||
// `,`
|
||||
.comma]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue