diff --git a/simple_test.c b/simple_test.c deleted file mode 100644 index 9f52f8f..0000000 --- a/simple_test.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include -#include - -int simple_add(int x, int y); -int main(void); - - -int simple_add(int x, int y) { - (x + y); -} - -int main(void) { - int result = simple_add(5, 3); - return result; -} - diff --git a/src/c_ir.rs b/src/c_ir.rs index dbe85d4..e69de29 100644 --- a/src/c_ir.rs +++ b/src/c_ir.rs @@ -1,157 +0,0 @@ -#[derive(Debug, Clone)] -pub enum CType { - Void, - Int, - Float, - Bool, - Char, - Ptr(Box), - Struct(String), - UnnamedStruct(Vec), - Array(Box, usize), // type and size - Func(Vec, Box), // args and return -} - -impl CType { - pub fn to_string(&self) -> String { - match self { - CType::Void => "void".to_string(), - CType::Int => "int".to_string(), - CType::Float => "float".to_string(), - CType::Bool => "bool".to_string(), - CType::Char => "char".to_string(), - CType::Ptr(inner) => format!("{}*", inner.to_string()), - CType::Struct(name) => format!("struct {}", name), - CType::UnnamedStruct(fields) => { - let field_strs: Vec = fields - .iter() - .map(|f| format!(" {} {};", f.ty.to_string(), f.name)) - .collect(); - format!("struct {{\n{}\n}}", field_strs.join("\n")) - } - CType::Array(inner, size) => format!("{}[{}]", inner.to_string(), size), - CType::Func(args, ret) => { - let arg_strs: Vec = args.iter().map(|t| t.to_string()).collect(); - format!("{} (*)({})", ret.to_string(), arg_strs.join(", ")) - } - } - } -} - -#[derive(Debug, Clone)] -pub struct CVarDecl { - pub name: String, - pub ty: CType, - pub initializer: Option, -} - -#[derive(Debug, Clone)] -pub struct CStructDecl { - pub name: String, - pub fields: Vec, -} - -#[derive(Debug, Clone)] -pub struct CFuncDecl { - pub name: String, - pub return_type: CType, - pub params: Vec, - pub body: Option>, -} - -#[derive(Debug, Clone)] -pub enum CExpr { - IntLit(i64), - FloatLit(f64), - BoolLit(bool), - StringLit(String), - Var(String), - Call(String, Vec), - BinOp(Box, CBinaryOp, Box), - UnOp(CUnaryOp, Box), - Cast(Box, CType), - StructLit(String, Vec<(String, CExpr)>), - EnumLit(String, String, Vec), // enum_name, variant_name, args - ArrayLit(Vec), - Index(Box, Box), - Dot(Box, String), - AddrOf(Box), - Deref(Box), -} - -#[derive(Debug, Clone)] -pub enum CBinaryOp { - Add, - Sub, - Mul, - Div, - Mod, - Eq, - Neq, - Lt, - Gt, - Leq, - Geq, - And, - Or, -} - -impl CBinaryOp { - pub fn to_string(&self) -> &'static str { - match self { - CBinaryOp::Add => "+", - CBinaryOp::Sub => "-", - CBinaryOp::Mul => "*", - CBinaryOp::Div => "/", - CBinaryOp::Mod => "%", - CBinaryOp::Eq => "==", - CBinaryOp::Neq => "!=", - CBinaryOp::Lt => "<", - CBinaryOp::Gt => ">", - CBinaryOp::Leq => "<=", - CBinaryOp::Geq => ">=", - CBinaryOp::And => "&&", - CBinaryOp::Or => "||", - } - } -} - -#[derive(Debug, Clone)] -pub enum CUnaryOp { - Neg, - Not, - Ref, - Deref, -} - -impl CUnaryOp { - pub fn to_string(&self) -> &'static str { - match self { - CUnaryOp::Neg => "-", - CUnaryOp::Not => "!", - CUnaryOp::Ref => "&", - CUnaryOp::Deref => "*", - } - } -} - -#[derive(Debug, Clone)] -pub enum CStmt { - VarDecl(CVarDecl), - Expr(CExpr), - Assign(CExpr, CExpr), - If(CExpr, Vec, Option>), - While(CExpr, Vec), - For(CVarDecl, CExpr, CExpr, Vec), // init, cond, incr, body - Return(Option), - Break, - Continue, - Block(Vec), -} - -#[derive(Debug, Clone)] -pub enum CToplevel { - StructDecl(CStructDecl), - FuncDecl(CFuncDecl), - VarDecl(CVarDecl), -} diff --git a/src/codegen/declaration_transpiler.rs b/src/codegen/declaration_transpiler.rs index 3f82ccf..e69de29 100644 --- a/src/codegen/declaration_transpiler.rs +++ b/src/codegen/declaration_transpiler.rs @@ -1,185 +0,0 @@ -use crate::ast::*; -use crate::c_ir::*; -use crate::typechecker::Type; -use std::collections::HashMap; - -pub struct DeclarationTranspiler { - type_map: HashMap, -} - -impl DeclarationTranspiler { - pub fn new() -> Self { - DeclarationTranspiler { - type_map: HashMap::new(), - } - } - - pub fn transpile_struct(&self, struct_: &TypedStruct) -> Result { - let mut fields = Vec::new(); - - for field in &struct_.fields { - let field_type = self.type_annot_to_ctype(&Some(field.field_type.clone()))?; - fields.push(CVarDecl { - name: field.name.clone(), - ty: field_type, - initializer: None, - }); - } - - Ok(CStructDecl { - name: struct_.name.clone(), - fields, - }) - } - - 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()))?, - 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()))?, - None => { - return Err(format!( - "Function parameter {} missing type annotation", - name - )); - } - }; - params.push(CVarDecl { - name: name.clone(), - ty: param_type, - initializer: None, - }); - } - - // Note: body will be transpiled separately by statements transpiler - Ok(CFuncDecl { - name: func.name.clone(), - return_type, - params, - body: None, - }) - } - - pub fn transpile_enum(&self, enum_: &TypedEnum) -> Result, String> { - let mut structs = Vec::new(); - - // For each variant, create a struct - for (i, variant) in enum_.variants.iter().enumerate() { - 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()))?; - fields.push(CVarDecl { - name: field_name, - ty: c_type, - initializer: None, - }); - } - - structs.push(CStructDecl { - name: struct_name, - fields, - }); - } - - // Create union of all variants - let union_name = format!("{}_union", enum_.name); - let mut union_fields = Vec::new(); - for variant in &enum_.variants { - let field_name = variant.name.to_lowercase(); - let struct_name = format!("{}_{}", enum_.name, variant.name); - union_fields.push(CVarDecl { - name: field_name, - ty: CType::Struct(struct_name), - initializer: None, - }); - } - - let union_name_clone = union_name.clone(); - structs.push(CStructDecl { - name: union_name, - fields: union_fields, - }); - - // Create main enum struct - let enum_fields = vec![ - CVarDecl { - name: "discriminant".to_string(), - ty: CType::Int, - initializer: None, - }, - CVarDecl { - name: "data".to_string(), - ty: CType::Struct(union_name_clone), - initializer: None, - }, - ]; - - structs.push(CStructDecl { - name: enum_.name.clone(), - fields: enum_fields, - }); - - Ok(structs) - } - - fn type_annot_to_ctype(&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::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()))?; - Ok(CType::Ptr(Box::new(inner_type))) - } - Some(TypeAnnot::Array(inner)) => { - let inner_type = self.type_annot_to_ctype(&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()))?; - c_fields.push(CVarDecl { - name: format!("field{}", i), - ty: field_type, - initializer: None, - }); - } - Ok(CType::UnnamedStruct(c_fields)) - } - 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()))?); - } - let c_ret = self.type_annot_to_ctype(&Some(*ret.clone()))?; - Ok(CType::Func(c_args, Box::new(c_ret))) - } - _ => Ok(CType::Void), // Default - } - } -} diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs deleted file mode 100644 index 7014f92..0000000 --- a/src/codegen/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod declaration_transpiler; -pub mod statements_transpiler; -pub mod transpiler; diff --git a/src/codegen/statements_transpiler.rs b/src/codegen/statements_transpiler.rs index bdd38de..e69de29 100644 --- a/src/codegen/statements_transpiler.rs +++ b/src/codegen/statements_transpiler.rs @@ -1,340 +0,0 @@ -use crate::ast::*; -use crate::c_ir::*; - -pub struct StatementsTranspiler; - -impl StatementsTranspiler { - pub fn new() -> Self { - StatementsTranspiler - } - - pub fn transpile_expr(&self, expr: &TypedExpr) -> Result { - match &expr.kind { - TypedExprKind::Int(i) => Ok(CExpr::IntLit(*i)), - TypedExprKind::Float(f) => Ok(CExpr::FloatLit(*f)), - TypedExprKind::Bool(b) => Ok(CExpr::BoolLit(*b)), - TypedExprKind::String(s) => Ok(CExpr::StringLit(s.clone())), - TypedExprKind::Variable(name) => Ok(CExpr::Var(name.clone())), - TypedExprKind::Call(func, args) => { - let func_expr = self.transpile_expr(func)?; - let func_name = match func_expr { - CExpr::Var(name) => name, - _ => return Err("Function calls must be on variables for now".to_string()), - }; - let c_args = args - .iter() - .map(|arg| self.transpile_expr(arg)) - .collect::, _>>()?; - Ok(CExpr::Call(func_name, c_args)) - } - TypedExprKind::BinOp(lhs, op, rhs) => { - let c_lhs = self.transpile_expr(lhs)?; - let c_rhs = self.transpile_expr(rhs)?; - let c_op = self.binop_to_c_binop(op)?; - Ok(CExpr::BinOp(Box::new(c_lhs), c_op, Box::new(c_rhs))) - } - TypedExprKind::UnOp(op, expr) => { - let c_expr = self.transpile_expr(expr)?; - let c_op = self.unop_to_c_unop(op)?; - Ok(CExpr::UnOp(c_op, Box::new(c_expr))) - } - TypedExprKind::Index(array, index) => { - let c_array = self.transpile_expr(array)?; - let c_index = self.transpile_expr(index)?; - Ok(CExpr::Index(Box::new(c_array), Box::new(c_index))) - } - TypedExprKind::Dot(obj, field) => { - let c_obj = self.transpile_expr(obj)?; - Ok(CExpr::Dot(Box::new(c_obj), field.clone())) - } - TypedExprKind::StructLit(struct_name, fields) => { - let c_fields = fields - .iter() - .map(|(name, expr)| { - let c_expr = self.transpile_expr(expr)?; - Ok::<(String, CExpr), String>((name.clone(), c_expr)) - }) - .collect::, _>>()?; - Ok(CExpr::StructLit(struct_name.clone(), c_fields)) - } - TypedExprKind::Array(array_exprs) => { - let c_exprs = array_exprs - .iter() - .map(|expr| self.transpile_expr(expr)) - .collect::, _>>()?; - Ok(CExpr::ArrayLit(c_exprs)) - } - TypedExprKind::Cast(expr, type_annot) => { - let c_expr = self.transpile_expr(expr)?; - // Simplified: assuming we can map type annotations to C types - let c_type = self.type_annot_to_ctype(type_annot)?; - Ok(CExpr::Cast(Box::new(c_expr), c_type)) - } - TypedExprKind::Tuple(_) => { - // Simplified: treat as void for now - Ok(CExpr::IntLit(0)) - } - TypedExprKind::EnumLit(enum_name, variant_name, args) => { - let c_args = args - .iter() - .map(|arg| self.transpile_expr(arg)) - .collect::, _>>()?; - Ok(CExpr::EnumLit( - enum_name.clone(), - variant_name.clone(), - c_args, - )) - } - TypedExprKind::If(cond, then_expr, else_expr) => { - // Conditional expressions - for now, simplify to function call - // This is not ideal but works for basic cases - Err("Conditional expressions not yet supported".to_string()) - } - _ => Err(format!("Unsupported expression: {:?}", expr.kind)), - } - } - - pub fn transpile_stmt(&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)?; - let initializer = Some(self.transpile_expr(init_expr)?); - let var_decl = CVarDecl { - name: name.clone(), - ty: c_type, - initializer, - }; - Ok(CStmt::VarDecl(var_decl)) - } - TypedExprKind::Assign(lhs, rhs) => { - let c_lhs = self.transpile_expr(lhs)?; - let c_rhs = self.transpile_expr(rhs)?; - Ok(CStmt::Assign(c_lhs, c_rhs)) - } - TypedExprKind::Return(ret_expr) => { - let c_ret = match ret_expr { - Some(expr) => Some(self.transpile_expr(expr)?), - None => None, - }; - Ok(CStmt::Return(c_ret)) - } - TypedExprKind::If(cond, then_expr, else_expr) => { - let c_cond = self.transpile_expr(cond)?; - let then_stmts = self.expr_to_stmts(then_expr)?; - let else_stmts = match else_expr { - Some(else_expr) => Some(self.expr_to_stmts(else_expr)?), - None => None, - }; - Ok(CStmt::If(c_cond, then_stmts, else_stmts)) - } - TypedExprKind::While(cond, body) => { - let c_cond = self.transpile_expr(cond)?; - let body_stmts = self.expr_to_stmts(body)?; - Ok(CStmt::While(c_cond, body_stmts)) - } - TypedExprKind::Do(exprs) => { - let mut stmts = Vec::new(); - for expr in exprs { - stmts.push(self.transpile_stmt(expr)?); - } - Ok(CStmt::Block(stmts)) - } - TypedExprKind::For(_binding_id, var_name, iterable, body) => { - // Simplified for loop handling - // For now, assume range iteration - match &iterable.kind { - 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 body_stmts = self.expr_to_stmts(body)?; - Ok(CStmt::For(init, cond, CExpr::IntLit(1), body_stmts)) - } - _ => Err("Only range iteration supported for for loops".to_string()), - } - } - TypedExprKind::Break => Ok(CStmt::Break), - TypedExprKind::Continue => Ok(CStmt::Continue), - _ => { - // For other expressions, treat as expression statements - let c_expr = self.transpile_expr(expr)?; - Ok(CStmt::Expr(c_expr)) - } - } - } - - pub fn expr_to_stmts(&self, expr: &TypedExpr) -> Result, String> { - match &expr.kind { - TypedExprKind::Do(stmts) => { - let mut c_stmts = Vec::new(); - for (i, stmt) in stmts.iter().enumerate() { - if i == stmts.len() - 1 { - // Last expression in a block should be returned - match &stmt.kind { - TypedExprKind::Return(_) => { - c_stmts.push(self.transpile_stmt(stmt)?); - } - _ => { - // Convert to return statement - let c_expr = self.transpile_expr(stmt)?; - c_stmts.push(CStmt::Return(Some(c_expr))); - } - } - } else { - c_stmts.push(self.transpile_stmt(stmt)?); - } - } - Ok(c_stmts) - } - _ => Ok(vec![self.transpile_stmt(expr)?]), - } - } - - fn binop_to_c_binop(&self, op: &BinOp) -> Result { - match op { - BinOp::Add => Ok(CBinaryOp::Add), - BinOp::Sub => Ok(CBinaryOp::Sub), - BinOp::Mul => Ok(CBinaryOp::Mul), - BinOp::Div => Ok(CBinaryOp::Div), - BinOp::Mod => Ok(CBinaryOp::Mod), - BinOp::Eq => Ok(CBinaryOp::Eq), - BinOp::Neq => Ok(CBinaryOp::Neq), - BinOp::Lt => Ok(CBinaryOp::Lt), - BinOp::Gt => Ok(CBinaryOp::Gt), - BinOp::Leq => Ok(CBinaryOp::Leq), - BinOp::Geq => Ok(CBinaryOp::Geq), - BinOp::And => Ok(CBinaryOp::And), - BinOp::Or => Ok(CBinaryOp::Or), - } - } - - fn unop_to_c_unop(&self, op: &UnOp) -> Result { - match op { - UnOp::Neg => Ok(CUnaryOp::Neg), - UnOp::Not => Ok(CUnaryOp::Not), - UnOp::Ref => Ok(CUnaryOp::Ref), - UnOp::Deref => Ok(CUnaryOp::Deref), - } - } - - fn type_to_ctype(&self, ty: &crate::typechecker::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) => { - Ok(CType::Ptr(Box::new(self.type_to_ctype(inner)?))) - } - crate::typechecker::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) => { - let mut fields = Vec::new(); - for (i, inner_ty) in types.iter().enumerate() { - let c_type = self.type_to_ctype(inner_ty)?; - fields.push(CVarDecl { - name: format!("field{}", i), - ty: c_type, - initializer: None, - }); - } - Ok(CType::UnnamedStruct(fields)) - } - crate::typechecker::Type::Function(args, ret) => { - let mut c_args = Vec::new(); - for arg in args { - c_args.push(self.type_to_ctype(arg)?); - } - let c_ret = self.type_to_ctype(ret)?; - Ok(CType::Func(c_args, Box::new(c_ret))) - } - crate::typechecker::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 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()), - } - } - - 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::Cons(name, _args) => { - // Generic types - for now just use the base name - Ok(CType::Struct(name.clone())) - } - TypeAnnot::Ptr(inner) => { - let inner_type = self.type_annot_to_ctype(inner)?; - Ok(CType::Ptr(Box::new(inner_type))) - } - TypeAnnot::Array(inner) => { - let inner_type = self.type_annot_to_ctype(inner)?; - Ok(CType::Ptr(Box::new(inner_type))) - } - 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(field_annot)?; - c_fields.push(CVarDecl { - name: format!("field{}", i), - ty: field_type, - initializer: None, - }); - } - Ok(CType::UnnamedStruct(c_fields)) - } - TypeAnnot::Function(args, ret) => { - let mut c_args = Vec::new(); - for arg in args { - c_args.push(self.type_annot_to_ctype(arg)?); - } - let c_ret = self.type_annot_to_ctype(ret)?; - Ok(CType::Func(c_args, Box::new(c_ret))) - } - _ => Err(format!("Unsupported type annotation: {:?}", annot)), - } - } -} diff --git a/src/codegen/transpiler.rs b/src/codegen/transpiler.rs index 1804cfe..e69de29 100644 --- a/src/codegen/transpiler.rs +++ b/src/codegen/transpiler.rs @@ -1,282 +0,0 @@ -use crate::ast::*; -use crate::c_ir::*; -use crate::codegen::declaration_transpiler::DeclarationTranspiler; -use crate::codegen::statements_transpiler::StatementsTranspiler; -use std::collections::HashMap; - -pub struct Transpiler { - structs: HashMap, - functions: Vec, - globals: Vec, - decl_transpiler: DeclarationTranspiler, - stmt_transpiler: StatementsTranspiler, -} - -impl Transpiler { - pub fn new() -> Self { - Transpiler { - structs: HashMap::new(), - functions: Vec::new(), - globals: Vec::new(), - decl_transpiler: DeclarationTranspiler::new(), - stmt_transpiler: StatementsTranspiler::new(), - } - } - - pub fn transpile_program(&mut self, nodes: &[TypedASTNode]) -> Result { - // First pass: collect declarations - for node in nodes { - self.collect_declaration(node)?; - } - - // Second pass: transpile function bodies - self.transpile_function_bodies(nodes)?; - - // Generate C code - let mut output = String::new(); - - // Add includes - output.push_str("#include \n"); - output.push_str("#include \n"); - output.push_str("#include \n"); - output.push_str("#include \n\n"); - - // Generate struct declarations - for struct_decl in self.structs.values() { - output.push_str(&self.generate_struct_decl(struct_decl)); - output.push_str(";\n\n"); - } - - // Generate function declarations (prototypes) - for func in &self.functions { - output.push_str(&self.generate_func_proto(func)); - output.push_str(";\n"); - } - output.push_str("\n"); - - // Generate global variables - for global in &self.globals { - output.push_str(&self.generate_var_decl(global)); - output.push_str(";\n"); - } - output.push_str("\n"); - - // Generate function definitions - for func in &self.functions { - output.push_str(&self.generate_func_def(func)); - output.push_str("\n"); - } - - Ok(output) - } - - fn collect_declaration(&mut self, node: &TypedASTNode) -> Result<(), String> { - match &node.kind { - TypedASTNodeKind::Struct(s) => { - let struct_decl = self.decl_transpiler.transpile_struct(s)?; - self.structs.insert(s.name.clone(), struct_decl); - } - TypedASTNodeKind::Enum(e) => { - let enum_structs = self.decl_transpiler.transpile_enum(e)?; - for struct_decl in enum_structs { - self.structs.insert(struct_decl.name.clone(), struct_decl); - } - } - TypedASTNodeKind::Function(f) => { - let mut func_decl = self.decl_transpiler.transpile_function(f)?; - // Body will be filled later - func_decl.body = Some(Vec::new()); - self.functions.push(func_decl); - } - TypedASTNodeKind::Extern(e) => { - // For externs, we might need to add function prototypes - // But for now, skip as they're handled differently - } - _ => { - // Other node types (traits, etc.) - handle later - } - } - Ok(()) - } - - fn transpile_function_bodies(&mut self, nodes: &[TypedASTNode]) -> Result<(), String> { - for node in nodes { - if let TypedASTNodeKind::Function(f) = &node.kind { - // Find the corresponding function declaration - if let Some(func_decl) = self.functions.iter_mut().find(|fd| fd.name == f.name) { - let body_stmts = self.stmt_transpiler.expr_to_stmts(&f.body)?; - func_decl.body = Some(body_stmts); - } - } - } - Ok(()) - } - - fn generate_struct_decl(&self, struct_decl: &CStructDecl) -> String { - let mut output = format!("struct {} {{\n", struct_decl.name); - for field in &struct_decl.fields { - output.push_str(&format!(" {} {};\n", field.ty.to_string(), field.name)); - } - output.push_str("}"); - output - } - - fn generate_func_proto(&self, func: &CFuncDecl) -> String { - let params_str = if func.params.is_empty() { - "void".to_string() - } else { - func.params - .iter() - .map(|p| format!("{} {}", p.ty.to_string(), p.name)) - .collect::>() - .join(", ") - }; - format!( - "{} {}({})", - func.return_type.to_string(), - func.name, - params_str - ) - } - - fn generate_func_def(&self, func: &CFuncDecl) -> String { - let proto = self.generate_func_proto(func); - let mut output = format!("{} {{\n", proto); - - if let Some(body) = &func.body { - for stmt in body { - output.push_str(&self.generate_stmt(stmt)); - } - } - - output.push_str("}\n"); - output - } - - fn generate_var_decl(&self, var: &CVarDecl) -> String { - let mut output = format!("{} {}", var.ty.to_string(), var.name); - if let Some(init) = &var.initializer { - output.push_str(&format!(" = {}", self.generate_expr(init))); - } - output - } - - fn generate_stmt(&self, stmt: &CStmt) -> String { - match stmt { - CStmt::VarDecl(var) => format!(" {};\n", self.generate_var_decl(var)), - CStmt::Expr(expr) => format!(" {};\n", self.generate_expr(expr)), - CStmt::Assign(lhs, rhs) => format!( - " {} = {};\n", - self.generate_expr(lhs), - self.generate_expr(rhs) - ), - CStmt::Return(Some(expr)) => format!(" return {};\n", self.generate_expr(expr)), - CStmt::Return(None) => " return;\n".to_string(), - CStmt::If(cond, then_stmts, else_stmts) => { - let mut output = format!(" if ({}) {{\n", self.generate_expr(cond)); - for stmt in then_stmts { - output.push_str(&format!(" {}", self.generate_stmt(stmt))); - } - output.push_str(" }"); - if let Some(else_stmts) = else_stmts { - output.push_str(" else {\n"); - for stmt in else_stmts { - output.push_str(&format!(" {}", self.generate_stmt(stmt))); - } - output.push_str(" }"); - } - output.push_str("\n"); - output - } - CStmt::While(cond, body) => { - let mut output = format!(" while ({}) {{\n", self.generate_expr(cond)); - for stmt in body { - output.push_str(&format!(" {}", self.generate_stmt(stmt))); - } - output.push_str(" }\n"); - output - } - CStmt::Block(stmts) => { - let mut output = " {\n".to_string(); - for stmt in stmts { - output.push_str(&format!(" {}", self.generate_stmt(stmt))); - } - output.push_str(" }\n"); - output - } - _ => "// TODO: unimplemented stmt\n".to_string(), - } - } - - fn generate_expr(&self, expr: &CExpr) -> String { - match expr { - CExpr::IntLit(i) => format!("{}", i), - CExpr::FloatLit(f) => format!("{:.6}", f), - CExpr::BoolLit(b) => format!("{}", b), - CExpr::StringLit(s) => format!("\"{}\"", s), - CExpr::Var(name) => name.clone(), - CExpr::Call(func, args) => { - let args_str = args - .iter() - .map(|arg| self.generate_expr(arg)) - .collect::>() - .join(", "); - format!("{}({})", func, args_str) - } - CExpr::BinOp(lhs, op, rhs) => { - format!( - "({} {} {})", - self.generate_expr(lhs), - op.to_string(), - self.generate_expr(rhs) - ) - } - CExpr::UnOp(op, expr) => { - format!("{}{}", op.to_string(), self.generate_expr(expr)) - } - CExpr::Cast(expr, ty) => { - format!("({}) {}", ty.to_string(), self.generate_expr(expr)) - } - CExpr::AddrOf(expr) => format!("&{}", self.generate_expr(expr)), - CExpr::Deref(expr) => format!("*{}", self.generate_expr(expr)), - CExpr::Dot(expr, field) => format!("{}.{}", self.generate_expr(expr), field), - CExpr::Index(array, index) => format!( - "{}[{}]", - self.generate_expr(array), - self.generate_expr(index) - ), - CExpr::StructLit(struct_name, fields) => { - let field_inits: Vec = fields - .iter() - .map(|(name, expr)| format!(".{} = {}", name, self.generate_expr(expr))) - .collect(); - format!("(struct {}){{ {} }}", struct_name, field_inits.join(", ")) - } - CExpr::EnumLit(enum_name, variant_name, args) => { - // Find the variant index - for simplicity, assume variants are in order - // TODO: This should be stored properly - let variant_index = 0; // Placeholder - need to map variant name to index - - let variant_struct_name = format!("{}_{}", enum_name, variant_name); - let union_field_name = variant_name.to_lowercase(); - - let struct_init = if args.is_empty() { - "{}".to_string() - } else { - let field_inits: Vec = args - .iter() - .enumerate() - .map(|(i, arg)| format!(".field_{} = {}", i, self.generate_expr(arg))) - .collect(); - format!("{{ {} }}", field_inits.join(", ")) - }; - - format!( - "({}){{ .discriminant = {}, .data = {{ .{} = ({}{}) }} }}", - enum_name, variant_index, union_field_name, variant_struct_name, struct_init - ) - } - _ => "// TODO: unimplemented expr".to_string(), - } - } -} diff --git a/src/lambda_lower.rs b/src/lambda_lower.rs index 6ccc465..08ce1db 100644 --- a/src/lambda_lower.rs +++ b/src/lambda_lower.rs @@ -17,24 +17,14 @@ impl LambdaLowerer { } } - fn collect_free_vars( - &self, - expr: &Expr, - lambda_params: &[String], - ) -> std::collections::HashSet { + fn collect_free_vars(&self, expr: &Expr, lambda_params: &[String]) -> std::collections::HashSet { let mut free_vars = std::collections::HashSet::new(); let mut local_scope = std::collections::HashSet::new(); self.collect_free_vars_expr(expr, lambda_params, &mut free_vars, &mut local_scope); free_vars } - fn collect_free_vars_expr( - &self, - expr: &Expr, - lambda_params: &[String], - free_vars: &mut std::collections::HashSet, - local_scope: &mut std::collections::HashSet, - ) { + fn collect_free_vars_expr(&self, expr: &Expr, lambda_params: &[String], free_vars: &mut std::collections::HashSet, local_scope: &mut std::collections::HashSet) { match &expr.kind { ExprKind::Variable(name) => { if !lambda_params.contains(name) && !local_scope.contains(name) { @@ -146,12 +136,7 @@ impl LambdaLowerer { self.collect_free_vars_expr(end, lambda_params, free_vars, local_scope); } // Terminal expressions don't contain variables - ExprKind::Int(_) - | ExprKind::Float(_) - | ExprKind::Bool(_) - | ExprKind::String(_) - | ExprKind::Break - | ExprKind::Continue => {} + ExprKind::Int(_) | ExprKind::Float(_) | ExprKind::Bool(_) | ExprKind::String(_) | ExprKind::Break | ExprKind::Continue => {} } } @@ -198,8 +183,7 @@ impl LambdaLowerer { let new_kind = match &expr.kind { ExprKind::Lambda(args, body) => { // Collect free variables (captured variables) - let lambda_params: Vec = - args.iter().map(|(name, _)| name.clone()).collect(); + let lambda_params: Vec = args.iter().map(|(name, _)| name.clone()).collect(); let free_vars = self.collect_free_vars(body, &lambda_params); if free_vars.is_empty() { @@ -228,7 +212,9 @@ impl LambdaLowerer { }; // Store the generated function - self.generated_functions.borrow_mut().push(lambda_func); + self.generated_functions + .borrow_mut() + .push(lambda_func); // Replace the lambda with a reference to the generated function ExprKind::Variable(lambda_name) @@ -258,7 +244,10 @@ impl LambdaLowerer { ExprKind::If(cond, then_expr, else_expr) => { let lowered_cond = self.lower_expr(cond)?; let lowered_then = self.lower_expr(then_expr)?; - let lowered_else = else_expr.as_ref().map(|e| self.lower_expr(e)).transpose()?; + let lowered_else = else_expr + .as_ref() + .map(|e| self.lower_expr(e)) + .transpose()?; ExprKind::If( Box::new(lowered_cond), Box::new(lowered_then), @@ -319,7 +308,10 @@ impl LambdaLowerer { ExprKind::Dot(Box::new(lowered_obj), field.clone()) } ExprKind::EarlyReturn(expr) => { - let lowered_expr = expr.as_ref().map(|e| self.lower_expr(e)).transpose()?; + let lowered_expr = expr + .as_ref() + .map(|e| self.lower_expr(e)) + .transpose()?; ExprKind::EarlyReturn(lowered_expr.map(Box::new)) } ExprKind::OptionalChain(obj, field) => { @@ -327,7 +319,10 @@ impl LambdaLowerer { ExprKind::OptionalChain(lowered_obj.map(Box::new), field.clone()) } ExprKind::Return(expr) => { - let lowered_expr = expr.as_ref().map(|e| self.lower_expr(e)).transpose()?; + let lowered_expr = expr + .as_ref() + .map(|e| self.lower_expr(e)) + .transpose()?; ExprKind::Return(lowered_expr.map(Box::new)) } ExprKind::Array(exprs) => { diff --git a/src/lib.rs b/src/lib.rs index dc1f045..352e25a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,8 @@ pub const EXTENSION: &str = ".sui"; pub mod ast; -pub mod c_ir; -pub mod codegen; -pub mod lambda_lower; pub mod lexer; -pub mod monomorphize; pub mod parser; +pub mod lambda_lower; pub mod typechecker; +pub mod monomorphize; diff --git a/src/main.rs b/src/main.rs index c5c96b0..3dc3ed4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,8 @@ use logos::Logos; use std::fs; use suicmez::{ - codegen::transpiler::Transpiler, - lambda_lower::LambdaLowerer, - lexer::Token, + lexer::Token, parser::Parser, lambda_lower::LambdaLowerer, typechecker::TypeChecker, monomorphize::{Monomorphizer, check_no_typevars}, - parser::Parser, - typechecker::TypeChecker, }; fn main() { @@ -49,6 +45,7 @@ fn run_test_suite() { } fn format_parse_error(source: &str, error: &suicmez::parser::ParseError) -> String { + // Find the line containing the error let lines: Vec<&str> = source.lines().collect(); let mut current_pos = 0; @@ -72,10 +69,7 @@ fn format_parse_error(source: &str, error: &suicmez::parser::ParseError) -> Stri let line_end_col = (error.span.end - line_start).min(line.len()); // Print spaces and squiggly line for the span - result.push_str(&format!( - "{} | ", - " ".repeat((line_idx + 1).to_string().len()) - )); + result.push_str(&format!("{} | ", " ".repeat((line_idx + 1).to_string().len()))); for _ in 0..line_start_col { result.push(' '); } @@ -85,10 +79,7 @@ fn format_parse_error(source: &str, error: &suicmez::parser::ParseError) -> Stri result.push('\n'); // Print caret at the start position - result.push_str(&format!( - "{} | ", - " ".repeat((line_idx + 1).to_string().len()) - )); + result.push_str(&format!("{} | ", " ".repeat((line_idx + 1).to_string().len()))); for _ in 0..line_start_col { result.push(' '); } @@ -101,66 +92,7 @@ fn format_parse_error(source: &str, error: &suicmez::parser::ParseError) -> Stri } // Fallback if we can't find the line - format!( - "Parse error: {} (at byte {})", - error.message, error.span.start - ) -} - -fn format_type_error(source: &str, error: &suicmez::typechecker::TypeError) -> String { - // Find the line containing the error - let lines: Vec<&str> = source.lines().collect(); - let mut current_pos = 0; - - for (line_idx, line) in lines.iter().enumerate() { - let line_start = current_pos; - let line_end = current_pos + line.len(); - - // Check if the error span intersects with this line - if error.span.start < line_end && error.span.end > line_start { - let mut result = String::new(); - - // Print the error message - result.push_str(&format!("Type error: {}\n", error.kind)); - - // Print the line number and content - result.push_str(&format!("{} | {}\n", line_idx + 1, line)); - - // Calculate column positions within the line - let line_start_col = error.span.start.saturating_sub(line_start); - let line_end_col = (error.span.end - line_start).min(line.len()); - - // Print spaces and squiggly line for the span - result.push_str(&format!( - "{} | ", - " ".repeat((line_idx + 1).to_string().len()) - )); - for _ in 0..line_start_col { - result.push(' '); - } - for _ in line_start_col..line_end_col { - result.push('~'); - } - result.push('\n'); - - // Print caret at the start position - result.push_str(&format!( - "{} | ", - " ".repeat((line_idx + 1).to_string().len()) - )); - for _ in 0..line_start_col { - result.push(' '); - } - result.push('^'); - - return result; - } - - current_pos = line_end + 1; // +1 for the newline character - } - - // Fallback if we can't find the line - format!("Type error: {} (at byte {})", error.kind, error.span.start) + format!("Parse error: {} (at byte {})", error.message, error.span.start) } fn run_file(filename: &str) -> Result<(), String> { @@ -194,20 +126,19 @@ fn run_file(filename: &str) -> Result<(), String> { // Lower lambdas to generated functions let lowerer = LambdaLowerer::new(); - let lowered_nodes = lowerer - .lower_program(&ast_nodes) + let lowered_nodes = lowerer.lower_program(&ast_nodes) .map_err(|e| format!("Lambda lowering error: {}", e))?; - println!( - "Lambda lowering passed! {} nodes after lowering.", - lowered_nodes.len() - ); + println!("Lambda lowering passed! {} nodes after lowering.", lowered_nodes.len()); // Typecheck the AST let mut typechecker = TypeChecker::new(); - let typed_nodes = typechecker - .typecheck_program(&lowered_nodes) - .map_err(|e| format_type_error(&source, &e))?; + let typed_nodes = typechecker.typecheck_program(&lowered_nodes).map_err(|e| { + format!( + "Type error at {}:{}: {:?}", + e.span.file, e.span.start, e.kind + ) + })?; println!( "Type checking passed! {} nodes typechecked.", @@ -248,19 +179,17 @@ fn run_file(filename: &str) -> Result<(), String> { // Monomorphize the AST let monomorphizer = Monomorphizer::new(); - let mono_nodes = monomorphizer - .monomorphize_program(&typed_nodes) - .map_err(|e| { - format!( - "Monomorphization error: {}{}", - e.message, - if let Some(span) = &e.span { - format!(" at {}:{}", span.file, span.start) - } else { - String::new() - } - ) - })?; + let mono_nodes = monomorphizer.monomorphize_program(&typed_nodes).map_err(|e| { + format!( + "Monomorphization error: {}{}", + e.message, + if let Some(span) = &e.span { + format!(" at {}:{}", span.file, span.start) + } else { + String::new() + } + ) + })?; println!( "Monomorphization passed! {} nodes after specialization.", @@ -314,18 +243,5 @@ fn run_file(filename: &str) -> Result<(), String> { println!("Type variable check passed! No type variables remain in AST."); - // Generate C code - let mut transpiler = Transpiler::new(); - let c_code = transpiler - .transpile_program(&mono_nodes) - .map_err(|e| format!("Code generation error: {}", e))?; - - // Write C code to file - let c_filename = filename.replace(".sui", ".c"); - fs::write(&c_filename, &c_code) - .map_err(|e| format!("Error writing C file {}: {}", c_filename, e))?; - - println!("C code generated successfully: {}", c_filename); - Ok(()) } diff --git a/src/typechecker.rs b/src/typechecker.rs index 63ecda5..5c594ef 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -1,7 +1,6 @@ // src/typechecker.rs use crate::ast::*; use std::collections::HashMap; -use std::fmt; #[derive(Debug, Clone, PartialEq)] pub enum Type { @@ -87,75 +86,6 @@ pub enum TypeErrorKind { Other(String), } -impl fmt::Display for TypeErrorKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - TypeErrorKind::TypeMismatch(expected, actual) => { - write!( - f, - "Type mismatch: expected {}, found {}", - expected.to_string(), - actual.to_string() - ) - } - TypeErrorKind::UndefinedVariable(name) => { - write!(f, "Undefined variable '{}'", name) - } - TypeErrorKind::UndefinedType(name) => { - write!(f, "Undefined type '{}'", name) - } - TypeErrorKind::UndefinedFunction(name) => { - write!(f, "Undefined function '{}'", name) - } - TypeErrorKind::UndefinedField(field, ty) => { - write!(f, "Undefined field '{}' on type {}", field, ty.to_string()) - } - TypeErrorKind::UndefinedVariant(enum_name, variant) => { - write!(f, "Undefined variant '{}' in enum '{}'", variant, enum_name) - } - TypeErrorKind::ArityMismatch(expected, actual) => { - write!( - f, - "Function expects {} arguments, but {} were provided", - expected, actual - ) - } - TypeErrorKind::NotAFunction(ty) => { - write!(f, "Expected a function, but found {}", ty.to_string()) - } - TypeErrorKind::NotAnArray(ty) => { - write!(f, "Expected an array, but found {}", ty.to_string()) - } - TypeErrorKind::NotAStruct(ty) => { - write!(f, "Expected a struct, but found {}", ty.to_string()) - } - TypeErrorKind::NotAnEnum(ty) => { - write!(f, "Expected an enum, but found {}", ty.to_string()) - } - TypeErrorKind::InvalidCast(from, to) => { - write!( - f, - "Invalid cast from {} to {}", - from.to_string(), - to.to_string() - ) - } - TypeErrorKind::InvalidPattern(msg) => { - write!(f, "Invalid pattern: {}", msg) - } - TypeErrorKind::MutableityError(msg) => { - write!(f, "Mutability error: {}", msg) - } - TypeErrorKind::LinearityError(msg) => { - write!(f, "Linearity error: {}", msg) - } - TypeErrorKind::Other(msg) => { - write!(f, "{}", msg) - } - } - } -} - #[derive(Clone)] struct VarInfo { ty: Type, diff --git a/tests/basic_types.c b/tests/basic_types.c deleted file mode 100644 index 85ba69b..0000000 --- a/tests/basic_types.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include -#include -#include - -int main(void); - - -int main(void) { - int x = 5; - float y = 10.500000; - bool z = true; - char* s = "hello"; - return x; -} - diff --git a/tests/control_flow.c b/tests/control_flow.c deleted file mode 100644 index a6acdcf..0000000 --- a/tests/control_flow.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include -#include - -int main(void); - - -int main(void) { - if (true) { - 1; - } else { - 0; - } - int i = 0; - while ((i < 5)) { - i = (i + 1); - } - return i; -} - diff --git a/tests/control_flow.sui b/tests/control_flow.sui index 391b8cd..af58199 100644 --- a/tests/control_flow.sui +++ b/tests/control_flow.sui @@ -5,7 +5,7 @@ fn main() -> int do else 0 - let mut i = 0; + let i = 0; while i < 5 i = i + 1; i diff --git a/tests/structs.c b/tests/structs.c deleted file mode 100644 index d2a2577..0000000 --- a/tests/structs.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include -#include - -struct Point { - int x; - int y; -}; - -int main(void); - - -int main(void) { - struct Point p = (struct Point){ .x = 5, .y = 10 }; - struct Person person = (struct Person){ .name = "Alice", .age = 30 }; - return (p.x + person.age); -} - diff --git a/tests/structs.sui b/tests/structs.sui index 0638ea6..f837276 100644 --- a/tests/structs.sui +++ b/tests/structs.sui @@ -9,8 +9,8 @@ struct Person age: T, end -fn main() -> int do +fn main() -> int do let p = Point { x: 5, y: 10 }; let person = Person { name: "Alice", age: 30 }; - p.x + person.age + p.x end diff --git a/tests/traits.sui b/tests/traits.sui index e1c8c79..e724364 100644 --- a/tests/traits.sui +++ b/tests/traits.sui @@ -13,7 +13,5 @@ impl Number : Show end fn main() -> int do - let number = Number {value: 40}; - number.show(); - 0 + 42 end