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,
PanicIfNoMatch,
MatchConstant,
MatchType,
MatchTuple,
PushTuple,
LoadTuple,
@ -140,6 +141,7 @@ impl std::fmt::Display for Op {
ResetMatch => "reset_match",
PanicIfNoMatch => "panic_if_no_match",
MatchConstant => "match_constant",
MatchType => "match_type",
MatchTuple => "match_tuple",
PushTuple => "push_tuple",
LoadTuple => "load_tuple",
@ -210,7 +212,7 @@ impl Chunk {
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch
| TypeOf | Duplicate | Decrement | Truncate | Noop | LoadTuple | LoadList | Eq
| Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At | Not | Panic
| EmptyString | ConcatStrings | Stringify => {
| EmptyString | ConcatStrings | Stringify | MatchType => {
println!("{i:04}: {op}")
}
Constant | MatchConstant => {
@ -359,10 +361,12 @@ impl Compiler {
)
}
self.chunk.constants.push(val);
self.chunk.bytecode.push(Op::Constant as u8);
self.spans.push(self.span);
self.chunk.bytecode.push(constant_index as u8);
self.spans.push(self.span);
self.emit_op(Op::Constant);
// self.chunk.bytecode.push(Op::Constant as u8);
// 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;
}
@ -380,10 +384,12 @@ impl Compiler {
if constant_index == self.chunk.constants.len() {
self.chunk.constants.push(val);
}
self.chunk.bytecode.push(Op::MatchConstant as u8);
self.spans.push(self.span);
self.chunk.bytecode.push(constant_index as u8);
self.spans.push(self.span);
self.emit_op(Op::MatchConstant);
self.emit_byte(constant_index);
// self.chunk.bytecode.push(Op::MatchConstant as u8);
// 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) {
@ -572,6 +578,12 @@ impl Compiler {
}
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) => {
let existing_str = self.chunk.strings.iter().position(|e| e == s);
let str_index = match existing_str {
@ -1142,7 +1154,6 @@ impl Compiler {
| Do(..)
| Splat(..)
| InterpolatedPattern(..)
| AsPattern(..)
| Splattern(..) => todo!(),
And | Or => unreachable!(),
}
@ -1160,7 +1171,7 @@ impl Compiler {
| MatchFalse | MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen
| PanicNoMatch | TypeOf | Duplicate | Truncate | Decrement | LoadTuple
| 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}")
}
Constant | MatchConstant => {

View File

@ -74,10 +74,8 @@ pub fn run(src: &'static str) {
pub fn main() {
env::set_var("RUST_BACKTRACE", "1");
let src = "
let x = 42
let y = :foo
let z = \"thing\"
\"{x} {y} {z}\"
let (x as :keyword, y as :number) = (:ok, 42)
[x, y]
";
run(src);
}

View File

@ -249,6 +249,15 @@ impl<'a> Vm<'a> {
self.matches = true;
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 => {
let idx = self.stack.len() - self.match_depth as usize - 1;
if self.stack[idx] == Value::Nil {
@ -579,14 +588,15 @@ impl<'a> Vm<'a> {
self.push(Value::String(Rc::new("".to_string())));
self.ip += 1;
}
//TODO: don't use the schlemiel's algo here
ConcatStrings => {
let second = self.pop();
let first = self.pop();
let combined = match (first, second) {
(Value::String(first), Value::String(second)) => {
let mut newstr = first.as_ref().clone();
newstr.push_str(second.as_str());
Value::String(Rc::new(newstr))
let mut new = first.as_ref().clone();
new.push_str(second.as_str());
Value::String(Rc::new(new))
}
_ => unreachable!(),
};