Add operators, math, time, string, collection, and HOF builtins to El

This commit is contained in:
Will Anderson
2026-04-29 03:58:16 -05:00
parent a42429012e
commit 8d4d9ed786
15 changed files with 972 additions and 19 deletions
+14
View File
@@ -69,6 +69,13 @@ pub enum Bytecode {
Sub,
Mul,
Div,
Mod,
BitAnd,
BitOr,
BitXor,
BitNot,
Shl,
Shr,
// ── Comparison ────────────────────────────────────────────────────────────
Eq,
@@ -155,6 +162,13 @@ impl std::fmt::Display for Bytecode {
Bytecode::Sub => write!(f, "SUB"),
Bytecode::Mul => write!(f, "MUL"),
Bytecode::Div => write!(f, "DIV"),
Bytecode::Mod => write!(f, "MOD"),
Bytecode::BitAnd => write!(f, "BITAND"),
Bytecode::BitOr => write!(f, "BITOR"),
Bytecode::BitXor => write!(f, "BITXOR"),
Bytecode::BitNot => write!(f, "BITNOT"),
Bytecode::Shl => write!(f, "SHL"),
Bytecode::Shr => write!(f, "SHR"),
Bytecode::Eq => write!(f, "EQ"),
Bytecode::NotEq => write!(f, "NEQ"),
Bytecode::Lt => write!(f, "LT"),
+25 -2
View File
@@ -273,6 +273,12 @@ impl Codegen {
BinOp::GtEq => Bytecode::GtEq,
BinOp::And => Bytecode::And,
BinOp::Or => Bytecode::Or,
BinOp::Mod => Bytecode::Mod,
BinOp::BitAnd => Bytecode::BitAnd,
BinOp::BitOr => Bytecode::BitOr,
BinOp::BitXor => Bytecode::BitXor,
BinOp::Shl => Bytecode::Shl,
BinOp::Shr => Bytecode::Shr,
};
self.emit(instr);
}
@@ -280,6 +286,10 @@ impl Codegen {
self.gen_expr(inner)?;
self.emit(Bytecode::Not);
}
Expr::UnaryBitNot(inner) => {
self.gen_expr(inner)?;
self.emit(Bytecode::BitNot);
}
Expr::Call { func, args } => {
// Push arguments left-to-right
for arg in args {
@@ -326,8 +336,12 @@ impl Codegen {
let after_else = self.current_idx();
self.patch_jump(jump_end, after_else);
} else {
let after_then = self.current_idx();
self.patch_jump(jump_false, after_then);
// No else branch: if-without-else is a statement, not a value
// expression. Discard the then-block's pushed value so both
// paths leave the stack at the same height (net zero change).
self.emit(Bytecode::Pop);
let after_pop = self.current_idx();
self.patch_jump(jump_false, after_pop); // false path skips Pop too
}
}
Expr::Match { subject, arms } => {
@@ -451,6 +465,15 @@ impl Codegen {
fields: field_names,
});
}
Expr::MapLiteral(pairs) => {
// Push each key-value pair, then collect with BuildMap.
let n = pairs.len() as u32;
for (key_expr, val_expr) in pairs {
self.gen_expr(key_expr)?;
self.gen_expr(val_expr)?;
}
self.emit(Bytecode::BuildMap(n));
}
Expr::With { base, updates } => {
// Generate base struct clone then apply updates
self.gen_expr(base)?;