move patterns, clauses into AST

This commit is contained in:
Scott Richmond 2024-12-10 22:26:52 -05:00
parent cab1b3f173
commit f5a6facb1c
5 changed files with 144 additions and 145 deletions

View File

@ -4,7 +4,7 @@ use ran::ran_f64;
use std::rc::Rc; use std::rc::Rc;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Base<'src> { pub enum BaseFn<'src> {
Nullary(fn() -> Value<'src>), Nullary(fn() -> Value<'src>),
Unary(fn(&Value<'src>) -> Value<'src>), Unary(fn(&Value<'src>) -> Value<'src>),
Binary(fn(&Value<'src>, &Value<'src>) -> Value<'src>), Binary(fn(&Value<'src>, &Value<'src>) -> Value<'src>),
@ -572,59 +572,59 @@ pub fn r#mod<'src>(x: &Value, y: &Value) -> Value<'src> {
pub fn base<'src>() -> Vec<(String, Value<'src>)> { pub fn base<'src>() -> Vec<(String, Value<'src>)> {
let members = vec![ let members = vec![
("add", Value::Base(Base::Binary(add))), ("add", Value::Base(BaseFn::Binary(add))),
("and", Value::Base(Base::Binary(and))), ("and", Value::Base(BaseFn::Binary(and))),
("append", Value::Base(Base::Binary(append))), ("append", Value::Base(BaseFn::Binary(append))),
("assoc", Value::Base(Base::Ternary(assoc))), ("assoc", Value::Base(BaseFn::Ternary(assoc))),
("at", Value::Base(Base::Binary(at))), ("at", Value::Base(BaseFn::Binary(at))),
("atan_2", Value::Base(Base::Binary(atan_2))), ("atan_2", Value::Base(BaseFn::Binary(atan_2))),
("bool", Value::Base(Base::Unary(r#bool))), ("bool", Value::Base(BaseFn::Unary(r#bool))),
("ceil", Value::Base(Base::Unary(ceil))), ("ceil", Value::Base(BaseFn::Unary(ceil))),
("chars", Value::Base(Base::Unary(chars))), ("chars", Value::Base(BaseFn::Unary(chars))),
("concat", Value::Base(Base::Binary(concat))), ("concat", Value::Base(BaseFn::Binary(concat))),
("cos", Value::Base(Base::Unary(cos))), ("cos", Value::Base(BaseFn::Unary(cos))),
("count", Value::Base(Base::Unary(count))), ("count", Value::Base(BaseFn::Unary(count))),
("dec", Value::Base(Base::Unary(dec))), ("dec", Value::Base(BaseFn::Unary(dec))),
("dissoc", Value::Base(Base::Binary(dissoc))), ("dissoc", Value::Base(BaseFn::Binary(dissoc))),
("div", Value::Base(Base::Binary(div))), ("div", Value::Base(BaseFn::Binary(div))),
("doc!", Value::Base(Base::Unary(doc))), ("doc!", Value::Base(BaseFn::Unary(doc))),
("downcase", Value::Base(Base::Unary(downcase))), ("downcase", Value::Base(BaseFn::Unary(downcase))),
("eq?", Value::Base(Base::Binary(eq))), ("eq?", Value::Base(BaseFn::Binary(eq))),
("first", Value::Base(Base::Unary(first))), ("first", Value::Base(BaseFn::Unary(first))),
("floor", Value::Base(Base::Unary(floor))), ("floor", Value::Base(BaseFn::Unary(floor))),
("get", Value::Base(Base::Binary(get))), ("get", Value::Base(BaseFn::Binary(get))),
("gt?", Value::Base(Base::Binary(gt))), ("gt?", Value::Base(BaseFn::Binary(gt))),
("gte?", Value::Base(Base::Binary(gte))), ("gte?", Value::Base(BaseFn::Binary(gte))),
("inc", Value::Base(Base::Unary(inc))), ("inc", Value::Base(BaseFn::Unary(inc))),
("last", Value::Base(Base::Unary(last))), ("last", Value::Base(BaseFn::Unary(last))),
("list", Value::Base(Base::Unary(list))), ("list", Value::Base(BaseFn::Unary(list))),
("lt?", Value::Base(Base::Binary(lt))), ("lt?", Value::Base(BaseFn::Binary(lt))),
("lte?", Value::Base(Base::Binary(lte))), ("lte?", Value::Base(BaseFn::Binary(lte))),
("mod", Value::Base(Base::Binary(r#mod))), ("mod", Value::Base(BaseFn::Binary(r#mod))),
("mult", Value::Base(Base::Binary(mult))), ("mult", Value::Base(BaseFn::Binary(mult))),
("number", Value::Base(Base::Unary(number))), ("number", Value::Base(BaseFn::Unary(number))),
("or", Value::Base(Base::Binary(or))), ("or", Value::Base(BaseFn::Binary(or))),
("pi", Value::Number(std::f64::consts::PI)), ("pi", Value::Number(std::f64::consts::PI)),
("print!", Value::Base(Base::Unary(print))), ("print!", Value::Base(BaseFn::Unary(print))),
("random", Value::Base(Base::Nullary(random))), ("random", Value::Base(BaseFn::Nullary(random))),
("range", Value::Base(Base::Binary(range))), ("range", Value::Base(BaseFn::Binary(range))),
("rest", Value::Base(Base::Unary(rest))), ("rest", Value::Base(BaseFn::Unary(rest))),
("round", Value::Base(Base::Unary(round))), ("round", Value::Base(BaseFn::Unary(round))),
("show", Value::Base(Base::Unary(show))), ("show", Value::Base(BaseFn::Unary(show))),
("sin", Value::Base(Base::Unary(sin))), ("sin", Value::Base(BaseFn::Unary(sin))),
("slice", Value::Base(Base::Ternary(slice))), ("slice", Value::Base(BaseFn::Ternary(slice))),
("split", Value::Base(Base::Binary(split))), ("split", Value::Base(BaseFn::Binary(split))),
("sqrt", Value::Base(Base::Unary(sqrt))), ("sqrt", Value::Base(BaseFn::Unary(sqrt))),
("sqrt_2", Value::Number(std::f64::consts::SQRT_2)), ("sqrt_2", Value::Number(std::f64::consts::SQRT_2)),
("store!", Value::Base(Base::Binary(store))), ("store!", Value::Base(BaseFn::Binary(store))),
("sub", Value::Base(Base::Binary(sub))), ("sub", Value::Base(BaseFn::Binary(sub))),
("tan", Value::Base(Base::Unary(tan))), ("tan", Value::Base(BaseFn::Unary(tan))),
("trim", Value::Base(Base::Unary(trim))), ("trim", Value::Base(BaseFn::Unary(trim))),
("triml", Value::Base(Base::Unary(triml))), ("triml", Value::Base(BaseFn::Unary(triml))),
("trimr", Value::Base(Base::Unary(trimr))), ("trimr", Value::Base(BaseFn::Unary(trimr))),
("type", Value::Base(Base::Unary(r#type))), ("type", Value::Base(BaseFn::Unary(r#type))),
("unbox", Value::Base(Base::Unary(unbox))), ("unbox", Value::Base(BaseFn::Unary(unbox))),
("upcase", Value::Base(Base::Unary(upcase))), ("upcase", Value::Base(BaseFn::Unary(upcase))),
]; ];
let pkg = Value::Dict(HashMap::from(members)); let pkg = Value::Dict(HashMap::from(members));
vec![("base".to_string(), pkg)] vec![("base".to_string(), pkg)]

View File

@ -1,5 +1,6 @@
use crate::base::*; use crate::base::*;
use crate::parser::*; use crate::parser::*;
use crate::spans::*;
use crate::value::{Fn, Value}; use crate::value::{Fn, Value};
use imbl::HashMap; use imbl::HashMap;
use imbl::Vector; use imbl::Vector;
@ -71,16 +72,17 @@ impl<'src> Context<'src> {
} }
} }
pub fn match_pattern(&mut self, patt: &Pattern, val: &Value<'src>) -> Option<&Context<'src>> { pub fn match_pattern(&mut self, patt: &Ast, val: &Value<'src>) -> Option<&Context<'src>> {
use Ast::*;
match (patt, val) { match (patt, val) {
(Pattern::Nil, Value::Nil) => Some(self), (NilPattern, Value::Nil) => Some(self),
(Pattern::Placeholder, _) => Some(self), (PlaceholderPattern, _) => Some(self),
(Pattern::Number(x), Value::Number(y)) => self.match_eq(x, y), (NumberPattern(x), Value::Number(y)) => self.match_eq(x, y),
(Pattern::Boolean(x), Value::Boolean(y)) => self.match_eq(x, y), (BooleanPattern(x), Value::Boolean(y)) => self.match_eq(x, y),
(Pattern::Keyword(x), Value::Keyword(y)) => self.match_eq(x, y), (KeywordPattern(x), Value::Keyword(y)) => self.match_eq(x, y),
(Pattern::String(x), Value::InternedString(y)) => self.match_eq(x, y), (StringPattern(x), Value::InternedString(y)) => self.match_eq(x, y),
(Pattern::String(x), Value::AllocatedString(y)) => self.match_eq(&x.to_string(), y), (StringPattern(x), Value::AllocatedString(y)) => self.match_eq(&x.to_string(), y),
(Pattern::Interpolated(_, StringMatcher(matcher)), Value::InternedString(y)) => { (InterpolatedPattern(_, StringMatcher(matcher)), Value::InternedString(y)) => {
match matcher(y.to_string()) { match matcher(y.to_string()) {
Some(matches) => { Some(matches) => {
let mut matches = matches let mut matches = matches
@ -98,11 +100,11 @@ impl<'src> Context<'src> {
None => None, None => None,
} }
} }
(Pattern::Word(w), val) => { (WordPattern(w), val) => {
self.bind(w.to_string(), &val); self.bind(w.to_string(), &val);
Some(self) Some(self)
} }
(Pattern::As(word, type_str), value) => { (AsPattern(word, type_str), value) => {
let ludus_type = r#type(value); let ludus_type = r#type(value);
let type_kw = Value::Keyword(type_str); let type_kw = Value::Keyword(type_str);
if type_kw == ludus_type { if type_kw == ludus_type {
@ -112,16 +114,14 @@ impl<'src> Context<'src> {
None None
} }
} }
(Pattern::Tuple(x), Value::Tuple(y)) => { (TuplePattern(x), Value::Tuple(y)) => {
let has_splat = x let has_splat = x.iter().any(|patt| matches!(patt, (Splattern(_), _)));
.iter()
.any(|patt| matches!(patt, (Pattern::Splattern(_), _)));
if x.len() > y.len() || (!has_splat && x.len() != y.len()) { if x.len() > y.len() || (!has_splat && x.len() != y.len()) {
return None; return None;
}; };
let to = self.locals.len(); let to = self.locals.len();
for i in 0..x.len() { for i in 0..x.len() {
if let Pattern::Splattern(patt) = &x[i].0 { if let Splattern(patt) = &x[i].0 {
let mut list = Vector::new(); let mut list = Vector::new();
for i in i..y.len() { for i in i..y.len() {
list.push_back(y[i].clone()) list.push_back(y[i].clone())
@ -135,16 +135,14 @@ impl<'src> Context<'src> {
} }
Some(self) Some(self)
} }
(Pattern::List(x), Value::List(y)) => { (ListPattern(x), Value::List(y)) => {
let has_splat = x let has_splat = x.iter().any(|patt| matches!(patt, (Splattern(_), _)));
.iter()
.any(|patt| matches!(patt, (Pattern::Splattern(_), _)));
if x.len() > y.len() || (!has_splat && x.len() != y.len()) { if x.len() > y.len() || (!has_splat && x.len() != y.len()) {
return None; return None;
}; };
let to = self.locals.len(); let to = self.locals.len();
for (i, (patt, _)) in x.iter().enumerate() { for (i, (patt, _)) in x.iter().enumerate() {
if let Pattern::Splattern(patt) = &patt { if let Splattern(patt) = &patt {
let list = Value::List(y.skip(i)); let list = Value::List(y.skip(i));
self.match_pattern(&patt.0, &list); self.match_pattern(&patt.0, &list);
} else if self.match_pattern(patt, y.get(i).unwrap()).is_none() { } else if self.match_pattern(patt, y.get(i).unwrap()).is_none() {
@ -157,10 +155,8 @@ impl<'src> Context<'src> {
// TODO: optimize this on several levels // TODO: optimize this on several levels
// - [ ] opportunistic mutation // - [ ] opportunistic mutation
// - [ ] get rid of all the pointer indirection in word splats // - [ ] get rid of all the pointer indirection in word splats
(Pattern::Dict(x), Value::Dict(y)) => { (DictPattern(x), Value::Dict(y)) => {
let has_splat = x let has_splat = x.iter().any(|patt| matches!(patt, (Splattern(_), _)));
.iter()
.any(|patt| matches!(patt, (Pattern::Splattern(_), _)));
if x.len() > y.len() || (!has_splat && x.len() != y.len()) { if x.len() > y.len() || (!has_splat && x.len() != y.len()) {
return None; return None;
}; };
@ -168,7 +164,7 @@ impl<'src> Context<'src> {
let mut matched = vec![]; let mut matched = vec![];
for (pattern, _) in x { for (pattern, _) in x {
match pattern { match pattern {
Pattern::Pair(key, patt) => { PairPattern(key, patt) => {
if let Some(val) = y.get(key) { if let Some(val) = y.get(key) {
if self.match_pattern(&patt.0, val).is_none() { if self.match_pattern(&patt.0, val).is_none() {
self.pop_to(to); self.pop_to(to);
@ -180,8 +176,8 @@ impl<'src> Context<'src> {
return None; return None;
}; };
} }
Pattern::Splattern(pattern) => match pattern.0 { Splattern(pattern) => match pattern.0 {
Pattern::Word(w) => { WordPattern(w) => {
// TODO: find a way to take ownership // TODO: find a way to take ownership
// this will ALWAYS make structural changes, because of this clone // this will ALWAYS make structural changes, because of this clone
// we want opportunistic mutation if possible // we want opportunistic mutation if possible
@ -191,7 +187,7 @@ impl<'src> Context<'src> {
} }
self.bind(w.to_string(), &Value::Dict(unmatched)); self.bind(w.to_string(), &Value::Dict(unmatched));
} }
Pattern::Placeholder => (), PlaceholderPattern => (),
_ => unreachable!(), _ => unreachable!(),
}, },
_ => unreachable!(), _ => unreachable!(),
@ -206,14 +202,15 @@ impl<'src> Context<'src> {
pub fn match_clauses( pub fn match_clauses(
&mut self, &mut self,
value: &Value<'src>, value: &Value<'src>,
clauses: &'src [MatchClause], clauses: &'src [Spanned<Ast>],
) -> LResult<'src> { ) -> LResult<'src> {
{ {
let parent = self.ast; let parent = self.ast;
let to = self.locals.len(); let to = self.locals.len();
for MatchClause { patt, body, guard } in clauses.iter() { let mut clauses = clauses.iter();
while let Some((Ast::MatchClause(patt, guard, body), _)) = clauses.next() {
if let Some(_) = self.match_pattern(&patt.0, value) { if let Some(_) = self.match_pattern(&patt.0, value) {
let pass_guard = match guard { let pass_guard = match guard.as_ref() {
None => true, None => true,
Some((ast, _)) => { Some((ast, _)) => {
self.ast = ast; self.ast = ast;
@ -240,30 +237,31 @@ impl<'src> Context<'src> {
} }
pub fn apply(&mut self, callee: Value<'src>, caller: Value<'src>) -> LResult<'src> { pub fn apply(&mut self, callee: Value<'src>, caller: Value<'src>) -> LResult<'src> {
use Value::*;
match (callee, caller) { match (callee, caller) {
(Value::Keyword(kw), Value::Dict(dict)) => { (Keyword(kw), Dict(dict)) => {
if let Some(val) = dict.get(kw) { if let Some(val) = dict.get(kw) {
Ok(val.clone()) Ok(val.clone())
} else { } else {
Ok(Value::Nil) Ok(Nil)
} }
} }
(Value::Dict(dict), Value::Keyword(kw)) => { (Dict(dict), Keyword(kw)) => {
if let Some(val) = dict.get(kw) { if let Some(val) = dict.get(kw) {
Ok(val.clone()) Ok(val.clone())
} else { } else {
Ok(Value::Nil) Ok(Nil)
} }
} }
(Value::Fn(f), Value::Tuple(args)) => { (Fn(f), Tuple(args)) => {
let args = Value::Tuple(args); let args = Tuple(args);
self.match_clauses(&args, f.body) self.match_clauses(&args, f.body)
} }
(Value::Fn(_f), Value::Args(_args)) => todo!(), (Fn(_f), Args(_args)) => todo!(),
(_, Value::Keyword(_)) => Ok(Value::Nil), (_, Keyword(_)) => Ok(Nil),
(_, Value::Args(_)) => Err(LErr::new(format!("you may only call a function"))), (_, Args(_)) => Err(LErr::new(format!("you may only call a function"))),
(Value::Base(f), Value::Tuple(args)) => match f { (Base(f), Tuple(args)) => match f {
Base::Nullary(f) => { BaseFn::Nullary(f) => {
let num_args = args.len(); let num_args = args.len();
if num_args != 0 { if num_args != 0 {
Err(LErr::new(format!( Err(LErr::new(format!(
@ -273,7 +271,7 @@ impl<'src> Context<'src> {
Ok(f()) Ok(f())
} }
} }
Base::Unary(f) => { BaseFn::Unary(f) => {
let num_args = args.len(); let num_args = args.len();
if num_args != 1 { if num_args != 1 {
Err(LErr::new(format!( Err(LErr::new(format!(
@ -283,7 +281,7 @@ impl<'src> Context<'src> {
Ok(f(&args[0])) Ok(f(&args[0]))
} }
} }
Base::Binary(r#fn) => { BaseFn::Binary(r#fn) => {
let num_args = args.len(); let num_args = args.len();
if num_args != 2 { if num_args != 2 {
Err(LErr::new(format!( Err(LErr::new(format!(
@ -293,7 +291,7 @@ impl<'src> Context<'src> {
Ok(r#fn(&args[0], &args[1])) Ok(r#fn(&args[0], &args[1]))
} }
} }
Base::Ternary(f) => { BaseFn::Ternary(f) => {
let num_args = args.len(); let num_args = args.len();
if num_args != 3 { if num_args != 3 {
Err(LErr::new(format!( Err(LErr::new(format!(
@ -309,15 +307,16 @@ impl<'src> Context<'src> {
} }
pub fn eval(&mut self) -> LResult<'src> { pub fn eval(&mut self) -> LResult<'src> {
use Ast::*;
let root = self.ast; let root = self.ast;
let result = match self.ast { let result = match self.ast {
Ast::Nil => Ok(Value::Nil), Nil => Ok(Value::Nil),
Ast::Boolean(b) => Ok(Value::Boolean(*b)), Boolean(b) => Ok(Value::Boolean(*b)),
Ast::Number(n) => Ok(Value::Number(*n)), Number(n) => Ok(Value::Number(*n)),
Ast::Keyword(k) => Ok(Value::Keyword(k)), Keyword(k) => Ok(Value::Keyword(k)),
Ast::String(s) => Ok(Value::InternedString(s)), String(s) => Ok(Value::InternedString(s)),
Ast::Interpolated(parts) => { Interpolated(parts) => {
let mut interpolated = String::new(); let mut interpolated = std::string::String::new();
for part in parts { for part in parts {
match &part.0 { match &part.0 {
StringPart::Data(s) => interpolated.push_str(s.as_str()), StringPart::Data(s) => interpolated.push_str(s.as_str()),
@ -330,7 +329,7 @@ impl<'src> Context<'src> {
} }
Ok(Value::AllocatedString(Rc::new(interpolated))) Ok(Value::AllocatedString(Rc::new(interpolated)))
} }
Ast::Block(exprs) => { Block(exprs) => {
let parent = self.ast; let parent = self.ast;
let to = self.locals.len(); let to = self.locals.len();
let mut result = Value::Nil; let mut result = Value::Nil;
@ -342,7 +341,7 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
Ok(result) Ok(result)
} }
Ast::If(cond, if_true, if_false) => { If(cond, if_true, if_false) => {
let parent = self.ast; let parent = self.ast;
self.ast = &cond.0; self.ast = &cond.0;
let truthy = self.eval()?.bool(); let truthy = self.eval()?.bool();
@ -351,7 +350,7 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
result result
} }
Ast::List(members) => { List(members) => {
let parent = self.ast; let parent = self.ast;
let mut vect = Vector::new(); let mut vect = Vector::new();
for member in members { for member in members {
@ -373,7 +372,7 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
Ok(Value::List(vect)) Ok(Value::List(vect))
} }
Ast::Tuple(members) => { Tuple(members) => {
let parent = self.ast; let parent = self.ast;
let mut vect = Vec::new(); let mut vect = Vec::new();
for member in members { for member in members {
@ -383,11 +382,11 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
Ok(Value::Tuple(Rc::new(vect))) Ok(Value::Tuple(Rc::new(vect)))
} }
Ast::Word(w) | Ast::Splat(w) => { Word(w) | Ast::Splat(w) => {
let val = self.resolve(&w.to_string())?; let val = self.resolve(&w.to_string())?;
Ok(val) Ok(val)
} }
Ast::Let(patt, expr) => { Let(patt, expr) => {
let parent = self.ast; let parent = self.ast;
self.ast = &expr.0; self.ast = &expr.0;
let val = self.eval()?; let val = self.eval()?;
@ -398,9 +397,8 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
result result
} }
Ast::Placeholder => Ok(Value::Placeholder), Placeholder => Ok(Value::Placeholder),
Ast::Error => unreachable!(), Arguments(a) => {
Ast::Arguments(a) => {
let parent = self.ast; let parent = self.ast;
let mut args = vec![]; let mut args = vec![];
for (arg, _) in a.iter() { for (arg, _) in a.iter() {
@ -416,7 +414,7 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
result result
} }
Ast::Dict(terms) => { Dict(terms) => {
let parent = self.ast; let parent = self.ast;
let mut dict = HashMap::new(); let mut dict = HashMap::new();
for term in terms { for term in terms {
@ -441,7 +439,7 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
Ok(Value::Dict(dict)) Ok(Value::Dict(dict))
} }
Ast::LBox(name, expr) => { LBox(name, expr) => {
let parent = self.ast; let parent = self.ast;
self.ast = &expr.0; self.ast = &expr.0;
let val = self.eval()?; let val = self.eval()?;
@ -450,7 +448,7 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
Ok(boxed) Ok(boxed)
} }
Ast::Synthetic(root, first, rest) => { Synthetic(root, first, rest) => {
let parent = self.ast; let parent = self.ast;
self.ast = &root.0; self.ast = &root.0;
let root = self.eval()?; let root = self.eval()?;
@ -465,10 +463,12 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
Ok(curr) Ok(curr)
} }
Ast::When(clauses) => { When(clauses) => {
let parent = self.ast; let parent = self.ast;
for clause in clauses.iter() { for clause in clauses.iter() {
let WhenClause { cond, body } = &clause.0; let WhenClause(cond, body) = &clause.0 else {
unreachable!()
};
self.ast = &cond.0; self.ast = &cond.0;
if self.eval()?.bool() { if self.eval()?.bool() {
self.ast = &body.0; self.ast = &body.0;
@ -479,7 +479,7 @@ impl<'src> Context<'src> {
} }
Err(LErr::new(format!("no match"))) Err(LErr::new(format!("no match")))
} }
Ast::Match(value, clauses) => { Match(value, clauses) => {
let parent = self.ast; let parent = self.ast;
self.ast = &value.0; self.ast = &value.0;
let value = self.eval()?; let value = self.eval()?;
@ -487,9 +487,9 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
result result
} }
Ast::Fn(name, clauses, doc) => { Fn(name, clauses, doc) => {
let doc = doc.map(|s| s.to_string()); let doc = doc.map(|s| s.to_string());
let the_fn = Value::Fn::<'src>(Rc::new(Fn::<'src> { let the_fn = Value::Fn::<'src>(Rc::new(crate::value::Fn::<'src> {
name: name.to_string(), name: name.to_string(),
body: clauses, body: clauses,
doc, doc,
@ -497,13 +497,13 @@ impl<'src> Context<'src> {
self.bind(name.to_string(), &the_fn); self.bind(name.to_string(), &the_fn);
Ok(the_fn) Ok(the_fn)
} }
Ast::FnDeclaration(_name) => Ok(Value::Nil), FnDeclaration(_name) => Ok(Value::Nil),
Ast::Panic(msg) => { Panic(msg) => {
self.ast = &msg.0; self.ast = &msg.0;
let msg = self.eval()?; let msg = self.eval()?;
Err(LErr::new(format!("{msg}"))) Err(LErr::new(format!("{msg}")))
} }
Ast::Repeat(times, body) => { Repeat(times, body) => {
let parent = self.ast; let parent = self.ast;
self.ast = &times.0; self.ast = &times.0;
let times_num = match self.eval() { let times_num = match self.eval() {
@ -517,7 +517,7 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
Ok(Value::Nil) Ok(Value::Nil)
} }
Ast::Do(terms) => { Do(terms) => {
let parent = self.ast; let parent = self.ast;
self.ast = &terms[0].0; self.ast = &terms[0].0;
let mut result = self.eval()?; let mut result = self.eval()?;
@ -530,10 +530,7 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
Ok(result) Ok(result)
} }
Ast::Pair(..) => { Loop(init, clauses) => {
unreachable!()
}
Ast::Loop(init, clauses) => {
let parent = self.ast; let parent = self.ast;
self.ast = &init.0; self.ast = &init.0;
let mut args = self.eval()?; let mut args = self.eval()?;
@ -547,7 +544,7 @@ impl<'src> Context<'src> {
} }
} }
} }
Ast::Recur(args) => { Recur(args) => {
let parent = self.ast; let parent = self.ast;
let mut vect = Vec::new(); let mut vect = Vec::new();
for arg in args { for arg in args {
@ -557,6 +554,7 @@ impl<'src> Context<'src> {
self.ast = parent; self.ast = parent;
Ok(Value::Recur(vect)) Ok(Value::Recur(vect))
} }
_ => unreachable!(),
}; };
self.ast = root; self.ast = root;
result result

View File

@ -150,26 +150,25 @@ pub fn run(src: &'static str) {
let mut valxor = validator::Validator::new(&ast, span, &dummy_prelude); let mut valxor = validator::Validator::new(&ast, span, &dummy_prelude);
valxor.validate(); // valxor.validate();
dbg!(valxor); // dbg!(valxor);
// let mut ctx = prelude(); let mut ctx = prelude();
// ctx.ast = &ast; ctx.ast = &ast;
// let result = ctx.eval(); let result = ctx.eval();
// match result { match result {
// Ok(result) => println!("{}", result), Ok(result) => println!("{}", result),
// Err(LErr { msg, .. }) => println!("Errors!\n{}", msg), Err(LErr { msg, .. }) => println!("Errors!\n{}", msg),
// } }
} }
pub fn main() { pub fn main() {
let src = " let src = "
loop () with { let #{:a (x, y), :b [1, 2, (a, b)]} = #{:a (1, 2), :b [1, 2, (7, 8)]}
() -> :baz (x, y, a, b)
}
"; ";
run(src); run(src);
// struct_scalpel::print_dissection_info::<value::Value>() // struct_scalpel::print_dissection_info::<value::Value>()

View File

@ -470,6 +470,7 @@ impl<'a> Validator<'a> {
} }
// terminals can never be invalid // terminals can never be invalid
Ast::Nil | Ast::Boolean(_) | Ast::Number(_) | Ast::Keyword(_) | Ast::String(_) => (), Ast::Nil | Ast::Boolean(_) | Ast::Number(_) | Ast::Keyword(_) | Ast::String(_) => (),
_ => todo!(),
}; };
self.ast = root; self.ast = root;
} }

View File

@ -1,5 +1,6 @@
use crate::base::*; use crate::base::*;
use crate::parser::*; use crate::parser::*;
use crate::spans::*;
use imbl::*; use imbl::*;
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt; use std::fmt;
@ -9,7 +10,7 @@ use struct_scalpel::Dissectible;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Fn<'src> { pub struct Fn<'src> {
pub name: String, pub name: String,
pub body: &'src Vec<MatchClause>, pub body: &'src Vec<Spanned<Ast>>,
pub doc: Option<String>, pub doc: Option<String>,
} }
@ -29,7 +30,7 @@ pub enum Value<'src> {
Dict(HashMap<&'static str, Self>), Dict(HashMap<&'static str, Self>),
Box(&'static str, Rc<RefCell<Self>>), Box(&'static str, Rc<RefCell<Self>>),
Fn(Rc<Fn<'src>>), Fn(Rc<Fn<'src>>),
Base(Base<'src>), Base(BaseFn<'src>),
Recur(Vec<Self>), Recur(Vec<Self>),
// Set(HashSet<Self>), // Set(HashSet<Self>),
// Sets are hard // Sets are hard