use crate::compiler::parser::*;
pub struct Codegen;
impl Codegen {
pub fn generate(&self, stmts: &[Stmt]) -> String {
let mut output = String::from("#include <stdint.h>\n#include <stdbool.h>\n#include <stdio.h>\n\n");
for stmt in stmts {
output.push_str(&self.gen_stmt(stmt));
output.push('\n');
}
output
}
fn indent_with(&self, spaces: usize, code: &str) -> String {
let prefix = " ".repeat(spaces);
code.lines()
.map(|l| if l.trim().is_empty() { l.to_string() } else { format!("{}{}", prefix, l) })
.collect::<Vec<_>>()
.join("\n")
}
fn gen_stmt(&self, stmt: &Stmt) -> String {
match stmt {
Stmt::Print(exprs) => {
let mut formats = String::new();
let mut args = Vec::new();
for expr in exprs{
let val = self.gen_expr(expr);
let fmt = match expr{
Expr::StringLiteral(_) => "%s",
Expr::IntLiteral(_) | Expr::UIntLiteral(_) => "%llu",
Expr::BoolLiteral(_) => "%s", Expr::BinaryOp { .. } => "%lld", Expr::Ident(_) => "%d",
Expr::Vec {..} => "%p", _ => "%d",
};
formats.push_str(fmt);
formats.push(' ');
if let Expr::BoolLiteral(_) = expr {
args.push(format!("({}) ? \"true\" : \"false\"", val));
} else {
args.push(val);
}
}
if args.is_empty() {
format!("printf(\"\\n\");")
} else {
format!("printf(\"{}\\n\", {});", formats.trim(), args.join(", "))
}
}
Stmt::CompoundAssign { target, op, value } => {
let mut code = String::new();
let op_str = match op {
BinOp::CompoundAdd => "+=",
BinOp::CompoundSub => "-=",
BinOp::CompoundMul => "*=",
BinOp::CompoundDiv => "/=",
_ => panic!("Operador composto inválido no codegen"),
};
let val_str = self.gen_expr(value);
code.push_str(&format!("{} {} {};", target, op_str, val_str));
self.indent_with(4, &code)
}
Stmt::Assignment(a) => {
self.indent_with(4, &format!("{} = {};", &a.target, self.gen_expr(&a.value)))
}
Stmt::VarDecl(v) => {
let prefix = match v.mutability{
Mutability::Const => "const ",
Mutability::Mutable => "",
};
let code = match &v.ty{
Type::Vec { inner, size } => {
let inner_ty = Self::gen_type(inner);
let val = self.gen_expr(&v.value);
format!("{} {} {}[{}] = {};", prefix, inner_ty, v.name, size, val)
}
_ => {
let ty = Self::gen_type(&v.ty);
let val = self.gen_expr(&v.value);
format!("{}{} {} = {};", prefix, ty, v.name, val)
}
};
code
}
Stmt::Break => "break;".to_string(),
Stmt::Continue => "continue;".to_string(),
Stmt::FuncDecl(f) => {
let ret_ty = Self::gen_type(&f.return_type.as_ref().unwrap_or(&Type::Void));
let params: Vec<String> = f.params.iter()
.map(|(ty, name)| format!("{} {}", Self::gen_type(ty), name))
.collect();
let mut body = String::new();
for s in &f.body {
body.push_str(" ");
body.push_str(&self.gen_stmt(s));
body.push('\n');
}
let has_return = f.body.iter().any(|s| matches!(s, Stmt::Return(_)));
if f.name == "main" && matches!(f.return_type, Some(Type::Int)) && !has_return{
body.push_str(" return 0;\n");
}
format!("{} {}({}) {{\n{}}}", ret_ty, f.name, params.join(", "), body)
}
Stmt::Return(e) => format!("return {};", self.gen_expr(e)),
Stmt::ForLoop(u) => {
let start_code = self.gen_expr(&u.start);
let end_code = self.gen_expr(&u.end);
let mut body_code = String::new();
for s in &u.body{
body_code.push_str(&self.gen_stmt(s));
body_code.push('\n');
}
format!(
"for (int {} = {}; {} < {}; {}++)\n {{\n{}\n }}",
u.var,
start_code,
u.var,
end_code,
u.var,
self.indent_with(8, &body_code),
)
}
Stmt::WhileLoop(w) => {
let cond = self.gen_expr(&w.cond);
let mut body_code = String::new();
for s in &w.body{
body_code.push_str(&self.gen_stmt(s));
body_code.push('\n');
}
format!(
"while({}) {{\n{}\n }}",
cond,
self.indent_with(8, &body_code)
)
}
Stmt::IfStatement(i) => {
let cond = self.gen_expr(&i.condition);
let mut out = format!("if {}{{\n", cond);
for s in &i.then_branch {
out.push_str(&format!(" {}\n", self.gen_stmt(s)));
}
out.push_str(" }");
if let Some(else_b) = &i.else_branch {
if else_b.len() == 1 && matches!(else_b[0], Stmt::IfStatement(_)) {
out.push_str("else "); out.push_str(&self.gen_stmt(&else_b[0])); } else {
out.push_str("else {\n");
for s in else_b {
out.push_str(&format!(" {}\n", self.gen_stmt(s)));
}
out.push_str(" }");
}
}
out
} }
}
fn gen_expr(&self, expr: &Expr) -> String {
match expr {
Expr::UIntLiteral(v) => v.to_string(),
Expr::IntLiteral(v) => v.to_string(),
Expr::BoolLiteral(v) => v.to_string(),
Expr::StringLiteral(v) => format!("\"{}\"", v),
Expr::Ident(s) => s.clone(),
Expr::Vec { values, size: _ } => {
if values.is_empty(){
"{0}".to_string()
}else{
let elems: Vec<String> = values.iter()
.map(|e| self.gen_expr(e))
.collect();
format!("{{{}}}", elems.join(", "))
}
}
Expr::BinaryOp { left, op, right } => {
let op_str = match op {
BinOp::Add => "+".to_string(),
BinOp::Sub => "-".to_string(),
BinOp::Mul => "*".to_string(),
BinOp::Div => "/".to_string(),
BinOp::DoubleEqual => "==".to_string(),
BinOp::Greater => ">".to_string(),
BinOp::GreaterEqual => ">=".to_string(),
BinOp::Less => "<".to_string(),
BinOp::LessEqual => "<=".to_string(),
BinOp::Percent => "%".to_string(),
BinOp::IndentityOp => "==".to_string(),
_ => "unknown".to_string()
};
format!("({} {} {})", self.gen_expr(left), op_str, &self.gen_expr(right))
}
Expr::Identity { expr, negated } => {
let inner = self.gen_expr(expr);
if *negated {
format!("(!{})", inner)
} else {
format!("({})", inner)
}
}
Expr::Call { name, args } => {
let args_str: Vec<String> = args.iter().map(|e| self.gen_expr(e)).collect();
format!("{}({})", name, args_str.join(", "))
}
_ => "0".to_string(),
}
}
fn gen_type(ty: &Type) -> String {
match ty {
Type::U8 => "uint8_t".to_string(),
Type::U16 => "uint16_t".to_string(),
Type::U32 => "uint32_t".to_string(),
Type::U64 => "uint64_t".to_string(),
Type::UInt => "uint64_t".to_string(),
Type::U128 => "unsigned __int128".to_string(),
Type::I8 => "int8_t".to_string(),
Type::I16 => "int16_t".to_string(),
Type::I32 => "int32_t".to_string(),
Type::I64 => "int64_t".to_string(),
Type::I128 => "__int128".to_string(),
Type::Bool => "bool".to_string(),
Type::Str => "char*".to_string(),
Type::Void => "void".to_string(),
Type::Int => "int".to_string(),
_ => "int".to_string(),
}
}
}