Skip to content

Commit

Permalink
Throw instruction + Pattern Mismatch
Browse files Browse the repository at this point in the history
  • Loading branch information
ecton committed Feb 13, 2024
1 parent 3217237 commit 8310429
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 9 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ fn fib {
All of these examples create a function named `fib` that accepts one parameter
and produce identical results.

A full language reference is available in the [Muse User's Guide][guide] is
A full [language reference][language-ref] is available in the [Muse User's Guide][guide] is
available in the User's Guide.

[design-goals]: TODO
[guide]: TODO
[design-goals]: https://khonsu.dev/muse/main/guide/design.html
[guide]: https://khonsu.dev/muse/main/guide/
[language-ref]: https://khonsu.dev/muse/main/guide/reference.html
4 changes: 2 additions & 2 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::syntax::{
Variable,
};
use crate::vm::bitcode::{
BinaryKind, BitcodeBlock, BitcodeFunction, Label, Op, OpDestination, ValueOrSource,
BinaryKind, BitcodeBlock, BitcodeFunction, FaultKind, Label, Op, OpDestination, ValueOrSource,
};
use crate::vm::{Code, Register, Stack};

Expand Down Expand Up @@ -756,7 +756,7 @@ impl<'a> Scope<'a> {
}

if refutable == Refutability::Refutable {
self.compiler.code.copy((), dest);
self.compiler.code.throw(FaultKind::PatternMismatch);
}
}

Expand Down
16 changes: 15 additions & 1 deletion src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ use serde::{Deserialize, Serialize};

#[cfg(not(feature = "dispatched"))]
use self::bitcode::trusted_loaded_source_to_value;
use self::bitcode::{BinaryKind, BitcodeFunction, Label, Op, OpDestination, ValueOrSource};
use self::bitcode::{
BinaryKind, BitcodeFunction, FaultKind, Label, Op, OpDestination, ValueOrSource,
};
use crate::compiler::{BitcodeModule, BlockDeclaration, UnaryKind};
use crate::list::List;
#[cfg(not(feature = "dispatched"))]
Expand Down Expand Up @@ -792,6 +794,7 @@ impl Vm {
LoadedOp::LoadModule { module, dest } => {
self.op_load_module(code_index, *module, *dest)
}
LoadedOp::Throw(kind) => Err(Fault::from_kind(*kind, self)),
};

match result {
Expand Down Expand Up @@ -1350,6 +1353,7 @@ impl Frame {
pub enum Fault {
UnknownSymbol(Symbol),
IncorrectNumberOfArguments,
PatternMismatch,
OperationOnNil,
MissingModule,
NotAFunction,
Expand Down Expand Up @@ -1405,6 +1409,14 @@ impl Fault {
Fault::Waiting => Symbol::from("waiting").into(),
Fault::FrameChanged => Symbol::from("frame_changed").into(),
Fault::Exception(value) => value.clone(),
Fault::PatternMismatch => Symbol::from("mismatch").into(),
}
}

fn from_kind(kind: FaultKind, vm: &mut Vm) -> Self {
match kind {
FaultKind::Exception => Self::Exception(vm[Register(0)].take()),
FaultKind::PatternMismatch => Self::PatternMismatch,
}
}
}
Expand Down Expand Up @@ -1644,6 +1656,7 @@ impl CodeData {
let dest = self.load_dest(dest);
self.push_loaded(LoadedOp::LoadModule { module, dest });
}
Op::Throw(kind) => self.push_loaded(LoadedOp::Throw(*kind)),
}
}

Expand Down Expand Up @@ -1903,6 +1916,7 @@ enum LoadedOp {
module: usize,
dest: OpDestination,
},
Throw(FaultKind),
}

#[derive(Debug, Clone, Copy, PartialEq)]
Expand Down
12 changes: 12 additions & 0 deletions src/vm/bitcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ pub enum Op {
name: Symbol,
arity: ValueOrSource,
},
Throw(FaultKind),
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, Hash)]
pub enum FaultKind {
Exception,
PatternMismatch,
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -330,6 +337,10 @@ impl BitcodeBlock {
});
}

pub fn throw(&mut self, kind: FaultKind) {
self.push(Op::Throw(kind));
}

pub fn set_exception_handler(
&mut self,
target: impl Into<ValueOrSource>,
Expand Down Expand Up @@ -608,6 +619,7 @@ impl From<&'_ Code> for BitcodeBlock {
module: code.data.modules[*initializer].clone(),
dest: *dest,
},
LoadedOp::Throw(kind) => Op::Throw(*kind),
});
}

Expand Down
61 changes: 58 additions & 3 deletions src/vm/dispatched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use std::ops::ControlFlow;
use std::sync::Arc;

use super::bitcode::{
trusted_loaded_source_to_value, BinaryKind, BitcodeFunction, Label, Op, OpDestination,
ValueOrSource,
trusted_loaded_source_to_value, BinaryKind, BitcodeFunction, FaultKind, Label, Op,
OpDestination, ValueOrSource,
};
use super::{
precompiled_regex, Code, CodeData, Function, LoadedOp, Module, PrecompiledRegex, Register,
Expand Down Expand Up @@ -195,6 +195,12 @@ impl CodeData {
&loaded.dest,
self,
),
LoadedOp::Matches(loaded) => match_matches(
&trusted_loaded_source_to_value(&loaded.op1, self),
&trusted_loaded_source_to_value(&loaded.op2, self),
&loaded.dest,
self,
),
LoadedOp::Call { name, arity } => match_call(
&trusted_loaded_source_to_value(&name, self),
&trusted_loaded_source_to_value(&arity, self),
Expand Down Expand Up @@ -246,6 +252,9 @@ impl CodeData {
LoadedOp::LoadModule { module, dest } => {
match_load_module(&self.modules[module].clone(), &dest, self);
}
LoadedOp::Throw(kind) => {
self.push_dispatched(Throw(kind));
}
}
}

Expand Down Expand Up @@ -275,6 +284,19 @@ impl Instruction for Return {
}
}

#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
pub struct Throw(pub FaultKind);

impl Instruction for Throw {
fn execute(&self, vm: &mut Vm) -> Result<ControlFlow<()>, Fault> {
Err(Fault::from_kind(self.0, vm))
}

fn as_op(&self) -> Op {
Op::Throw(self.0)
}
}

#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
pub struct Load<From, Dest> {
pub source: From,
Expand Down Expand Up @@ -859,6 +881,38 @@ where
pub type Equal<Lhs, Rhs, Dest> = Eq<Lhs, Rhs, Dest, false>;
pub type NotEqual<Lhs, Rhs, Dest> = Eq<Lhs, Rhs, Dest, true>;

#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
pub struct Matches<Lhs, Rhs, Dest> {
pub lhs: Lhs,
pub rhs: Rhs,
pub dest: Dest,
}

impl<Lhs, Rhs, Dest> Instruction for Matches<Lhs, Rhs, Dest>
where
Lhs: Source,
Rhs: Source,
Dest: Destination,
{
fn execute(&self, vm: &mut Vm) -> Result<ControlFlow<()>, Fault> {
let lhs = self.lhs.load(vm)?;
let rhs = self.rhs.load(vm)?;
let matches = lhs.matches(vm, &rhs)?;
self.dest.store(vm, Value::Bool(matches))?;

Ok(ControlFlow::Continue(()))
}

fn as_op(&self) -> Op {
Op::BinOp {
op1: self.lhs.as_source(),
op2: self.rhs.as_source(),
dest: self.dest.as_dest(),
kind: BinaryKind::LogicalXor,
}
}
}

#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
pub struct Assign<Lhs, Rhs, Dest> {
pub lhs: Lhs,
Expand Down Expand Up @@ -1462,6 +1516,7 @@ define_match_binop!(match_equal, compile_equal, Equal);
define_match_binop!(match_not_equal, compile_not_equal, NotEqual);
define_match_binop!(match_gt, compile_gt, GreaterThan);
define_match_binop!(match_gte, compile_gte, GreaterThanOrEqual);
define_match_binop!(match_matches, compile_matches, Matches);
define_match_binop!(match_bitwise_and, compile_bitwise_and, BitwiseAnd);
define_match_binop!(match_bitwise_or, compile_bitwise_or, BitwiseOr);
define_match_binop!(match_bitwise_xor, compile_bitwise_xor, BitwiseXor);
Expand Down Expand Up @@ -1542,7 +1597,7 @@ where
{
fn execute(&self, vm: &mut Vm) -> Result<ControlFlow<()>, Fault> {
let value = self.declaration.load(vm)?;
vm.declare_inner(self.name.clone(), value.clone(), self.mutable);
vm.declare_inner(self.name.clone(), value.clone(), self.mutable)?;

self.dest.store(vm, value)?;

Expand Down
14 changes: 14 additions & 0 deletions tests/cases/match.rsn
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,18 @@ match_tuple: {
[1, a] => a,
}"#,
output: Int(2),
}

mismatch: {
src: r#"match true {
false => 0,
}"#,
output: Fault(PatternMismatch),
}

try_mismatch: {
src: r#"match true {
false => 0,
}?"#,
output: Nil,
}
2 changes: 2 additions & 0 deletions tests/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ enum VmFault {
Timeout,
Waiting,
FrameChanged,
PatternMismatch,
Exception(Box<TestOutput>),
}

Expand Down Expand Up @@ -96,6 +97,7 @@ impl From<Fault> for VmFault {
Fault::Timeout => Self::Timeout,
Fault::Waiting => Self::Waiting,
Fault::FrameChanged => Self::FrameChanged,
Fault::PatternMismatch => Self::PatternMismatch,
Fault::Exception(value) => Self::Exception(Box::new(TestOutput::from(value))),
}
}
Expand Down

0 comments on commit 8310429

Please sign in to comment.