add as patterns
This commit is contained in:
parent
cda217f6ef
commit
34ab24c4c9
|
@ -33,6 +33,7 @@ pub enum Op {
|
||||||
MatchWord,
|
MatchWord,
|
||||||
PanicIfNoMatch,
|
PanicIfNoMatch,
|
||||||
MatchConstant,
|
MatchConstant,
|
||||||
|
MatchType,
|
||||||
MatchTuple,
|
MatchTuple,
|
||||||
PushTuple,
|
PushTuple,
|
||||||
LoadTuple,
|
LoadTuple,
|
||||||
|
@ -140,6 +141,7 @@ impl std::fmt::Display for Op {
|
||||||
ResetMatch => "reset_match",
|
ResetMatch => "reset_match",
|
||||||
PanicIfNoMatch => "panic_if_no_match",
|
PanicIfNoMatch => "panic_if_no_match",
|
||||||
MatchConstant => "match_constant",
|
MatchConstant => "match_constant",
|
||||||
|
MatchType => "match_type",
|
||||||
MatchTuple => "match_tuple",
|
MatchTuple => "match_tuple",
|
||||||
PushTuple => "push_tuple",
|
PushTuple => "push_tuple",
|
||||||
LoadTuple => "load_tuple",
|
LoadTuple => "load_tuple",
|
||||||
|
@ -210,7 +212,7 @@ impl Chunk {
|
||||||
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch
|
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch
|
||||||
| TypeOf | Duplicate | Decrement | Truncate | Noop | LoadTuple | LoadList | Eq
|
| TypeOf | Duplicate | Decrement | Truncate | Noop | LoadTuple | LoadList | Eq
|
||||||
| Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At | Not | Panic
|
| Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At | Not | Panic
|
||||||
| EmptyString | ConcatStrings | Stringify => {
|
| EmptyString | ConcatStrings | Stringify | MatchType => {
|
||||||
println!("{i:04}: {op}")
|
println!("{i:04}: {op}")
|
||||||
}
|
}
|
||||||
Constant | MatchConstant => {
|
Constant | MatchConstant => {
|
||||||
|
@ -359,10 +361,12 @@ impl Compiler {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
self.chunk.constants.push(val);
|
self.chunk.constants.push(val);
|
||||||
self.chunk.bytecode.push(Op::Constant as u8);
|
self.emit_op(Op::Constant);
|
||||||
self.spans.push(self.span);
|
// self.chunk.bytecode.push(Op::Constant as u8);
|
||||||
self.chunk.bytecode.push(constant_index as u8);
|
// self.spans.push(self.span);
|
||||||
self.spans.push(self.span);
|
self.emit_byte(constant_index);
|
||||||
|
// self.chunk.bytecode.push(constant_index as u8);
|
||||||
|
// self.spans.push(self.span);
|
||||||
self.stack_depth += 1;
|
self.stack_depth += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,10 +384,12 @@ impl Compiler {
|
||||||
if constant_index == self.chunk.constants.len() {
|
if constant_index == self.chunk.constants.len() {
|
||||||
self.chunk.constants.push(val);
|
self.chunk.constants.push(val);
|
||||||
}
|
}
|
||||||
self.chunk.bytecode.push(Op::MatchConstant as u8);
|
self.emit_op(Op::MatchConstant);
|
||||||
self.spans.push(self.span);
|
self.emit_byte(constant_index);
|
||||||
self.chunk.bytecode.push(constant_index as u8);
|
// self.chunk.bytecode.push(Op::MatchConstant as u8);
|
||||||
self.spans.push(self.span);
|
// self.spans.push(self.span);
|
||||||
|
// self.chunk.bytecode.push(constant_index as u8);
|
||||||
|
// self.spans.push(self.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_op(&mut self, op: Op) {
|
fn emit_op(&mut self, op: Op) {
|
||||||
|
@ -572,6 +578,12 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
self.match_constant(Value::Keyword(kw_index));
|
self.match_constant(Value::Keyword(kw_index));
|
||||||
}
|
}
|
||||||
|
AsPattern(word, typ) => {
|
||||||
|
self.emit_constant(self.chunk.kw_from(typ).unwrap());
|
||||||
|
self.emit_op(Op::MatchType);
|
||||||
|
self.stack_depth -= 1;
|
||||||
|
self.bind(word);
|
||||||
|
}
|
||||||
StringPattern(s) => {
|
StringPattern(s) => {
|
||||||
let existing_str = self.chunk.strings.iter().position(|e| e == s);
|
let existing_str = self.chunk.strings.iter().position(|e| e == s);
|
||||||
let str_index = match existing_str {
|
let str_index = match existing_str {
|
||||||
|
@ -1142,7 +1154,6 @@ impl Compiler {
|
||||||
| Do(..)
|
| Do(..)
|
||||||
| Splat(..)
|
| Splat(..)
|
||||||
| InterpolatedPattern(..)
|
| InterpolatedPattern(..)
|
||||||
| AsPattern(..)
|
|
||||||
| Splattern(..) => todo!(),
|
| Splattern(..) => todo!(),
|
||||||
And | Or => unreachable!(),
|
And | Or => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -1160,7 +1171,7 @@ impl Compiler {
|
||||||
| MatchFalse | MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen
|
| MatchFalse | MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen
|
||||||
| PanicNoMatch | TypeOf | Duplicate | Truncate | Decrement | LoadTuple
|
| PanicNoMatch | TypeOf | Duplicate | Truncate | Decrement | LoadTuple
|
||||||
| LoadList | Eq | Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At
|
| LoadList | Eq | Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At
|
||||||
| Not | Panic | EmptyString | ConcatStrings | Stringify => {
|
| Not | Panic | EmptyString | ConcatStrings | Stringify | MatchType => {
|
||||||
println!("{i:04}: {op}")
|
println!("{i:04}: {op}")
|
||||||
}
|
}
|
||||||
Constant | MatchConstant => {
|
Constant | MatchConstant => {
|
||||||
|
|
|
@ -74,10 +74,8 @@ pub fn run(src: &'static str) {
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
env::set_var("RUST_BACKTRACE", "1");
|
env::set_var("RUST_BACKTRACE", "1");
|
||||||
let src = "
|
let src = "
|
||||||
let x = 42
|
let (x as :keyword, y as :number) = (:ok, 42)
|
||||||
let y = :foo
|
[x, y]
|
||||||
let z = \"thing\"
|
|
||||||
\"{x} {y} {z}\"
|
|
||||||
";
|
";
|
||||||
run(src);
|
run(src);
|
||||||
}
|
}
|
||||||
|
|
16
src/vm.rs
16
src/vm.rs
|
@ -249,6 +249,15 @@ impl<'a> Vm<'a> {
|
||||||
self.matches = true;
|
self.matches = true;
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
}
|
}
|
||||||
|
MatchType => {
|
||||||
|
let as_type = self.pop();
|
||||||
|
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||||
|
let val_type = self.stack[idx].type_of();
|
||||||
|
let val_type = self.chunk.kw_from(val_type).unwrap();
|
||||||
|
self.matches = val_type == as_type;
|
||||||
|
self.ip += 1;
|
||||||
|
self.interpret()
|
||||||
|
}
|
||||||
MatchNil => {
|
MatchNil => {
|
||||||
let idx = self.stack.len() - self.match_depth as usize - 1;
|
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||||
if self.stack[idx] == Value::Nil {
|
if self.stack[idx] == Value::Nil {
|
||||||
|
@ -579,14 +588,15 @@ impl<'a> Vm<'a> {
|
||||||
self.push(Value::String(Rc::new("".to_string())));
|
self.push(Value::String(Rc::new("".to_string())));
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
}
|
}
|
||||||
|
//TODO: don't use the schlemiel's algo here
|
||||||
ConcatStrings => {
|
ConcatStrings => {
|
||||||
let second = self.pop();
|
let second = self.pop();
|
||||||
let first = self.pop();
|
let first = self.pop();
|
||||||
let combined = match (first, second) {
|
let combined = match (first, second) {
|
||||||
(Value::String(first), Value::String(second)) => {
|
(Value::String(first), Value::String(second)) => {
|
||||||
let mut newstr = first.as_ref().clone();
|
let mut new = first.as_ref().clone();
|
||||||
newstr.push_str(second.as_str());
|
new.push_str(second.as_str());
|
||||||
Value::String(Rc::new(newstr))
|
Value::String(Rc::new(new))
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user