[fine] Panic embeds description, start match
This commit is contained in:
parent
548d9387d6
commit
9ce5794c30
3 changed files with 94 additions and 35 deletions
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ fun attack(weapon: MeleeWeapon or RangedWeapon, monster: Monster, distance: f64)
|
|||
// `and` that follows the declaration in the `is` still has the variables
|
||||
// from the `is` binding in scope.
|
||||
if weapon is MeleeWeapon and distance > 1 or
|
||||
weapon is w : RangedWeapon and (distance < w.minRange or distance > w.maxRange) {
|
||||
weapon is w:RangedWeapon and (distance < w.minRange or distance > w.maxRange) {
|
||||
print("You are out of range");
|
||||
return
|
||||
}
|
||||
|
|
@ -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`
|
||||
// @no-errors
|
||||
// @ignore not finished yet, still compiler bugs
|
||||
// @no-errors
|
||||
// @eval: Float(90.0)
|
||||
Loading…
Add table
Add a link
Reference in a new issue