Files
one/generator.v
2026-02-04 22:35:26 +01:00

164 lines
3.5 KiB
V

module main
import strings
import os
struct Generator {
mut:
out strings.Builder
}
fn mangle_var(name string) string {
return 'v${name}'
}
fn (mut g Generator) get_c_type(typ string) string {
c_type := if typ == 'real' { 'double' } else { typ }
return c_type
}
fn (mut g Generator) gen_stmt(stmt Stmt) {
match stmt {
VarDecl {
c_type := g.get_c_type(stmt.type)
if stmt.const {
g.out.write_string('const ')
}
g.out.write_string('${c_type} ${mangle_var(stmt.name)} = ')
g.gen_expr(stmt.value)
g.out.writeln(';')
}
ExprStmt {
g.gen_expr(stmt.expr)
g.out.writeln(';')
}
ReturnStmt {
g.out.write_string('return ')
g.gen_expr(stmt.expr)
g.out.writeln(';')
}
Block {
g.out.writeln('{')
for inner_stmt in stmt.stmts {
g.gen_stmt(inner_stmt)
}
g.out.writeln('}')
}
FuncDecl {
c_type := g.get_c_type(stmt.ret_type)
g.out.write_string('${c_type} ${stmt.name}(')
for param in stmt.params {
g.gen_stmt(param)
if param != stmt.params[stmt.params.len-1]{
g.out.write_string(', ')
}
}
g.out.write_string(')')
g.gen_stmt(stmt.block)
}
Param {
c_type := g.get_c_type(stmt.type)
g.out.write_string('${c_type} ${mangle_var(stmt.name)}')
}
}
}
fn (mut g Generator) gen_expr(expr Expr) {
match expr {
RealLiteral {
g.out.write_string(expr.val.str())
}
IntegerLiteral {
g.out.write_string(expr.val.str())
}
BoolLiteral {
g.out.write_string(expr.val.str())
}
Variable {
g.out.write_string(mangle_var(expr.name))
}
UnaryExpr {
g.out.write_string('${expr.ident}${expr.op}')
}
BinaryExpr {
g.out.write_string('(')
g.gen_expr(expr.left)
g.out.write_string(' ${expr.op} ')
g.gen_expr(expr.right)
g.out.write_string(')')
}
PrintExpr {
g.out.write_string('printf(\"%')
format := match expr.type {
'int', 'bool' {'d'}
'real' {'lf'}
else {panic("Tried printing illegal type")}
}
g.out.write_string('${format}\\n\", ')
g.gen_expr(expr.expr)
g.out.write_string(')')
}
TypeCast {
c_type := g.get_c_type(expr.type)
g.out.write_string('(${c_type})')
g.gen_expr(expr.expr)
}
ParenExpr {
g.out.write_string('(')
g.gen_expr(expr.expr)
g.out.write_string(')')
}
FnCall {
g.out.write_string('${expr.name}(')
for arg in expr.args {
g.gen_expr(arg)
if arg != expr.args[expr.args.len-1]{
g.out.write_string(', ')
}
}
g.out.write_string(')')
}
else {panic("Unimplemented expression")}
}
}
fn (mut g Generator) gen_c(program []Stmt) string {
g.out.writeln('#include <stdio.h>')
g.out.writeln('#include <stdbool.h>')
for stmt in program {
g.gen_stmt(stmt)
}
return g.out.str()
}
fn compile_with_clang(c_code string, output_name string, keep_c bool) {
// 1. Write the C code to a temporary file
c_file := 'middle_c.c'
os.write_file(c_file, c_code) or {
eprintln('Failed to write C file: $err')
return
}
// 2. Construct the clang command
// We'll use -O2 for optimization and -o to specify the output binary
clang_cmd := 'clang ${c_file} -o ${output_name} -O2'
println('Executing: ${clang_cmd}')
// 3. Run the command
result := os.execute(clang_cmd)
if result.exit_code != 0 {
eprintln('Clang Compilation Failed:')
eprintln(result.output)
} else {
println('Compilation successful! Binary created: $output_name')
// Optional: Remove the temporary C file
if !keep_c {
os.rm(c_file) or { }
}
}
}