This commit is contained in:
Masashi 2025-12-16 17:54:16 +05:30
commit 00f39ac9ca
13 changed files with 111 additions and 68 deletions

View file

@ -240,6 +240,7 @@ pub enum ExprKind {
Return(Option<Box<Expr>>), Return(Option<Box<Expr>>),
Break, Break,
Continue, Continue,
Defer(Box<Expr>),
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -273,7 +274,7 @@ pub enum UnOp {
Not, Not,
Ref, Ref,
Deref, Deref,
PreInc PreInc,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -429,6 +430,7 @@ pub enum TypedExprKind {
Return(Option<Box<TypedExpr>>), Return(Option<Box<TypedExpr>>),
Break, Break,
Continue, Continue,
Defer(Box<TypedExpr>),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -122,7 +122,7 @@ pub enum CUnaryOp {
Not, Not,
Ref, Ref,
Deref, Deref,
PreInc PreInc,
} }
impl CUnaryOp { impl CUnaryOp {
@ -132,7 +132,7 @@ impl CUnaryOp {
CUnaryOp::Not => "!", CUnaryOp::Not => "!",
CUnaryOp::Ref => "&", CUnaryOp::Ref => "&",
CUnaryOp::Deref => "*", CUnaryOp::Deref => "*",
CUnaryOp::PreInc => "++" CUnaryOp::PreInc => "++",
} }
} }
} }

View file

@ -187,8 +187,20 @@ impl StatementsTranspiler {
} }
TypedExprKind::Do(exprs) => { TypedExprKind::Do(exprs) => {
let mut stmts = Vec::new(); let mut stmts = Vec::new();
let mut defers = Vec::new();
for expr in exprs { for expr in exprs {
stmts.push(self.transpile_stmt(expr)?); match &expr.kind {
TypedExprKind::Defer(defer_expr) => {
defers.push(self.transpile_stmt(defer_expr)?);
}
_ => {
stmts.push(self.transpile_stmt(expr)?);
}
}
}
// Execute defers in reverse order at the end
for defer_stmt in defers.into_iter().rev() {
stmts.push(defer_stmt);
} }
Ok(CStmt::Block(stmts)) Ok(CStmt::Block(stmts))
} }
@ -211,10 +223,8 @@ impl StatementsTranspiler {
Box::new(end_expr), Box::new(end_expr),
); );
let incr = CExpr::UnOp( let incr =
CUnaryOp::PreInc, CExpr::UnOp(CUnaryOp::PreInc, Box::new(CExpr::Var(var_name.clone())));
Box::new(CExpr::Var(var_name.clone())),
);
let body_stmts = self.expr_to_stmts(body)?; let body_stmts = self.expr_to_stmts(body)?;
Ok(CStmt::For(init, cond, incr, body_stmts)) Ok(CStmt::For(init, cond, incr, body_stmts))
@ -224,32 +234,26 @@ impl StatementsTranspiler {
TypedExprKind::Variable(var) => { TypedExprKind::Variable(var) => {
let elem_ty = match &iterable.ty { let elem_ty = match &iterable.ty {
Type::Array(inner) => self.type_to_ctype(inner)?, Type::Array(inner) => self.type_to_ctype(inner)?,
_ => return Err(format!( _ => {
"Cannot iterate over non-array variable `{}`", return Err(format!(
var "Cannot iterate over non-array variable `{}`",
)), var
));
}
}; };
// i = 0 // i = 0
let (idx_name, idx_decl) = self.fresh_tmp_var( let (idx_name, idx_decl) =
"_i", self.fresh_tmp_var("_i", CType::Int, Some(CExpr::IntLit(0)));
CType::Int,
Some(CExpr::IntLit(0)),
);
let cond = CExpr::BinOp( let cond = CExpr::BinOp(
Box::new(CExpr::Var(idx_name.clone())), Box::new(CExpr::Var(idx_name.clone())),
CBinaryOp::Lt, CBinaryOp::Lt,
Box::new(CExpr::Dot( Box::new(CExpr::Dot(Box::new(CExpr::Var(var.clone())), "len".into())),
Box::new(CExpr::Var(var.clone())),
"len".into(),
)),
); );
let incr = CExpr::UnOp( let incr =
CUnaryOp::PreInc, CExpr::UnOp(CUnaryOp::PreInc, Box::new(CExpr::Var(idx_name.clone())));
Box::new(CExpr::Var(idx_name.clone())),
);
// let x = array.data[i] // let x = array.data[i]
let bind = CStmt::VarDecl(CVarDecl { let bind = CStmt::VarDecl(CVarDecl {
@ -292,11 +296,8 @@ impl StatementsTranspiler {
); );
// i = 0 // i = 0
let (idx_name, idx_decl) = self.fresh_tmp_var( let (idx_name, idx_decl) =
"_i", self.fresh_tmp_var("_i", CType::Int, Some(CExpr::IntLit(0)));
CType::Int,
Some(CExpr::IntLit(0)),
);
let cond = CExpr::BinOp( let cond = CExpr::BinOp(
Box::new(CExpr::Var(idx_name.clone())), Box::new(CExpr::Var(idx_name.clone())),
@ -304,10 +305,8 @@ impl StatementsTranspiler {
Box::new(CExpr::IntLit(arr_len as i64)), Box::new(CExpr::IntLit(arr_len as i64)),
); );
let incr = CExpr::UnOp( let incr =
CUnaryOp::PreInc, CExpr::UnOp(CUnaryOp::PreInc, Box::new(CExpr::Var(idx_name.clone())));
Box::new(CExpr::Var(idx_name.clone())),
);
let bind = CStmt::VarDecl(CVarDecl { let bind = CStmt::VarDecl(CVarDecl {
name: var_name.clone(), name: var_name.clone(),
@ -332,6 +331,7 @@ impl StatementsTranspiler {
} }
TypedExprKind::Break => Ok(CStmt::Break), TypedExprKind::Break => Ok(CStmt::Break),
TypedExprKind::Continue => Ok(CStmt::Continue), TypedExprKind::Continue => Ok(CStmt::Continue),
TypedExprKind::Defer(_) => Err("Defer should be handled in Do blocks".to_string()),
_ => { _ => {
// For other expressions, treat as expression statements // For other expressions, treat as expression statements
let c_expr = self.transpile_expr(expr)?; let c_expr = self.transpile_expr(expr)?;
@ -344,21 +344,36 @@ impl StatementsTranspiler {
match &expr.kind { match &expr.kind {
TypedExprKind::Do(stmts) => { TypedExprKind::Do(stmts) => {
let mut c_stmts = Vec::new(); let mut c_stmts = Vec::new();
let mut defers = Vec::new();
let mut last_stmt = None;
for (i, stmt) in stmts.iter().enumerate() { for (i, stmt) in stmts.iter().enumerate() {
if i == stmts.len() - 1 { match &stmt.kind {
// Last expression in a block should be returned TypedExprKind::Defer(defer_expr) => {
match &stmt.kind { defers.push(self.transpile_stmt(defer_expr)?);
TypedExprKind::Return(_) => { }
_ => {
if i == stmts.len() - 1 {
last_stmt = Some(stmt);
} else {
c_stmts.push(self.transpile_stmt(stmt)?); c_stmts.push(self.transpile_stmt(stmt)?);
} }
_ => {
// Convert to return statement
let c_expr = self.transpile_expr(stmt)?;
c_stmts.push(CStmt::Return(Some(c_expr)));
}
} }
} else { }
c_stmts.push(self.transpile_stmt(stmt)?); }
// Execute defers in reverse order before the last statement
for defer_stmt in defers.into_iter().rev() {
c_stmts.push(defer_stmt);
}
if let Some(last) = last_stmt {
match &last.kind {
TypedExprKind::Return(_) => {
c_stmts.push(self.transpile_stmt(last)?);
}
_ => {
// Convert to return statement
let c_expr = self.transpile_expr(last)?;
c_stmts.push(CStmt::Return(Some(c_expr)));
}
} }
} }
Ok(c_stmts) Ok(c_stmts)
@ -402,12 +417,8 @@ impl StatementsTranspiler {
Type::Bool => Ok(CType::Bool), Type::Bool => Ok(CType::Bool),
Type::String => Ok(CType::Ptr(Box::new(CType::Char))), Type::String => Ok(CType::Ptr(Box::new(CType::Char))),
Type::Unit => Ok(CType::Void), Type::Unit => Ok(CType::Void),
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)?))) Type::Array(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::Struct(name, _) => Ok(CType::Struct(name.clone())),
Type::Enum(name, _) => Ok(CType::Struct(name.clone())), Type::Enum(name, _) => Ok(CType::Struct(name.clone())),
Type::Tuple(types) => { Type::Tuple(types) => {
@ -480,8 +491,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)),
} }
} }
} }

View file

@ -1,8 +1,8 @@
use crate::ast::*; use crate::ast::*;
use crate::c_ir::*; use crate::c_ir::*;
use std::collections::HashMap;
use crate::c_lowerer::declaration_transpiler::DeclarationTranspiler; use crate::c_lowerer::declaration_transpiler::DeclarationTranspiler;
use crate::c_lowerer::statements_transpiler::StatementsTranspiler; use crate::c_lowerer::statements_transpiler::StatementsTranspiler;
use std::collections::HashMap;
pub struct Transpiler { pub struct Transpiler {
structs: HashMap<String, CStructDecl>, structs: HashMap<String, CStructDecl>,
@ -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(typed_trait ) => {} TypedASTNodeKind::Trait(typed_trait) => {}
TypedASTNodeKind::Use(_) => {} TypedASTNodeKind::Use(_) => {}
} }
Ok(()) Ok(())
@ -227,19 +227,20 @@ 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)));
} }
output.push_str(" }\n"); output.push_str(" }\n");
output output
} }
CStmt::Break => { CStmt::Break => "break;\n".to_string(),
"break;\n".to_string() CStmt::Continue => "continue;\n".to_string(),
}
CStmt::Continue => {
"continue;\n".to_string()
}
} }
} }
@ -313,7 +314,10 @@ impl Transpiler {
} }
CExpr::ArrayLit(array_lit) => { CExpr::ArrayLit(array_lit) => {
let vec = array_lit.iter().map(|expr| self.generate_expr(expr)).collect::<Vec<_>>(); let vec = array_lit
.iter()
.map(|expr| self.generate_expr(expr))
.collect::<Vec<_>>();
let len = vec.len(); let len = vec.len();
format!("{}[{}]{{ {} }}", vec[0], len, vec.join(", ")) format!("{}[{}]{{ {} }}", vec[0], len, vec.join(", "))
} }

View file

@ -145,6 +145,9 @@ impl LambdaLowerer {
self.collect_free_vars_expr(start, lambda_params, free_vars, local_scope); self.collect_free_vars_expr(start, lambda_params, free_vars, local_scope);
self.collect_free_vars_expr(end, lambda_params, free_vars, local_scope); self.collect_free_vars_expr(end, lambda_params, free_vars, local_scope);
} }
ExprKind::Defer(expr) => {
self.collect_free_vars_expr(expr, lambda_params, free_vars, local_scope);
}
// Terminal expressions don't contain variables // Terminal expressions don't contain variables
ExprKind::Int(_) ExprKind::Int(_)
| ExprKind::Float(_) | ExprKind::Float(_)
@ -372,6 +375,7 @@ impl LambdaLowerer {
| ExprKind::Variable(_) | ExprKind::Variable(_)
| ExprKind::Break | ExprKind::Break
| ExprKind::Continue => expr.kind.clone(), | ExprKind::Continue => expr.kind.clone(),
ExprKind::Defer(inner) => ExprKind::Defer(Box::new(self.lower_expr(inner)?)),
}; };
Ok(Expr { Ok(Expr {

View file

@ -150,6 +150,9 @@ pub enum Token {
#[token("continue")] #[token("continue")]
KeywordContinue, KeywordContinue,
#[token("defer")]
KeywordDefer,
#[token("+")] #[token("+")]
Plus, Plus,

View file

@ -2,8 +2,8 @@ pub const EXTENSION: &str = ".sui";
pub mod ast; pub mod ast;
pub mod c_ir; pub mod c_ir;
pub mod codegen;
pub mod c_lowerer; pub mod c_lowerer;
pub mod codegen;
pub mod lambda_lower; pub mod lambda_lower;
pub mod lexer; pub mod lexer;
pub mod monomorphize; pub mod monomorphize;

View file

@ -327,6 +327,11 @@ impl Monomorphizer {
| TypedExprKind::String(_) | TypedExprKind::String(_)
| TypedExprKind::Break | TypedExprKind::Break
| TypedExprKind::Continue => expr.kind.clone(), | TypedExprKind::Continue => expr.kind.clone(),
TypedExprKind::Defer(inner) => {
let (new_inner, mut inner_needs) = self.monomorphize_expr(inner)?;
needs.append(&mut inner_needs);
TypedExprKind::Defer(Box::new(new_inner))
}
TypedExprKind::Array(elems) => { TypedExprKind::Array(elems) => {
let mut new_elems = Vec::new(); let mut new_elems = Vec::new();

View file

@ -1720,7 +1720,18 @@ impl Parser {
self.next(); self.next();
break; break;
} }
exprs.push(self.parse_expr()?); if matches!(self.peek(), Some(Token::KeywordDefer)) {
self.next();
let expr = self.parse_expr()?;
let end = expr.span.end;
exprs.push(Expr {
kind: ExprKind::Defer(Box::new(expr)),
span: Span::new(&(start..end), self.file.clone()),
attributes: Vec::new(),
});
} else {
exprs.push(self.parse_expr()?);
}
if matches!(self.peek(), Some(Token::Semicolon)) { if matches!(self.peek(), Some(Token::Semicolon)) {
self.next(); self.next();

View file

@ -1410,6 +1410,11 @@ impl TypeChecker {
ExprKind::Break => (TypedExprKind::Break, Type::Never), ExprKind::Break => (TypedExprKind::Break, Type::Never),
ExprKind::Continue => (TypedExprKind::Continue, Type::Never), ExprKind::Continue => (TypedExprKind::Continue, Type::Never),
ExprKind::Defer(expr) => {
let typed_expr = self.typecheck_expr(expr)?;
(TypedExprKind::Defer(Box::new(typed_expr)), Type::Unit)
}
ExprKind::EarlyReturn(value) => { ExprKind::EarlyReturn(value) => {
let typed_value = if let Some(v) = value { let typed_value = if let Some(v) = value {
Some(Box::new(self.typecheck_expr(v)?)) Some(Box::new(self.typecheck_expr(v)?))

View file

@ -2,7 +2,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
int main(void); int main(void);