GAMEEEEEEEEEE
This commit is contained in:
parent
859e7d7560
commit
e0a42d0262
45 changed files with 2771 additions and 782 deletions
53
src/c_ir.rs
53
src/c_ir.rs
|
|
@ -8,10 +8,25 @@ pub enum CType {
|
|||
Ptr(Box<CType>),
|
||||
Struct(String),
|
||||
UnnamedStruct(Vec<CVarDecl>),
|
||||
Array(Box<CType>, usize), // type and size
|
||||
Array(Box<CType>), // heap-allocated array wrapper with data pointer, len, capacity
|
||||
Func(Vec<CType>, Box<CType>), // args and return
|
||||
}
|
||||
|
||||
impl CType {
|
||||
/// Check if this type should be heap-allocated
|
||||
pub fn is_heap_allocated(&self) -> bool {
|
||||
matches!(self, CType::Array(_) | CType::Struct(_) | CType::Ptr(_))
|
||||
}
|
||||
|
||||
/// Check if this is a copyable (stack-allocated) type
|
||||
pub fn is_copyable(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
CType::Void | CType::Int | CType::Float | CType::Bool | CType::Char | CType::Ptr(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl CType {
|
||||
pub fn to_string(&self) -> String {
|
||||
match self {
|
||||
|
|
@ -29,7 +44,7 @@ impl CType {
|
|||
.collect();
|
||||
format!("struct {{\n{}\n}}", field_strs.join("\n"))
|
||||
}
|
||||
CType::Array(inner, size) => format!("{}[{}]", inner.to_string(), size),
|
||||
CType::Array(inner) => format!("struct sui_array_{}", inner.to_string().replace(" ", "_").replace("*", "ptr")),
|
||||
CType::Func(args, ret) => {
|
||||
let arg_strs: Vec<String> = args.iter().map(|t| t.to_string()).collect();
|
||||
format!("{} (*)({})", ret.to_string(), arg_strs.join(", "))
|
||||
|
|
@ -61,22 +76,24 @@ pub struct CFuncDecl {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CExpr {
|
||||
IntLit(i64),
|
||||
FloatLit(f64),
|
||||
BoolLit(bool),
|
||||
StringLit(String),
|
||||
Var(String),
|
||||
Call(String, Vec<CExpr>),
|
||||
BinOp(Box<CExpr>, CBinaryOp, Box<CExpr>),
|
||||
UnOp(CUnaryOp, Box<CExpr>),
|
||||
Cast(Box<CExpr>, CType),
|
||||
StructLit(String, Vec<(String, CExpr)>),
|
||||
EnumLit(String, String, Vec<CExpr>), // enum_name, variant_name, args
|
||||
ArrayLit(Vec<CExpr>),
|
||||
Index(Box<CExpr>, Box<CExpr>),
|
||||
Dot(Box<CExpr>, String),
|
||||
AddrOf(Box<CExpr>),
|
||||
Deref(Box<CExpr>),
|
||||
IntLit(i64),
|
||||
FloatLit(f64),
|
||||
BoolLit(bool),
|
||||
StringLit(String),
|
||||
Var(String),
|
||||
Call(String, Vec<CExpr>),
|
||||
BinOp(Box<CExpr>, CBinaryOp, Box<CExpr>),
|
||||
UnOp(CUnaryOp, Box<CExpr>),
|
||||
Cast(Box<CExpr>, CType),
|
||||
StructLit(String, Vec<(String, CExpr)>),
|
||||
EnumLit(String, String, Vec<CExpr>), // enum_name, variant_name, args
|
||||
ArrayLit(Vec<CExpr>),
|
||||
Index(Box<CExpr>, Box<CExpr>),
|
||||
Dot(Box<CExpr>, String),
|
||||
AddrOf(Box<CExpr>),
|
||||
Deref(Box<CExpr>),
|
||||
Assign(Box<CExpr>, Box<CExpr>), // Assignment expression (lhs = rhs)
|
||||
Ternary(Box<CExpr>, Box<CExpr>, Box<CExpr>), // cond ? then : else
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ impl DeclarationTranspiler {
|
|||
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()))
|
||||
Ok(CType::Ptr(Box::new(CType::Struct(name.clone()))))
|
||||
}
|
||||
Some(TypeAnnot::Ptr(inner)) => {
|
||||
let inner_type = self.type_annot_to_c_type(&Some(*inner.clone()))?;
|
||||
|
|
@ -145,6 +145,7 @@ impl DeclarationTranspiler {
|
|||
}
|
||||
Some(TypeAnnot::Array(inner)) => {
|
||||
let inner_type = self.type_annot_to_c_type(&Some(*inner.clone()))?;
|
||||
// Arrays are pointers to the element type
|
||||
Ok(CType::Ptr(Box::new(inner_type)))
|
||||
}
|
||||
Some(TypeAnnot::Tuple(fields)) => {
|
||||
|
|
@ -178,6 +179,6 @@ pub fn convert_to_c_type(name: &String) -> Result<CType, String> {
|
|||
"float" => Ok(CType::Float),
|
||||
"bool" => Ok(CType::Bool),
|
||||
"string" => Ok(CType::Ptr(Box::new(CType::Char))),
|
||||
_ => Ok(CType::Struct(name.clone())), // Assume struct
|
||||
_ => Ok(CType::Ptr(Box::new(CType::Struct(name.clone())))), // Assume heap-allocated struct
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,16 +138,27 @@ impl StatementsTranspiler {
|
|||
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)),
|
||||
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<CStmt, String> {
|
||||
pub fn transpile_stmt(&mut self, expr: &TypedExpr) -> Result<CStmt, String> {
|
||||
match &expr.kind {
|
||||
TypedExprKind::Let(_binding_id, name, _kind, _type_annot, init_expr) => {
|
||||
let c_type = self.type_to_ctype(&expr.ty)?;
|
||||
|
|
@ -171,20 +182,12 @@ impl StatementsTranspiler {
|
|||
};
|
||||
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::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();
|
||||
|
|
@ -224,10 +227,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_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
|
||||
|
|
@ -269,9 +272,9 @@ impl StatementsTranspiler {
|
|||
});
|
||||
|
||||
let mut body_stmts = vec![bind];
|
||||
body_stmts.extend(self.expr_to_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]
|
||||
|
|
@ -291,7 +294,7 @@ impl StatementsTranspiler {
|
|||
// tmp_arr = { ... }
|
||||
let (arr_name, arr_decl) = self.fresh_tmp_var(
|
||||
"_arr",
|
||||
CType::Array(Box::new(elem_ty.clone()), arr_len),
|
||||
CType::Array(Box::new(elem_ty.clone())),
|
||||
Some(CExpr::ArrayLit(c_elems)),
|
||||
);
|
||||
|
||||
|
|
@ -317,13 +320,13 @@ impl StatementsTranspiler {
|
|||
)),
|
||||
});
|
||||
|
||||
let mut body_stmts = vec![bind];
|
||||
body_stmts.extend(self.expr_to_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()),
|
||||
|
|
@ -382,6 +385,35 @@ impl StatementsTranspiler {
|
|||
}
|
||||
}
|
||||
|
||||
/// Convert expression to statements for loop bodies (no implicit return)
|
||||
pub fn expr_to_loop_stmts(&mut self, expr: &TypedExpr) -> Result<Vec<CStmt>, String> {
|
||||
match &expr.kind {
|
||||
TypedExprKind::Do(stmts) => {
|
||||
let mut c_stmts = Vec::new();
|
||||
let mut defers = Vec::new();
|
||||
for stmt in stmts {
|
||||
match &stmt.kind {
|
||||
TypedExprKind::Defer(defer_expr) => {
|
||||
defers.push(self.transpile_stmt(defer_expr)?);
|
||||
}
|
||||
_ => {
|
||||
c_stmts.push(self.transpile_stmt(stmt)?);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Execute defers in reverse order at the end
|
||||
for defer_stmt in defers.into_iter().rev() {
|
||||
c_stmts.push(defer_stmt);
|
||||
}
|
||||
Ok(c_stmts)
|
||||
}
|
||||
_ => {
|
||||
// For non-Do expressions in loops, just transpile as statement
|
||||
Ok(vec![self.transpile_stmt(expr)?])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn binop_to_c_binop(&self, op: &BinOp) -> Result<CBinaryOp, String> {
|
||||
match op {
|
||||
BinOp::Add => Ok(CBinaryOp::Add),
|
||||
|
|
@ -418,9 +450,13 @@ impl StatementsTranspiler {
|
|||
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)?))),
|
||||
Type::Array(inner) => Ok(CType::Ptr(Box::new(self.type_to_ctype(inner)?))),
|
||||
Type::Struct(name, _) => Ok(CType::Struct(name.clone())),
|
||||
Type::Enum(name, _) => Ok(CType::Struct(name.clone())),
|
||||
Type::Array(inner) => {
|
||||
let inner_type = self.type_to_ctype(inner)?;
|
||||
// Arrays are pointers to the element type
|
||||
Ok(CType::Ptr(Box::new(inner_type)))
|
||||
}
|
||||
Type::Struct(name, _) => Ok(CType::Ptr(Box::new(CType::Struct(name.clone())))),
|
||||
Type::Enum(name, _) => Ok(CType::Ptr(Box::new(CType::Struct(name.clone())))),
|
||||
Type::Tuple(types) => {
|
||||
let mut fields = Vec::new();
|
||||
for (i, inner_ty) in types.iter().enumerate() {
|
||||
|
|
@ -462,7 +498,7 @@ impl StatementsTranspiler {
|
|||
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()))
|
||||
Ok(CType::Ptr(Box::new(CType::Struct(name.clone()))))
|
||||
}
|
||||
TypeAnnot::Ptr(inner) => {
|
||||
let inner_type = self.type_annot_to_ctype(inner)?;
|
||||
|
|
@ -470,6 +506,7 @@ impl StatementsTranspiler {
|
|||
}
|
||||
TypeAnnot::Array(inner) => {
|
||||
let inner_type = self.type_annot_to_ctype(inner)?;
|
||||
// Arrays are pointers to the element type
|
||||
Ok(CType::Ptr(Box::new(inner_type)))
|
||||
}
|
||||
TypeAnnot::Tuple(fields) => {
|
||||
|
|
|
|||
|
|
@ -2,24 +2,69 @@ use crate::ast::*;
|
|||
use crate::c_ir::*;
|
||||
use crate::c_lowerer::declaration_transpiler::DeclarationTranspiler;
|
||||
use crate::c_lowerer::statements_transpiler::StatementsTranspiler;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Extract variable name from a declaration like "int x = 10"
|
||||
fn extract_var_declaration(code: &str) -> Option<String> {
|
||||
// Pattern: type name = ...
|
||||
let parts: Vec<&str> = code.split('=').collect();
|
||||
if parts.len() >= 2 {
|
||||
let left = parts[0].trim();
|
||||
// Extract the variable name (last word before =)
|
||||
if let Some(var_name) = left.split_whitespace().last() {
|
||||
if !var_name.is_empty() {
|
||||
return Some(var_name.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Extract variable name from an assignment like "x = y + 1"
|
||||
fn extract_var_assignment(code: &str) -> Option<String> {
|
||||
// Pattern: name = ...
|
||||
let parts: Vec<&str> = code.split('=').collect();
|
||||
if parts.len() >= 2 {
|
||||
let left = parts[0].trim();
|
||||
// Check if it looks like a simple variable (no whitespace = simple type)
|
||||
if !left.contains(' ') && !left.contains('*') && !left.contains('[') {
|
||||
return Some(left.to_string());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub struct Transpiler {
|
||||
structs: HashMap<String, CStructDecl>,
|
||||
structs: Vec<CStructDecl>, // Changed from HashMap to preserve order
|
||||
functions: Vec<CFuncDecl>,
|
||||
globals: Vec<CVarDecl>,
|
||||
decl_transpiler: DeclarationTranspiler,
|
||||
stmt_transpiler: StatementsTranspiler,
|
||||
array_types: std::collections::HashSet<String>, // Track array types we need to generate
|
||||
has_main: bool, // Track if we found a main function
|
||||
}
|
||||
|
||||
impl Transpiler {
|
||||
pub fn new() -> Self {
|
||||
Transpiler {
|
||||
structs: HashMap::new(),
|
||||
structs: Vec::new(),
|
||||
functions: Vec::new(),
|
||||
globals: Vec::new(),
|
||||
decl_transpiler: DeclarationTranspiler::new(),
|
||||
stmt_transpiler: StatementsTranspiler::new(),
|
||||
array_types: std::collections::HashSet::new(),
|
||||
has_main: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn register_array_type(&mut self, elem_type: &CType) {
|
||||
self.array_types
|
||||
.insert(Self::get_array_struct_name(elem_type));
|
||||
}
|
||||
|
||||
fn collect_array_types_from_ctype(&mut self, ty: &CType) {
|
||||
match ty {
|
||||
CType::Ptr(inner) => self.collect_array_types_from_ctype(inner),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -30,17 +75,57 @@ impl Transpiler {
|
|||
|
||||
self.lower_function_bodies_to_c_ir(nodes)?;
|
||||
|
||||
// Rename main to suic_main and track that we have a main
|
||||
if let Some(main_func) = self.functions.iter_mut().find(|f| f.name == "main") {
|
||||
main_func.name = "suic_main".to_string();
|
||||
self.has_main = true;
|
||||
}
|
||||
|
||||
// Generate C code
|
||||
let mut output = String::new();
|
||||
|
||||
// Add includes
|
||||
output.push_str("#include \"../libsuicmez/libsuicmez.h\"\n");
|
||||
output.push_str("#include <stdio.h>\n");
|
||||
output.push_str("#include <stdlib.h>\n");
|
||||
output.push_str("#include <stdbool.h>\n");
|
||||
output.push_str("#include <string.h>\n");
|
||||
output.push_str("\n");
|
||||
|
||||
// GC functions
|
||||
output.push_str("void* gc_suic_alloc(size_t size);\n");
|
||||
output.push_str("void suic_gc_free(void* ptr);\n");
|
||||
output.push_str("\n");
|
||||
|
||||
// Helper functions for heap allocation
|
||||
output.push_str("// Helper for allocating arrays\n");
|
||||
output.push_str(
|
||||
"static void* suic_alloc_array(size_t elem_size, size_t len, void* init_data) {\n",
|
||||
);
|
||||
output.push_str(" void* ptr = gc_suic_alloc(elem_size * len);\n");
|
||||
output.push_str(" if (init_data) memcpy(ptr, init_data, elem_size * len);\n");
|
||||
output.push_str(" return ptr;\n");
|
||||
output.push_str("}\n");
|
||||
output.push_str("\n");
|
||||
|
||||
// Helper for allocating structs
|
||||
output.push_str("// Helper for allocating structs\n");
|
||||
output.push_str("static void* suic_alloc_struct(size_t size, void* init_data) {\n");
|
||||
output.push_str(" void* ptr = gc_suic_alloc(size);\n");
|
||||
output.push_str(" if (init_data) memcpy(ptr, init_data, size);\n");
|
||||
output.push_str(" return ptr;\n");
|
||||
output.push_str("}\n");
|
||||
output.push_str("\n");
|
||||
|
||||
// Generate array wrapper structs for all array types used
|
||||
for array_type_name in &self.array_types {
|
||||
output.push_str(&self.generate_array_struct(array_type_name));
|
||||
output.push_str(";\n");
|
||||
}
|
||||
output.push_str("\n");
|
||||
|
||||
// Generate struct declarations
|
||||
for struct_decl in self.structs.values() {
|
||||
for struct_decl in &self.structs {
|
||||
output.push_str(&self.generate_struct_decl(struct_decl));
|
||||
output.push_str(";\n");
|
||||
}
|
||||
|
|
@ -65,6 +150,12 @@ impl Transpiler {
|
|||
output.push_str("\n");
|
||||
}
|
||||
|
||||
// Generate wrapper main if we found a main function
|
||||
if self.has_main {
|
||||
output.push_str(&self.generate_wrapper_main());
|
||||
output.push_str("\n");
|
||||
}
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
|
|
@ -72,16 +163,28 @@ impl Transpiler {
|
|||
match &node.kind {
|
||||
TypedASTNodeKind::Struct(s) => {
|
||||
let struct_decl = self.decl_transpiler.transpile_struct(s)?;
|
||||
self.structs.insert(s.name.clone(), struct_decl);
|
||||
// Collect array types from struct fields
|
||||
for field in &struct_decl.fields {
|
||||
self.collect_array_types_from_ctype(&field.ty);
|
||||
}
|
||||
self.structs.push(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);
|
||||
for field in &struct_decl.fields {
|
||||
self.collect_array_types_from_ctype(&field.ty);
|
||||
}
|
||||
self.structs.push(struct_decl);
|
||||
}
|
||||
}
|
||||
TypedASTNodeKind::Function(f) => {
|
||||
let mut func_decl = self.decl_transpiler.transpile_function(f)?;
|
||||
// Collect array types from function signature
|
||||
self.collect_array_types_from_ctype(&func_decl.return_type);
|
||||
for param in &func_decl.params {
|
||||
self.collect_array_types_from_ctype(¶m.ty);
|
||||
}
|
||||
// Body will be filled later
|
||||
func_decl.body = Some(Vec::new());
|
||||
self.functions.push(func_decl);
|
||||
|
|
@ -89,6 +192,10 @@ impl Transpiler {
|
|||
TypedASTNodeKind::Impl(imp) => {
|
||||
for method in &imp.methods {
|
||||
let mut func_decl = self.decl_transpiler.transpile_function(method)?;
|
||||
self.collect_array_types_from_ctype(&func_decl.return_type);
|
||||
for param in &func_decl.params {
|
||||
self.collect_array_types_from_ctype(¶m.ty);
|
||||
}
|
||||
func_decl.name = format!("{}_{}", imp.target, method.name);
|
||||
func_decl.body = Some(Vec::new());
|
||||
self.functions.push(func_decl);
|
||||
|
|
@ -133,6 +240,22 @@ impl Transpiler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_array_struct(&self, array_type_name: &str) -> String {
|
||||
let mut output = format!("struct {} {{\n", array_type_name);
|
||||
output.push_str(" void* data;\n");
|
||||
output.push_str(" size_t len;\n");
|
||||
output.push_str(" size_t capacity;\n");
|
||||
output.push_str("}");
|
||||
output
|
||||
}
|
||||
|
||||
fn get_array_struct_name(elem_type: &CType) -> String {
|
||||
format!(
|
||||
"sui_array_{}",
|
||||
elem_type.to_string().replace(" ", "_").replace("*", "ptr")
|
||||
)
|
||||
}
|
||||
|
||||
fn generate_struct_decl(&self, struct_decl: &CStructDecl) -> String {
|
||||
let mut output = format!("struct {} {{\n", struct_decl.name);
|
||||
for field in &struct_decl.fields {
|
||||
|
|
@ -174,6 +297,19 @@ impl Transpiler {
|
|||
output
|
||||
}
|
||||
|
||||
fn generate_wrapper_main(&self) -> String {
|
||||
let mut output = String::new();
|
||||
output.push_str("int main(int argc, char* argv[]) {\n");
|
||||
output.push_str(" // init gc and stuff\n");
|
||||
output.push_str(" // init globals\n");
|
||||
output.push_str(" // init event loop\n");
|
||||
output.push_str(" int result = suic_main();\n");
|
||||
output.push_str(" // free the stuff\n");
|
||||
output.push_str(" return result;\n");
|
||||
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 {
|
||||
|
|
@ -182,8 +318,67 @@ impl Transpiler {
|
|||
output
|
||||
}
|
||||
|
||||
fn generate_heap_alloc(&self, ty: &CType) -> String {
|
||||
match ty {
|
||||
CType::Struct(name) => {
|
||||
format!("(struct {}*)suic_gc_alloc(sizeof(struct {}))", name, name)
|
||||
}
|
||||
CType::Array(elem_type) => {
|
||||
format!(
|
||||
"(struct {}*)suic_gc_alloc(sizeof(struct {}))",
|
||||
Self::get_array_struct_name(elem_type),
|
||||
Self::get_array_struct_name(elem_type)
|
||||
)
|
||||
}
|
||||
_ => "NULL".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_debug_print(&self, code: &str) -> String {
|
||||
// Extract the actual statement for the debug message
|
||||
let trimmed = code.trim_end_matches('\n').trim_start();
|
||||
let trimmed_no_semi = trimmed.trim_end_matches(';');
|
||||
|
||||
if trimmed_no_semi.is_empty() {
|
||||
return code.to_string();
|
||||
}
|
||||
|
||||
let mut result = code.trim_end_matches('\n').to_string();
|
||||
result.push('\n');
|
||||
|
||||
// Escape quotes in the output
|
||||
let escaped_code = trimmed_no_semi.replace("\"", "\\\"");
|
||||
|
||||
// Try to extract variable name and format for printing
|
||||
if let Some(var_name) = extract_var_declaration(trimmed_no_semi) {
|
||||
// For declarations, determine the format specifier
|
||||
let format_spec = if trimmed_no_semi.contains("char*") {
|
||||
"%s"
|
||||
} else if trimmed_no_semi.contains("float") {
|
||||
"%f"
|
||||
} else if trimmed_no_semi.contains("*") {
|
||||
"%p" // pointer
|
||||
} else {
|
||||
"%d"
|
||||
};
|
||||
result.push_str(&format!(
|
||||
" printf(\"| {} | \\n {}\\n\", {});\n",
|
||||
escaped_code, format_spec, var_name
|
||||
));
|
||||
} else if let Some(var_name) = extract_var_assignment(trimmed_no_semi) {
|
||||
result.push_str(&format!(
|
||||
" printf(\"| {} | \\n %d\\n\", {});\n",
|
||||
escaped_code, var_name
|
||||
));
|
||||
} else {
|
||||
result.push_str(&format!(" printf(\"| {} |\\n\");\n", escaped_code));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn generate_stmt(&self, stmt: &CStmt) -> String {
|
||||
match stmt {
|
||||
let code = 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!(
|
||||
|
|
@ -241,6 +436,13 @@ impl Transpiler {
|
|||
}
|
||||
CStmt::Break => "break;\n".to_string(),
|
||||
CStmt::Continue => "continue;\n".to_string(),
|
||||
};
|
||||
|
||||
// Add debug print for simple statements only (not control flow)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -249,7 +451,13 @@ impl Transpiler {
|
|||
CExpr::IntLit(i) => format!("{}", i),
|
||||
CExpr::FloatLit(f) => format!("{:.6}", f),
|
||||
CExpr::BoolLit(b) => format!("{}", b),
|
||||
CExpr::StringLit(s) => format!("\"{}\"", s),
|
||||
CExpr::StringLit(s) => {
|
||||
format!(
|
||||
"suic_alloc_array(sizeof(char), {}, \"{}\")",
|
||||
s.len() + 1, // +1 for null terminator
|
||||
s
|
||||
)
|
||||
}
|
||||
CExpr::Var(name) => name.clone(),
|
||||
CExpr::Call(func, args) => {
|
||||
let args_str = args
|
||||
|
|
@ -257,7 +465,51 @@ impl Transpiler {
|
|||
.map(|arg| self.generate_expr(arg))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
format!("{}({})", func, args_str)
|
||||
|
||||
// Map Sui function names to C function names for built-ins
|
||||
let c_func_name = match func.as_str() {
|
||||
"ode_init" => "suic_ode_init",
|
||||
"ode_close" => "suic_ode_close",
|
||||
"ode_world_create" => "suic_ode_world_create",
|
||||
"ode_world_destroy" => "suic_ode_world_destroy",
|
||||
"ode_world_set_gravity" => "suic_ode_world_set_gravity",
|
||||
"ode_world_step" => "suic_ode_world_step",
|
||||
"ode_body_create" => "suic_ode_body_create",
|
||||
"ode_body_destroy" => "suic_ode_body_destroy",
|
||||
"ode_body_set_position" => "suic_ode_body_set_position",
|
||||
"ode_body_set_linear_vel" => "suic_ode_body_set_linear_vel",
|
||||
"ode_body_set_box_mass" => "suic_ode_body_set_box_mass",
|
||||
"ode_create_box_geom" => "suic_ode_create_box_geom",
|
||||
"ode_geom_set_body" => "suic_ode_geom_set_body",
|
||||
"ode_geom_destroy" => "suic_ode_geom_destroy",
|
||||
"ode_simple_space_create" => "suic_ode_simple_space_create",
|
||||
"ode_space_destroy" => "suic_ode_space_destroy",
|
||||
"ode_create_plane_geom" => "suic_ode_create_plane_geom",
|
||||
"ode_body_get_position" => "suic_ode_body_get_position",
|
||||
"ode_space_collide" => "suic_ode_space_collide",
|
||||
"ode_joint_group_create" => "suic_ode_joint_group_create",
|
||||
"ode_joint_group_destroy" => "suic_ode_joint_group_destroy",
|
||||
"ode_joint_group_empty" => "suic_ode_joint_group_empty",
|
||||
"ode_body_get_linear_vel" => "suic_ode_body_get_linear_vel",
|
||||
"ode_body_get_rotation" => "suic_ode_body_get_rotation",
|
||||
"ode_body_set_rotation" => "suic_ode_body_set_rotation",
|
||||
// Raylib functions
|
||||
"init_window" => "suic_init_window",
|
||||
"close_window" => "suic_close_window",
|
||||
"window_should_close" => "suic_window_should_close",
|
||||
"set_target_fps" => "suic_set_target_fps",
|
||||
"begin_drawing" => "suic_begin_drawing",
|
||||
"end_drawing" => "suic_end_drawing",
|
||||
"clear_background" => "suic_clear_background",
|
||||
"begin_mode3d" => "suic_begin_mode3d",
|
||||
"end_mode3d" => "suic_end_mode3d",
|
||||
"draw_cube" => "suic_draw_cube",
|
||||
"draw_cube_wires" => "suic_draw_cube_wires",
|
||||
"is_key_down" => "suic_is_key_down",
|
||||
_ => func,
|
||||
};
|
||||
|
||||
format!("{}({})", c_func_name, args_str)
|
||||
}
|
||||
CExpr::BinOp(lhs, op, rhs) => {
|
||||
format!(
|
||||
|
|
@ -275,7 +527,7 @@ impl Transpiler {
|
|||
}
|
||||
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::Dot(expr, field) => format!("(*{}).{}", self.generate_expr(expr), field),
|
||||
CExpr::Index(array, index) => format!(
|
||||
"{}[{}]",
|
||||
self.generate_expr(array),
|
||||
|
|
@ -286,7 +538,12 @@ impl Transpiler {
|
|||
.iter()
|
||||
.map(|(name, expr)| format!(".{} = {}", name, self.generate_expr(expr)))
|
||||
.collect();
|
||||
format!("(struct {}){{ {} }}", struct_name, field_inits.join(", "))
|
||||
format!(
|
||||
"suic_alloc_struct(sizeof(struct {}), &(struct {}){{ {} }})",
|
||||
struct_name,
|
||||
struct_name,
|
||||
field_inits.join(", ")
|
||||
)
|
||||
}
|
||||
CExpr::EnumLit(enum_name, variant_name, args) => {
|
||||
// Find the variant index - for simplicity, assume variants are in order
|
||||
|
|
@ -297,7 +554,7 @@ impl Transpiler {
|
|||
let union_field_name = variant_name.to_lowercase();
|
||||
|
||||
let struct_init = if args.is_empty() {
|
||||
"{}".to_string()
|
||||
"".to_string()
|
||||
} else {
|
||||
let field_inits: Vec<String> = args
|
||||
.iter()
|
||||
|
|
@ -307,19 +564,48 @@ impl Transpiler {
|
|||
format!("{{ {} }}", field_inits.join(", "))
|
||||
};
|
||||
|
||||
let variant_init = if struct_init.is_empty() {
|
||||
format!("(struct {}){{}}", variant_struct_name)
|
||||
} else {
|
||||
format!("(struct {}){}", variant_struct_name, struct_init)
|
||||
};
|
||||
|
||||
format!(
|
||||
"({}){{ .discriminant = {}, .data = {{ .{} = ({}{}) }} }}",
|
||||
enum_name, variant_index, union_field_name, variant_struct_name, struct_init
|
||||
"suic_alloc_struct(sizeof(struct {}), &(struct {}){{ .discriminant = {}, .data = {{ .{} = {} }} }})",
|
||||
enum_name, enum_name, variant_index, union_field_name, variant_init
|
||||
)
|
||||
}
|
||||
|
||||
CExpr::ArrayLit(array_lit) => {
|
||||
let vec = array_lit
|
||||
.iter()
|
||||
.map(|expr| self.generate_expr(expr))
|
||||
.collect::<Vec<_>>();
|
||||
let len = vec.len();
|
||||
format!("{}[{}]{{ {} }}", vec[0], len, vec.join(", "))
|
||||
if array_lit.is_empty() {
|
||||
"NULL".to_string()
|
||||
} else {
|
||||
let vec: Vec<String> = array_lit
|
||||
.iter()
|
||||
.map(|expr| self.generate_expr(expr))
|
||||
.collect();
|
||||
// Generate heap-allocated array using helper function
|
||||
format!(
|
||||
"suic_alloc_array(sizeof(int), {}, (int[]){{{}}})",
|
||||
vec.len(),
|
||||
vec.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
CExpr::Assign(lhs, rhs) => {
|
||||
format!(
|
||||
"({} = {})",
|
||||
self.generate_expr(lhs),
|
||||
self.generate_expr(rhs)
|
||||
)
|
||||
}
|
||||
CExpr::Ternary(cond, then_expr, else_expr) => {
|
||||
format!(
|
||||
"({} ? {} : {})",
|
||||
self.generate_expr(cond),
|
||||
self.generate_expr(then_expr),
|
||||
self.generate_expr(else_expr)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -366,7 +366,12 @@ impl Monomorphizer {
|
|||
if !field_types.is_empty() {
|
||||
self.infer_struct_specialization(name, &field_types, &mut needs);
|
||||
}
|
||||
TypedExprKind::StructLit(name.clone(), new_fields)
|
||||
let new_kind = TypedExprKind::StructLit(name.clone(), new_fields);
|
||||
let mut temp_expr = expr.clone();
|
||||
temp_expr.kind = new_kind.clone();
|
||||
// Collect specialization needs from the struct literal's type
|
||||
self.collect_needs_from_expr_type(&temp_expr, &mut needs);
|
||||
new_kind
|
||||
}
|
||||
|
||||
TypedExprKind::EnumLit(enum_name, variant, args) => {
|
||||
|
|
|
|||
|
|
@ -351,6 +351,9 @@ impl TypeChecker {
|
|||
self.collect_definitions(node)?;
|
||||
}
|
||||
|
||||
// Add built-in functions
|
||||
self.add_builtin_functions();
|
||||
|
||||
// Second pass: typecheck everything
|
||||
self.env.enter_scope();
|
||||
let mut typed_nodes = Vec::new();
|
||||
|
|
@ -362,6 +365,218 @@ impl TypeChecker {
|
|||
Ok(typed_nodes)
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
||||
// Input
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
fn collect_definitions(&mut self, node: &ASTNode) -> Result<(), TypeError> {
|
||||
match &node.kind {
|
||||
ASTNodeKind::Struct(s) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue