2019-12-24 20:54:43 +03:00
|
|
|
module cgen
|
|
|
|
|
|
|
|
import (
|
|
|
|
strings
|
2019-12-27 07:43:17 +03:00
|
|
|
v.ast
|
2019-12-29 10:51:55 +03:00
|
|
|
term
|
2019-12-24 20:54:43 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
struct Gen {
|
|
|
|
out strings.Builder
|
|
|
|
}
|
|
|
|
|
2019-12-27 07:43:17 +03:00
|
|
|
pub fn gen(program ast.Program) string {
|
2019-12-28 13:02:06 +03:00
|
|
|
mut g := Gen{
|
|
|
|
out: strings.new_builder(100)
|
|
|
|
}
|
2019-12-28 16:11:05 +03:00
|
|
|
for stmt in program.stmts {
|
|
|
|
g.stmt(stmt)
|
2019-12-24 20:54:43 +03:00
|
|
|
g.writeln('')
|
|
|
|
}
|
2019-12-27 07:43:17 +03:00
|
|
|
return (g.out.str())
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|
|
|
|
|
2019-12-28 13:02:06 +03:00
|
|
|
pub fn (g &Gen) save() {}
|
2019-12-24 20:54:43 +03:00
|
|
|
|
|
|
|
pub fn (g mut Gen) write(s string) {
|
|
|
|
g.out.write(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (g mut Gen) writeln(s string) {
|
|
|
|
g.out.writeln(s)
|
|
|
|
}
|
|
|
|
|
2019-12-28 16:11:05 +03:00
|
|
|
fn (g mut Gen) stmt(node ast.Stmt) {
|
|
|
|
match node {
|
2019-12-28 21:16:04 +03:00
|
|
|
ast.AssignStmt {
|
|
|
|
g.expr(it.left)
|
|
|
|
g.write(' $it.op.str() ')
|
|
|
|
g.expr(it.right)
|
|
|
|
g.writeln(';')
|
|
|
|
}
|
2019-12-28 16:11:05 +03:00
|
|
|
ast.FnDecl {
|
2019-12-29 09:24:17 +03:00
|
|
|
g.write('$it.typ.name ${it.name}(')
|
|
|
|
for arg in it.args {
|
|
|
|
g.write(arg.typ.name + ' ' + arg.name)
|
|
|
|
}
|
|
|
|
g.writeln(') { ')
|
2019-12-28 16:11:05 +03:00
|
|
|
for stmt in it.stmts {
|
|
|
|
g.stmt(stmt)
|
|
|
|
}
|
|
|
|
g.writeln('}')
|
|
|
|
}
|
|
|
|
ast.Return {
|
|
|
|
g.write('return ')
|
|
|
|
g.expr(it.expr)
|
|
|
|
g.writeln(';')
|
|
|
|
}
|
|
|
|
ast.VarDecl {
|
|
|
|
g.write('$it.typ.name $it.name = ')
|
|
|
|
g.expr(it.expr)
|
|
|
|
g.writeln(';')
|
|
|
|
}
|
|
|
|
ast.ExprStmt {
|
|
|
|
g.expr(it.expr)
|
2019-12-29 10:51:55 +03:00
|
|
|
match it.expr {
|
|
|
|
// no ; after an if expression
|
|
|
|
ast.IfExpr {}
|
|
|
|
else {
|
|
|
|
g.writeln(';')
|
|
|
|
}
|
|
|
|
}
|
2019-12-28 16:11:05 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
verror('stmt bad node')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-26 13:27:35 +03:00
|
|
|
fn (g mut Gen) expr(node ast.Expr) {
|
2019-12-28 13:02:06 +03:00
|
|
|
// println('cgen expr()')
|
2019-12-24 20:54:43 +03:00
|
|
|
match node {
|
2019-12-26 13:21:41 +03:00
|
|
|
ast.IntegerLiteral {
|
2019-12-24 20:54:43 +03:00
|
|
|
g.write(it.val.str())
|
|
|
|
}
|
2019-12-27 12:03:29 +03:00
|
|
|
ast.FloatLiteral {
|
|
|
|
g.write(it.val)
|
|
|
|
}
|
2019-12-26 12:02:38 +03:00
|
|
|
ast.UnaryExpr {
|
|
|
|
g.expr(it.left)
|
|
|
|
g.write(' $it.op ')
|
|
|
|
}
|
2019-12-24 20:54:43 +03:00
|
|
|
ast.StringLiteral {
|
2019-12-27 10:52:20 +03:00
|
|
|
g.write('tos3("$it.val")')
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|
|
|
|
ast.BinaryExpr {
|
2019-12-26 13:27:35 +03:00
|
|
|
g.expr(it.left)
|
2019-12-24 20:54:43 +03:00
|
|
|
match it.op {
|
2019-12-28 13:02:06 +03:00
|
|
|
.plus {
|
|
|
|
g.write(' + ')
|
|
|
|
}
|
|
|
|
.minus {
|
|
|
|
g.write(' - ')
|
|
|
|
}
|
|
|
|
.mul {
|
|
|
|
g.write(' * ')
|
|
|
|
}
|
|
|
|
.div {
|
|
|
|
g.write(' / ')
|
|
|
|
}
|
|
|
|
.plus_assign {
|
|
|
|
g.write(' += ')
|
|
|
|
}
|
2019-12-24 20:54:43 +03:00
|
|
|
else {}
|
2019-12-28 13:02:06 +03:00
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
g.expr(it.right)
|
2019-12-28 16:11:05 +03:00
|
|
|
// if it.op in [.plus_assign] {
|
|
|
|
// g.writeln(';')
|
|
|
|
// }
|
2019-12-28 13:02:06 +03:00
|
|
|
// if typ.name != typ2.name {
|
|
|
|
// verror('bad types $typ.name $typ2.name')
|
|
|
|
// }
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|
2019-12-29 09:24:17 +03:00
|
|
|
ast.CallExpr {
|
2019-12-29 10:51:55 +03:00
|
|
|
g.write('${it.name}(')
|
|
|
|
for i, expr in it.args {
|
|
|
|
g.expr(expr)
|
|
|
|
if i != it.args.len - 1 {
|
|
|
|
g.write(', ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g.write(')')
|
2019-12-29 09:24:17 +03:00
|
|
|
}
|
2019-12-28 16:11:05 +03:00
|
|
|
ast.Ident {
|
|
|
|
g.write('$it.name')
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|
2019-12-29 10:51:55 +03:00
|
|
|
ast.BoolLiteral {
|
|
|
|
if it.val == true {
|
|
|
|
g.write('true')
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
g.write('false')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast.IfExpr {
|
|
|
|
g.write('if (')
|
|
|
|
g.expr(it.cond)
|
|
|
|
g.writeln(') {')
|
|
|
|
for stmt in it.stmts {
|
|
|
|
g.stmt(stmt)
|
|
|
|
}
|
|
|
|
g.writeln('}')
|
|
|
|
}
|
2019-12-24 20:54:43 +03:00
|
|
|
else {
|
2019-12-29 10:51:55 +03:00
|
|
|
println(term.red('cgen.expr(): bad node'))
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn verror(s string) {
|
|
|
|
println(s)
|
|
|
|
exit(1)
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|