From 7a4bf5ff29b72a91729b1074f0593eb124eb2de7 Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Mon, 18 Nov 2024 20:01:27 -0500 Subject: [PATCH] list splatterns! --- src/main.rs | 2 +- src/vm.rs | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7e1eee6..ea8c73d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,7 +55,7 @@ use crate::base::*; pub fn main() { let src = " -let (x, y, ...z) = (1, 2, 3) +let [x, y, ...z] = [1, 2, 3, 4] z "; let (tokens, lex_errs) = lexer().parse(src).into_output_errors(); diff --git a/src/vm.rs b/src/vm.rs index 658eb4a..cd51e18 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -110,16 +110,28 @@ pub fn match_pattern<'src, 'a>( Some(ctx) } (Pattern::List(x), Value::List(y)) => { - if x.len() != y.len() { + let has_splat = x.iter().any(|patt| { + if let (Pattern::Splattern(_), _) = patt { + true + } else { + false + } + }); + if x.len() > y.len() || (!has_splat && x.len() != y.len()) { return None; }; let to = ctx.len(); for i in 0..x.len() { - if let None = match_pattern(&x[i].0, y.get(i).unwrap(), ctx) { - while ctx.len() > to { - ctx.pop(); + if let Pattern::Splattern(patt) = &x[i].0 { + let list = Value::List(y.skip(i)); + match_pattern(&(*patt).0, &list, ctx); + } else { + if let None = match_pattern(&x[i].0, &y.get(i).unwrap(), ctx) { + while ctx.len() > to { + ctx.pop(); + } + return None; } - return None; } } Some(ctx)