Add operators, math, time, string, collection, and HOF builtins to El
This commit is contained in:
@@ -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"),
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
Reference in New Issue
Block a user