defer
This commit is contained in:
parent
a32db747e6
commit
00f39ac9ca
13 changed files with 111 additions and 68 deletions
|
|
@ -240,6 +240,7 @@ pub enum ExprKind {
|
|||
Return(Option<Box<Expr>>),
|
||||
Break,
|
||||
Continue,
|
||||
Defer(Box<Expr>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
|
@ -273,7 +274,7 @@ pub enum UnOp {
|
|||
Not,
|
||||
Ref,
|
||||
Deref,
|
||||
PreInc
|
||||
PreInc,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -429,6 +430,7 @@ pub enum TypedExprKind {
|
|||
Return(Option<Box<TypedExpr>>),
|
||||
Break,
|
||||
Continue,
|
||||
Defer(Box<TypedExpr>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ pub enum CUnaryOp {
|
|||
Not,
|
||||
Ref,
|
||||
Deref,
|
||||
PreInc
|
||||
PreInc,
|
||||
}
|
||||
|
||||
impl CUnaryOp {
|
||||
|
|
@ -132,7 +132,7 @@ impl CUnaryOp {
|
|||
CUnaryOp::Not => "!",
|
||||
CUnaryOp::Ref => "&",
|
||||
CUnaryOp::Deref => "*",
|
||||
CUnaryOp::PreInc => "++"
|
||||
CUnaryOp::PreInc => "++",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
pub mod declaration_transpiler;
|
||||
pub mod statements_transpiler;
|
||||
pub mod statements_transpiler;
|
||||
|
|
|
|||
|
|
@ -187,8 +187,20 @@ impl StatementsTranspiler {
|
|||
}
|
||||
TypedExprKind::Do(exprs) => {
|
||||
let mut stmts = Vec::new();
|
||||
let mut defers = Vec::new();
|
||||
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))
|
||||
}
|
||||
|
|
@ -211,10 +223,8 @@ impl StatementsTranspiler {
|
|||
Box::new(end_expr),
|
||||
);
|
||||
|
||||
let incr = CExpr::UnOp(
|
||||
CUnaryOp::PreInc,
|
||||
Box::new(CExpr::Var(var_name.clone())),
|
||||
);
|
||||
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, incr, body_stmts))
|
||||
|
|
@ -224,32 +234,26 @@ impl StatementsTranspiler {
|
|||
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
|
||||
)),
|
||||
_ => {
|
||||
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 (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(),
|
||||
)),
|
||||
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 incr =
|
||||
CExpr::UnOp(CUnaryOp::PreInc, Box::new(CExpr::Var(idx_name.clone())));
|
||||
|
||||
// let x = array.data[i]
|
||||
let bind = CStmt::VarDecl(CVarDecl {
|
||||
|
|
@ -292,11 +296,8 @@ impl StatementsTranspiler {
|
|||
);
|
||||
|
||||
// i = 0
|
||||
let (idx_name, idx_decl) = self.fresh_tmp_var(
|
||||
"_i",
|
||||
CType::Int,
|
||||
Some(CExpr::IntLit(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())),
|
||||
|
|
@ -304,10 +305,8 @@ impl StatementsTranspiler {
|
|||
Box::new(CExpr::IntLit(arr_len as i64)),
|
||||
);
|
||||
|
||||
let incr = CExpr::UnOp(
|
||||
CUnaryOp::PreInc,
|
||||
Box::new(CExpr::Var(idx_name.clone())),
|
||||
);
|
||||
let incr =
|
||||
CExpr::UnOp(CUnaryOp::PreInc, Box::new(CExpr::Var(idx_name.clone())));
|
||||
|
||||
let bind = CStmt::VarDecl(CVarDecl {
|
||||
name: var_name.clone(),
|
||||
|
|
@ -332,6 +331,7 @@ impl StatementsTranspiler {
|
|||
}
|
||||
TypedExprKind::Break => Ok(CStmt::Break),
|
||||
TypedExprKind::Continue => Ok(CStmt::Continue),
|
||||
TypedExprKind::Defer(_) => Err("Defer should be handled in Do blocks".to_string()),
|
||||
_ => {
|
||||
// For other expressions, treat as expression statements
|
||||
let c_expr = self.transpile_expr(expr)?;
|
||||
|
|
@ -344,21 +344,36 @@ impl StatementsTranspiler {
|
|||
match &expr.kind {
|
||||
TypedExprKind::Do(stmts) => {
|
||||
let mut c_stmts = Vec::new();
|
||||
let mut defers = Vec::new();
|
||||
let mut last_stmt = None;
|
||||
for (i, stmt) in stmts.iter().enumerate() {
|
||||
if i == stmts.len() - 1 {
|
||||
// Last expression in a block should be returned
|
||||
match &stmt.kind {
|
||||
TypedExprKind::Return(_) => {
|
||||
match &stmt.kind {
|
||||
TypedExprKind::Defer(defer_expr) => {
|
||||
defers.push(self.transpile_stmt(defer_expr)?);
|
||||
}
|
||||
_ => {
|
||||
if i == stmts.len() - 1 {
|
||||
last_stmt = Some(stmt);
|
||||
} else {
|
||||
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)
|
||||
|
|
@ -402,12 +417,8 @@ impl StatementsTranspiler {
|
|||
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)?)))
|
||||
}
|
||||
Type::Array(inner) => {
|
||||
Ok(CType::Ptr(Box::new(self.type_to_ctype(inner)?)))
|
||||
}
|
||||
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::Tuple(types) => {
|
||||
|
|
@ -480,8 +491,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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
pub mod transpiler;
|
||||
pub mod transpiler;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::ast::*;
|
||||
use crate::c_ir::*;
|
||||
use std::collections::HashMap;
|
||||
use crate::c_lowerer::declaration_transpiler::DeclarationTranspiler;
|
||||
use crate::c_lowerer::statements_transpiler::StatementsTranspiler;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct Transpiler {
|
||||
structs: HashMap<String, CStructDecl>,
|
||||
|
|
@ -99,7 +99,7 @@ impl Transpiler {
|
|||
// But for now, skip as they're handled differently
|
||||
}
|
||||
TypedASTNodeKind::Load(_) => {}
|
||||
TypedASTNodeKind::Trait(typed_trait ) => {}
|
||||
TypedASTNodeKind::Trait(typed_trait) => {}
|
||||
TypedASTNodeKind::Use(_) => {}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -227,19 +227,20 @@ impl Transpiler {
|
|||
}
|
||||
|
||||
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 {
|
||||
output.push_str(&format!(" {}", self.generate_stmt(stmt)));
|
||||
}
|
||||
output.push_str(" }\n");
|
||||
output
|
||||
}
|
||||
CStmt::Break => {
|
||||
"break;\n".to_string()
|
||||
}
|
||||
CStmt::Continue => {
|
||||
"continue;\n".to_string()
|
||||
}
|
||||
CStmt::Break => "break;\n".to_string(),
|
||||
CStmt::Continue => "continue;\n".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +314,10 @@ impl Transpiler {
|
|||
}
|
||||
|
||||
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();
|
||||
format!("{}[{}]{{ {} }}", vec[0], len, vec.join(", "))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,6 +145,9 @@ impl LambdaLowerer {
|
|||
self.collect_free_vars_expr(start, 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
|
||||
ExprKind::Int(_)
|
||||
| ExprKind::Float(_)
|
||||
|
|
@ -372,6 +375,7 @@ impl LambdaLowerer {
|
|||
| ExprKind::Variable(_)
|
||||
| ExprKind::Break
|
||||
| ExprKind::Continue => expr.kind.clone(),
|
||||
ExprKind::Defer(inner) => ExprKind::Defer(Box::new(self.lower_expr(inner)?)),
|
||||
};
|
||||
|
||||
Ok(Expr {
|
||||
|
|
|
|||
|
|
@ -150,6 +150,9 @@ pub enum Token {
|
|||
#[token("continue")]
|
||||
KeywordContinue,
|
||||
|
||||
#[token("defer")]
|
||||
KeywordDefer,
|
||||
|
||||
#[token("+")]
|
||||
Plus,
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ pub const EXTENSION: &str = ".sui";
|
|||
|
||||
pub mod ast;
|
||||
pub mod c_ir;
|
||||
pub mod codegen;
|
||||
pub mod c_lowerer;
|
||||
pub mod codegen;
|
||||
pub mod lambda_lower;
|
||||
pub mod lexer;
|
||||
pub mod monomorphize;
|
||||
|
|
|
|||
|
|
@ -327,6 +327,11 @@ impl Monomorphizer {
|
|||
| TypedExprKind::String(_)
|
||||
| TypedExprKind::Break
|
||||
| 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) => {
|
||||
let mut new_elems = Vec::new();
|
||||
|
|
|
|||
|
|
@ -1720,7 +1720,18 @@ impl Parser {
|
|||
self.next();
|
||||
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)) {
|
||||
self.next();
|
||||
|
|
|
|||
|
|
@ -1410,6 +1410,11 @@ impl TypeChecker {
|
|||
ExprKind::Break => (TypedExprKind::Break, 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) => {
|
||||
let typed_value = if let Some(v) = value {
|
||||
Some(Box::new(self.typecheck_expr(v)?))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void);
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue