move patterns, clauses into AST
This commit is contained in:
parent
cab1b3f173
commit
f5a6facb1c
104
src/base.rs
104
src/base.rs
|
@ -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)]
|
||||||
|
|
156
src/context.rs
156
src/context.rs
|
@ -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 = ×.0;
|
self.ast = ×.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
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -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 = *
|
ctx.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>()
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user