diff --git a/src/c_lowerer/declaration_transpiler.rs b/src/c_lowerer/declaration_transpiler.rs index 3f82ccf..5545674 100644 --- a/src/c_lowerer/declaration_transpiler.rs +++ b/src/c_lowerer/declaration_transpiler.rs @@ -18,7 +18,7 @@ impl DeclarationTranspiler { let mut fields = Vec::new(); for field in &struct_.fields { - let field_type = self.type_annot_to_ctype(&Some(field.field_type.clone()))?; + let field_type = self.type_annot_to_c_type(&Some(field.field_type.clone()))?; fields.push(CVarDecl { name: field.name.clone(), ty: field_type, @@ -34,14 +34,14 @@ impl DeclarationTranspiler { pub fn transpile_function(&self, func: &TypedFunction) -> Result { let return_type = match &func.return_type { - Some(type_annot) => self.type_annot_to_ctype(&Some(type_annot.clone()))?, + Some(type_annot) => self.type_annot_to_c_type(&Some(type_annot.clone()))?, None => CType::Void, }; let mut params = Vec::new(); for (_binding_id, name, type_annot) in &func.args { let param_type = match type_annot { - Some(annot) => self.type_annot_to_ctype(&Some(annot.clone()))?, + Some(annot) => self.type_annot_to_c_type(&Some(annot.clone()))?, None => { return Err(format!( "Function parameter {} missing type annotation", @@ -69,14 +69,14 @@ impl DeclarationTranspiler { let mut structs = Vec::new(); // For each variant, create a struct - for (i, variant) in enum_.variants.iter().enumerate() { + for variant in enum_.variants.iter() { let struct_name = format!("{}_{}", enum_.name, variant.name); let mut fields = Vec::new(); // Add variant fields (no discriminant in variant struct) for (j, field_type) in variant.fields.iter().enumerate() { let field_name = format!("field_{}", j); - let c_type = self.type_annot_to_ctype(&Some(field_type.clone()))?; + let c_type = self.type_annot_to_c_type(&Some(field_type.clone()))?; fields.push(CVarDecl { name: field_name, ty: c_type, @@ -131,38 +131,26 @@ impl DeclarationTranspiler { Ok(structs) } - fn type_annot_to_ctype(&self, annot: &Option) -> Result { + fn type_annot_to_c_type(&self, annot: &Option) -> Result { match annot { - Some(TypeAnnot::Var(name)) => match name.as_str() { - "int" => Ok(CType::Int), - "float" => Ok(CType::Float), - "bool" => Ok(CType::Bool), - "string" => Ok(CType::Ptr(Box::new(CType::Char))), - _ => Ok(CType::Struct(name.clone())), // Assume struct - }, - Some(TypeAnnot::Cons(name, args)) if args.is_empty() => match name.as_str() { - "int" => Ok(CType::Int), - "float" => Ok(CType::Float), - "bool" => Ok(CType::Bool), - "string" => Ok(CType::Ptr(Box::new(CType::Char))), - _ => Ok(CType::Struct(name.clone())), // Assume struct - }, + Some(TypeAnnot::Var(name)) => convert_to_c_type(name), + Some(TypeAnnot::Cons(name, args)) if args.is_empty() => convert_to_c_type(name), Some(TypeAnnot::Cons(name, _args)) => { // Generic types - for now just use the base name Ok(CType::Struct(name.clone())) } Some(TypeAnnot::Ptr(inner)) => { - let inner_type = self.type_annot_to_ctype(&Some(*inner.clone()))?; + let inner_type = self.type_annot_to_c_type(&Some(*inner.clone()))?; Ok(CType::Ptr(Box::new(inner_type))) } Some(TypeAnnot::Array(inner)) => { - let inner_type = self.type_annot_to_ctype(&Some(*inner.clone()))?; + let inner_type = self.type_annot_to_c_type(&Some(*inner.clone()))?; Ok(CType::Ptr(Box::new(inner_type))) } Some(TypeAnnot::Tuple(fields)) => { let mut c_fields = Vec::new(); for (i, field_annot) in fields.iter().enumerate() { - let field_type = self.type_annot_to_ctype(&Some(field_annot.clone()))?; + let field_type = self.type_annot_to_c_type(&Some(field_annot.clone()))?; c_fields.push(CVarDecl { name: format!("field{}", i), ty: field_type, @@ -174,12 +162,22 @@ impl DeclarationTranspiler { Some(TypeAnnot::Function(args, ret)) => { let mut c_args = Vec::new(); for arg in args { - c_args.push(self.type_annot_to_ctype(&Some(arg.clone()))?); + c_args.push(self.type_annot_to_c_type(&Some(arg.clone()))?); } - let c_ret = self.type_annot_to_ctype(&Some(*ret.clone()))?; + let c_ret = self.type_annot_to_c_type(&Some(*ret.clone()))?; Ok(CType::Func(c_args, Box::new(c_ret))) } _ => Ok(CType::Void), // Default } } } + +pub fn convert_to_c_type(name: &String) -> Result { + match String::as_str(name) { + "int" => Ok(CType::Int), + "float" => Ok(CType::Float), + "bool" => Ok(CType::Bool), + "string" => Ok(CType::Ptr(Box::new(CType::Char))), + _ => Ok(CType::Struct(name.clone())), // Assume struct + } +} diff --git a/src/c_lowerer/statements_transpiler.rs b/src/c_lowerer/statements_transpiler.rs index a462fd8..bb1e1dd 100644 --- a/src/c_lowerer/statements_transpiler.rs +++ b/src/c_lowerer/statements_transpiler.rs @@ -1,12 +1,48 @@ use crate::ast::*; use crate::c_ir::*; +use crate::c_lowerer::declaration_transpiler::convert_to_c_type; use crate::typechecker::Type; -pub struct StatementsTranspiler; +pub struct StatementsTranspiler { + tmp_counter: usize, +} impl StatementsTranspiler { pub fn new() -> Self { - StatementsTranspiler + Self { tmp_counter: 0 } + } + + fn fresh_tmp_name(&mut self, prefix: &str) -> String { + let name = format!("{}_{}", prefix, self.tmp_counter); + self.tmp_counter += 1; + name + } + + pub fn fresh_tmp_var( + &mut self, + prefix: &str, + ty: CType, + initializer: Option, + ) -> (String, CVarDecl) { + let name = self.fresh_tmp_name(prefix); + + let decl = CVarDecl { + name: name.clone(), + ty, + initializer, + }; + + (name, decl) + } + + pub fn fresh_tmp_expr( + &mut self, + prefix: &str, + ty: CType, + initializer: Option, + ) -> (CExpr, CVarDecl) { + let (name, decl) = self.fresh_tmp_var(prefix, ty, initializer); + (CExpr::Var(name), decl) } pub fn transpile_expr(&self, expr: &TypedExpr) -> Result { @@ -111,7 +147,7 @@ impl StatementsTranspiler { } } - pub fn transpile_stmt(&self, expr: &TypedExpr) -> Result { + pub fn transpile_stmt(&mut self, expr: &TypedExpr) -> Result { match &expr.kind { TypedExprKind::Let(_binding_id, name, _kind, _type_annot, init_expr) => { let c_type = self.type_to_ctype(&expr.ty)?; @@ -157,36 +193,141 @@ impl StatementsTranspiler { Ok(CStmt::Block(stmts)) } TypedExprKind::For(_binding_id, var_name, iterable, body) => { - // Simplified for loop handling - // For now, assume range iteration match &iterable.kind { + // for i in start..end TypedExprKind::Range(start, end) => { let start_expr = self.transpile_expr(start)?; let end_expr = self.transpile_expr(end)?; - // Create a simple for loop: for(int i = start; i < end; i++) + let init = CVarDecl { name: var_name.clone(), ty: CType::Int, initializer: Some(start_expr), }; + let cond = CExpr::BinOp( Box::new(CExpr::Var(var_name.clone())), CBinaryOp::Lt, Box::new(end_expr), ); - let incr = CExpr::UnOp(CUnaryOp::Neg, Box::new(CExpr::IntLit(-1))); // i++ - let incr_stmt = CStmt::Assign( - CExpr::Var(var_name.clone()), - CExpr::BinOp( - Box::new(CExpr::Var(var_name.clone())), - CBinaryOp::Add, - Box::new(CExpr::IntLit(1)), - ), + + let incr = CExpr::UnOp( + CUnaryOp::PreInc, + Box::new(CExpr::Var(var_name.clone())), ); + let body_stmts = self.expr_to_stmts(body)?; - Ok(CStmt::For(init, cond, CExpr::IntLit(1), body_stmts)) + Ok(CStmt::For(init, cond, incr, body_stmts)) } - _ => Err("Only range iteration supported for for loops".to_string()), + + // for x in array_var + TypedExprKind::Variable(var) => { + let elem_ty = match &iterable.ty { + Type::Array(inner) => self.type_to_ctype(inner)?, + _ => return Err(format!( + "Cannot iterate over non-array variable `{}`", + var + )), + }; + + // i = 0 + let (idx_name, idx_decl) = self.fresh_tmp_var( + "_i", + CType::Int, + Some(CExpr::IntLit(0)), + ); + + let cond = CExpr::BinOp( + Box::new(CExpr::Var(idx_name.clone())), + CBinaryOp::Lt, + Box::new(CExpr::Dot( + Box::new(CExpr::Var(var.clone())), + "len".into(), + )), + ); + + let incr = CExpr::UnOp( + CUnaryOp::PreInc, + Box::new(CExpr::Var(idx_name.clone())), + ); + + // let x = array.data[i] + let bind = CStmt::VarDecl(CVarDecl { + name: var_name.clone(), + ty: elem_ty, + initializer: Some(CExpr::Index( + Box::new(CExpr::Dot( + Box::new(CExpr::Var(var.clone())), + "data".into(), + )), + Box::new(CExpr::Var(idx_name.clone())), + )), + }); + + let mut body_stmts = vec![bind]; + body_stmts.extend(self.expr_to_stmts(body)?); + + Ok(CStmt::For(idx_decl, cond, incr, body_stmts)) + } + + // for x in [a, b, c] + TypedExprKind::Array(array) => { + let elem_ty = match &iterable.ty { + Type::Array(inner) => self.type_to_ctype(inner)?, + _ => return Err("For-loop iterable is not an array".to_string()), + }; + + let c_elems = array + .iter() + .map(|e| self.transpile_expr(e)) + .collect::, _>>()?; + + let arr_len = c_elems.len(); + + // tmp_arr = { ... } + let (arr_name, arr_decl) = self.fresh_tmp_var( + "_arr", + CType::Array(Box::new(elem_ty.clone()), arr_len), + Some(CExpr::ArrayLit(c_elems)), + ); + + // i = 0 + let (idx_name, idx_decl) = self.fresh_tmp_var( + "_i", + CType::Int, + Some(CExpr::IntLit(0)), + ); + + let cond = CExpr::BinOp( + Box::new(CExpr::Var(idx_name.clone())), + CBinaryOp::Lt, + Box::new(CExpr::IntLit(arr_len as i64)), + ); + + let incr = CExpr::UnOp( + CUnaryOp::PreInc, + Box::new(CExpr::Var(idx_name.clone())), + ); + + let bind = CStmt::VarDecl(CVarDecl { + name: var_name.clone(), + ty: elem_ty, + initializer: Some(CExpr::Index( + Box::new(CExpr::Var(arr_name.clone())), + Box::new(CExpr::Var(idx_name.clone())), + )), + }); + + let mut body_stmts = vec![bind]; + body_stmts.extend(self.expr_to_stmts(body)?); + + Ok(CStmt::Block(vec![ + CStmt::VarDecl(arr_decl), + CStmt::For(idx_decl, cond, incr, body_stmts), + ])) + } + + _ => Err("Unsupported iterable in for loop".to_string()), } } TypedExprKind::Break => Ok(CStmt::Break), @@ -199,7 +340,7 @@ impl StatementsTranspiler { } } - pub fn expr_to_stmts(&self, expr: &TypedExpr) -> Result, String> { + pub fn expr_to_stmts(&mut self, expr: &TypedExpr) -> Result, String> { match &expr.kind { TypedExprKind::Do(stmts) => { let mut c_stmts = Vec::new(); @@ -250,25 +391,26 @@ impl StatementsTranspiler { UnOp::Not => Ok(CUnaryOp::Not), UnOp::Ref => Ok(CUnaryOp::Ref), UnOp::Deref => Ok(CUnaryOp::Deref), + UnOp::PreInc => Ok(CUnaryOp::PreInc), } } - fn type_to_ctype(&self, ty: &crate::typechecker::Type) -> Result { + fn type_to_ctype(&self, ty: &Type) -> Result { match ty { - crate::typechecker::Type::Int => Ok(CType::Int), - crate::typechecker::Type::Float => Ok(CType::Float), - crate::typechecker::Type::Bool => Ok(CType::Bool), - crate::typechecker::Type::String => Ok(CType::Ptr(Box::new(CType::Char))), - crate::typechecker::Type::Unit => Ok(CType::Void), - crate::typechecker::Type::Ptr(inner) => { + Type::Int => Ok(CType::Int), + Type::Float => Ok(CType::Float), + Type::Bool => Ok(CType::Bool), + Type::String => Ok(CType::Ptr(Box::new(CType::Char))), + Type::Unit => Ok(CType::Void), + Type::Ptr(inner) => { Ok(CType::Ptr(Box::new(self.type_to_ctype(inner)?))) } - crate::typechecker::Type::Array(inner) => { + Type::Array(inner) => { Ok(CType::Ptr(Box::new(self.type_to_ctype(inner)?))) } - crate::typechecker::Type::Struct(name, _) => Ok(CType::Struct(name.clone())), - crate::typechecker::Type::Enum(name, _) => Ok(CType::Struct(name.clone())), - crate::typechecker::Type::Tuple(types) => { + Type::Struct(name, _) => Ok(CType::Struct(name.clone())), + Type::Enum(name, _) => Ok(CType::Struct(name.clone())), + Type::Tuple(types) => { let mut fields = Vec::new(); for (i, inner_ty) in types.iter().enumerate() { let c_type = self.type_to_ctype(inner_ty)?; @@ -280,7 +422,7 @@ impl StatementsTranspiler { } Ok(CType::UnnamedStruct(fields)) } - crate::typechecker::Type::Function(args, ret) => { + Type::Function(args, ret) => { let mut c_args = Vec::new(); for arg in args { c_args.push(self.type_to_ctype(arg)?); @@ -288,37 +430,25 @@ impl StatementsTranspiler { let c_ret = self.type_to_ctype(ret)?; Ok(CType::Func(c_args, Box::new(c_ret))) } - crate::typechecker::Type::Generic(name, _args) => { + Type::Generic(name, _args) => { // Generic types should have been monomorphized away, // but if they remain, treat them as struct types // For now, just use the base name Ok(CType::Struct(name.clone())) } - crate::typechecker::Type::TypeVar(name) => { + Type::TypeVar(name) => { // Type variables should have been resolved during monomorphization Err(format!("Unresolved type variable: {}", name)) } - crate::typechecker::Type::Never => Ok(CType::Void), - crate::typechecker::Type::Unknown => Err("Unknown type".to_string()), + Type::Never => Ok(CType::Void), + Type::Unknown => Err("Unknown type".to_string()), } } fn type_annot_to_ctype(&self, annot: &TypeAnnot) -> Result { match annot { - TypeAnnot::Var(name) => match name.as_str() { - "int" => Ok(CType::Int), - "float" => Ok(CType::Float), - "bool" => Ok(CType::Bool), - "string" => Ok(CType::Ptr(Box::new(CType::Char))), - _ => Ok(CType::Struct(name.clone())), - }, - TypeAnnot::Cons(name, args) if args.is_empty() => match name.as_str() { - "int" => Ok(CType::Int), - "float" => Ok(CType::Float), - "bool" => Ok(CType::Bool), - "string" => Ok(CType::Ptr(Box::new(CType::Char))), - _ => Ok(CType::Struct(name.clone())), - }, + TypeAnnot::Var(name) => convert_to_c_type(name), + TypeAnnot::Cons(name, args) if args.is_empty() => convert_to_c_type(name), TypeAnnot::Cons(name, _args) => { // Generic types - for now just use the base name Ok(CType::Struct(name.clone())) @@ -351,7 +481,7 @@ impl StatementsTranspiler { let c_ret = self.type_annot_to_ctype(ret)?; Ok(CType::Func(c_args, Box::new(c_ret))) } - _ => Err(format!("Unsupported type annotation: {:?}", annot)), + //_ => Err(format!("Unsupported type annotation: {:?}", annot)), } } }