add as patterns

This commit is contained in:
Scott Richmond 2025-05-30 14:57:51 -04:00
parent cda217f6ef
commit 34ab24c4c9
3 changed files with 37 additions and 18 deletions

View File

@ -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 => {

View File

@ -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);
} }

View File

@ -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!(),
}; };