for loop; struct decl; struct init; < > <= >=
parent
8a4bce667c
commit
806691c1db
12
v2.v
12
v2.v
|
@ -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')
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue