compiler2: proof of concept cgen

pull/3219/head^2
Alexander Medvednikov 2019-12-24 20:54:43 +03:00
parent fe8a6abb41
commit 8d9f89e728
6 changed files with 193 additions and 21 deletions

View File

@ -980,6 +980,9 @@ fn (p mut Parser) fn_args(f mut Fn) {
p.next()
}
}
//if types_only && p.peek() == .lcbr {
//println('wtf')
//}
}
// foo *(1, 2, 3, mut bar)*

View File

@ -10,15 +10,19 @@ import (
struct Foo {}
// pub type Expr = Foo | IfExpr | BinaryExpr | IntegerExpr
pub type Expr = Foo | IfExpr | BinaryExpr | ScalarExpr | UnaryExpr
pub type Expr = Foo | IfExpr | BinaryExpr | ScalarExpr | UnaryExpr |
StringLiteral | IntegerExpr
pub type Stmt = Foo | VarDecl
/*
pub struct IntegerExpr {
pub:
val int
}
*/
pub struct StringLiteral {
pub:
val string
}
/*
pub enum Expr {
@ -28,10 +32,24 @@ pub enum Expr {
}
*/
/*
pub struct Stmt {
pos int
//end int
}
*/
pub struct VarDecl {
pub:
name string
expr Expr
}
pub struct Program {
pub:
exprs []Expr
}
// A single identifier
struct Ident {

View File

@ -0,0 +1,82 @@
module cgen
import (
strings
compiler2.ast
)
struct Gen {
out strings.Builder
}
pub fn gen(program ast.Program) {
mut g := Gen{out:strings.new_builder(100)}
for expr in program.exprs {
g.expr(expr)
g.writeln('')
}
println(g.out.str())
}
pub fn (g &Gen) save() {
}
pub fn (g mut Gen) write(s string) {
g.out.write(s)
}
pub fn (g mut Gen) writeln(s string) {
g.out.writeln(s)
}
struct Type {
name string
}
const (
string_type = Type{'string'}
int_type = Type{'int'}
void_type = Type{'void'}
)
fn (g mut Gen) expr(node ast.Expr) Type {
//println('cgen expr()')
match node {
ast.IntegerExpr {
g.write(it.val.str())
return int_type
}
ast.StringLiteral {
g.write('"$it.val"')
return string_type
}
ast.BinaryExpr {
typ := g.expr(it.left)
match it.op {
.plus { g.write(' + ') }
.minus { g.write(' - ') }
.mul { g.write(' * ') }
.div { g.write(' / ') }
else {}
}
typ2 := g.expr(it.right)
if typ.name != typ2.name {
println('bad types $typ.name $typ2.name')
}
return typ
}
ast.VarDecl {
g.write('var $it.name = ')
g.expr(it.expr)
g.writeln(';')
return void_type
}
else {
println('bad node')
}
}
return void_type
}

View File

@ -28,6 +28,17 @@ pub fn parse_expr(text string) ast.Expr {
return p.expr(token.lowest_prec)
}
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() {
res := p.scanner.scan()
p.tok = res.tok
@ -41,37 +52,76 @@ pub fn (p mut Parser) expr(rbp int) ast.Expr {
tok := p.tok
lit := p.lit
p.next()
mut left := ast.Expr{}
mut node := ast.Expr{
}
match tok {
.lpar {
left = p.expr(0)
node = p.expr(0)
if p.tok != .rpar {
panic("Parse Error: expected )")
panic('Parse Error: expected )')
}
p.next()
}
else {
// TODO: fix bug. note odd conditon instead of else if (same below)
if tok.is_scalar() {
left = ast.ScalarExpr{val: lit, typ: tok}
node = ast.ScalarExpr{
val: lit
typ: tok
}
}
if !tok.is_scalar() && tok.is_unary() {
left = ast.UnaryExpr{left: p.expr(token.highest_prec), op: tok}
node = ast.UnaryExpr{
left: p.expr(token.highest_prec)
op: tok
}
}
}
}}
// left binding power
for rbp < p.tok.precedence() {
tok2 := p.tok
p.next()
// left denotation (infix)
if tok2.is_right_assoc() {
left = ast.BinaryExpr{left: left, op: tok2, right: p.expr(tok2.precedence() - 1)}
node = ast.BinaryExpr{
left: node
op: tok2
right: p.expr(tok2.precedence() - 1)
}
}
if !tok2.is_right_assoc() && tok2.is_left_assoc() {
left = ast.BinaryExpr{left: left, op: tok2, right: p.expr(tok2.precedence())}
node = ast.BinaryExpr{
left: node
op: tok2
right: p.expr(tok2.precedence())
}
}
return left
}
return node
}
fn (p mut Parser) stmt() ast.Stmt {
if p.tok == .name {
name := p.lit
p.next()
if p.tok == .decl_assign {
p.next()
return ast.VarDecl{
name: name
expr: p.expr(token.lowest_prec)
}
}
}
/*
match node {
Ident {
}
}
*/
return ast.VarDecl{
}
}

View File

@ -1,6 +1,9 @@
module parser
import compiler2.ast
import (
compiler2.ast
compiler2.cgen
)
fn test_parser() {
//expr := ast.IntegerExpr {val:10}
@ -62,4 +65,17 @@ fn walk(node ast.Expr) {
}
else { }
}
/*
//expr := parse_expr('3 + 7 * 2')
expr := parse_stmt('a := 3 + "f"')
program := ast.Program{
exprs: [
expr,
//parse_expr('2 * 2'),
]
}
cgen.gen(program)
//cgen.save()
*/
}

View File

@ -29,6 +29,9 @@ pub fn (b mut Builder) write_b(data byte) {
}
pub fn (b mut Builder) write(s string) {
if s == '' {
return
}
b.buf.push_many(s.str, s.len)
// for c in s {
// b.buf << c