diff --git a/src/c_ir.rs b/src/c_ir.rs index 748a20a..aca4d2a 100644 --- a/src/c_ir.rs +++ b/src/c_ir.rs @@ -8,7 +8,7 @@ pub enum CType { Ptr(Box), Struct(String), UnnamedStruct(Vec), - Array(Box), // heap-allocated array wrapper with data pointer, len, capacity + Array(Box), // heap-allocated array wrapper with data pointer, len, capacity Func(Vec, Box), // args and return } @@ -44,7 +44,10 @@ impl CType { .collect(); format!("struct {{\n{}\n}}", field_strs.join("\n")) } - CType::Array(inner) => format!("struct sui_array_{}", inner.to_string().replace(" ", "_").replace("*", "ptr")), + CType::Array(inner) => format!( + "struct sui_array_{}", + inner.to_string().replace(" ", "_").replace("*", "ptr") + ), CType::Func(args, ret) => { let arg_strs: Vec = args.iter().map(|t| t.to_string()).collect(); format!("{} (*)({})", ret.to_string(), arg_strs.join(", ")) @@ -76,24 +79,24 @@ pub struct CFuncDecl { #[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), - Assign(Box, Box), // Assignment expression (lhs = rhs) - Ternary(Box, Box, Box), // cond ? then : else + 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), + Assign(Box, Box), // Assignment expression (lhs = rhs) + Ternary(Box, Box, Box), // cond ? then : else } #[derive(Debug, Clone)] diff --git a/src/c_lowerer/statements_transpiler.rs b/src/c_lowerer/statements_transpiler.rs index 00d00eb..2038f25 100644 --- a/src/c_lowerer/statements_transpiler.rs +++ b/src/c_lowerer/statements_transpiler.rs @@ -138,27 +138,31 @@ impl StatementsTranspiler { c_args, )) } - TypedExprKind::If(cond, then_expr, else_expr) => { - // Conditional expressions: (cond ? then_expr : else_expr) - let c_cond = self.transpile_expr(cond)?; - let c_then = self.transpile_expr(then_expr)?; - let c_else = match else_expr { - Some(else_expr) => self.transpile_expr(else_expr)?, - None => return Err("If expressions must have an else branch".to_string()), - }; - Ok(CExpr::Ternary(Box::new(c_cond), Box::new(c_then), Box::new(c_else))) - } - TypedExprKind::Assign(lhs, rhs) => { - // Assignments are expressions in C, so we can transpile them - let c_lhs = self.transpile_expr(lhs)?; - let c_rhs = self.transpile_expr(rhs)?; - Ok(CExpr::Assign(Box::new(c_lhs), Box::new(c_rhs))) - } - _ => Err(format!("Unsupported expression: {:?}", expr.kind)), + TypedExprKind::If(cond, then_expr, else_expr) => { + // Conditional expressions: (cond ? then_expr : else_expr) + let c_cond = self.transpile_expr(cond)?; + let c_then = self.transpile_expr(then_expr)?; + let c_else = match else_expr { + Some(else_expr) => self.transpile_expr(else_expr)?, + None => return Err("If expressions must have an else branch".to_string()), + }; + Ok(CExpr::Ternary( + Box::new(c_cond), + Box::new(c_then), + Box::new(c_else), + )) + } + TypedExprKind::Assign(lhs, rhs) => { + // Assignments are expressions in C, so we can transpile them + let c_lhs = self.transpile_expr(lhs)?; + let c_rhs = self.transpile_expr(rhs)?; + Ok(CExpr::Assign(Box::new(c_lhs), Box::new(c_rhs))) + } + _ => Err(format!("Unsupported expression: {:?}", expr.kind)), } } - pub fn transpile_stmt(&mut 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)?; @@ -183,11 +187,11 @@ impl StatementsTranspiler { Ok(CStmt::Return(c_ret)) } - TypedExprKind::While(cond, body) => { - let c_cond = self.transpile_expr(cond)?; - let body_stmts = self.expr_to_loop_stmts(body)?; - Ok(CStmt::While(c_cond, body_stmts)) - } + TypedExprKind::While(cond, body) => { + let c_cond = self.transpile_expr(cond)?; + let body_stmts = self.expr_to_loop_stmts(body)?; + Ok(CStmt::While(c_cond, body_stmts)) + } TypedExprKind::Do(exprs) => { let mut stmts = Vec::new(); let mut defers = Vec::new(); @@ -227,10 +231,10 @@ impl StatementsTranspiler { ); let incr = - CExpr::UnOp(CUnaryOp::PreInc, Box::new(CExpr::Var(var_name.clone()))); + CExpr::UnOp(CUnaryOp::PreInc, Box::new(CExpr::Var(var_name.clone()))); - let body_stmts = self.expr_to_loop_stmts(body)?; - Ok(CStmt::For(init, cond, incr, body_stmts)) + let body_stmts = self.expr_to_loop_stmts(body)?; + Ok(CStmt::For(init, cond, incr, body_stmts)) } // for x in array_var @@ -272,9 +276,9 @@ impl StatementsTranspiler { }); let mut body_stmts = vec![bind]; - body_stmts.extend(self.expr_to_loop_stmts(body)?); + body_stmts.extend(self.expr_to_loop_stmts(body)?); - Ok(CStmt::For(idx_decl, cond, incr, body_stmts)) + Ok(CStmt::For(idx_decl, cond, incr, body_stmts)) } // for x in [a, b, c] @@ -320,13 +324,13 @@ impl StatementsTranspiler { )), }); - let mut body_stmts = vec![bind]; - body_stmts.extend(self.expr_to_loop_stmts(body)?); + let mut body_stmts = vec![bind]; + body_stmts.extend(self.expr_to_loop_stmts(body)?); - Ok(CStmt::Block(vec![ - CStmt::VarDecl(arr_decl), - CStmt::For(idx_decl, cond, incr, body_stmts), - ])) + Ok(CStmt::Block(vec![ + CStmt::VarDecl(arr_decl), + CStmt::For(idx_decl, cond, incr, body_stmts), + ])) } _ => Err("Unsupported iterable in for loop".to_string()), diff --git a/src/codegen/transpiler.rs b/src/codegen/transpiler.rs index f43c665..dae1960 100644 --- a/src/codegen/transpiler.rs +++ b/src/codegen/transpiler.rs @@ -40,7 +40,7 @@ pub struct Transpiler { decl_transpiler: DeclarationTranspiler, stmt_transpiler: StatementsTranspiler, array_types: std::collections::HashSet, // Track array types we need to generate - has_main: bool, // Track if we found a main function + has_main: bool, // Track if we found a main function } impl Transpiler { @@ -442,7 +442,7 @@ impl Transpiler { match stmt { CStmt::VarDecl(_) | CStmt::Expr(_) | CStmt::Assign(_, _) => self.add_debug_print(&code), CStmt::Return(_) => code, // Don't add debug print to return statements to avoid unreachable code - _ => code, // Control flow statements don't get debug prints + _ => code, // Control flow statements don't get debug prints } } diff --git a/src/main.rs b/src/main.rs index d2317ed..7d454da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,40 +1,42 @@ - use clap::Parser; - use std::fs; - use suicmez::{ - codegen::transpiler::Transpiler, - import_resolver::ImportResolver, - lambda_lower::LambdaLowerer, - monomorphize::{Monomorphizer, check_no_typevars}, - typechecker::TypeChecker, - }; +use clap::Parser; +use std::fs; +use suicmez::{ + codegen::transpiler::Transpiler, + import_resolver::ImportResolver, + lambda_lower::LambdaLowerer, + monomorphize::{Monomorphizer, check_no_typevars}, + typechecker::TypeChecker, +}; - #[derive(Parser)] - #[command(author, version, about = "A compiler for the Sui language")] - struct Args { - /// Run the test suite instead of compiling a file - #[arg(short, long)] - test: bool, +#[derive(Parser)] +#[command(author, version, about = "A compiler for the Sui language")] +struct Args { + /// Run the test suite instead of compiling a file + #[arg(short, long)] + test: bool, - /// The Sui source file to compile - file: Option, - } + /// The Sui source file to compile + file: Option, +} - fn main() { - let args = Args::parse(); +fn main() { + let args = Args::parse(); - if args.test { - run_test_suite(); - } else if let Some(filename) = args.file { - println!("Type checking file: {}", filename); + if args.test { + run_test_suite(); + } else if let Some(filename) = args.file { + println!("Type checking file: {}", filename); - if let Err(e) = run_file(&filename) { - eprintln!("Error: {}", e); - } - } else { - eprintln!("No file specified. Use --test to run the test suite or provide a Sui file to compile."); - std::process::exit(1); - } - } + if let Err(e) = run_file(&filename) { + eprintln!("Error: {}", e); + } + } else { + eprintln!( + "No file specified. Use --test to run the test suite or provide a Sui file to compile." + ); + std::process::exit(1); + } +} fn run_test_suite() { println!("Running test suite...\n"); @@ -181,8 +183,11 @@ fn run_file(filename: &str) -> Result<(), String> { .resolve(filename) .map_err(|e| format!("Import resolution error: {}", e))?; - println!("Import resolution complete! {} total nodes loaded", ast_nodes.len()); - + println!( + "Import resolution complete! {} total nodes loaded", + ast_nodes.len() + ); + // Read the source file for error reporting let source = fs::read_to_string(filename) .map_err(|e| format!("Error reading file {}: {}", filename, e))?; diff --git a/src/typechecker.rs b/src/typechecker.rs index d03a0a1..2dccee6 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -367,214 +367,420 @@ impl TypeChecker { fn add_builtin_functions(&mut self) { // ODE Physics Engine functions - self.env.functions.insert("ode_init".to_string(), FunctionType { - type_params: vec![], - params: vec![], - return_type: Type::Unit, - }); - self.env.functions.insert("ode_close".to_string(), FunctionType { - type_params: vec![], - params: vec![], - return_type: Type::Unit, - }); - self.env.functions.insert("ode_world_create".to_string(), FunctionType { - type_params: vec![], - params: vec![], - return_type: Type::Ptr(Box::new(Type::Unit)), // opaque pointer - }); - self.env.functions.insert("ode_world_destroy".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit))], - return_type: Type::Unit, - }); - self.env.functions.insert("ode_world_set_gravity".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Float, Type::Float, Type::Float], // world_id, x, y, z - return_type: Type::Unit, - }); - self.env.functions.insert("ode_world_step".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Float], - return_type: Type::Unit, - }); + self.env.functions.insert( + "ode_init".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_close".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_world_create".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Ptr(Box::new(Type::Unit)), // opaque pointer + }, + ); + self.env.functions.insert( + "ode_world_destroy".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Ptr(Box::new(Type::Unit))], + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_world_set_gravity".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Float, + Type::Float, + Type::Float, + ], // world_id, x, y, z + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_world_step".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Float], + return_type: Type::Unit, + }, + ); // Body management - self.env.functions.insert("ode_body_create".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit))], // world - return_type: Type::Ptr(Box::new(Type::Unit)), // body - }); - self.env.functions.insert("ode_body_destroy".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit))], // body - return_type: Type::Unit, - }); - self.env.functions.insert("ode_body_set_position".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Float, Type::Float, Type::Float], // body, x, y, z - return_type: Type::Unit, - }); - self.env.functions.insert("ode_body_set_linear_vel".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Float, Type::Float, Type::Float], // body, x, y, z - return_type: Type::Unit, - }); + self.env.functions.insert( + "ode_body_create".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Ptr(Box::new(Type::Unit))], // world + return_type: Type::Ptr(Box::new(Type::Unit)), // body + }, + ); + self.env.functions.insert( + "ode_body_destroy".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Ptr(Box::new(Type::Unit))], // body + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_body_set_position".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Float, + Type::Float, + Type::Float, + ], // body, x, y, z + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_body_set_linear_vel".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Float, + Type::Float, + Type::Float, + ], // body, x, y, z + return_type: Type::Unit, + }, + ); // Geometry and mass - self.env.functions.insert("ode_body_set_box_mass".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Float, Type::Float, Type::Float, Type::Float], // body, density, lx, ly, lz - return_type: Type::Unit, - }); - self.env.functions.insert("ode_create_box_geom".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Float, Type::Float, Type::Float], // space, lx, ly, lz - return_type: Type::Ptr(Box::new(Type::Unit)), // geom - }); - self.env.functions.insert("ode_create_plane_geom".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Float, Type::Float, Type::Float, Type::Float], // space, a, b, c, d - return_type: Type::Ptr(Box::new(Type::Unit)), // geom - }); - self.env.functions.insert("ode_geom_set_body".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Ptr(Box::new(Type::Unit))], // geom, body - return_type: Type::Unit, - }); - self.env.functions.insert("ode_geom_destroy".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit))], // geom - return_type: Type::Unit, - }); + self.env.functions.insert( + "ode_body_set_box_mass".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Float, + Type::Float, + Type::Float, + Type::Float, + ], // body, density, lx, ly, lz + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_create_box_geom".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Float, + Type::Float, + Type::Float, + ], // space, lx, ly, lz + return_type: Type::Ptr(Box::new(Type::Unit)), // geom + }, + ); + self.env.functions.insert( + "ode_create_plane_geom".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Float, + Type::Float, + Type::Float, + Type::Float, + ], // space, a, b, c, d + return_type: Type::Ptr(Box::new(Type::Unit)), // geom + }, + ); + self.env.functions.insert( + "ode_geom_set_body".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Ptr(Box::new(Type::Unit)), + ], // geom, body + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_geom_destroy".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Ptr(Box::new(Type::Unit))], // geom + return_type: Type::Unit, + }, + ); // Collision space - self.env.functions.insert("ode_simple_space_create".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit))], // parent space (can be null) - return_type: Type::Ptr(Box::new(Type::Unit)), // space - }); - self.env.functions.insert("ode_space_destroy".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit))], // space - return_type: Type::Unit, - }); + self.env.functions.insert( + "ode_simple_space_create".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Ptr(Box::new(Type::Unit))], // parent space (can be null) + return_type: Type::Ptr(Box::new(Type::Unit)), // space + }, + ); + self.env.functions.insert( + "ode_space_destroy".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Ptr(Box::new(Type::Unit))], // space + return_type: Type::Unit, + }, + ); // Collision detection and contact joints - self.env.functions.insert("ode_space_collide".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Ptr(Box::new(Type::Unit)), Type::Ptr(Box::new(Type::Unit))], // world, space, contactgroup - return_type: Type::Unit, - }); - self.env.functions.insert("ode_joint_group_create".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Int], // max_size - return_type: Type::Ptr(Box::new(Type::Unit)), // contactgroup - }); - self.env.functions.insert("ode_joint_group_destroy".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit))], // group - return_type: Type::Unit, - }); - self.env.functions.insert("ode_joint_group_empty".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit))], // group - return_type: Type::Unit, - }); + self.env.functions.insert( + "ode_space_collide".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Ptr(Box::new(Type::Unit)), + Type::Ptr(Box::new(Type::Unit)), + ], // world, space, contactgroup + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_joint_group_create".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int], // max_size + return_type: Type::Ptr(Box::new(Type::Unit)), // contactgroup + }, + ); + self.env.functions.insert( + "ode_joint_group_destroy".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Ptr(Box::new(Type::Unit))], // group + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_joint_group_empty".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Ptr(Box::new(Type::Unit))], // group + return_type: Type::Unit, + }, + ); // Additional body functions - self.env.functions.insert("ode_body_get_linear_vel".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Ptr(Box::new(Type::Float)), Type::Ptr(Box::new(Type::Float)), Type::Ptr(Box::new(Type::Float))], // body, x, y, z - return_type: Type::Unit, - }); - self.env.functions.insert("ode_body_get_rotation".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Ptr(Box::new(Type::Float)), Type::Ptr(Box::new(Type::Float)), Type::Ptr(Box::new(Type::Float)), Type::Ptr(Box::new(Type::Float))], // body, w, x, y, z - return_type: Type::Unit, - }); - self.env.functions.insert("ode_body_set_rotation".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Float, Type::Float, Type::Float, Type::Float], // body, w, x, y, z - return_type: Type::Unit, - }); + self.env.functions.insert( + "ode_body_get_linear_vel".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Ptr(Box::new(Type::Float)), + Type::Ptr(Box::new(Type::Float)), + Type::Ptr(Box::new(Type::Float)), + ], // body, x, y, z + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_body_get_rotation".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Ptr(Box::new(Type::Float)), + Type::Ptr(Box::new(Type::Float)), + Type::Ptr(Box::new(Type::Float)), + Type::Ptr(Box::new(Type::Float)), + ], // body, w, x, y, z + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "ode_body_set_rotation".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Float, + Type::Float, + Type::Float, + Type::Float, + ], // body, w, x, y, z + return_type: Type::Unit, + }, + ); // Raylib functions // Window management - self.env.functions.insert("init_window".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Int, Type::Int, Type::String], // width, height, title - return_type: Type::Bool, - }); - self.env.functions.insert("close_window".to_string(), FunctionType { - type_params: vec![], - params: vec![], - return_type: Type::Unit, - }); - self.env.functions.insert("window_should_close".to_string(), FunctionType { - type_params: vec![], - params: vec![], - return_type: Type::Bool, - }); - self.env.functions.insert("set_target_fps".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Int], // fps - return_type: Type::Unit, - }); + self.env.functions.insert( + "init_window".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int, Type::Int, Type::String], // width, height, title + return_type: Type::Bool, + }, + ); + self.env.functions.insert( + "close_window".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "window_should_close".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Bool, + }, + ); + self.env.functions.insert( + "set_target_fps".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int], // fps + return_type: Type::Unit, + }, + ); // Drawing - self.env.functions.insert("begin_drawing".to_string(), FunctionType { - type_params: vec![], - params: vec![], - return_type: Type::Unit, - }); - self.env.functions.insert("end_drawing".to_string(), FunctionType { - type_params: vec![], - params: vec![], - return_type: Type::Unit, - }); - self.env.functions.insert("clear_background".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Int, Type::Int, Type::Int, Type::Int], // r, g, b, a - return_type: Type::Unit, - }); + self.env.functions.insert( + "begin_drawing".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "end_drawing".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "clear_background".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int, Type::Int, Type::Int, Type::Int], // r, g, b, a + return_type: Type::Unit, + }, + ); // 3D Mode - self.env.functions.insert("begin_mode3d".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Int], // pos_x,y,z target_x,y,z up_x,y,z fovy projection - return_type: Type::Unit, - }); - self.env.functions.insert("end_mode3d".to_string(), FunctionType { - type_params: vec![], - params: vec![], - return_type: Type::Unit, - }); + self.env.functions.insert( + "begin_mode3d".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Int, + ], // pos_x,y,z target_x,y,z up_x,y,z fovy projection + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "end_mode3d".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); // 3D Drawing - self.env.functions.insert("draw_cube".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Int, Type::Int, Type::Int, Type::Int], // x,y,z width,height,length r,g,b,a - return_type: Type::Unit, - }); - self.env.functions.insert("draw_cube_wires".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Float, Type::Int, Type::Int, Type::Int, Type::Int], // x,y,z width,height,length r,g,b,a - return_type: Type::Unit, - }); + self.env.functions.insert( + "draw_cube".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Int, + Type::Int, + Type::Int, + Type::Int, + ], // x,y,z width,height,length r,g,b,a + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "draw_cube_wires".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Float, + Type::Int, + Type::Int, + Type::Int, + Type::Int, + ], // x,y,z width,height,length r,g,b,a + return_type: Type::Unit, + }, + ); // Input - self.env.functions.insert("is_key_down".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Int], // key - return_type: Type::Bool, - }); + self.env.functions.insert( + "is_key_down".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int], // key + return_type: Type::Bool, + }, + ); // Physics integration helper - self.env.functions.insert("ode_body_get_position".to_string(), FunctionType { - type_params: vec![], - params: vec![Type::Ptr(Box::new(Type::Unit)), Type::Ptr(Box::new(Type::Float)), Type::Ptr(Box::new(Type::Float)), Type::Ptr(Box::new(Type::Float))], // body, x, y, z - return_type: Type::Unit, - }); + self.env.functions.insert( + "ode_body_get_position".to_string(), + FunctionType { + type_params: vec![], + params: vec![ + Type::Ptr(Box::new(Type::Unit)), + Type::Ptr(Box::new(Type::Float)), + Type::Ptr(Box::new(Type::Float)), + Type::Ptr(Box::new(Type::Float)), + ], // body, x, y, z + return_type: Type::Unit, + }, + ); } fn collect_definitions(&mut self, node: &ASTNode) -> Result<(), TypeError> {