Compare commits
7 commits
6d34fe05fe
...
2d4bbaa174
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d4bbaa174 | |||
| 554db13c08 | |||
| 12fee4b213 | |||
| 21e37cd4f2 | |||
| bc1e2a2b21 | |||
| d45531ce44 | |||
| d247aa46eb |
8 changed files with 231 additions and 75 deletions
|
|
@ -273,6 +273,7 @@ pub enum UnOp {
|
||||||
Not,
|
Not,
|
||||||
Ref,
|
Ref,
|
||||||
Deref,
|
Deref,
|
||||||
|
PreInc
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ pub enum CUnaryOp {
|
||||||
Not,
|
Not,
|
||||||
Ref,
|
Ref,
|
||||||
Deref,
|
Deref,
|
||||||
|
PreInc
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CUnaryOp {
|
impl CUnaryOp {
|
||||||
|
|
@ -131,6 +132,7 @@ impl CUnaryOp {
|
||||||
CUnaryOp::Not => "!",
|
CUnaryOp::Not => "!",
|
||||||
CUnaryOp::Ref => "&",
|
CUnaryOp::Ref => "&",
|
||||||
CUnaryOp::Deref => "*",
|
CUnaryOp::Deref => "*",
|
||||||
|
CUnaryOp::PreInc => "++"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ impl DeclarationTranspiler {
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
|
|
||||||
for field in &struct_.fields {
|
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 {
|
fields.push(CVarDecl {
|
||||||
name: field.name.clone(),
|
name: field.name.clone(),
|
||||||
ty: field_type,
|
ty: field_type,
|
||||||
|
|
@ -34,14 +34,14 @@ impl DeclarationTranspiler {
|
||||||
|
|
||||||
pub fn transpile_function(&self, func: &TypedFunction) -> Result<CFuncDecl, String> {
|
pub fn transpile_function(&self, func: &TypedFunction) -> Result<CFuncDecl, String> {
|
||||||
let return_type = match &func.return_type {
|
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,
|
None => CType::Void,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
for (_binding_id, name, type_annot) in &func.args {
|
for (_binding_id, name, type_annot) in &func.args {
|
||||||
let param_type = match type_annot {
|
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 => {
|
None => {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Function parameter {} missing type annotation",
|
"Function parameter {} missing type annotation",
|
||||||
|
|
@ -69,14 +69,14 @@ impl DeclarationTranspiler {
|
||||||
let mut structs = Vec::new();
|
let mut structs = Vec::new();
|
||||||
|
|
||||||
// For each variant, create a struct
|
// 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 struct_name = format!("{}_{}", enum_.name, variant.name);
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
|
|
||||||
// Add variant fields (no discriminant in variant struct)
|
// Add variant fields (no discriminant in variant struct)
|
||||||
for (j, field_type) in variant.fields.iter().enumerate() {
|
for (j, field_type) in variant.fields.iter().enumerate() {
|
||||||
let field_name = format!("field_{}", j);
|
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 {
|
fields.push(CVarDecl {
|
||||||
name: field_name,
|
name: field_name,
|
||||||
ty: c_type,
|
ty: c_type,
|
||||||
|
|
@ -131,38 +131,26 @@ impl DeclarationTranspiler {
|
||||||
Ok(structs)
|
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 {
|
match annot {
|
||||||
Some(TypeAnnot::Var(name)) => match name.as_str() {
|
Some(TypeAnnot::Var(name)) => convert_to_c_type(name),
|
||||||
"int" => Ok(CType::Int),
|
Some(TypeAnnot::Cons(name, args)) if args.is_empty() => convert_to_c_type(name),
|
||||||
"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)) => {
|
Some(TypeAnnot::Cons(name, _args)) => {
|
||||||
// Generic types - for now just use the base name
|
// Generic types - for now just use the base name
|
||||||
Ok(CType::Struct(name.clone()))
|
Ok(CType::Struct(name.clone()))
|
||||||
}
|
}
|
||||||
Some(TypeAnnot::Ptr(inner)) => {
|
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)))
|
Ok(CType::Ptr(Box::new(inner_type)))
|
||||||
}
|
}
|
||||||
Some(TypeAnnot::Array(inner)) => {
|
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)))
|
Ok(CType::Ptr(Box::new(inner_type)))
|
||||||
}
|
}
|
||||||
Some(TypeAnnot::Tuple(fields)) => {
|
Some(TypeAnnot::Tuple(fields)) => {
|
||||||
let mut c_fields = Vec::new();
|
let mut c_fields = Vec::new();
|
||||||
for (i, field_annot) in fields.iter().enumerate() {
|
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 {
|
c_fields.push(CVarDecl {
|
||||||
name: format!("field{}", i),
|
name: format!("field{}", i),
|
||||||
ty: field_type,
|
ty: field_type,
|
||||||
|
|
@ -174,12 +162,22 @@ impl DeclarationTranspiler {
|
||||||
Some(TypeAnnot::Function(args, ret)) => {
|
Some(TypeAnnot::Function(args, ret)) => {
|
||||||
let mut c_args = Vec::new();
|
let mut c_args = Vec::new();
|
||||||
for arg in args {
|
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::Func(c_args, Box::new(c_ret)))
|
||||||
}
|
}
|
||||||
_ => Ok(CType::Void), // Default
|
_ => 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::ast::*;
|
||||||
use crate::c_ir::*;
|
use crate::c_ir::*;
|
||||||
|
use crate::c_lowerer::declaration_transpiler::convert_to_c_type;
|
||||||
use crate::typechecker::Type;
|
use crate::typechecker::Type;
|
||||||
|
|
||||||
pub struct StatementsTranspiler;
|
pub struct StatementsTranspiler {
|
||||||
|
tmp_counter: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl StatementsTranspiler {
|
impl StatementsTranspiler {
|
||||||
pub fn new() -> Self {
|
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> {
|
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 {
|
match &expr.kind {
|
||||||
TypedExprKind::Let(_binding_id, name, _kind, _type_annot, init_expr) => {
|
TypedExprKind::Let(_binding_id, name, _kind, _type_annot, init_expr) => {
|
||||||
let c_type = self.type_to_ctype(&expr.ty)?;
|
let c_type = self.type_to_ctype(&expr.ty)?;
|
||||||
|
|
@ -157,36 +193,141 @@ impl StatementsTranspiler {
|
||||||
Ok(CStmt::Block(stmts))
|
Ok(CStmt::Block(stmts))
|
||||||
}
|
}
|
||||||
TypedExprKind::For(_binding_id, var_name, iterable, body) => {
|
TypedExprKind::For(_binding_id, var_name, iterable, body) => {
|
||||||
// Simplified for loop handling
|
|
||||||
// For now, assume range iteration
|
|
||||||
match &iterable.kind {
|
match &iterable.kind {
|
||||||
|
// for i in start..end
|
||||||
TypedExprKind::Range(start, end) => {
|
TypedExprKind::Range(start, end) => {
|
||||||
let start_expr = self.transpile_expr(start)?;
|
let start_expr = self.transpile_expr(start)?;
|
||||||
let end_expr = self.transpile_expr(end)?;
|
let end_expr = self.transpile_expr(end)?;
|
||||||
// Create a simple for loop: for(int i = start; i < end; i++)
|
|
||||||
let init = CVarDecl {
|
let init = CVarDecl {
|
||||||
name: var_name.clone(),
|
name: var_name.clone(),
|
||||||
ty: CType::Int,
|
ty: CType::Int,
|
||||||
initializer: Some(start_expr),
|
initializer: Some(start_expr),
|
||||||
};
|
};
|
||||||
|
|
||||||
let cond = CExpr::BinOp(
|
let cond = CExpr::BinOp(
|
||||||
Box::new(CExpr::Var(var_name.clone())),
|
Box::new(CExpr::Var(var_name.clone())),
|
||||||
CBinaryOp::Lt,
|
CBinaryOp::Lt,
|
||||||
Box::new(end_expr),
|
Box::new(end_expr),
|
||||||
);
|
);
|
||||||
let incr = CExpr::UnOp(CUnaryOp::Neg, Box::new(CExpr::IntLit(-1))); // i++
|
|
||||||
let incr_stmt = CStmt::Assign(
|
let incr = CExpr::UnOp(
|
||||||
CExpr::Var(var_name.clone()),
|
CUnaryOp::PreInc,
|
||||||
CExpr::BinOp(
|
|
||||||
Box::new(CExpr::Var(var_name.clone())),
|
Box::new(CExpr::Var(var_name.clone())),
|
||||||
CBinaryOp::Add,
|
|
||||||
Box::new(CExpr::IntLit(1)),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let body_stmts = self.expr_to_stmts(body)?;
|
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),
|
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 {
|
match &expr.kind {
|
||||||
TypedExprKind::Do(stmts) => {
|
TypedExprKind::Do(stmts) => {
|
||||||
let mut c_stmts = Vec::new();
|
let mut c_stmts = Vec::new();
|
||||||
|
|
@ -250,25 +391,26 @@ impl StatementsTranspiler {
|
||||||
UnOp::Not => Ok(CUnaryOp::Not),
|
UnOp::Not => Ok(CUnaryOp::Not),
|
||||||
UnOp::Ref => Ok(CUnaryOp::Ref),
|
UnOp::Ref => Ok(CUnaryOp::Ref),
|
||||||
UnOp::Deref => Ok(CUnaryOp::Deref),
|
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 {
|
match ty {
|
||||||
crate::typechecker::Type::Int => Ok(CType::Int),
|
Type::Int => Ok(CType::Int),
|
||||||
crate::typechecker::Type::Float => Ok(CType::Float),
|
Type::Float => Ok(CType::Float),
|
||||||
crate::typechecker::Type::Bool => Ok(CType::Bool),
|
Type::Bool => Ok(CType::Bool),
|
||||||
crate::typechecker::Type::String => Ok(CType::Ptr(Box::new(CType::Char))),
|
Type::String => Ok(CType::Ptr(Box::new(CType::Char))),
|
||||||
crate::typechecker::Type::Unit => Ok(CType::Void),
|
Type::Unit => Ok(CType::Void),
|
||||||
crate::typechecker::Type::Ptr(inner) => {
|
Type::Ptr(inner) => {
|
||||||
Ok(CType::Ptr(Box::new(self.type_to_ctype(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)?)))
|
Ok(CType::Ptr(Box::new(self.type_to_ctype(inner)?)))
|
||||||
}
|
}
|
||||||
crate::typechecker::Type::Struct(name, _) => Ok(CType::Struct(name.clone())),
|
Type::Struct(name, _) => Ok(CType::Struct(name.clone())),
|
||||||
crate::typechecker::Type::Enum(name, _) => Ok(CType::Struct(name.clone())),
|
Type::Enum(name, _) => Ok(CType::Struct(name.clone())),
|
||||||
crate::typechecker::Type::Tuple(types) => {
|
Type::Tuple(types) => {
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
for (i, inner_ty) in types.iter().enumerate() {
|
for (i, inner_ty) in types.iter().enumerate() {
|
||||||
let c_type = self.type_to_ctype(inner_ty)?;
|
let c_type = self.type_to_ctype(inner_ty)?;
|
||||||
|
|
@ -280,7 +422,7 @@ impl StatementsTranspiler {
|
||||||
}
|
}
|
||||||
Ok(CType::UnnamedStruct(fields))
|
Ok(CType::UnnamedStruct(fields))
|
||||||
}
|
}
|
||||||
crate::typechecker::Type::Function(args, ret) => {
|
Type::Function(args, ret) => {
|
||||||
let mut c_args = Vec::new();
|
let mut c_args = Vec::new();
|
||||||
for arg in args {
|
for arg in args {
|
||||||
c_args.push(self.type_to_ctype(arg)?);
|
c_args.push(self.type_to_ctype(arg)?);
|
||||||
|
|
@ -288,37 +430,25 @@ impl StatementsTranspiler {
|
||||||
let c_ret = self.type_to_ctype(ret)?;
|
let c_ret = self.type_to_ctype(ret)?;
|
||||||
Ok(CType::Func(c_args, Box::new(c_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,
|
// Generic types should have been monomorphized away,
|
||||||
// but if they remain, treat them as struct types
|
// but if they remain, treat them as struct types
|
||||||
// For now, just use the base name
|
// For now, just use the base name
|
||||||
Ok(CType::Struct(name.clone()))
|
Ok(CType::Struct(name.clone()))
|
||||||
}
|
}
|
||||||
crate::typechecker::Type::TypeVar(name) => {
|
Type::TypeVar(name) => {
|
||||||
// Type variables should have been resolved during monomorphization
|
// Type variables should have been resolved during monomorphization
|
||||||
Err(format!("Unresolved type variable: {}", name))
|
Err(format!("Unresolved type variable: {}", name))
|
||||||
}
|
}
|
||||||
crate::typechecker::Type::Never => Ok(CType::Void),
|
Type::Never => Ok(CType::Void),
|
||||||
crate::typechecker::Type::Unknown => Err("Unknown type".to_string()),
|
Type::Unknown => Err("Unknown type".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_annot_to_ctype(&self, annot: &TypeAnnot) -> Result<CType, String> {
|
fn type_annot_to_ctype(&self, annot: &TypeAnnot) -> Result<CType, String> {
|
||||||
match annot {
|
match annot {
|
||||||
TypeAnnot::Var(name) => match name.as_str() {
|
TypeAnnot::Var(name) => convert_to_c_type(name),
|
||||||
"int" => Ok(CType::Int),
|
TypeAnnot::Cons(name, args) if args.is_empty() => convert_to_c_type(name),
|
||||||
"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) => {
|
TypeAnnot::Cons(name, _args) => {
|
||||||
// Generic types - for now just use the base name
|
// Generic types - for now just use the base name
|
||||||
Ok(CType::Struct(name.clone()))
|
Ok(CType::Struct(name.clone()))
|
||||||
|
|
@ -351,7 +481,7 @@ impl StatementsTranspiler {
|
||||||
let c_ret = self.type_annot_to_ctype(ret)?;
|
let c_ret = self.type_annot_to_ctype(ret)?;
|
||||||
Ok(CType::Func(c_args, Box::new(c_ret)))
|
Ok(CType::Func(c_args, Box::new(c_ret)))
|
||||||
}
|
}
|
||||||
_ => Err(format!("Unsupported type annotation: {:?}", annot)),
|
//_ => Err(format!("Unsupported type annotation: {:?}", annot)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ impl Transpiler {
|
||||||
// But for now, skip as they're handled differently
|
// But for now, skip as they're handled differently
|
||||||
}
|
}
|
||||||
TypedASTNodeKind::Load(_) => {}
|
TypedASTNodeKind::Load(_) => {}
|
||||||
TypedASTNodeKind::Trait(_) => {}
|
TypedASTNodeKind::Trait(typed_trait ) => {}
|
||||||
TypedASTNodeKind::Use(_) => {}
|
TypedASTNodeKind::Use(_) => {}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -227,7 +227,7 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
CStmt::For(init, cond, incr, body) => {
|
CStmt::For(init, cond, incr, body) => {
|
||||||
let mut output = format!("for ({}, {}, {}) {{", self.generate_var_decl(init), self.generate_expr(cond), self.generate_expr(incr));
|
let mut output = format!("for ({}; {}; {}) {{", self.generate_var_decl(init), self.generate_expr(cond), self.generate_expr(incr));
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
output.push_str(&format!(" {}", self.generate_stmt(stmt)));
|
output.push_str(&format!(" {}", self.generate_stmt(stmt)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -288,4 +288,7 @@ pub enum Token {
|
||||||
|
|
||||||
#[token("%=")]
|
#[token("%=")]
|
||||||
ModAssign,
|
ModAssign,
|
||||||
|
|
||||||
|
#[token("++")]
|
||||||
|
PlusPlus,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1273,6 +1273,16 @@ impl Parser {
|
||||||
attributes: Vec::new(),
|
attributes: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Some(Token::PlusPlus) => {
|
||||||
|
self.next();
|
||||||
|
let expr = self.parse_unary_expr()?;
|
||||||
|
let end = expr.span.end;
|
||||||
|
Ok(Expr {
|
||||||
|
kind: ExprKind::UnOp(UnOp::PreInc, Box::new(expr)),
|
||||||
|
span: Span::new(&(start..end), self.file.clone()),
|
||||||
|
attributes: Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
_ => self.parse_postfix_expr(),
|
_ => self.parse_postfix_expr(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -832,6 +832,18 @@ impl TypeChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UnOp::PreInc => {
|
||||||
|
if !matches!(typed_inner.ty, Type::Int | Type::Float) {
|
||||||
|
return Err(TypeError {
|
||||||
|
kind: TypeErrorKind::TypeMismatch(
|
||||||
|
Type::Int,
|
||||||
|
typed_inner.ty.clone(),
|
||||||
|
),
|
||||||
|
span: inner.span.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
typed_inner.ty.clone()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
TypedExprKind::UnOp(op.clone(), Box::new(typed_inner)),
|
TypedExprKind::UnOp(op.clone(), Box::new(typed_inner)),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue