1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00
v/vlib/v/cgen/cgen.v

163 lines
2.4 KiB
V
Raw Normal View History

2019-12-24 20:54:43 +03:00
module cgen
import (
strings
v.ast
term
2019-12-24 20:54:43 +03:00
)
struct Gen {
out strings.Builder
}
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('')
}
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)
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')
}
}
}
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 {
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
}
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 {
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
}
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 {
println(term.red('cgen.expr(): bad node'))
2019-12-24 20:54:43 +03:00
}
}
}
fn verror(s string) {
println(s)
exit(1)
2019-12-24 20:54:43 +03:00
}