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 ') g.out.writeln('#include ') 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 { } } } }