Compare commits
No commits in common. "9ce5794c30cbb50518e5b3919799c4a51d35d427" and "7cc625dd0100fbaf516b81c9306ab54b31db6aac" have entirely different histories.
9ce5794c30
...
7cc625dd01
4 changed files with 35 additions and 95 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
|
@ -1 +0,0 @@
|
||||||
* -text
|
|
||||||
|
|
@ -17,7 +17,7 @@ pub const EXTERN_USER_FIRST: usize = 100000;
|
||||||
// But I'm not cool.
|
// But I'm not cool.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
Panic(usize),
|
Panic,
|
||||||
|
|
||||||
BoolNot,
|
BoolNot,
|
||||||
Call(usize),
|
Call(usize),
|
||||||
|
|
@ -173,22 +173,6 @@ impl<'a> Compiler<'a> {
|
||||||
index
|
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) {
|
fn patch(&mut self, i: usize, f: impl FnOnce(usize) -> Instruction) {
|
||||||
let index = self.function.instructions.len();
|
let index = self.function.instructions.len();
|
||||||
self.function.instructions[i] = f(index);
|
self.function.instructions[i] = f(index);
|
||||||
|
|
@ -242,12 +226,12 @@ macro_rules! ice {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// macro_rules! inst_panic {
|
macro_rules! inst_panic {
|
||||||
// ($($t:tt)+) => {{
|
($($t:tt)+) => {{
|
||||||
// // eprintln!($($t)*);
|
// eprintln!($($t)*);
|
||||||
// Instruction::Panic
|
Instruction::Panic
|
||||||
// }};
|
}};
|
||||||
// }
|
}
|
||||||
|
|
||||||
// macro_rules! ice {
|
// macro_rules! ice {
|
||||||
// ($compiler:expr, $tr:expr, $($t:tt)*) => {{}};
|
// ($compiler:expr, $tr:expr, $($t:tt)*) => {{}};
|
||||||
|
|
@ -334,12 +318,11 @@ fn compile_expression(c: &mut Compiler, t: TreeRef) {
|
||||||
TreeKind::NewObjectExpression => compile_new_object_expression(c, t, tree),
|
TreeKind::NewObjectExpression => compile_new_object_expression(c, t, tree),
|
||||||
TreeKind::SelfReference => compile_self_reference(c),
|
TreeKind::SelfReference => compile_self_reference(c),
|
||||||
TreeKind::UnaryExpression => compile_unary_operator(c, t, tree),
|
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"),
|
_ => ice!(c, t, "{tree:?} is not an expression, cannot compile"),
|
||||||
};
|
};
|
||||||
if matches!(cr, None) {
|
if matches!(cr, None) {
|
||||||
c.push_panic(format!("panic compiling expression {:?}", tree));
|
c.push(inst_panic!("panic compiling expression {:?}", tree));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -359,7 +342,7 @@ fn compile_literal(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
||||||
let index = c.add_string(result);
|
let index = c.add_string(result);
|
||||||
c.push(Instruction::PushString(index))
|
c.push(Instruction::PushString(index))
|
||||||
}
|
}
|
||||||
Type::Error => c.push_panic(format!("compiling literal {:?}", tr)),
|
Type::Error => c.push(inst_panic!("compiling literal {:?}", tr)),
|
||||||
_ => ice!(c, t, "unsupported literal type: {t:?}"),
|
_ => ice!(c, t, "unsupported literal type: {t:?}"),
|
||||||
};
|
};
|
||||||
OK
|
OK
|
||||||
|
|
@ -429,10 +412,10 @@ where
|
||||||
fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
||||||
let op = tr.nth_token(1)?;
|
let op = tr.nth_token(1)?;
|
||||||
match op.kind {
|
match op.kind {
|
||||||
TokenKind::Plus => compile_simple_binary_expression(c, tr, |c, t| match t {
|
TokenKind::Plus => compile_simple_binary_expression(c, tr, |_, t| match t {
|
||||||
Type::F64 => Instruction::FloatAdd,
|
Type::F64 => Instruction::FloatAdd,
|
||||||
Type::String => Instruction::StringAdd,
|
Type::String => Instruction::StringAdd,
|
||||||
_ => c.inst_panic(format!("panic adding {}", t)),
|
_ => inst_panic!("panic adding {}", t),
|
||||||
}),
|
}),
|
||||||
TokenKind::Minus => {
|
TokenKind::Minus => {
|
||||||
compile_simple_binary_expression(c, tr, |_, _| Instruction::FloatSubtract)
|
compile_simple_binary_expression(c, tr, |_, _| Instruction::FloatSubtract)
|
||||||
|
|
@ -444,30 +427,30 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
||||||
compile_simple_binary_expression(c, tr, |_, _| Instruction::FloatDivide)
|
compile_simple_binary_expression(c, tr, |_, _| Instruction::FloatDivide)
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenKind::Less => compile_simple_binary_expression(c, tr, |c, t| match t {
|
TokenKind::Less => compile_simple_binary_expression(c, tr, |_, t| match t {
|
||||||
Type::F64 => Instruction::LessFloat,
|
Type::F64 => Instruction::LessFloat,
|
||||||
Type::String => Instruction::LessString,
|
Type::String => Instruction::LessString,
|
||||||
_ => c.inst_panic(format!("panic less {}", t)),
|
_ => inst_panic!("panic less {}", t),
|
||||||
}),
|
}),
|
||||||
TokenKind::LessEqual => {
|
TokenKind::LessEqual => {
|
||||||
compile_simple_binary_expression(c, tr, |c, t| match t {
|
compile_simple_binary_expression(c, tr, |_, t| match t {
|
||||||
Type::F64 => Instruction::GreaterFloat,
|
Type::F64 => Instruction::GreaterFloat,
|
||||||
Type::String => Instruction::GreaterString,
|
Type::String => Instruction::GreaterString,
|
||||||
_ => c.inst_panic(format!("panic less equal {}", t)),
|
_ => inst_panic!("panic less equal {}", t),
|
||||||
});
|
});
|
||||||
c.push(Instruction::BoolNot);
|
c.push(Instruction::BoolNot);
|
||||||
OK
|
OK
|
||||||
}
|
}
|
||||||
TokenKind::Greater => compile_simple_binary_expression(c, tr, |c, t| match t {
|
TokenKind::Greater => compile_simple_binary_expression(c, tr, |_, t| match t {
|
||||||
Type::F64 => Instruction::GreaterFloat,
|
Type::F64 => Instruction::GreaterFloat,
|
||||||
Type::String => Instruction::GreaterString,
|
Type::String => Instruction::GreaterString,
|
||||||
_ => c.inst_panic(format!("panic greater {}", t)),
|
_ => inst_panic!("panic greater {}", t),
|
||||||
}),
|
}),
|
||||||
TokenKind::GreaterEqual => {
|
TokenKind::GreaterEqual => {
|
||||||
compile_simple_binary_expression(c, tr, |c, t| match t {
|
compile_simple_binary_expression(c, tr, |_, t| match t {
|
||||||
Type::F64 => Instruction::LessFloat,
|
Type::F64 => Instruction::LessFloat,
|
||||||
Type::String => Instruction::LessString,
|
Type::String => Instruction::LessString,
|
||||||
_ => c.inst_panic(format!("panic greater equal {}", t)),
|
_ => inst_panic!("panic greater equal {}", t),
|
||||||
});
|
});
|
||||||
c.push(Instruction::BoolNot);
|
c.push(Instruction::BoolNot);
|
||||||
OK
|
OK
|
||||||
|
|
@ -536,7 +519,7 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
||||||
Type::F64 => Instruction::EqFloat,
|
Type::F64 => Instruction::EqFloat,
|
||||||
Type::String => Instruction::EqString,
|
Type::String => Instruction::EqString,
|
||||||
Type::Bool => Instruction::EqBool, // ?
|
Type::Bool => Instruction::EqBool, // ?
|
||||||
_ => c.inst_panic(format!("panic comparing {}", arg_type)),
|
_ => inst_panic!("panic comparing {}", arg_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -596,11 +579,11 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Declaration::ExternFunction { .. } => c.inst_panic("store ext"),
|
Declaration::ExternFunction { .. } => inst_panic!("store ext"),
|
||||||
Declaration::Function { .. } => c.inst_panic("store func"),
|
Declaration::Function { .. } => inst_panic!("store func"),
|
||||||
Declaration::Class { .. } => c.inst_panic("store class"),
|
Declaration::Class { .. } => inst_panic!("store class"),
|
||||||
Declaration::ImportedModule { .. } => c.inst_panic("store import"),
|
Declaration::ImportedModule { .. } => inst_panic!("store import"),
|
||||||
Declaration::ImportedDeclaration { .. } => c.inst_panic("store import decl"),
|
Declaration::ImportedDeclaration { .. } => inst_panic!("store import decl"),
|
||||||
};
|
};
|
||||||
c.push(instruction);
|
c.push(instruction);
|
||||||
OK
|
OK
|
||||||
|
|
@ -689,36 +672,6 @@ fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declarat
|
||||||
OK
|
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<()> {
|
fn compile_is_expression(c: &mut Compiler, tree: &Tree) -> Option<()> {
|
||||||
compile_expression(c, tree.nth_tree(0)?);
|
compile_expression(c, tree.nth_tree(0)?);
|
||||||
|
|
||||||
|
|
@ -813,7 +766,7 @@ fn compile_type_expr_eq(c: &mut Compiler, t: TreeRef) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if result.is_none() {
|
if result.is_none() {
|
||||||
c.push_panic(format!("panic compiling type expression eq {:?}", tree));
|
c.push(inst_panic!("panic compiling type expression eq {:?}", tree));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -924,7 +877,7 @@ fn compile_argument(c: &mut Compiler, tree: &Tree) -> CR {
|
||||||
fn compile_new_object_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
|
fn compile_new_object_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
|
||||||
// We pass in the arguments.... by... field order?
|
// We pass in the arguments.... by... field order?
|
||||||
let Type::Object(mid, ct, _) = c.semantics.type_of(t) else {
|
let Type::Object(mid, ct, _) = c.semantics.type_of(t) else {
|
||||||
c.push_panic("new obj not ob");
|
c.push(inst_panic!("new obj not ob"));
|
||||||
return OK;
|
return OK;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1010,7 +963,7 @@ fn compile_member_access(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
|
||||||
class.static_env.clone()
|
class.static_env.clone()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
c.push_panic("cannot get environment of {typ}");
|
c.push(inst_panic!("cannot get environment of {typ}"));
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1065,7 +1018,7 @@ fn compile_statement(c: &mut Compiler, t: TreeRef, gen_value: bool) {
|
||||||
_ => ice!(c, t, "unsupported statement tree kind {:?}", tree.kind),
|
_ => ice!(c, t, "unsupported statement tree kind {:?}", tree.kind),
|
||||||
};
|
};
|
||||||
if matches!(cr, None) {
|
if matches!(cr, None) {
|
||||||
c.push_panic(format!("stat {:?}", tree));
|
c.push(inst_panic!("stat {:?}", tree));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum VMErrorCode {
|
pub enum VMErrorCode {
|
||||||
#[error("code panic (syntax or semantic error): {0}")]
|
#[error("code panic (syntax or semantic error)")]
|
||||||
Panic(Rc<str>),
|
Panic,
|
||||||
#[error("internal error: stack underflow")]
|
#[error("internal error: stack underflow")]
|
||||||
StackUnderflow,
|
StackUnderflow,
|
||||||
#[error("internal error: stack type mismatch: {0:?} is not {1:?}")]
|
#[error("internal error: stack type mismatch: {0:?} is not {1:?}")]
|
||||||
|
|
@ -394,12 +394,7 @@ fn eval_one(
|
||||||
stack: &mut Vec<Frame>,
|
stack: &mut Vec<Frame>,
|
||||||
) -> Result<Flow> {
|
) -> Result<Flow> {
|
||||||
match instruction {
|
match instruction {
|
||||||
Instruction::Panic(index) => {
|
Instruction::Panic => return Err(VMErrorCode::Panic),
|
||||||
let v = f
|
|
||||||
.get_string(index)
|
|
||||||
.unwrap_or_else(|_| "!!panic string out of range!!".into());
|
|
||||||
return Err(VMErrorCode::Panic(v));
|
|
||||||
}
|
|
||||||
Instruction::BoolNot => {
|
Instruction::BoolNot => {
|
||||||
let value = f.pop_bool()?;
|
let value = f.pop_bool()?;
|
||||||
f.push_bool(!value);
|
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
|
// `and` that follows the declaration in the `is` still has the variables
|
||||||
// from the `is` binding in scope.
|
// from the `is` binding in scope.
|
||||||
if weapon is MeleeWeapon and distance > 1 or
|
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");
|
print("You are out of range");
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -127,12 +127,6 @@ fun test() -> f64 {
|
||||||
sum = sum + v;
|
sum = sum + v;
|
||||||
}
|
}
|
||||||
|
|
||||||
let it = new Iterator { current: 0 };
|
|
||||||
sum = sum + match it.next() {
|
|
||||||
v:f64 -> 100,
|
|
||||||
_ -> 1000,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Unroll by hand...
|
// Unroll by hand...
|
||||||
let it = new Iterator { current: 0 };
|
let it = new Iterator { current: 0 };
|
||||||
while true {
|
while true {
|
||||||
|
|
@ -147,6 +141,5 @@ fun test() -> f64 {
|
||||||
// like the above.
|
// like the above.
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ignore not finished yet, still compiler bugs
|
// @ignore never finished compiling `match`
|
||||||
// @no-errors
|
// @no-errors
|
||||||
// @eval: Float(90.0)
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue