[fine] Panic embeds description, start match

This commit is contained in:
John Doty 2024-03-24 07:08:45 -07:00
parent 548d9387d6
commit 9ce5794c30
3 changed files with 94 additions and 35 deletions

View file

@ -17,7 +17,7 @@ pub const EXTERN_USER_FIRST: usize = 100000;
// But I'm not cool.
#[derive(Debug, Clone, Copy)]
pub enum Instruction {
Panic,
Panic(usize),
BoolNot,
Call(usize),
@ -173,6 +173,22 @@ impl<'a> Compiler<'a> {
index
}
fn inst_panic<T>(&mut self, description: T) -> Instruction
where
T: Into<String>,
{
let index = self.add_string(description.into());
Instruction::Panic(index)
}
fn push_panic<T>(&mut self, description: T) -> usize
where
T: Into<String>,
{
let instruction = self.inst_panic(description);
self.push(instruction)
}
fn patch(&mut self, i: usize, f: impl FnOnce(usize) -> Instruction) {
let index = self.function.instructions.len();
self.function.instructions[i] = f(index);
@ -226,12 +242,12 @@ macro_rules! ice {
}}
}
macro_rules! inst_panic {
($($t:tt)+) => {{
// eprintln!($($t)*);
Instruction::Panic
}};
}
// macro_rules! inst_panic {
// ($($t:tt)+) => {{
// // eprintln!($($t)*);
// Instruction::Panic
// }};
// }
// macro_rules! ice {
// ($compiler:expr, $tr:expr, $($t:tt)*) => {{}};
@ -318,11 +334,12 @@ fn compile_expression(c: &mut Compiler, t: TreeRef) {
TreeKind::NewObjectExpression => compile_new_object_expression(c, t, tree),
TreeKind::SelfReference => compile_self_reference(c),
TreeKind::UnaryExpression => compile_unary_operator(c, t, tree),
TreeKind::MatchExpression => compile_match_expression(c, tree),
_ => ice!(c, t, "{tree:?} is not an expression, cannot compile"),
};
if matches!(cr, None) {
c.push(inst_panic!("panic compiling expression {:?}", tree));
c.push_panic(format!("panic compiling expression {:?}", tree));
}
}
@ -342,7 +359,7 @@ fn compile_literal(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
let index = c.add_string(result);
c.push(Instruction::PushString(index))
}
Type::Error => c.push(inst_panic!("compiling literal {:?}", tr)),
Type::Error => c.push_panic(format!("compiling literal {:?}", tr)),
_ => ice!(c, t, "unsupported literal type: {t:?}"),
};
OK
@ -412,10 +429,10 @@ where
fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
let op = tr.nth_token(1)?;
match op.kind {
TokenKind::Plus => compile_simple_binary_expression(c, tr, |_, t| match t {
TokenKind::Plus => compile_simple_binary_expression(c, tr, |c, t| match t {
Type::F64 => Instruction::FloatAdd,
Type::String => Instruction::StringAdd,
_ => inst_panic!("panic adding {}", t),
_ => c.inst_panic(format!("panic adding {}", t)),
}),
TokenKind::Minus => {
compile_simple_binary_expression(c, tr, |_, _| Instruction::FloatSubtract)
@ -427,30 +444,30 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
compile_simple_binary_expression(c, tr, |_, _| Instruction::FloatDivide)
}
TokenKind::Less => compile_simple_binary_expression(c, tr, |_, t| match t {
TokenKind::Less => compile_simple_binary_expression(c, tr, |c, t| match t {
Type::F64 => Instruction::LessFloat,
Type::String => Instruction::LessString,
_ => inst_panic!("panic less {}", t),
_ => c.inst_panic(format!("panic less {}", t)),
}),
TokenKind::LessEqual => {
compile_simple_binary_expression(c, tr, |_, t| match t {
compile_simple_binary_expression(c, tr, |c, t| match t {
Type::F64 => Instruction::GreaterFloat,
Type::String => Instruction::GreaterString,
_ => inst_panic!("panic less equal {}", t),
_ => c.inst_panic(format!("panic less equal {}", t)),
});
c.push(Instruction::BoolNot);
OK
}
TokenKind::Greater => compile_simple_binary_expression(c, tr, |_, t| match t {
TokenKind::Greater => compile_simple_binary_expression(c, tr, |c, t| match t {
Type::F64 => Instruction::GreaterFloat,
Type::String => Instruction::GreaterString,
_ => inst_panic!("panic greater {}", t),
_ => c.inst_panic(format!("panic greater {}", t)),
}),
TokenKind::GreaterEqual => {
compile_simple_binary_expression(c, tr, |_, t| match t {
compile_simple_binary_expression(c, tr, |c, t| match t {
Type::F64 => Instruction::LessFloat,
Type::String => Instruction::LessString,
_ => inst_panic!("panic greater equal {}", t),
_ => c.inst_panic(format!("panic greater equal {}", t)),
});
c.push(Instruction::BoolNot);
OK
@ -519,7 +536,7 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
Type::F64 => Instruction::EqFloat,
Type::String => Instruction::EqString,
Type::Bool => Instruction::EqBool, // ?
_ => inst_panic!("panic comparing {}", arg_type),
_ => c.inst_panic(format!("panic comparing {}", arg_type)),
}
}
})
@ -579,11 +596,11 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
}
}
Declaration::ExternFunction { .. } => inst_panic!("store ext"),
Declaration::Function { .. } => inst_panic!("store func"),
Declaration::Class { .. } => inst_panic!("store class"),
Declaration::ImportedModule { .. } => inst_panic!("store import"),
Declaration::ImportedDeclaration { .. } => inst_panic!("store import decl"),
Declaration::ExternFunction { .. } => c.inst_panic("store ext"),
Declaration::Function { .. } => c.inst_panic("store func"),
Declaration::Class { .. } => c.inst_panic("store class"),
Declaration::ImportedModule { .. } => c.inst_panic("store import"),
Declaration::ImportedDeclaration { .. } => c.inst_panic("store import decl"),
};
c.push(instruction);
OK
@ -672,6 +689,36 @@ fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declarat
OK
}
fn compile_match_expression(c: &mut Compiler, tree: &Tree) -> Option<()> {
compile_expression(c, tree.nth_tree(1)?);
let mut patches = Vec::new();
let match_body = tree.child_tree_of_kind(c.syntax, TreeKind::MatchBody)?;
for arm in match_body.children_of_kind(c.syntax, TreeKind::MatchArm) {
let arm = &c.syntax[arm];
// Evaluate pattern...
compile_pattern(c, arm.nth_tree(0)?)?;
// ...If false jump to next arm.
let jump_next_index = c.push(Instruction::JumpFalse(0));
// ...If true run expression and jump out.
compile_expression(c, arm.nth_tree(2)?);
patches.push(c.push(Instruction::Jump(0)));
c.patch(jump_next_index, |i| Instruction::JumpFalse(i));
}
c.push_panic("Fell through all match arms");
// Patch the jumps to the end of the match expression.
for patch in patches {
c.patch(patch, |i| Instruction::Jump(i));
}
OK
}
fn compile_is_expression(c: &mut Compiler, tree: &Tree) -> Option<()> {
compile_expression(c, tree.nth_tree(0)?);
@ -766,7 +813,7 @@ fn compile_type_expr_eq(c: &mut Compiler, t: TreeRef) {
};
if result.is_none() {
c.push(inst_panic!("panic compiling type expression eq {:?}", tree));
c.push_panic(format!("panic compiling type expression eq {:?}", tree));
}
}
@ -877,7 +924,7 @@ fn compile_argument(c: &mut Compiler, tree: &Tree) -> CR {
fn compile_new_object_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
// We pass in the arguments.... by... field order?
let Type::Object(mid, ct, _) = c.semantics.type_of(t) else {
c.push(inst_panic!("new obj not ob"));
c.push_panic("new obj not ob");
return OK;
};
@ -963,7 +1010,7 @@ fn compile_member_access(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
class.static_env.clone()
}
_ => {
c.push(inst_panic!("cannot get environment of {typ}"));
c.push_panic("cannot get environment of {typ}");
return None;
}
};
@ -1018,7 +1065,7 @@ fn compile_statement(c: &mut Compiler, t: TreeRef, gen_value: bool) {
_ => ice!(c, t, "unsupported statement tree kind {:?}", tree.kind),
};
if matches!(cr, None) {
c.push(inst_panic!("stat {:?}", tree));
c.push_panic(format!("stat {:?}", tree));
}
}

View file

@ -10,8 +10,8 @@ use thiserror::Error;
#[derive(Error, Debug)]
pub enum VMErrorCode {
#[error("code panic (syntax or semantic error)")]
Panic,
#[error("code panic (syntax or semantic error): {0}")]
Panic(Rc<str>),
#[error("internal error: stack underflow")]
StackUnderflow,
#[error("internal error: stack type mismatch: {0:?} is not {1:?}")]
@ -394,7 +394,12 @@ fn eval_one(
stack: &mut Vec<Frame>,
) -> Result<Flow> {
match instruction {
Instruction::Panic => return Err(VMErrorCode::Panic),
Instruction::Panic(index) => {
let v = f
.get_string(index)
.unwrap_or_else(|_| "!!panic string out of range!!".into());
return Err(VMErrorCode::Panic(v));
}
Instruction::BoolNot => {
let value = f.pop_bool()?;
f.push_bool(!value);

View file

@ -127,6 +127,12 @@ fun test() -> f64 {
sum = sum + v;
}
let it = new Iterator { current: 0 };
sum = sum + match it.next() {
v:f64 -> 100,
_ -> 1000,
};
// Unroll by hand...
let it = new Iterator { current: 0 };
while true {
@ -141,5 +147,6 @@ fun test() -> f64 {
// like the above.
}
// @ignore never finished compiling `match`
// @ignore not finished yet, still compiler bugs
// @no-errors
// @eval: Float(90.0)