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