diff --git a/Cargo.toml b/Cargo.toml index e87738c..428082a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ license = "MIT OR Apache-2.0" thiserror = "1.0" itertools = "0.10" rpds = "0.11" +archery = "0.4" rustyline = { version = "9.1", optional = true } rustyline-derive = { version = "0.6", optional = true } diff --git a/src/analyzer/analyzed_form.rs b/src/analyzer/analyzed_form.rs deleted file mode 100644 index e36e6fb..0000000 --- a/src/analyzer/analyzed_form.rs +++ /dev/null @@ -1,128 +0,0 @@ -use crate::namespace::Var; -use crate::reader::{Atom, Identifier, Symbol}; -use std::collections::HashSet; - -pub enum AnalyzedForm<'a> { - LexicalSymbol(&'a Identifier), - Var(Var), - Atom(&'a Atom), - List(AnalyzedList<'a>), - Vector(Vec>), - Map(Vec<(AnalyzedForm<'a>, AnalyzedForm<'a>)>), - Set(Vec>), -} - -pub enum AnalyzedList<'a> { - // (def! symbol form?) - Def(DefForm<'a>), - // (var symbol) - Var(&'a Symbol), - // (let* [bindings*] form*) - Let(LetForm<'a>), - // (loop* [bindings*] form*) - Loop(LexicalForm<'a>), - // (recur form*) - Recur(BodyForm<'a>), - // (if predicate consequent alternate?) - If(IfForm<'a>), - // (do form*) - Do(BodyForm<'a>), - //(fn* [parameters*] form*) - Fn(FnForm<'a>), - // (quote form) - Quote(Box>), - // (quasiquote form) - Quasiquote(Box>), - // // (unquote form) - // Unquote(Box>), - // // (splice-unquote form) - // SpliceUnquote(Box>), - // (defmacro! symbol fn*-form) - Defmacro(&'a Symbol, FnForm<'a>), - // (macroexpand macro-form) - Macroexpand(Box>), - // (try* form* catch*-form?) - Try(TryForm<'a>), - // (catch* exc-symbol form*) - Catch(CatchForm<'a>), - Form(Vec>), -} - -pub enum DefForm<'a> { - Bound(&'a Symbol, Box>), - Unbound(&'a Symbol), -} - -pub type LexicalBinding<'a> = (&'a Symbol, Box>); - -pub enum LexicalBindings<'a> { - Bound(Vec>), - Unbound(Vec<&'a Symbol>), -} - -pub struct LexicalForm<'a> { - pub bindings: LexicalBindings<'a>, - pub body: BodyForm<'a>, -} - -fn is_forward_visible(form: &AnalyzedForm<'_>) -> bool { - matches!(form, &AnalyzedForm::List(AnalyzedList::Fn(_))) -} - -impl<'a> LexicalForm<'a> { - pub(super) fn resolve_forward_declarations(&self) -> HashSet<&'a Symbol> { - let mut result = HashSet::new(); - match self.bindings { - LexicalBindings::Bound(bindings) => { - for (name, value) in bindings { - if is_forward_visible(value.as_ref()) { - result.insert(name); - } - } - } - LexicalBindings::Unbound(_) => {} - } - result - } -} - -pub struct LetForm<'a> { - pub lexical_form: LexicalForm<'a>, - // `let*` can produce "forward declarations" where some names - // in `scope` can be seen by all other names - pub forward_declarations: HashSet<&'a Symbol>, -} - -#[derive(Default)] -pub struct BodyForm<'a> { - body: Vec>, -} - -pub struct IfForm<'a> { - predicate: Box>, - consequent: Box>, - alternate: Option>>, -} - -pub struct FnForm<'a> { - parameters: Vec<&'a Symbol>, - variadic: Option<&'a Symbol>, - body: BodyForm<'a>, -} - -impl<'a> FnForm<'a> { - pub fn arity(&self) -> usize { - self.parameters.len() - } -} - -#[derive(Default)] -pub struct TryForm<'a> { - body: BodyForm<'a>, - catch: Option>, -} - -pub struct CatchForm<'a> { - exception_binding: &'a Symbol, - body: BodyForm<'a>, -} diff --git a/src/analyzer/analyzer.rs b/src/analyzer/analyzer.rs deleted file mode 100644 index 946d5cd..0000000 --- a/src/analyzer/analyzer.rs +++ /dev/null @@ -1,471 +0,0 @@ -use crate::collections::{PersistentList, PersistentMap, PersistentSet, PersistentVector}; -use crate::interpreter::{EvaluationResult, Interpreter, Scope, SyntaxError}; -use crate::value::{FnImpl, FnWithCapturesImpl, Value}; -use itertools::Itertools; -use std::collections::HashSet; -use std::iter::FromIterator; - -const MIN_VARIADIC_PARAM_COUNT: usize = 2; - -// type BindingRef<'a> = (&'a String, &'a Value); - -// each new `fn*` introduces a new "frame" -// forms within a `fn*` can introduce a new "scope" -// #[derive(Default, Debug)] -// struct Frame { -// scopes: Vec, -// forward_declarations: Vec, -// } - -// ref to a Frame in set of Frames and an identifier within that Frame -// type CaptureSet = HashSet<(usize, String)>; - -// pub struct LetBindings<'a> { -// bindings: Vec>, -// } - -// fn binding_declares_fn((name, value): &BindingRef) -> Option { -// match value { -// Value::List(elems) => match elems.first() { -// Some(Value::Symbol(s, None)) if s == "fn*" => Some(name.to_string()), -// _ => None, -// }, -// _ => None, -// } -// } - -// impl<'a> LetBindings<'a> { -// // allow let bindings that declare `fn*`s to capture other -// // let bindings that declare `fn*`s -// pub fn resolve_forward_declarations(&self) -> HashSet { -// self.bindings -// .iter() -// .filter_map(binding_declares_fn) -// .collect() -// } -// } - -// impl<'a> IntoIterator for LetBindings<'a> { -// type Item = BindingRef<'a>; -// type IntoIter = std::vec::IntoIter; - -// fn into_iter(self) -> Self::IntoIter { -// self.bindings.into_iter() -// } -// } - -// pub struct LetForm<'a> { -// pub bindings: LetBindings<'a>, -// pub body: PersistentList, -// } - -// fn parse_let_bindings(bindings_form: &Value) -> EvaluationResult { -// match bindings_form { -// Value::Vector(bindings) => { -// let bindings_count = bindings.len(); -// if bindings_count % 2 == 0 { -// let mut validated_bindings = Vec::with_capacity(bindings_count); -// for (name, value_form) in bindings.iter().tuples() { -// match name { -// Value::Symbol(s, None) => { -// validated_bindings.push((s, value_form)); -// } -// other => { -// return Err(SyntaxError::LexicalBindingsMustHaveSymbolNames( -// other.clone(), -// ) -// .into()); -// } -// } -// } -// Ok(LetBindings { -// bindings: validated_bindings, -// }) -// } else { -// Err(SyntaxError::LexicalBindingsMustBePaired(bindings.clone()).into()) -// } -// } -// other => Err(SyntaxError::LexicalBindingsMustBeVector(other.clone()).into()), -// } -// } - -// fn parse_let(forms: &PersistentList) -> EvaluationResult { -// let bindings_form = forms.first().ok_or(EvaluationError::WrongArity { -// expected: 1, -// realized: 0, -// })?; -// let body = forms.drop_first().ok_or(EvaluationError::WrongArity { -// expected: 2, -// realized: 1, -// })?; -// let bindings = parse_let_bindings(bindings_form)?; -// Ok(LetForm { bindings, body }) -// } - -// pub(crate) fn analyze_let(let_forms: &PersistentList) -> EvaluationResult { -// let let_form = parse_let(let_forms)?; -// Ok(let_form) -// } - -// pub struct Analyzer<'a> { -// interpreter: &'a mut Interpreter, -// } - -// impl<'a> Analyzer<'a> { -// fn new(interpreter: &'a mut Interpreter) -> Self { -// Self { interpreter } -// } - -// fn analyze_lexical_bindings_in_fn( -// &mut self, -// bindings: &PersistentVector, -// frames: &mut Vec, -// captures: &mut Vec, -// ) -> EvaluationResult { -// if bindings.len() % 2 != 0 { -// return Err(SyntaxError::LexicalBindingsMustBePaired(bindings.clone()).into()); -// } -// let mut analyzed_bindings = PersistentVector::new(); -// // NOTE: this is duplicated w/ `let*` analysis elsewhere... -// // TODO: consolidate to one analysis phase -// let mut forward_declarations = Scope::new(); -// for (name, value) in bindings.iter().tuples() { -// match name { -// Value::Symbol(s, None) => { -// if binding_declares_fn(&(s, value)).is_some() { -// forward_declarations.insert(s.clone(), Value::Symbol(s.clone(), None)); -// } -// } -// other => { -// return Err( -// SyntaxError::LexicalBindingsMustHaveSymbolNames(other.clone()).into(), -// ); -// } -// } -// } -// let bindings_scope_index = { -// let frame = frames.last_mut().expect("did push"); -// frame.scopes.push(Scope::new()); -// frame.forward_declarations.push(forward_declarations); -// frame.scopes.len() - 1 -// }; -// for (name, value) in bindings.iter().tuples() { -// let analyzed_value = self.analyze_form_in_fn(value, frames, captures)?; -// analyzed_bindings.push_back_mut(name.clone()); -// analyzed_bindings.push_back_mut(analyzed_value); -// // lexical bindings serially extend scope per binding: -// match name { -// Value::Symbol(s, None) => { -// let local_scopes = &mut frames.last_mut().expect("already pushed").scopes; -// let scope = local_scopes -// .get_mut(bindings_scope_index) -// .expect("did push bindings scope"); -// scope.insert(s.clone(), Value::Symbol(s.clone(), None)); -// } -// _ => unreachable!("already verified symbol names"), -// } -// } -// let frame = frames.last_mut().expect("did push"); -// frame.forward_declarations.pop(); -// Ok(Value::Vector(analyzed_bindings)) -// } - -// // Note: can only have captures over enclosing fns if we have recursive nesting of fns -// fn analyze_fn_in_fn_with_possible_captures( -// &mut self, -// body: PersistentList, -// bindings: &PersistentVector, -// frames: &mut Vec, -// captures: &mut Vec, -// ) -> EvaluationResult { -// captures.push(CaptureSet::new()); -// let analyzed_fn = self.analyze_symbols_in_fn(body, bindings, frames, captures)?; -// let captures_at_this_level = captures.pop().expect("did push"); -// if captures_at_this_level.is_empty() { -// return Ok(analyzed_fn); -// } -// let current_frame_index = frames.len() - 1; -// match analyzed_fn { -// Value::Fn(f) => { -// // Note: need to hoist captures if there are intervening functions along the way... -// for (captured_frame_index, capture) in &captures_at_this_level { -// if *captured_frame_index < current_frame_index { -// let target_captures = captures -// .get_mut(*captured_frame_index) -// .expect("already pushed captures"); -// target_captures.insert((*captured_frame_index, capture.to_string())); -// } -// } -// let captures = captures_at_this_level -// .iter() -// .map(|(_, capture)| (capture.to_string(), None)) -// .collect(); -// Ok(Value::FnWithCaptures(FnWithCapturesImpl { f, captures })) -// } -// _ => unreachable!("only returns Fn variant"), -// } -// } - -// fn analyze_list_in_fn( -// &mut self, -// elems: &PersistentList, -// frames: &mut Vec, -// captures: &mut Vec, -// ) -> EvaluationResult { -// let existing_scopes_count = { -// let local_scopes = &frames -// .last_mut() -// .expect("did push on analysis entry") -// .scopes; -// local_scopes.len() -// }; - -// // if first elem introduces a new lexical scope... -// let mut iter = elems.iter(); -// let mut analyzed_elems = vec![]; -// match iter.next() { -// Some(Value::Symbol(s, None)) if s == "let*" => { -// analyzed_elems.push(Value::Symbol(s.to_string(), None)); -// if let Some(Value::Vector(bindings)) = iter.next() { -// let analyzed_bindings = -// self.analyze_lexical_bindings_in_fn(bindings, frames, captures)?; -// analyzed_elems.push(analyzed_bindings); -// } -// } -// Some(Value::Symbol(s, None)) if s == "loop*" => { -// analyzed_elems.push(Value::Symbol(s.to_string(), None)); -// if let Some(Value::Vector(bindings)) = iter.next() { -// let analyzed_bindings = -// self.analyze_lexical_bindings_in_fn(bindings, frames, captures)?; -// analyzed_elems.push(analyzed_bindings); -// } -// } -// Some(Value::Symbol(s, None)) if s == "fn*" => { -// if let Some(Value::Vector(bindings)) = iter.next() { -// let body = iter.cloned().collect(); -// return self -// .analyze_fn_in_fn_with_possible_captures(body, bindings, frames, captures); -// } -// } -// Some(Value::Symbol(s, None)) if s == "catch*" => { -// if let Some(Value::Symbol(s, None)) = iter.next() { -// let mut bindings = PersistentVector::new(); -// bindings.push_back_mut(Value::Symbol(s.clone(), None)); -// let body = iter.cloned().collect(); -// return self.analyze_fn_in_fn_with_possible_captures( -// body, &bindings, frames, captures, -// ); -// } -// } -// Some(Value::Symbol(s, None)) if s == "quote" => { -// if let Some(Value::Symbol(s, None)) = iter.next() { -// let mut scope = Scope::new(); -// scope.insert(s.to_string(), Value::Symbol(s.to_string(), None)); -// let local_scopes = &mut frames.last_mut().expect("did push").scopes; -// local_scopes.push(scope); -// } -// } -// _ => {} -// } -// for elem in elems.iter().skip(analyzed_elems.len()) { -// let analyzed_elem = self.analyze_form_in_fn(elem, frames, captures)?; -// analyzed_elems.push(analyzed_elem); -// } -// let local_scopes = &mut frames.last_mut().expect("did push").scopes; -// local_scopes.truncate(existing_scopes_count); -// Ok(Value::List(PersistentList::from_iter(analyzed_elems))) -// } - -// // Analyze symbols (recursively) in `form`: -// // 1. Rewrite lambda parameters -// // 2. Capture references to external vars -// fn analyze_form_in_fn( -// &mut self, -// form: &Value, -// frames: &mut Vec, -// captures: &mut Vec, -// ) -> EvaluationResult { -// match form { -// Value::Symbol(identifier, ns_opt) => { -// let current_frame_index = frames.len() - 1; -// for (frame_index, frame) in frames.iter().enumerate().rev() { -// // NOTE: for now, need to side step rest of symbol resolution if a symbol -// // is part of a forward declaration... -// for scope in frame.forward_declarations.iter().rev() { -// if let Some(Value::Symbol(resolved_identifier, None)) = -// scope.get(identifier) -// { -// return Ok(Value::Symbol(resolved_identifier.clone(), None)); -// } -// } -// for scope in frame.scopes.iter().rev() { -// match scope.get(identifier) { -// Some(Value::Symbol(resolved_identifier, None)) => { -// let reference_outlives_source = frame_index < current_frame_index; -// // NOTE: current particularity of the implementation is to _not_ -// // capture forward declarations from `let*` bindings... -// if reference_outlives_source { -// let captures_at_level = captures -// .last_mut() -// .expect("did push captures to grab earlier frame"); -// // TODO: work through lifetimes here to avoid cloning... -// captures_at_level -// .insert((frame_index, resolved_identifier.clone())); -// } -// return Ok(Value::Symbol(resolved_identifier.clone(), None)); -// } -// Some(other) => { -// unreachable!("encountered unexpected value in `Scope`: {}", other) -// } -// None => {} -// } -// } -// } -// self.interpreter -// .resolve_symbol_to_var(identifier, ns_opt.as_ref()) -// } -// Value::List(elems) => { -// if elems.is_empty() { -// return Ok(Value::List(PersistentList::new())); -// } - -// let first = elems.first().unwrap(); -// let rest = elems.drop_first().expect("list is not empty"); -// if let Some(expansion) = self.interpreter.get_macro_expansion(first, &rest) { -// match expansion? { -// Value::List(elems) => self.analyze_list_in_fn(&elems, frames, captures), -// other => self.analyze_form_in_fn(&other, frames, captures), -// } -// } else { -// self.analyze_list_in_fn(elems, frames, captures) -// } -// } -// Value::Vector(elems) => { -// let mut analyzed_elems = PersistentVector::new(); -// for elem in elems.iter() { -// let analyzed_elem = self.analyze_form_in_fn(elem, frames, captures)?; -// analyzed_elems.push_back_mut(analyzed_elem); -// } -// Ok(Value::Vector(analyzed_elems)) -// } -// Value::Map(elems) => { -// let mut analyzed_elems = PersistentMap::new(); -// for (k, v) in elems.iter() { -// let analyzed_k = self.analyze_form_in_fn(k, frames, captures)?; -// let analyzed_v = self.analyze_form_in_fn(v, frames, captures)?; -// analyzed_elems.insert_mut(analyzed_k, analyzed_v); -// } -// Ok(Value::Map(analyzed_elems)) -// } -// Value::Set(elems) => { -// let mut analyzed_elems = PersistentSet::new(); -// for elem in elems.iter() { -// let analyzed_elem = self.analyze_form_in_fn(elem, frames, captures)?; -// analyzed_elems.insert_mut(analyzed_elem); -// } -// Ok(Value::Set(analyzed_elems)) -// } -// Value::Fn(_) => unreachable!(), -// Value::FnWithCaptures(_) => unreachable!(), -// Value::Primitive(_) => unreachable!(), -// Value::Recur(_) => unreachable!(), -// Value::Macro(_) => unreachable!(), -// Value::Exception(_) => unreachable!(), -// // Nil, Bool, Number, String, Keyword, Var, Atom -// other => Ok(other.clone()), -// } -// } - -// // fn extract_scope_from_fn_bindings( -// // &self, -// // params: &PersistentVector, -// // level: usize, -// // ) -> EvaluationResult<(Scope, bool)> { -// // let mut parameters = Scope::new(); -// // let mut variadic = false; -// // let params_count = params.len(); -// // for (index, param) in params.iter().enumerate() { -// // match param { -// // Value::Symbol(s, None) if s == "&" => { -// // if index + MIN_VARIADIC_PARAM_COUNT > params_count { -// // return Err(SyntaxError::VariadicArgMissing.into()); -// // } -// // variadic = true; -// // } -// // Value::Symbol(s, None) => { -// // if variadic { -// // if index + 1 != params_count { -// // return Err(SyntaxError::VariadicArgMustBeUnique(Value::Vector( -// // params.clone(), -// // )) -// // .into()); -// // } - -// // let parameter = lambda_parameter_key(index - 1, level); -// // parameters.insert(s.to_string(), Value::Symbol(parameter, None)); -// // } else { -// // let parameter = lambda_parameter_key(index, level); -// // parameters.insert(s.to_string(), Value::Symbol(parameter, None)); -// // } -// // } -// // other => { -// // return Err( -// // SyntaxError::LexicalBindingsMustHaveSymbolNames(other.clone()).into(), -// // ); -// // } -// // } -// // } -// // Ok((parameters, variadic)) -// // } - -// // Non-local symbols should: -// // 1. resolve to a parameter -// // 2. resolve to a value in the enclosing environment, which is captured -// // otherwise, the lambda is an error -// // -// // Note: parameters are resolved to (ordinal) reserved symbols -// fn analyze_symbols_in_fn( -// &mut self, -// body: PersistentList, -// params: &PersistentVector, -// frames: &mut Vec, -// // record any values captured from the environment that would outlive the lifetime of this particular lambda -// captures: &mut Vec, -// ) -> EvaluationResult { -// let level = frames.len(); -// let (parameters, variadic) = self.extract_scope_from_fn_bindings(params, level)?; -// let arity = if variadic { -// parameters.len() - 1 -// } else { -// parameters.len() -// }; -// let mut frame = Frame::default(); -// frame.scopes.push(parameters); - -// frames.push(frame); -// // walk the `body`, resolving symbols where possible... -// let mut analyzed_body = Vec::with_capacity(body.len()); -// for form in body.iter() { -// let analyzed_form = self.analyze_form_in_fn(form, frames, captures)?; -// analyzed_body.push(analyzed_form); -// } -// frames.pop(); -// Ok(Value::Fn(FnImpl { -// body: analyzed_body.into_iter().collect(), -// arity, -// level, -// variadic, -// })) -// } -// } - -// pub fn analyze_fn( -// interpreter: &mut Interpreter, -// body: PersistentList, -// params: &PersistentVector, -// ) -> EvaluationResult { -// let mut analyzer = Analyzer::new(interpreter); -// let mut frames = vec![]; -// let mut captures = vec![]; -// analyzer.analyze_symbols_in_fn(body, params, &mut frames, &mut captures) -// } diff --git a/src/analyzer/mod.rs b/src/analyzer/mod.rs index a5a6cb8..7a49a4a 100644 --- a/src/analyzer/mod.rs +++ b/src/analyzer/mod.rs @@ -1,12 +1,11 @@ -mod analyzed_form; - use crate::{ + collections::PersistentList, namespace::{Context as NamespaceContext, NamespaceError}, reader::{Atom, Form, Identifier, Symbol}, -}; -pub use analyzed_form::{ - AnalyzedForm, AnalyzedList, BodyForm, CatchForm, DefForm, FnForm, IfForm, LetForm, - LexicalBindings, LexicalForm, TryForm, + value::{ + BodyForm, CatchForm, DefForm, FnForm, IfForm, LetForm, LexicalBindings, LexicalForm, + RuntimeValue, SpecialForm, TryForm, + }, }; use itertools::Itertools; use std::collections::HashSet; @@ -17,10 +16,8 @@ use thiserror::Error; const MAX_ARGS_BOUND: usize = 129; const VARIADIC_PARAM_COUNT: usize = 2; -const VARIADIC_ARG: &Symbol = &Symbol { - identifier: Identifier::from("&"), - namespace: None, -}; +const VARIADIC_IDENTIFIER: &str = "&"; +const CATCH_IDENTIFIER: &str = "catch*"; #[derive(Debug, Clone, Error)] pub enum SymbolError { @@ -188,9 +185,9 @@ pub enum AnalysisError { pub type AnalysisResult = Result; -fn extract_symbol(form: &Form) -> Result<&Symbol, TypeError> { +fn extract_symbol(form: &Form) -> Result { match form { - Form::Atom(Atom::Symbol(symbol)) => Ok(symbol), + Form::Atom(Atom::Symbol(symbol)) => Ok(symbol.clone()), e => Err(TypeError { expected: "symbol".into(), provided: e.clone(), @@ -198,11 +195,12 @@ fn extract_symbol(form: &Form) -> Result<&Symbol, TypeError> { } } -fn extract_symbol_without_namespace(form: &Form) -> Result<&Symbol, TypeError> { +fn extract_symbol_without_namespace(form: &Form) -> Result { match extract_symbol(form)? { - s @ Symbol { - namespace: None, .. - } => Ok(s), + Symbol { + identifier, + namespace: None, + } => Ok(identifier.clone()), e => Err(TypeError { expected: "symbol without namespace".into(), provided: Form::Atom(Atom::Symbol(e.clone())), @@ -210,9 +208,9 @@ fn extract_symbol_without_namespace(form: &Form) -> Result<&Symbol, TypeError> { } } -fn extract_vector(form: &Form) -> Result<&Vec
, TypeError> { +fn extract_vector(form: &Form) -> Result, TypeError> { match form { - Form::Vector(v) => Ok(v), + Form::Vector(v) => Ok(v.clone()), e => Err(TypeError { expected: "vector".into(), provided: e.clone(), @@ -220,6 +218,7 @@ fn extract_vector(form: &Form) -> Result<&Vec, TypeError> { } } +#[derive(Copy, Clone)] enum LexicalMode { Bound, Unbound, @@ -228,7 +227,7 @@ enum LexicalMode { fn extract_lexical_form( forms: &[Form], lexical_mode: LexicalMode, -) -> Result<(&Vec, &[Form]), LexicalError> { +) -> Result<(Vec, Vec), LexicalError> { verify_arity(forms, 1..MAX_ARGS_BOUND).map_err(|err| LexicalError::Arity(err))?; let bindings = extract_vector(&forms[0]).map_err(LexicalError::Type)?; @@ -237,7 +236,7 @@ fn extract_lexical_form( return Err(LexicalError::BindingsMustBeBound); } - let body = &forms[1..]; + let body = Vec::from(&forms[1..]); Ok((bindings, body)) } @@ -252,14 +251,47 @@ fn verify_arity(forms: &[Form], range: Range) -> Result<(), ArityError> { } } -fn analyze_tail_fn_parameters<'a>(parameters: &'a [&Symbol]) -> AnalysisResult> { - match parameters { +fn analyze_fn_parameters( + mut parameters: Vec, +) -> AnalysisResult<(Vec, Option)> { + match parameters.len() { + 0 => Ok((parameters, None)), + 1 => { + if parameters[0] == VARIADIC_IDENTIFIER { + Err(AnalysisError::FnError(FnError::MissingVariadicArg)) + } else { + Ok((parameters, None)) + } + } + _ => { + let variadic_position = parameters.len() - VARIADIC_PARAM_COUNT; + let (fixed_parameters, possibly_variadic) = parameters.split_at(variadic_position); + let valid_fixed_parameters = fixed_parameters + .iter() + .all(|parameter| parameter != VARIADIC_IDENTIFIER); + if !valid_fixed_parameters { + return Err(AnalysisError::FnError( + FnError::VariadicArgNotInTailPosition, + )); + } + + let variadic_parameter = analyze_tail_fn_parameters(possibly_variadic)?; + if variadic_parameter.is_some() { + parameters.truncate(variadic_position); + } + Ok((parameters, variadic_parameter)) + } + } +} + +fn analyze_tail_fn_parameters(parameters: &[Identifier]) -> AnalysisResult> { + match ¶meters { &[a, b] => { - if a == VARIADIC_ARG { - if b == VARIADIC_ARG { + if a == VARIADIC_IDENTIFIER { + if b == VARIADIC_IDENTIFIER { Err(AnalysisError::FnError(FnError::VariadicArgNotUnique)) } else { - Ok(Some(b)) + Ok(Some(b.clone())) } } else { Ok(None) @@ -269,14 +301,25 @@ fn analyze_tail_fn_parameters<'a>(parameters: &'a [&Symbol]) -> AnalysisResult>; + +fn identifier_is_in_lexical_scope(scopes: &Scopes, identifier: &Identifier) -> bool { + for scope in scopes.iter().rev() { + if scope.contains(identifier) { + return true; + } + } + false +} + #[derive(Debug)] -pub struct Analyzer<'ana> { - namespaces: &'ana NamespaceContext, - scopes: Vec>, +pub struct Analyzer<'n> { + namespaces: &'n NamespaceContext, + scopes: Scopes, } -impl<'ana> Analyzer<'ana> { - pub fn new(namespaces: &'ana NamespaceContext) -> Self { +impl<'n> Analyzer<'n> { + pub fn new(namespaces: &'n NamespaceContext) -> Self { Self { namespaces, scopes: vec![], @@ -284,10 +327,10 @@ impl<'ana> Analyzer<'ana> { } // (def! name value?) - fn analyze_def<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_def(&mut self, args: &[Form]) -> AnalysisResult { verify_arity(args, 1..3).map_err(DefError::from)?; - let name = extract_symbol(&args[0]).map_err(DefError::from)?; + let name = extract_symbol(&args[0]).map_err(DefError::from)?.clone(); let form = if args.len() == 2 { let analyzed_value = self.analyze(&args[1])?; DefForm::Bound(name, Box::new(analyzed_value)) @@ -295,25 +338,25 @@ impl<'ana> Analyzer<'ana> { DefForm::Unbound(name) }; - Ok(AnalyzedList::Def(form)) + Ok(RuntimeValue::SpecialForm(SpecialForm::Def(form))) } // (var name) - fn analyze_var<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_var(&self, args: &[Form]) -> AnalysisResult { verify_arity(args, 1..2).map_err(VarError::from)?; let symbol = extract_symbol(&args[0]) - .map(AnalyzedList::Var) + .map(|identifier| RuntimeValue::SpecialForm(SpecialForm::Var(identifier.clone()))) .map_err(VarError::from)?; Ok(symbol) } - fn analyze_lexical_bindings<'a, E>( - &'a self, - bindings_form: &'a Vec, + fn analyze_lexical_bindings( + &mut self, + bindings_form: &[Form], lexical_mode: LexicalMode, - ) -> AnalysisResult> + ) -> AnalysisResult where E: From, AnalysisError: From, @@ -325,14 +368,14 @@ impl<'ana> Analyzer<'ana> { let analyzed_name = extract_symbol_without_namespace(name).map_err(|e| E::from(e.into()))?; let analyzed_value = self.analyze(value)?; - bindings.push((analyzed_name, Box::new(analyzed_value))); + bindings.push((analyzed_name.clone(), Box::new(analyzed_value))); } Ok(LexicalBindings::Bound(bindings)) } LexicalMode::Unbound => { let parameters = bindings_form .iter() - .map(extract_symbol_without_namespace) + .map(|form| extract_symbol_without_namespace(form).map(|s| s.clone())) .collect::, _>>() .map_err(|e| E::from(e.into()))?; Ok(LexicalBindings::Unbound(parameters)) @@ -340,29 +383,29 @@ impl<'ana> Analyzer<'ana> { } } - fn analyze_lexical_form<'a: 'ana, E>( - &'a mut self, - forms: &'a [Form], + fn analyze_lexical_form( + &mut self, + forms: &[Form], lexical_mode: LexicalMode, - ) -> AnalysisResult> + ) -> AnalysisResult where E: From, AnalysisError: From, { let (bindings_form, body) = extract_lexical_form(forms, lexical_mode).map_err(E::from)?; - let bindings = self.analyze_lexical_bindings::(bindings_form, lexical_mode)?; + let bindings = self.analyze_lexical_bindings::(&bindings_form, lexical_mode)?; let mut scope = HashSet::new(); - match bindings { + match &bindings { LexicalBindings::Bound(bindings) => { for (name, _) in bindings { - scope.insert(&name.identifier); + scope.insert(name.clone()); } } LexicalBindings::Unbound(bindings) => { for name in bindings { - scope.insert(&name.identifier); + scope.insert(name.clone()); } } } @@ -382,32 +425,34 @@ impl<'ana> Analyzer<'ana> { } // (let* [bindings*] body*) - fn analyze_let<'a: 'ana>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_let(&mut self, args: &[Form]) -> AnalysisResult { let lexical_form = self.analyze_lexical_form::(args, LexicalMode::Bound)?; let forward_declarations = lexical_form.resolve_forward_declarations(); - Ok(AnalyzedList::Let(LetForm { + Ok(RuntimeValue::SpecialForm(SpecialForm::Let(LetForm { lexical_form, forward_declarations, - })) + }))) } // (loop* [bindings*] body*) - fn analyze_loop<'a: 'ana>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_loop(&mut self, args: &[Form]) -> AnalysisResult { let lexical_form = self.analyze_lexical_form::(args, LexicalMode::Bound)?; - Ok(AnalyzedList::Loop(lexical_form)) + Ok(RuntimeValue::SpecialForm(SpecialForm::Loop(lexical_form))) } // (recur body*) - fn analyze_recur<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_recur(&mut self, args: &[Form]) -> AnalysisResult { let body = args .iter() .map(|form| self.analyze(form)) .collect::, _>>()?; - Ok(AnalyzedList::Recur(BodyForm { body })) + Ok(RuntimeValue::SpecialForm(SpecialForm::Recur(BodyForm { + body, + }))) } // (if predicate consequent alternate?) - fn analyze_if<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_if(&mut self, args: &[Form]) -> AnalysisResult { verify_arity(args, 2..4).map_err(IfError::from)?; let predicate = Box::new(self.analyze(&args[0])?); @@ -419,57 +464,25 @@ impl<'ana> Analyzer<'ana> { None }; - Ok(AnalyzedList::If(IfForm { + Ok(RuntimeValue::SpecialForm(SpecialForm::If(IfForm { predicate, consequent, alternate, - })) + }))) } // (do body*) - fn analyze_do<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_do(&mut self, args: &[Form]) -> AnalysisResult { let body = args .iter() .map(|form| self.analyze(form)) .collect::, _>>()?; - Ok(AnalyzedList::Do(BodyForm { body })) - } - - fn analyze_fn_parameters<'a>( - &'a self, - parameters: Vec<&'a Symbol>, - ) -> AnalysisResult<(Vec<&'a Symbol>, Option<&'a Symbol>)> { - match parameters.len() { - 0 => Ok((parameters, None)), - 1 => { - if parameters[0] == VARIADIC_ARG { - Err(AnalysisError::FnError(FnError::MissingVariadicArg)) - } else { - Ok((parameters, None)) - } - } - _ => { - let variadic_position = parameters.len() - VARIADIC_PARAM_COUNT; - let (fixed_parameters, possibly_variadic) = parameters.split_at(variadic_position); - let valid_fixed_parameters = fixed_parameters - .iter() - .all(|¶meter| parameter != VARIADIC_ARG); - if !valid_fixed_parameters { - return Err(AnalysisError::FnError( - FnError::VariadicArgNotInTailPosition, - )); - } - - let variadic_parameter = analyze_tail_fn_parameters(possibly_variadic)?; - if variadic_parameter.is_some() { - parameters.truncate(variadic_position); - } - Ok((parameters, variadic_parameter)) - } - } + Ok(RuntimeValue::SpecialForm(SpecialForm::Do(BodyForm { + body, + }))) } - fn extract_fn_form<'a: 'ana>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn extract_fn_form(&mut self, args: &[Form]) -> AnalysisResult { let LexicalForm { bindings, body } = self.analyze_lexical_form::(args, LexicalMode::Unbound)?; let parameters = match bindings { @@ -477,7 +490,7 @@ impl<'ana> Analyzer<'ana> { _ => unreachable!("lexical bindings have been validated to only have unbound symbols"), }; - let (parameters, variadic) = self.analyze_fn_parameters(parameters)?; + let (parameters, variadic) = analyze_fn_parameters(parameters)?; Ok(FnForm { parameters, @@ -487,69 +500,75 @@ impl<'ana> Analyzer<'ana> { } // (fn [parameters*] body*) - fn analyze_fn<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_fn(&mut self, args: &[Form]) -> AnalysisResult { let fn_form = self.extract_fn_form(args)?; - Ok(AnalyzedList::Fn(fn_form)) + Ok(RuntimeValue::SpecialForm(SpecialForm::Fn(fn_form))) } // (quote form) - fn analyze_quote<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_quote(&self, args: &[Form]) -> AnalysisResult { verify_arity(args, 1..2).map_err(QuoteError::from)?; - let form = self.analyze(&args[0])?; - - Ok(AnalyzedList::Quote(Box::new(form))) + Ok(RuntimeValue::SpecialForm(SpecialForm::Quote(Box::new( + RuntimeValue::from(&args[0]), + )))) } // (quasiquote form) - fn analyze_quasiquote<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_quasiquote(&self, args: &[Form]) -> AnalysisResult { verify_arity(args, 1..2).map_err(QuasiquoteError::from)?; - let form = self.analyze(&args[0])?; - - Ok(AnalyzedList::Quasiquote(Box::new(form))) + Ok(RuntimeValue::SpecialForm(SpecialForm::Quasiquote( + Box::new(RuntimeValue::from(&args[0])), + ))) } + // TODO: only try these in the context of `quasiquote`, like `try/catch` // // (unquote form) - // fn analyze_unquote<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + // fn analyze_unquote(& self, args: & [Form]) -> AnalysisResult { // verify_arity(args, 1..2).map_err(UnquoteError::from)?; // let form = self.analyze(&args[0])?; - // Ok(AnalyzedList::Unquote(Box::new(form))) + // Ok(RuntimeValue::Unquote(Box::new(form))) // } // // (splice-unquote form) - // fn analyze_splice_unquote<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + // fn analyze_splice_unquote(& self, args: & [Form]) -> AnalysisResult { // verify_arity(args, 1..2).map_err(SpliceUnquoteError::from)?; // let form = self.analyze(&args[0])?; - // Ok(AnalyzedList::SpliceUnquote(Box::new(form))) + // Ok(RuntimeValue::SpliceUnquote(Box::new(form))) // } // (defmacro! symbol fn*-form) - fn analyze_defmacro<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_defmacro(&mut self, args: &[Form]) -> AnalysisResult { verify_arity(args, 2..3).map_err(DefmacroError::from)?; let name = extract_symbol(&args[0]).map_err(DefmacroError::from)?; let body = self.extract_fn_form(&args[1..])?; - Ok(AnalyzedList::Defmacro(name, body)) + Ok(RuntimeValue::SpecialForm(SpecialForm::Defmacro( + name.clone(), + body, + ))) } // (macroexpand form) - fn analyze_macroexpand<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_macroexpand(&mut self, args: &[Form]) -> AnalysisResult { verify_arity(args, 1..2).map_err(MacroexpandError::from)?; let form = self.analyze(&args[0])?; - Ok(AnalyzedList::Macroexpand(Box::new(form))) + Ok(RuntimeValue::SpecialForm(SpecialForm::Macroexpand( + Box::new(form), + ))) } // (try* form* catch*-form?) - fn analyze_try<'a>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_try(&mut self, args: &[Form]) -> AnalysisResult { let try_form = match args.len() { 0 => TryForm::default(), _ => { @@ -558,13 +577,26 @@ impl<'ana> Analyzer<'ana> { .iter() .map(|form| self.analyze(form)) .collect::, _>>()?; - let catch = match self.analyze(last_form)? { - AnalyzedForm::List(AnalyzedList::Catch(catch_form)) => Some(catch_form), - form => { - body.push(form); - None - } + let catch = match last_form { + Form::List(form) => match form.split_first() { + Some((first, rest)) => match first { + Form::Atom(Atom::Symbol(Symbol { + identifier, + namespace: None, + })) if identifier == CATCH_IDENTIFIER => { + let catch = self.analyze_catch(rest)?; + Some(catch) + } + _ => None, + }, + None => None, + }, + _ => None, }; + if catch.is_none() { + let analyzed_form = self.analyze(last_form)?; + body.push(analyzed_form); + } TryForm { body: BodyForm { body }, @@ -573,17 +605,17 @@ impl<'ana> Analyzer<'ana> { } }; - Ok(AnalyzedList::Try(try_form)) + Ok(RuntimeValue::SpecialForm(SpecialForm::Try(try_form))) } // (catch* exc-symbol form*) - fn analyze_catch<'a: 'ana>(&'a self, args: &'a [Form]) -> AnalysisResult> { + fn analyze_catch(&mut self, args: &[Form]) -> AnalysisResult { verify_arity(args, 1..MAX_ARGS_BOUND).map_err(CatchError::from)?; let exception_binding = extract_symbol_without_namespace(&args[0]).map_err(CatchError::from)?; - let mut scope = HashSet::from([&exception_binding.identifier]); + let scope = HashSet::from([exception_binding.clone()]); self.scopes.push(scope); let body = args[1..] @@ -591,135 +623,123 @@ impl<'ana> Analyzer<'ana> { .map(|form| self.analyze(form)) .collect::, _>>()?; - self.scopes.pop(); + self.scopes.pop().unwrap(); - Ok(AnalyzedList::Catch(CatchForm { + Ok(CatchForm { exception_binding, body: BodyForm { body }, - })) + }) } - fn analyze_list_with_possible_special_form<'a>( - &'a self, - operator: &'a Atom, - rest: &'a [Form], - ) -> AnalysisResult> { + fn analyze_list_with_possible_special_form( + &mut self, + operator: &Atom, + operands: &[Form], + ) -> AnalysisResult { match operator { - Atom::Symbol(symbol) => match symbol { - Symbol { + Atom::Symbol( + symbol @ Symbol { identifier: s, namespace: None, - } => match s.as_str() { - "def!" => self.analyze_def(rest), - "var" => self.analyze_var(rest), - "let*" => self.analyze_let(rest), - "loop*" => self.analyze_loop(rest), - "recur" => self.analyze_recur(rest), - "if" => self.analyze_if(rest), - "do" => self.analyze_do(rest), - "fn*" => self.analyze_fn(rest), - "quote" => self.analyze_quote(rest), - "quasiquote" => self.analyze_quasiquote(rest), - // "unquote" => self.analyze_unquote(rest), - // "splice-unquote" => self.analyze_splice_unquote(rest), - "defmacro!" => self.analyze_defmacro(rest), - "macroexpand" => self.analyze_macroexpand(rest), - "try*" => self.analyze_try(rest), - "catch*" => self.analyze_catch(rest), - _ => { - let mut inner = vec![AnalyzedForm::Atom(operator)]; - inner.extend( - rest.iter() - .map(|f| self.analyze(f)) - .collect::, _>>()?, - ); - Ok(AnalyzedList::Form(inner)) - } }, - _ => unreachable!("only call this function with one of the prior variants"), + ) => match s.as_str() { + "def!" => self.analyze_def(operands), + "var" => self.analyze_var(operands), + "let*" => self.analyze_let(operands), + "loop*" => self.analyze_loop(operands), + "recur" => self.analyze_recur(operands), + "if" => self.analyze_if(operands), + "do" => self.analyze_do(operands), + "fn*" => self.analyze_fn(operands), + "quote" => self.analyze_quote(operands), + "quasiquote" => self.analyze_quasiquote(operands), + "defmacro!" => self.analyze_defmacro(operands), + "macroexpand" => self.analyze_macroexpand(operands), + "try*" => self.analyze_try(operands), + _ => { + let first = self.analyze_symbol(symbol)?; + self.analyze_list_without_special_form(first, operands) + } }, _ => unreachable!("only call this function with one of the prior variants"), } } - fn analyze_list<'a>(&'a self, forms: &'a [Form]) -> AnalysisResult> { - let inner = match forms.split_first() { + fn analyze_list_without_special_form( + &mut self, + first: RuntimeValue, + rest: &[Form], + ) -> AnalysisResult { + // TODO evaluate in order to reveal errors left-to-right + let mut inner = PersistentList::new(); + for form in rest.iter().rev() { + let analyzed_form = self.analyze(form)?; + inner.push_front_mut(analyzed_form); + } + inner.push_front_mut(first); + Ok(RuntimeValue::List(inner)) + } + + fn analyze_list(&mut self, forms: &[Form]) -> AnalysisResult { + match forms.split_first() { Some((first, rest)) => match first { Form::Atom( atom @ Atom::Symbol(Symbol { namespace: None, .. }), - ) => self.analyze_list_with_possible_special_form(atom, rest)?, + ) => self.analyze_list_with_possible_special_form(atom, rest), first => { - let mut inner = vec![self.analyze(first)?]; - inner.extend( - rest.iter() - .map(|f| self.analyze(f)) - .collect::, _>>()?, - ); - AnalyzedList::Form(inner) + let first = self.analyze(first)?; + self.analyze_list_without_special_form(first, rest) } }, - None => AnalyzedList::Form(vec![]), - }; - Ok(AnalyzedForm::List(inner)) + None => Ok(RuntimeValue::List(PersistentList::new())), + } } - fn identifier_is_in_lexical_scope(&self, identifier: &Identifier) -> bool { - for scope in self.scopes.iter().rev() { - if scope.contains(identifier) { - return true; - } + pub fn analyze_symbol(&self, symbol: &Symbol) -> AnalysisResult { + if symbol.namespace.is_none() + && identifier_is_in_lexical_scope(&self.scopes, &symbol.identifier) + { + return Ok(RuntimeValue::LexicalSymbol(symbol.identifier.clone())); } - false - } - pub fn analyze_symbol<'a>(&'a self, symbol: &'a Symbol) -> AnalysisResult> { - let form = match self.namespaces.resolve_symbol(symbol) { - Ok(var) => AnalyzedForm::Var(var), - Err(e @ NamespaceError::MissingIdentifier(..)) => { - let identifier = &symbol.identifier; - if self.identifier_is_in_lexical_scope(identifier) { - AnalyzedForm::LexicalSymbol(identifier) - } else { - return Err(SymbolError::from(e).into()); - } - } - Err(err) => return Err(SymbolError::from(err).into()), - }; - Ok(form) + self.namespaces + .resolve_symbol(symbol) + .map(RuntimeValue::Var) + .map_err(|err| SymbolError::from(err).into()) } // `analyze` performs static analysis of `form` to provide data optimized for evaluation - // 1. Syntax: can an `AnalyzedForm` be produced from a `Form` - // 2. Semantics: some `AnalyzedForm`s have some invariants that can be verified statically + // 1. Syntax: can an `RuntimeValue` be produced from a `Form` + // 2. Semantics: some `RuntimeValue`s have some invariants that can be verified statically // like constraints on special forms - pub fn analyze<'a>(&'a self, form: &'a Form) -> AnalysisResult> { + pub fn analyze(&mut self, form: &Form) -> AnalysisResult { let analyzed_form = match form { Form::Atom(Atom::Symbol(s)) => self.analyze_symbol(s)?, - Form::Atom(a) => AnalyzedForm::Atom(a), + Form::Atom(a) => a.into(), Form::List(elems) => self.analyze_list(elems)?, - Form::Vector(elems) => AnalyzedForm::Vector( + Form::Vector(elems) => RuntimeValue::Vector( elems .iter() .map(|f| self.analyze(f)) - .collect::, _>>()?, + .collect::>()?, ), - Form::Map(elems) => AnalyzedForm::Map( + Form::Map(elems) => RuntimeValue::Map( elems .iter() - .map(|(x, y)| -> AnalysisResult<(AnalyzedForm, AnalyzedForm)> { + .map(|(x, y)| -> AnalysisResult<(RuntimeValue, RuntimeValue)> { let analyzed_x = self.analyze(x)?; let analyzed_y = self.analyze(y)?; Ok((analyzed_x, analyzed_y)) }) - .collect::, _>>()?, + .collect::>()?, ), - Form::Set(elems) => AnalyzedForm::Set( + Form::Set(elems) => RuntimeValue::Set( elems .iter() .map(|f| self.analyze(f)) - .collect::, _>>()?, + .collect::>()?, ), }; Ok(analyzed_form) diff --git a/src/collections.rs b/src/collections.rs index 1783395..a31d95c 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -1,4 +1,125 @@ -pub use rpds::{ - HashTrieMap as PersistentMap, HashTrieSet as PersistentSet, List as PersistentList, - Vector as PersistentVector, -}; +use itertools::sorted; +use std::cmp::Ordering; +use std::hash::{Hash, Hasher}; +use std::iter::{FromIterator, IntoIterator}; +use std::ops::{Deref, DerefMut}; + +use archery::RcK; +use rpds::map::hash_trie_map::Iter as MapIter; +use rpds::set::hash_trie_set::Iter as SetIter; +use rpds::{HashTrieMap, HashTrieSet}; +pub use rpds::{List as PersistentList, Vector as PersistentVector}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct PersistentMap(HashTrieMap); + +impl Deref for PersistentMap { + type Target = HashTrieMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for PersistentMap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl PartialOrd for PersistentMap { + fn partial_cmp(&self, other: &Self) -> Option { + Some(sorted(self.0.iter()).cmp(sorted(other.0.iter()))) + } +} + +impl Ord for PersistentMap { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } +} + +impl Hash for PersistentMap { + fn hash(&self, state: &mut H) { + self.0.size().hash(state); + sorted(self.0.iter()).for_each(|binding| binding.hash(state)); + } +} + +impl<'a, K: Eq + Hash + Ord, V: Eq + Ord + Hash> IntoIterator for &'a PersistentMap { + type Item = (&'a K, &'a V); + type IntoIter = MapIter<'a, K, V, RcK>; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } +} + +impl PersistentMap { + pub fn new() -> Self { + Self(HashTrieMap::new()) + } +} + +impl FromIterator<(K, V)> for PersistentMap { + fn from_iter>(into_iter: I) -> Self { + Self(HashTrieMap::from_iter(into_iter)) + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct PersistentSet(HashTrieSet); + +impl Deref for PersistentSet { + type Target = HashTrieSet; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for PersistentSet { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl PartialOrd for PersistentSet { + fn partial_cmp(&self, other: &Self) -> Option { + Some(sorted(self.0.iter()).cmp(sorted(other.0.iter()))) + } +} + +impl Ord for PersistentSet { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } +} + +impl Hash for PersistentSet { + fn hash(&self, state: &mut H) { + self.0.size().hash(state); + sorted(self.0.iter()).for_each(|binding| binding.hash(state)); + } +} + +impl<'a, T: Hash + Eq + Ord> IntoIterator for &'a PersistentSet { + type Item = &'a T; + type IntoIter = SetIter<'a, T, RcK>; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } +} + +impl PersistentSet { + pub fn new() -> Self { + Self(HashTrieSet::new()) + } +} + +impl FromIterator for PersistentSet { + fn from_iter>(into_iter: I) -> Self { + Self(HashTrieSet::from_iter(into_iter)) + } +} diff --git a/src/interpreter.rs b/src/interpreter.rs index c49bd05..fcf6107 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -1,46 +1,37 @@ -use crate::analyzer::{ - AnalysisError, AnalyzedForm, AnalyzedList, Analyzer, BodyForm, CatchError, CatchForm, DefForm, - FnForm, IfForm, LetForm, LexicalBindings, LexicalForm, TryForm, -}; +use crate::analyzer::{AnalysisError, Analyzer}; use crate::collections::{PersistentList, PersistentMap, PersistentSet, PersistentVector}; use crate::lang::core; -use crate::namespace::{Context as NamespaceContext, Namespace, NamespaceError, Var}; +use crate::namespace::{Context as NamespaceContext, NamespaceDesc, NamespaceError, Var}; use crate::reader::{read, Form, Identifier, ReadError, Symbol}; use crate::value::{ - exception_from_system_err, list_with_values, var_impl_into_inner, ExceptionImpl, FnImpl, - FnWithCapturesImpl, NativeFn, RuntimeValue, Value, + exception_from_system_err, + //Value, + BodyForm, + CatchForm, + DefForm, + ExceptionImpl, + FnForm, + IfForm, + LetForm, + LexicalBindings, + LexicalForm, + //FnImpl, + //FnWithCapturesImpl, + RuntimeValue, + SpecialForm, + TryForm, }; use std::cell::RefCell; use std::collections::HashMap; use std::collections::HashSet; use std::default::Default; use std::fmt::Write; -use std::iter::FromIterator; -use std::iter::IntoIterator; use std::rc::Rc; use std::time::SystemTimeError; use std::{fmt, io}; use thiserror::Error; -const COMMAND_LINE_ARGS_SYMBOL: &str = "*command-line-args*"; -const SPECIAL_FORMS: &[&str] = &[ - "def!", // (def! symbol form) - "var", // (var symbol) - "let*", // (let* [bindings*] form*) - "loop*", // (loop* [bindings*] form*) - "recur", // (recur form*) - "if", // (if predicate consequent alternate?) - "do", // (do form*) - "fn*", // (fn* [parameter*] form*) - "quote", // (quote form) - "quasiquote", // (quasiquote form) - "unquote", // (unquote form) - "splice-unquote", // (splice-unquote form) - "defmacro!", // (defmacro! symbol fn*-form) - "macroexpand", // (macroexpand macro-form) - "try*", // (try* form* catch*-form?) - "catch*", // (catch* exc-symbol form*) -]; +const COMMAND_LINE_ARGS_IDENTIFIER: &str = "*command-line-args*"; #[derive(Debug, Error, Clone)] pub enum InterpreterError { @@ -78,15 +69,15 @@ impl From for InterpreterError { #[derive(Debug, Error, Clone)] pub enum SyntaxError { #[error("lexical bindings must be pairs of names and values but found unpaired set `{0}`")] - LexicalBindingsMustBePaired(PersistentVector), + LexicalBindingsMustBePaired(PersistentVector), #[error("expected vector of lexical bindings instead of `{0}`")] - LexicalBindingsMustBeVector(Value), + LexicalBindingsMustBeVector(RuntimeValue), #[error("names in form must be non-namespaced symbols unlike `{0}`")] - LexicalBindingsMustHaveSymbolNames(Value), + LexicalBindingsMustHaveSymbolNames(RuntimeValue), #[error("missing argument for variadic binding")] VariadicArgMissing, #[error("found multiple variadic arguments in `{0}`; only one is allowed.")] - VariadicArgMustBeUnique(Value), + VariadicArgMustBeUnique(RuntimeValue), } #[derive(Debug, Error, Clone)] @@ -94,7 +85,7 @@ pub enum EvaluationError { #[error("form invoked with an argument of the incorrect type: expected a value of type(s) `{expected}` but found value `{realized}`")] WrongType { expected: &'static str, - realized: Value, + realized: RuntimeValue, }, #[error("form invoked with incorrect arity: provided {realized} arguments but expected {expected} arguments")] WrongArity { expected: usize, realized: usize }, @@ -103,11 +94,11 @@ pub enum EvaluationError { #[error("symbol `{0}` could not be resolved")] UnableToResolveSymbolToValue(String), #[error("cannot invoke the supplied value `{0}`")] - CannotInvoke(Value), + CannotInvoke(RuntimeValue), #[error("missing value for captured symbol `{0}`")] MissingCapturedValue(String), #[error("cannot deref an unbound var `{0}`")] - CannotDerefUnboundVar(Value), + CannotDerefUnboundVar(RuntimeValue), #[error("overflow detected during arithmetic operation of {0} and {1}")] Overflow(i64, i64), #[error("could not negate {0}")] @@ -117,7 +108,7 @@ pub enum EvaluationError { #[error("requested index {0} in collection with length {1}")] IndexOutOfBounds(usize, usize), #[error("map cannot be constructed with an odd number of arguments: `{0}` with length `{1}`")] - MapRequiresPairs(Value, usize), + MapRequiresPairs(RuntimeValue, usize), #[error("exception: {0}")] Exception(ExceptionImpl), #[error("syntax error: {0}")] @@ -135,156 +126,120 @@ pub enum EvaluationError { pub type EvaluationResult = Result; pub type SymbolIndex = HashSet; -pub type Scope<'a> = HashMap<&'a Identifier, RuntimeValue>; - -// fn lambda_parameter_key(index: usize, level: usize) -> String { -// let mut key = String::new(); -// let _ = write!(&mut key, ":system-fn-%{}/{}", index, level); -// key +pub type Scope = HashMap; + +// fn eval_quasiquote_list_inner( +// elems: impl Iterator, +// ) -> EvaluationResult { +// let mut result = Value::List(PersistentList::new()); +// for form in elems { +// match form { +// Value::List(inner) => { +// if let Some(first_inner) = inner.first() { +// match first_inner { +// Value::Symbol(s, None) if s == "splice-unquote" => { +// if let Some(rest) = inner.drop_first() { +// if let Some(second) = rest.first() { +// result = list_with_values(vec![ +// Value::Symbol( +// "concat".to_string(), +// Some("core".to_string()), +// ), +// second.clone(), +// result, +// ]); +// } +// } else { +// return Err(EvaluationError::WrongArity { +// expected: 1, +// realized: 0, +// }); +// } +// } +// _ => { +// result = list_with_values(vec![ +// Value::Symbol("cons".to_string(), Some("core".to_string())), +// eval_quasiquote(form)?, +// result, +// ]); +// } +// } +// } else { +// result = list_with_values(vec![ +// Value::Symbol("cons".to_string(), Some("core".to_string())), +// Value::List(PersistentList::new()), +// result, +// ]); +// } +// } +// form => { +// result = list_with_values(vec![ +// Value::Symbol("cons".to_string(), Some("core".to_string())), +// eval_quasiquote(form)?, +// result, +// ]); +// } +// } +// } +// Ok(result) // } -// `scopes` from most specific to least specific -fn resolve_symbol_in_scopes<'a>( - scopes: impl Iterator>, - identifier: &str, -) -> Option<&'a Value> { - for scope in scopes { - if let Some(value) = scope.get(identifier) { - return Some(value); - } - } - None -} - -fn eval_quasiquote_list_inner<'a>( - elems: impl Iterator, -) -> EvaluationResult { - let mut result = Value::List(PersistentList::new()); - for form in elems { - match form { - Value::List(inner) => { - if let Some(first_inner) = inner.first() { - match first_inner { - Value::Symbol(s, None) if s == "splice-unquote" => { - if let Some(rest) = inner.drop_first() { - if let Some(second) = rest.first() { - result = list_with_values(vec![ - Value::Symbol( - "concat".to_string(), - Some("core".to_string()), - ), - second.clone(), - result, - ]); - } - } else { - return Err(EvaluationError::WrongArity { - expected: 1, - realized: 0, - }); - } - } - _ => { - result = list_with_values(vec![ - Value::Symbol("cons".to_string(), Some("core".to_string())), - eval_quasiquote(form)?, - result, - ]); - } - } - } else { - result = list_with_values(vec![ - Value::Symbol("cons".to_string(), Some("core".to_string())), - Value::List(PersistentList::new()), - result, - ]); - } - } - form => { - result = list_with_values(vec![ - Value::Symbol("cons".to_string(), Some("core".to_string())), - eval_quasiquote(form)?, - result, - ]); - } - } - } - Ok(result) -} - -fn eval_quasiquote_list(elems: &PersistentList) -> EvaluationResult { - if let Some(first) = elems.first() { - match first { - Value::Symbol(s, None) if s == "unquote" => { - if let Some(rest) = elems.drop_first() { - if let Some(argument) = rest.first() { - return Ok(argument.clone()); - } - } - return Err(EvaluationError::WrongArity { - realized: 0, - expected: 1, - }); - } - _ => return eval_quasiquote_list_inner(elems.reverse().iter()), - } - } - Ok(Value::List(PersistentList::new())) -} - -fn eval_quasiquote_vector(elems: &PersistentVector) -> EvaluationResult { - Ok(list_with_values(vec![ - Value::Symbol("vec".to_string(), Some("core".to_string())), - eval_quasiquote_list_inner(elems.iter().rev())?, - ])) -} +// fn eval_quasiquote_list(elems: &PersistentList) -> EvaluationResult { +// if let Some(first) = elems.first() { +// match first { +// Value::Symbol(s, None) if s == "unquote" => { +// if let Some(rest) = elems.drop_first() { +// if let Some(argument) = rest.first() { +// return Ok(argument.clone()); +// } +// } +// return Err(EvaluationError::WrongArity { +// realized: 0, +// expected: 1, +// }); +// } +// _ => return eval_quasiquote_list_inner(elems.reverse().iter()), +// } +// } +// Ok(Value::List(PersistentList::new())) +// } -// TODO fix types -fn eval_quasiquote(form: AnalyzedForm) -> EvaluationResult { - match form { - Value::List(elems) => eval_quasiquote_list(elems), - Value::Vector(elems) => eval_quasiquote_vector(elems), - elem @ Value::Map(_) | elem @ Value::Symbol(..) => { - let args = vec![Value::Symbol("quote".to_string(), None), elem.clone()]; - Ok(list_with_values(args.into_iter())) - } - v => Ok(v.clone()), - } -} +// fn eval_quasiquote_vector(elems: &PersistentVector) -> EvaluationResult { +// Ok(list_with_values(vec![ +// Value::Symbol("vec".to_string(), Some("core".to_string())), +// eval_quasiquote_list_inner(elems.iter().rev())?, +// ])) +// } -fn do_to_exactly_one_arg( - operand_forms: PersistentList, - mut action: A, -) -> EvaluationResult -where - A: FnMut(&Value) -> EvaluationResult, -{ - if operand_forms.len() != 1 { - return Err(EvaluationError::WrongArity { - expected: 1, - realized: operand_forms.len(), - }); - } - let arg = operand_forms.first().unwrap(); - action(arg) -} +// fn eval_quasiquote(form: RuntimeValue) -> EvaluationResult { +// match form { +// Value::List(elems) => eval_quasiquote_list(&elems), +// Value::Vector(elems) => eval_quasiquote_vector(&elems), +// elem @ Value::Map(_) | elem @ Value::Symbol(..) => { +// let args = vec![Value::Symbol("quote".to_string(), None), elem.clone()]; +// Ok(list_with_values(args.into_iter())) +// } +// v => Ok(v.clone()), +// } +// } -fn update_captures( - captures: &mut HashMap>, - scopes: &[Scope], -) -> EvaluationResult<()> { - for (capture, value) in captures { - if value.is_none() { - let captured_value = resolve_symbol_in_scopes(scopes.iter().rev(), capture) - .ok_or_else(|| { - EvaluationError::UnableToResolveSymbolToValue(capture.to_string()) - })?; - *value = Some(captured_value.clone()); - } - } - Ok(()) -} +// fn update_captures( +// captures: &mut HashMap>, +// scopes: &[Scope], +// ) -> EvaluationResult<()> { +// for (capture, value) in captures { +// if value.is_none() { +// let captured_value = resolve_symbol_in_scopes(scopes.iter().rev(), capture) +// .ok_or_else(|| { +// EvaluationError::UnableToResolveSymbolToValue(capture.to_string()) +// })?; +// *value = Some(captured_value.clone()); +// } +// } +// Ok(()) +// } +#[derive(Debug)] enum ControlFlow { Continue, Recur(Vec), @@ -295,43 +250,32 @@ pub struct Interpreter { namespaces: NamespaceContext, symbol_index: Option>>, - // stack of scopes - // contains at least one scope, the "default" scope pub(crate) scopes: Vec, control_stack: Vec, - // low-res backtrace - pub(crate) apply_stack: Vec, + // pub(crate) apply_stack: Vec, // index into `apply_stack` pointing at the first form to error - failed_form: Option, + // failed_form: Option, } impl Default for Interpreter { fn default() -> Self { - // build the default scope, which resolves special forms to themselves - // so that they fall through to the interpreter's evaluation - let mut default_scope = Scope::new(); - for form in SPECIAL_FORMS { - default_scope.insert(form.to_string(), Value::Symbol(form.to_string(), None)); - } - let mut interpreter = Interpreter { namespaces: NamespaceContext::default(), symbol_index: None, - scopes: vec![default_scope], + scopes: vec![], control_stack: vec![], - apply_stack: vec![], - failed_form: None, + // apply_stack: vec![], + // failed_form: None, }; - // load the "core" namespace interpreter - .activate_namespace(core::loader) - .expect("is valid namespace"); + .load_namespace(core::namespace()) + .expect("is valid"); // add support for `*command-line-args*` let mut buffer = String::new(); - let _ = write!(&mut buffer, "(def! {} '())", COMMAND_LINE_ARGS_SYMBOL) + let _ = write!(&mut buffer, "(def! {} '())", COMMAND_LINE_ARGS_IDENTIFIER) .expect("can write to string"); interpreter.interpret(&buffer).expect("valid source"); @@ -339,11 +283,9 @@ impl Default for Interpreter { } } -pub type NamespaceLoader = fn(&mut Interpreter) -> EvaluationResult<()>; - impl Interpreter { - pub fn activate_namespace(&mut self, loader: NamespaceLoader) -> EvaluationResult<()> { - loader(self) + pub fn current_namespace(&self) -> &Identifier { + self.namespaces.current_namespace_name() } pub fn register_symbol_index(&mut self, symbol_index: Rc>) { @@ -359,30 +301,46 @@ impl Interpreter { self.symbol_index = Some(symbol_index); } - // Returns the name of the loaded namespace - pub fn load_namespace(&mut self, namespace: Namespace) -> EvaluationResult<()> { - let key = &namespace.name; - if let Some(existing) = self.namespaces.get_mut(key) { - existing.merge(&namespace)?; - } else { - self.namespaces.insert(key.clone(), namespace); + pub fn load_namespace( + &mut self, + NamespaceDesc { + name, + namespace, + source, + }: NamespaceDesc, + ) -> EvaluationResult<()> { + self.namespaces.intern_namespace(&name, namespace); + + if let Some(source) = source { + self.interpret(source)?; } + Ok(()) } /// Store `args` in the var referenced by `COMMAND_LINE_ARGS_SYMBOL`. pub fn intern_args(&mut self, args: impl Iterator) { - let form = args.map(Value::String).collect(); - self.intern_var(COMMAND_LINE_ARGS_SYMBOL, Value::List(form)) - .expect("'*command-line-args* constructed correctly"); + let form = args.map(RuntimeValue::String).collect(); + self.intern( + &Symbol { + identifier: COMMAND_LINE_ARGS_IDENTIFIER.to_string(), + namespace: None, + }, + Some(RuntimeValue::List(form)), + ) + .expect("'*command-line-args* constructed correctly"); } /// Read the interned command line argument at position `n` in the collection. pub fn command_line_arg(&mut self, n: usize) -> EvaluationResult { - match self.resolve_symbol(COMMAND_LINE_ARGS_SYMBOL, None)? { - Value::List(args) => match args.iter().nth(n) { + let symbol = Symbol { + identifier: COMMAND_LINE_ARGS_IDENTIFIER.to_string(), + namespace: None, + }; + match self.resolve_symbol_to_value(&symbol)? { + RuntimeValue::List(args) => match args.iter().nth(n) { Some(value) => match value { - Value::String(arg) => Ok(arg.clone()), + RuntimeValue::String(arg) => Ok(arg.clone()), _ => unreachable!(), }, None => Err(EvaluationError::Interpreter( @@ -394,9 +352,9 @@ impl Interpreter { } fn intern(&mut self, symbol: &Symbol, value: Option) -> EvaluationResult { - let namespace = match symbol.namespace { - Some(ns) => self.namespaces.get_namespace(&ns), - None => self.namespaces.current_namespace(), + let namespace = match &symbol.namespace { + Some(ns) => self.namespaces.get_namespace_mut(ns), + None => self.namespaces.current_namespace_mut(), }; let var = namespace.intern(&symbol.identifier, value)?; @@ -408,15 +366,15 @@ impl Interpreter { Ok(var) } - fn unintern_var(&mut self, identifier: &str) { - let current_namespace = self.current_namespace().to_string(); + // fn unintern_var(&mut self, identifier: &str) { + // let current_namespace = self.current_namespace().to_string(); - let ns = self - .namespaces - .get_mut(¤t_namespace) - .expect("current namespace always resolves"); - ns.remove(identifier); - } + // let ns = self + // .namespaces + // .get_mut(¤t_namespace) + // .expect("current namespace always resolves"); + // ns.remove(identifier); + // } // return a ref to some var in the current namespace // fn resolve_var_in_current_namespace(&self, identifier: &str) -> EvaluationResult { @@ -441,32 +399,31 @@ impl Interpreter { // } // symbol -> namespace -> var - pub(crate) fn resolve_symbol_to_var( - &self, - identifier: &str, - ns_opt: Option<&String>, - ) -> EvaluationResult { - // if namespaced, check there - if let Some(ns_desc) = ns_opt { - return self.resolve_var_in_namespace(identifier, ns_desc); - } - // else resolve in lexical scopes - if let Some(value) = resolve_symbol_in_scopes(self.scopes.iter().rev(), identifier) { - return Ok(value.clone()); - } - // otherwise check current namespace - self.resolve_var_in_current_namespace(identifier) - } + // pub(crate) fn resolve_symbol_to_var( + // &self, + // identifier: &str, + // ns_opt: Option<&String>, + // ) -> EvaluationResult { + // // if namespaced, check there + // if let Some(ns_desc) = ns_opt { + // return self.resolve_var_in_namespace(identifier, ns_desc); + // } + // // else resolve in lexical scopes + // if let Some(value) = resolve_symbol_in_scopes(self.scopes.iter().rev(), identifier) { + // return Ok(value.clone()); + // } + // // otherwise check current namespace + // self.resolve_var_in_current_namespace(identifier) + // } - // symbol -> namespace -> var -> value - fn resolve_symbol(&self, identifier: &str, ns_opt: Option<&String>) -> EvaluationResult { - match self.resolve_symbol_to_var(identifier, ns_opt)? { - Value::Var(v) => match var_impl_into_inner(&v) { - Some(value) => Ok(value), - None => Ok(Value::Var(v)), - }, - other => Ok(other), - } + fn resolve_symbol_to_value(&self, symbol: &Symbol) -> EvaluationResult { + // TODO: fixme + // let var = self.namespaces.resolve_symbol(symbol)?; + // match var { + // Var::Bound(value) => value.clone(), + // Var::Unbound => panic!("hmmm"), + // } + Ok(RuntimeValue::Nil) } // fn enter_scope(&mut self) { @@ -480,133 +437,133 @@ impl Interpreter { /// Exits the current lexical scope. /// NOTE: exposed for some prelude functionality. - pub fn leave_scope(&mut self) { + pub(crate) fn leave_scope(&mut self) { let _ = self.scopes.pop().expect("no underflow in scope stack"); } - fn apply_macro( - &mut self, - f: &FnImpl, - operands: &PersistentList, - ) -> EvaluationResult { - let result = self.apply_fn_inner(f, operands, operands.len())?; - if let Value::List(forms) = result { - return self.expand_macro_if_present(&forms); - } - Ok(result) - } + // fn apply_macro( + // &mut self, + // f: &FnImpl, + // operands: &PersistentList, + // ) -> EvaluationResult { + // let result = self.apply_fn_inner(f, operands, operands.len())?; + // if let Value::List(forms) = result { + // return self.expand_macro_if_present(&forms); + // } + // Ok(result) + // } - fn expand_macro_if_present( - &mut self, - forms: &PersistentList, - ) -> EvaluationResult { - if let Some(first) = forms.first() { - let rest = forms.drop_first().expect("list is not empty"); - if let Some(expansion) = self.get_macro_expansion(first, &rest) { - expansion - } else { - Ok(Value::List(forms.clone())) - } - } else { - Ok(Value::List(PersistentList::new())) - } - } + // fn expand_macro_if_present( + // &mut self, + // forms: &PersistentList, + // ) -> EvaluationResult { + // if let Some(first) = forms.first() { + // let rest = forms.drop_first().expect("list is not empty"); + // if let Some(expansion) = self.get_macro_expansion(first, &rest) { + // expansion + // } else { + // Ok(Value::List(forms.clone())) + // } + // } else { + // Ok(Value::List(PersistentList::new())) + // } + // } /// Apply the given `Fn` to the supplied `args`. /// Exposed for various `prelude` functions. - pub(crate) fn apply_fn_inner<'a>( - &mut self, - FnImpl { - body, - arity, - level, - variadic, - }: &FnImpl, - args: impl IntoIterator, - args_count: usize, - ) -> EvaluationResult { - let arity = *arity; - let level = *level; - let variadic = *variadic; - - let correct_arity = if variadic { - args_count >= arity - } else { - args_count == arity - }; - if !correct_arity { - return Err(EvaluationError::WrongArity { - expected: arity, - realized: args_count, - }); - } - self.enter_scope(); - let mut iter = args.into_iter().enumerate(); - if arity > 0 { - for (index, arg) in &mut iter { - let parameter = lambda_parameter_key(index, level); - self.insert_value_in_current_scope(¶meter, arg.clone()); - - if index == arity - 1 { - break; - } - } - } - if variadic { - let operand = Value::List(iter.map(|(_, arg)| arg.clone()).collect()); - let parameter = lambda_parameter_key(arity, level); - self.insert_value_in_current_scope(¶meter, operand); - } - let mut result = self.eval_do_inner(body); - if let Ok(Value::FnWithCaptures(FnWithCapturesImpl { f, mut captures })) = result { - update_captures(&mut captures, &self.scopes)?; - result = Ok(Value::FnWithCaptures(FnWithCapturesImpl { f, captures })) - } - self.leave_scope(); - result - } + // pub(crate) fn apply_fn_inner( + // &mut self, + // FnImpl { + // body, + // arity, + // level, + // variadic, + // }: &FnImpl, + // args: impl IntoIterator, + // args_count: usize, + // ) -> EvaluationResult { + // let arity = *arity; + // let level = *level; + // let variadic = *variadic; + + // let correct_arity = if variadic { + // args_count >= arity + // } else { + // args_count == arity + // }; + // if !correct_arity { + // return Err(EvaluationError::WrongArity { + // expected: arity, + // realized: args_count, + // }); + // } + // self.enter_scope(); + // let mut iter = args.into_iter().enumerate(); + // if arity > 0 { + // for (index, arg) in &mut iter { + // let parameter = lambda_parameter_key(index, level); + // self.insert_value_in_current_scope(¶meter, arg.clone()); + + // if index == arity - 1 { + // break; + // } + // } + // } + // if variadic { + // let operand = Value::List(iter.map(|(_, arg)| arg.clone()).collect()); + // let parameter = lambda_parameter_key(arity, level); + // self.insert_value_in_current_scope(¶meter, operand); + // } + // let mut result = self.eval_do_inner(body); + // if let Ok(Value::FnWithCaptures(FnWithCapturesImpl { f, mut captures })) = result { + // update_captures(&mut captures, &self.scopes)?; + // result = Ok(Value::FnWithCaptures(FnWithCapturesImpl { f, captures })) + // } + // self.leave_scope(); + // result + // } - fn apply_fn( - &mut self, - f: &FnImpl, - operand_forms: PersistentList, - ) -> EvaluationResult { - let mut args = Vec::with_capacity(operand_forms.len()); - for form in &operand_forms { - let result = self.evaluate_form(form)?; - args.push(result); - } - self.apply_fn_inner(f, &args, args.len()) - } + // fn apply_fn( + // &mut self, + // f: &FnImpl, + // operand_forms: PersistentList, + // ) -> EvaluationResult { + // let mut args = Vec::with_capacity(operand_forms.len()); + // for form in &operand_forms { + // let result = self.evaluate_form(form)?; + // args.push(result); + // } + // self.apply_fn_inner(f, &args, args.len()) + // } - fn apply_primitive( - &mut self, - native_fn: NativeFn, - operand_forms: PersistentList, - ) -> EvaluationResult { - let mut operands = vec![]; - for operand_form in &operand_forms { - let operand = self.evaluate_form(operand_form)?; - operands.push(operand); - } - native_fn(self, &operands) - } + // fn apply_primitive( + // &mut self, + // native_fn: NativeFn, + // operand_forms: PersistentList, + // ) -> EvaluationResult { + // let mut operands = vec![]; + // for operand_form in &operand_forms { + // let operand = self.evaluate_form(operand_form)?; + // operands.push(operand); + // } + // native_fn(self, &operands) + // } - pub fn extend_from_captures( - &mut self, - captures: &HashMap>, - ) -> EvaluationResult<()> { - self.enter_scope(); - for (capture, value) in captures { - if let Some(value) = value { - self.insert_value_in_current_scope(capture, value.clone()); - } else { - self.leave_scope(); - return Err(EvaluationError::MissingCapturedValue(capture.to_string())); - } - } - Ok(()) - } + // pub fn extend_from_captures( + // &mut self, + // captures: &HashMap>, + // ) -> EvaluationResult<()> { + // self.enter_scope(); + // for (capture, value) in captures { + // if let Some(value) = value { + // self.insert_value_in_current_scope(capture, value.clone()); + // } else { + // self.leave_scope(); + // return Err(EvaluationError::MissingCapturedValue(capture.to_string())); + // } + // } + // Ok(()) + // } // fn eval_def_inner(&mut self, id: &str, value_form: &Value) -> EvaluationResult { // // need to only adjust var if this `def!` is successful @@ -849,290 +806,293 @@ impl Interpreter { // self.evaluate_form(&expansion) // } - fn eval_defmacro_legacy( - &mut self, - operand_forms: PersistentList, - ) -> EvaluationResult { - match self.eval_def(operand_forms)? { - Value::Var(var) => match var_impl_into_inner(&var) { - Some(Value::Fn(f)) => { - var.update(Value::Macro(f)); - Ok(Value::Var(var)) - } - Some(other) => { - self.unintern_var(&var.identifier); - Err(EvaluationError::WrongType { - expected: "Fn", - realized: other, - }) - } - None => { - self.unintern_var(&var.identifier); - Err(EvaluationError::WrongType { - expected: "Fn", - realized: Value::Var(var), - }) - } - }, - _ => unreachable!("eval def only returns Value::Var"), - } - } + // fn eval_defmacro_legacy( + // &mut self, + // operand_forms: PersistentList, + // ) -> EvaluationResult { + // match self.eval_def(operand_forms)? { + // Value::Var(var) => match var_impl_into_inner(&var) { + // Some(Value::Fn(f)) => { + // var.update(Value::Macro(f)); + // Ok(Value::Var(var)) + // } + // Some(other) => { + // self.unintern_var(&var.identifier); + // Err(EvaluationError::WrongType { + // expected: "Fn", + // realized: other, + // }) + // } + // None => { + // self.unintern_var(&var.identifier); + // Err(EvaluationError::WrongType { + // expected: "Fn", + // realized: Value::Var(var), + // }) + // } + // }, + // _ => unreachable!("eval def only returns Value::Var"), + // } + // } - fn eval_macroexpand( - &mut self, - operand_forms: PersistentList, - ) -> EvaluationResult { - do_to_exactly_one_arg(operand_forms, |arg| match self.evaluate_form(arg)? { - Value::List(elems) => self.expand_macro_if_present(&elems), - other => Ok(other), - }) - } + // fn eval_macroexpand_legacy( + // &mut self, + // operand_forms: PersistentList, + // ) -> EvaluationResult { + // do_to_exactly_one_arg(operand_forms, |arg| match self.evaluate_form(arg)? { + // Value::List(elems) => self.expand_macro_if_present(&elems), + // other => Ok(other), + // }) + // } - fn eval_try(&mut self, operand_forms: PersistentList) -> EvaluationResult { - let catch_form = match operand_forms.last() { - Some(Value::List(last_form)) => match last_form.first() { - Some(Value::Symbol(s, None)) if s == "catch*" => { - // FIXME: deduplicate analysis of `catch*` here... - if let Some(catch_form) = last_form.drop_first() { - if let Some(exception_symbol) = catch_form.first() { - match exception_symbol { - s @ Value::Symbol(_, None) => { - // if let Some(exception_body) = catch_form.drop_first() { - // let mut exception_binding = PersistentVector::new(); - // exception_binding.push_back_mut(s.clone()); - // let body = - // analyze_fn(self, exception_body, &exception_binding)?; - // Some(body) - // } else { - // None - // } - None - } - other => { - return Err(SyntaxError::LexicalBindingsMustHaveSymbolNames( - other.clone(), - ) - .into()); - } - } - } else { - None - } - } else { - return Err(EvaluationError::WrongArity { - expected: 2, - realized: 0, - }); - } - } - _ => None, - }, - // FIXME: avoid clones here... - Some(f @ Value::Fn(..)) => Some(f.clone()), - Some(f @ Value::FnWithCaptures(..)) => Some(f.clone()), - _ => None, - }; - let forms_to_eval = if catch_form.is_none() { - operand_forms - } else { - let mut forms_to_eval = vec![]; - for (index, form) in operand_forms.iter().enumerate() { - if index == operand_forms.len() - 1 { - break; - } - forms_to_eval.push(form.clone()); - } - PersistentList::from_iter(forms_to_eval) - }; - let apply_stack_pointer = self.apply_stack.len(); - match self.eval_do_inner(&forms_to_eval) { - Ok(result) => Ok(result), - Err(err) => match catch_form { - Some(Value::Fn(FnImpl { body, level, .. })) => { - self.failed_form.take(); - self.apply_stack.truncate(apply_stack_pointer); - self.enter_scope(); - let parameter = lambda_parameter_key(0, level); - self.insert_value_in_current_scope(¶meter, exception_from_system_err(err)); - let result = self.eval_do_inner(&body); - self.leave_scope(); - result - } - Some(Value::FnWithCaptures(FnWithCapturesImpl { - f: FnImpl { body, level, .. }, - mut captures, - })) => { - self.failed_form.take(); - self.apply_stack.truncate(apply_stack_pointer); - // FIXME: here we pull values from scopes just to turn around and put them back in a child scope. - // Can we skip this? - update_captures(&mut captures, &self.scopes)?; - self.extend_from_captures(&captures)?; - self.enter_scope(); - let parameter = lambda_parameter_key(0, level); - self.insert_value_in_current_scope(¶meter, exception_from_system_err(err)); - let result = self.eval_do_inner(&body); - self.leave_scope(); - self.leave_scope(); - result - } - None => Err(err), - _ => unreachable!("`catch*` form yields callable or nothing via syntax analysis"), - }, - } - } + // fn eval_try_legacy(&mut self, operand_forms: PersistentList) -> EvaluationResult { + // let catch_form = match operand_forms.last() { + // Some(Value::List(last_form)) => match last_form.first() { + // Some(Value::Symbol(s, None)) if s == "catch*" => { + // // FIXME: deduplicate analysis of `catch*` here... + // if let Some(catch_form) = last_form.drop_first() { + // if let Some(exception_symbol) = catch_form.first() { + // match exception_symbol { + // s @ Value::Symbol(_, None) => { + // // if let Some(exception_body) = catch_form.drop_first() { + // // let mut exception_binding = PersistentVector::new(); + // // exception_binding.push_back_mut(s.clone()); + // // let body = + // // analyze_fn(self, exception_body, &exception_binding)?; + // // Some(body) + // // } else { + // // None + // // } + // None + // } + // other => { + // return Err(SyntaxError::LexicalBindingsMustHaveSymbolNames( + // other.clone(), + // ) + // .into()); + // } + // } + // } else { + // None + // } + // } else { + // return Err(EvaluationError::WrongArity { + // expected: 2, + // realized: 0, + // }); + // } + // } + // _ => None, + // }, + // // FIXME: avoid clones here... + // Some(f @ Value::Fn(..)) => Some(f.clone()), + // Some(f @ Value::FnWithCaptures(..)) => Some(f.clone()), + // _ => None, + // }; + // let forms_to_eval = if catch_form.is_none() { + // operand_forms + // } else { + // let mut forms_to_eval = vec![]; + // for (index, form) in operand_forms.iter().enumerate() { + // if index == operand_forms.len() - 1 { + // break; + // } + // forms_to_eval.push(form.clone()); + // } + // PersistentList::from_iter(forms_to_eval) + // }; + // let apply_stack_pointer = self.apply_stack.len(); + // match self.eval_do_inner(&forms_to_eval) { + // Ok(result) => Ok(result), + // Err(err) => match catch_form { + // Some(Value::Fn(FnImpl { body, level, .. })) => { + // self.failed_form.take(); + // self.apply_stack.truncate(apply_stack_pointer); + // self.enter_scope(); + // let parameter = lambda_parameter_key(0, level); + // self.insert_value_in_current_scope(¶meter, exception_from_system_err(err)); + // let result = self.eval_do_inner(&body); + // self.leave_scope(); + // result + // } + // Some(Value::FnWithCaptures(FnWithCapturesImpl { + // f: FnImpl { body, level, .. }, + // mut captures, + // })) => { + // self.failed_form.take(); + // self.apply_stack.truncate(apply_stack_pointer); + // // FIXME: here we pull values from scopes just to turn around and put them back in a child scope. + // // Can we skip this? + // update_captures(&mut captures, &self.scopes)?; + // self.extend_from_captures(&captures)?; + // self.enter_scope(); + // let parameter = lambda_parameter_key(0, level); + // self.insert_value_in_current_scope(¶meter, exception_from_system_err(err)); + // let result = self.eval_do_inner(&body); + // self.leave_scope(); + // self.leave_scope(); + // result + // } + // None => Err(err), + // _ => unreachable!("`catch*` form yields callable or nothing via syntax analysis"), + // }, + // } + // } - pub(crate) fn get_macro_expansion( - &mut self, - operator: &Value, - operands: &PersistentList, - ) -> Option> { - match operator { - Value::Symbol(identifier, ns_opt) => { - if let Ok(Value::Macro(f)) = self.resolve_symbol(identifier, ns_opt.as_ref()) { - Some(self.apply_macro(&f, operands)) - } else { - None - } - } - Value::Var(v) => { - if let Some(Value::Macro(f)) = var_impl_into_inner(v) { - Some(self.apply_macro(&f, operands)) - } else { - None - } - } - _ => None, - } - } + // pub(crate) fn get_macro_expansion( + // &mut self, + // operator: &Value, + // operands: &PersistentList, + // ) -> Option> { + // match operator { + // Value::Symbol(identifier, ns_opt) => { + // if let Ok(Value::Macro(f)) = self.resolve_symbol(identifier, ns_opt.as_ref()) { + // Some(self.apply_macro(&f, operands)) + // } else { + // None + // } + // } + // Value::Var(v) => { + // if let Some(Value::Macro(f)) = var_impl_into_inner(v) { + // Some(self.apply_macro(&f, operands)) + // } else { + // None + // } + // } + // _ => None, + // } + // } - fn eval_list(&mut self, forms: &PersistentList) -> EvaluationResult { - if forms.is_empty() { - return Ok(Value::List(PersistentList::new())); - } + // fn eval_list_legacy(&mut self, forms: &PersistentList) -> EvaluationResult { + // if forms.is_empty() { + // return Ok(Value::List(PersistentList::new())); + // } - let operator_form = forms.first().unwrap(); - let operand_forms = forms.drop_first().unwrap_or_default(); - if let Some(expansion) = self.get_macro_expansion(operator_form, &operand_forms) { - match expansion? { - Value::List(forms) => return self.eval_list(&forms), - other => return self.evaluate_form(&other), - } - } - match operator_form { - Value::Symbol(s, None) if s == "def!" => self.eval_def(operand_forms), - Value::Symbol(s, None) if s == "var" => self.eval_var(operand_forms), - Value::Symbol(s, None) if s == "let*" => self.eval_let(operand_forms), - Value::Symbol(s, None) if s == "loop*" => self.eval_loop(operand_forms), - Value::Symbol(s, None) if s == "recur" => self.eval_recur(operand_forms), - Value::Symbol(s, None) if s == "if" => self.eval_if(operand_forms), - Value::Symbol(s, None) if s == "do" => self.eval_do(operand_forms), - Value::Symbol(s, None) if s == "fn*" => self.eval_fn(operand_forms), - Value::Symbol(s, None) if s == "quote" => self.eval_quote(operand_forms), - Value::Symbol(s, None) if s == "quasiquote" => self.eval_quasiquote(operand_forms), - Value::Symbol(s, None) if s == "defmacro!" => self.eval_defmacro(operand_forms), - Value::Symbol(s, None) if s == "macroexpand" => self.eval_macroexpand(operand_forms), - Value::Symbol(s, None) if s == "try*" => self.eval_try(operand_forms), - operator_form => match self.evaluate_form(operator_form)? { - Value::Fn(f) => self.apply_fn(&f, operand_forms), - Value::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { - self.extend_from_captures(&captures)?; - let result = self.apply_fn(&f, operand_forms); - self.leave_scope(); - result - } - Value::Primitive(native_fn) => { - self.apply_stack.push(operator_form.clone()); - match self.apply_primitive(native_fn, operand_forms) { - result @ Ok(..) => { - self.apply_stack.pop().unwrap(); - result - } - err @ Err(..) => { - if self.failed_form.is_none() { - self.failed_form = Some(self.apply_stack.len() - 1); - } - err - } - } - } - v => Err(EvaluationError::CannotInvoke(v)), - }, - } - } + // let operator_form = forms.first().unwrap(); + // let operand_forms = forms.drop_first().unwrap_or_default(); + // if let Some(expansion) = self.get_macro_expansion(operator_form, &operand_forms) { + // match expansion? { + // Value::List(forms) => return self.eval_list(&forms), + // other => return self.evaluate_form(&other), + // } + // } + // match operator_form { + // Value::Symbol(s, None) if s == "def!" => self.eval_def(operand_forms), + // Value::Symbol(s, None) if s == "var" => self.eval_var(operand_forms), + // Value::Symbol(s, None) if s == "let*" => self.eval_let(operand_forms), + // Value::Symbol(s, None) if s == "loop*" => self.eval_loop(operand_forms), + // Value::Symbol(s, None) if s == "recur" => self.eval_recur(operand_forms), + // Value::Symbol(s, None) if s == "if" => self.eval_if(operand_forms), + // Value::Symbol(s, None) if s == "do" => self.eval_do(operand_forms), + // Value::Symbol(s, None) if s == "fn*" => self.eval_fn(operand_forms), + // Value::Symbol(s, None) if s == "quote" => self.eval_quote(operand_forms), + // Value::Symbol(s, None) if s == "quasiquote" => self.eval_quasiquote(operand_forms), + // Value::Symbol(s, None) if s == "defmacro!" => self.eval_defmacro(operand_forms), + // Value::Symbol(s, None) if s == "macroexpand" => self.eval_macroexpand(operand_forms), + // Value::Symbol(s, None) if s == "try*" => self.eval_try(operand_forms), + // operator_form => match self.evaluate_form(operator_form)? { + // Value::Fn(f) => self.apply_fn(&f, operand_forms), + // Value::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { + // self.extend_from_captures(&captures)?; + // let result = self.apply_fn(&f, operand_forms); + // self.leave_scope(); + // result + // } + // Value::Primitive(native_fn) => { + // self.apply_stack.push(operator_form.clone()); + // match self.apply_primitive(native_fn, operand_forms) { + // result @ Ok(..) => { + // self.apply_stack.pop().unwrap(); + // result + // } + // err @ Err(..) => { + // if self.failed_form.is_none() { + // self.failed_form = Some(self.apply_stack.len() - 1); + // } + // err + // } + // } + // } + // v => Err(EvaluationError::CannotInvoke(v)), + // }, + // } + // } /// Evaluate the `form` according to the semantics of the language. - pub fn evaluate(&mut self, form: &Value) -> EvaluationResult { - let result = self.evaluate_form(form); - self.failed_form.take(); - self.apply_stack.clear(); - result - } + // pub fn evaluate(&mut self, form: &Value) -> EvaluationResult { + // let result = self.evaluate_form(form); + // self.failed_form.take(); + // self.apply_stack.clear(); + // result + // } - fn evaluate_form(&mut self, form: &Value) -> EvaluationResult { - match form { - Value::Nil => Ok(Value::Nil), - Value::Bool(b) => Ok(Value::Bool(*b)), - Value::Number(n) => Ok(Value::Number(*n)), - Value::String(s) => Ok(Value::String(s.to_string())), - Value::Keyword(id, ns_opt) => Ok(Value::Keyword( - id.to_string(), - ns_opt.as_ref().map(String::from), - )), - Value::Symbol(id, ns_opt) => self.resolve_symbol(id, ns_opt.as_ref()), - Value::List(forms) => self.eval_list(forms), - Value::Vector(forms) => { - let mut result = PersistentVector::new(); - for form in forms { - let value = self.evaluate_form(form)?; - result.push_back_mut(value); - } - Ok(Value::Vector(result)) - } - Value::Map(forms) => { - let mut result = PersistentMap::new(); - for (k, v) in forms { - let key = self.evaluate_form(k)?; - let value = self.evaluate_form(v)?; - result.insert_mut(key, value); - } - Ok(Value::Map(result)) - } - Value::Set(forms) => { - let mut result = PersistentSet::new(); - for form in forms { - let value = self.evaluate_form(form)?; - result.insert_mut(value); - } - Ok(Value::Set(result)) - } - Value::Var(v) => match var_impl_into_inner(v) { - Some(value) => Ok(value), - None => Ok(Value::Var(v.clone())), - }, - f @ Value::Fn(_) => Ok(f.clone()), - Value::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { - let mut captures = captures.clone(); - update_captures(&mut captures, &self.scopes)?; - Ok(Value::FnWithCaptures(FnWithCapturesImpl { - f: f.clone(), - captures, - })) - } - f @ Value::Primitive(_) => Ok(f.clone()), - Value::Recur(_) => unreachable!(), - a @ Value::Atom(_) => Ok(a.clone()), - Value::Macro(_) => unreachable!(), - Value::Exception(_) => unreachable!(), - } - } + // fn evaluate_form(&mut self, form: &Value) -> EvaluationResult { + // match form { + // Value::Nil => Ok(Value::Nil), + // Value::Bool(b) => Ok(Value::Bool(*b)), + // Value::Number(n) => Ok(Value::Number(*n)), + // Value::String(s) => Ok(Value::String(s.to_string())), + // Value::Keyword(id, ns_opt) => Ok(Value::Keyword( + // id.to_string(), + // ns_opt.as_ref().map(String::from), + // )), + // Value::Symbol(id, ns_opt) => self.resolve_symbol(id, ns_opt.as_ref()), + // Value::List(forms) => self.eval_list(forms), + // Value::Vector(forms) => { + // let mut result = PersistentVector::new(); + // for form in forms { + // let value = self.evaluate_form(form)?; + // result.push_back_mut(value); + // } + // Ok(Value::Vector(result)) + // } + // Value::Map(forms) => { + // let mut result = PersistentMap::new(); + // for (k, v) in forms { + // let key = self.evaluate_form(k)?; + // let value = self.evaluate_form(v)?; + // result.insert_mut(key, value); + // } + // Ok(Value::Map(result)) + // } + // Value::Set(forms) => { + // let mut result = PersistentSet::new(); + // for form in forms { + // let value = self.evaluate_form(form)?; + // result.insert_mut(value); + // } + // Ok(Value::Set(result)) + // } + // Value::Var(v) => match var_impl_into_inner(v) { + // Some(value) => Ok(value), + // None => Ok(Value::Var(v.clone())), + // }, + // f @ Value::Fn(_) => Ok(f.clone()), + // Value::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { + // let mut captures = captures.clone(); + // update_captures(&mut captures, &self.scopes)?; + // Ok(Value::FnWithCaptures(FnWithCapturesImpl { + // f: f.clone(), + // captures, + // })) + // } + // f @ Value::Primitive(_) => Ok(f.clone()), + // Value::Recur(_) => unreachable!(), + // a @ Value::Atom(_) => Ok(a.clone()), + // Value::Macro(_) => unreachable!(), + // Value::Exception(_) => unreachable!(), + // } + // } - /// Evaluate `form` in the global scope of the interpreter. - /// This method is exposed for the `eval` primitive which - /// has these semantics. - pub(crate) fn evaluate_in_global_scope(&mut self, form: &Value) -> EvaluationResult { - let mut child_scopes: Vec<_> = self.scopes.drain(1..).collect(); - let result = self.evaluate_form(form); + // Evaluate `form` in the global scope of the interpreter. + // This method is exposed for the `eval` primitive which + // has these semantics. + pub(crate) fn evaluate_in_global_scope( + &mut self, + form: &RuntimeValue, + ) -> EvaluationResult { + let mut child_scopes: Vec<_> = self.scopes.drain(0..).collect(); + let result = self.evaluate_analyzed_form(form); self.scopes.append(&mut child_scopes); result } @@ -1140,79 +1100,77 @@ impl Interpreter { fn resolve_in_lexical_scopes(&self, identifier: &Identifier) -> RuntimeValue { for scope in self.scopes.iter().rev() { if let Some(value) = scope.get(identifier) { + // TODO: wrap in Rc for cheap clone? return value.clone(); } } unreachable!("analysis guarantees identifier is in scope") } - fn eval_def(&mut self, form: DefForm) -> EvaluationResult { + fn eval_def(&mut self, form: &DefForm) -> EvaluationResult { let var = match form { DefForm::Bound(symbol, form) => { - let value = self.evaluate_analyzed_form(*form)?; - self.intern(symbol, Some(value))? + let value = self.evaluate_analyzed_form(form)?; + self.intern(&symbol, Some(value))? } - DefForm::Unbound(symbol) => self.intern(symbol, None)?, + DefForm::Unbound(symbol) => self.intern(&symbol, None)?, }; Ok(RuntimeValue::Var(var)) } fn eval_var(&self, symbol: &Symbol) -> EvaluationResult { self.namespaces - .resolve_symbol(symbol) + .resolve_symbol(&symbol) .map(RuntimeValue::Var) .map_err(EvaluationError::from) } - fn extend_lexical_scope<'a>( - &'a mut self, - bindings: impl Iterator, - ) { - let scope = Scope::from(bindings); + fn extend_lexical_scope(&mut self, bindings: impl Iterator) { + let scope = Scope::from_iter(bindings); self.scopes.push(scope); } fn eval_body_form(&mut self, BodyForm { body }: &BodyForm) -> EvaluationResult { let mut result = RuntimeValue::Nil; - for &form in body { + for form in body { result = self.evaluate_analyzed_form(form)? } Ok(result) } - fn eval_let( - &mut self, - LetForm { - lexical_form, - forward_declarations, - }: LetForm, - ) -> EvaluationResult { + fn eval_let(&mut self, let_form: &LetForm) -> EvaluationResult { + let lexical_form = &let_form.lexical_form; + let forward_declarations = &let_form.forward_declarations; + let has_forward_declarations = !forward_declarations.is_empty(); if has_forward_declarations { - self.extend_lexical_scope( - forward_declarations - .into_iter() - .map(|symbol| (&symbol.identifier, RuntimeValue::Var(Var::Unbound))), - ); + self.extend_lexical_scope(forward_declarations.iter().map(|&index| { + ( + let_form.identifier_for_binding(index).unwrap().clone(), + RuntimeValue::Var(Var::Unbound), + ) + })); } - let bindings = match lexical_form.bindings { + let bindings = match &lexical_form.bindings { LexicalBindings::Bound(bindings) => bindings - .into_iter() - .map(|(symbol, form)| Ok((&symbol.identifier, self.evaluate_analyzed_form(*form)?))) - .collect::, _>>() - .map_err(|err| { + .iter() + .map(|(identifier, form)| { + Ok((identifier.clone(), self.evaluate_analyzed_form(form)?)) + }) + .collect::, EvaluationError>>() + .map_err(|err: EvaluationError| { if has_forward_declarations { self.leave_scope(); } err })?, - LexicalBindings::Unbound(bindings) => { + LexicalBindings::Unbound(_) => { unreachable!("let* cannot have unbound local symbols") } }; // TODO: are forward decls being resolved correctly? - self.extend_lexical_scope(bindings.iter()); + self.extend_lexical_scope(bindings.into_iter()); let result = self.eval_body_form(&lexical_form.body); @@ -1223,20 +1181,19 @@ impl Interpreter { result } - fn eval_loop<'a>( - &'a mut self, - lexical_form: LexicalForm<'a>, - ) -> EvaluationResult { - let bindings = match lexical_form.bindings { + fn eval_loop(&mut self, lexical_form: &LexicalForm) -> EvaluationResult { + let bindings = match &lexical_form.bindings { LexicalBindings::Bound(bindings) => bindings - .into_iter() - .map(|(symbol, form)| Ok((&symbol.identifier, self.evaluate_analyzed_form(*form)?))) - .collect::, _>>()?, - LexicalBindings::Unbound(bindings) => { + .iter() + .map(|(identifier, form)| { + Ok((identifier.clone(), self.evaluate_analyzed_form(form)?)) + }) + .collect::, EvaluationError>>()?, + LexicalBindings::Unbound(_) => { unreachable!("let* cannot have unbound local symbols") } }; - self.extend_lexical_scope(bindings.iter()); + self.extend_lexical_scope(bindings.into_iter()); let delimiter = self.control_stack.len(); self.control_stack.push(ControlFlow::Continue); @@ -1249,8 +1206,9 @@ impl Interpreter { })?; while let ControlFlow::Recur(values) = self.control_stack.pop().unwrap() { let scope = self.scopes.last_mut().unwrap(); - for ((name, _), value) in bindings.iter().zip(values.into_iter()) { - scope.insert(*name, value); + let bindings = lexical_form.bindings.names(); + for (name, value) in bindings.iter().zip(values.into_iter()) { + scope.insert(name.to_string(), value); } result = self.eval_body_form(body).map_err(|err| { self.control_stack.truncate(delimiter); @@ -1265,9 +1223,9 @@ impl Interpreter { Ok(result) } - fn eval_recur(&mut self, BodyForm { body }: BodyForm) -> EvaluationResult { + fn eval_recur(&mut self, BodyForm { body }: &BodyForm) -> EvaluationResult { let result = body - .into_iter() + .iter() .map(|form| self.evaluate_analyzed_form(form)) .collect::, _>>()?; self.control_stack.push(ControlFlow::Recur(result)); @@ -1280,45 +1238,59 @@ impl Interpreter { predicate, consequent, alternate, - }: IfForm, + }: &IfForm, ) -> EvaluationResult { - let predicate = self.evaluate_analyzed_form(*predicate)?; + let predicate = self.evaluate_analyzed_form(predicate)?; let falsey = matches!(predicate, RuntimeValue::Nil | RuntimeValue::Bool(false)); if falsey { if let Some(alternate) = alternate { - self.evaluate_analyzed_form(*alternate) + self.evaluate_analyzed_form(alternate) } else { Ok(RuntimeValue::Nil) } } else { - self.evaluate_analyzed_form(*consequent) + self.evaluate_analyzed_form(consequent) } } - fn eval_fn(&mut self, fn_form: FnForm) -> EvaluationResult { - // TODO: address lifetimes - Ok(RuntimeValue::Fn(fn_form)) + fn eval_fn(&mut self, fn_form: &FnForm) -> EvaluationResult { + Ok(RuntimeValue::Fn(fn_form.clone())) } - fn eval_quote(&mut self, form: Box) -> EvaluationResult { - Ok(form.into()) + fn eval_quote(&mut self, form: &RuntimeValue) -> EvaluationResult { + // TODO + // Ok(form.into()) + Ok(RuntimeValue::Nil) } - fn eval_quasiquote(&mut self, form: Box) -> EvaluationResult { - let expansion = eval_quasiquote(form)?; - self.evaluate_analyzed_form(expansion) + fn eval_quasiquote(&mut self, form: &RuntimeValue) -> EvaluationResult { + // TODO + // let expansion = eval_quasiquote(form)?; + // self.evaluate_analyzed_form(expansion) + Ok(RuntimeValue::Nil) } - fn eval_defmacro(&mut self, name: &Symbol, fn_form: FnForm) -> EvaluationResult { + fn eval_defmacro(&mut self, name: &Symbol, fn_form: &FnForm) -> EvaluationResult { // TODO + Ok(RuntimeValue::Nil) } - fn eval_macroexpand(&mut self, form: Box) -> EvaluationResult { + fn eval_macroexpand(&mut self, form: &RuntimeValue) -> EvaluationResult { // TODO + Ok(RuntimeValue::Nil) } - fn eval_try(&mut self, TryForm { body, catch }: TryForm) -> EvaluationResult { - // TODO + fn eval_try(&mut self, TryForm { body, catch }: &TryForm) -> EvaluationResult { + match self.eval_body_form(&body) { + Ok(result) => Ok(result), + Err(err) => { + if let Some(catch_form) = catch { + self.eval_catch(catch_form, err) + } else { + Err(err) + } + } + } } fn eval_catch( @@ -1326,878 +1298,959 @@ impl Interpreter { CatchForm { exception_binding, body, - }: CatchError, + }: &CatchForm, + err: EvaluationError, ) -> EvaluationResult { - // TODO + let exception = exception_from_system_err(err); + + let bindings = [(exception_binding.clone(), exception)]; + self.extend_lexical_scope(bindings.into_iter()); + + let result = self.eval_body_form(body); + + self.leave_scope(); + result } - fn evaluate_analyzed_form(&mut self, form: AnalyzedForm) -> EvaluationResult { - let value = match form { - AnalyzedForm::LexicalSymbol(identifier) => self.resolve_in_lexical_scopes(identifier), - AnalyzedForm::Var(var) => { - match var { - Var::Bound(value) => { - // TODO fix - RuntimeValue::Nil - } - Var::Unbound => RuntimeValue::Var(var), + fn apply_fn( + &mut self, + f: &FnForm, + mut args: Vec, + ) -> EvaluationResult { + let correct_arity = if f.variadic() { + args.len() >= f.arity() + } else { + args.len() == f.arity() + }; + if !correct_arity { + // TODO better wording on error? + return Err(EvaluationError::WrongArity { + expected: f.arity(), + realized: args.len(), + }); + } + + let variable = args.drain(f.arity()..).collect::>(); + + let bindings = f.parameters.iter().cloned().zip(args.into_iter()); + if f.variadic() { + let variadic_binding = f.variadic.as_ref().unwrap().clone(); + let variadic_arg = RuntimeValue::List(PersistentList::from_iter(variable)); + + self.extend_lexical_scope(bindings.chain([(variadic_binding, variadic_arg)])); + } else { + self.extend_lexical_scope(bindings); + } + + let result = self.eval_body_form(&f.body); + + self.leave_scope(); + result + } + + fn evaluate_analyzed_list( + &mut self, + coll: &PersistentList, + ) -> EvaluationResult { + if let Some(operator) = coll.first() { + let operands = coll.drop_first().unwrap(); + // TODO macroexpand + match self.evaluate_analyzed_form(operator)? { + RuntimeValue::Fn(f) => { + let operands = operands + .iter() + .map(|form| self.evaluate_analyzed_form(form)) + .collect::, _>>()?; + self.apply_fn(&f, operands) } - } - AnalyzedForm::Atom(atom) => atom.into(), - AnalyzedForm::List(inner) => match inner { - AnalyzedList::Def(form) => self.eval_def(form), - AnalyzedList::Var(symbol) => self.eval_var(symbol), - AnalyzedList::Let(form) => self.eval_let(form), - AnalyzedList::Loop(form) => self.eval_loop(form), - AnalyzedList::Recur(form) => self.eval_recur(form), - AnalyzedList::If(form) => self.eval_if(form), - AnalyzedList::Do(form) => self.eval_body_form(&form), - AnalyzedList::Fn(form) => self.eval_fn(form), - AnalyzedList::Quote(form) => self.eval_quote(form), - AnalyzedList::Quasiquote(form) => self.eval_quasiquote(form), - // AnalyzedList::Unquote(form) => self.eval_unquote(form), - // AnalyzedList::SpliceUnquote(form) => self.eval_splice_unquote(form), - AnalyzedList::Defmacro(name, form) => self.eval_defmacro(name, form), - AnalyzedList::Macroexpand(form) => self.eval_macroexpand(form), - AnalyzedList::Try(form) => self.eval_try(form), - AnalyzedList::Catch(form) => self.eval_catch(form), - AnalyzedList::Form(coll) => { - let evaluated_coll = coll - .into_iter() + RuntimeValue::Primitive(f) => { + let operands = operands + .iter() .map(|form| self.evaluate_analyzed_form(form)) - .collect::>()?; - RuntimeValue::List(evaluated_coll) + .collect::, _>>()?; + f.apply(self, &operands) } + v => Err(EvaluationError::CannotInvoke(v)), + } + } else { + Ok(RuntimeValue::List(PersistentList::new())) + } + } + + fn evaluate_special_form(&mut self, form: &SpecialForm) -> EvaluationResult { + match form { + SpecialForm::Def(form) => self.eval_def(form), + SpecialForm::Var(symbol) => self.eval_var(symbol), + SpecialForm::Let(form) => self.eval_let(form), + SpecialForm::Loop(form) => self.eval_loop(form), + SpecialForm::Recur(form) => self.eval_recur(form), + SpecialForm::If(form) => self.eval_if(form), + SpecialForm::Do(form) => self.eval_body_form(&form), + SpecialForm::Fn(form) => self.eval_fn(form), + SpecialForm::Quote(form) => self.eval_quote(form), + SpecialForm::Quasiquote(form) => self.eval_quasiquote(form), + SpecialForm::Defmacro(name, form) => self.eval_defmacro(name, form), + SpecialForm::Macroexpand(form) => self.eval_macroexpand(form), + SpecialForm::Try(form) => self.eval_try(form), + } + } + + fn evaluate_analyzed_form(&mut self, form: &RuntimeValue) -> EvaluationResult { + let value = match form { + RuntimeValue::Nil => form.clone(), + RuntimeValue::Bool(..) => form.clone(), + RuntimeValue::Number(..) => form.clone(), + RuntimeValue::String(..) => form.clone(), + RuntimeValue::Keyword(..) => form.clone(), + RuntimeValue::Symbol(..) => { + // TODO resolve? + form.clone() + } + RuntimeValue::LexicalSymbol(identifier) => self.resolve_in_lexical_scopes(identifier), + RuntimeValue::Var(var) => match var { + Var::Bound(value) => value.borrow().clone(), + Var::Unbound => RuntimeValue::Var(Var::Unbound), }, - AnalyzedForm::Vector(coll) => { + RuntimeValue::List(coll) => self.evaluate_analyzed_list(coll)?, + RuntimeValue::Vector(coll) => { let evaluated_coll = coll - .into_iter() + .iter() .map(|form| self.evaluate_analyzed_form(form)) - .collect::>()?; + .collect::, _>>()?; RuntimeValue::Vector(evaluated_coll) } - AnalyzedForm::Map(coll) => { - let evaluated_coll = coll - .into_iter() - .map(|(key, value)| { - let evaluated_key = self.evaluate_analyzed_form(form); - let evaluated_value = self.evaluate_analyzed_form(form); - [evaluated_key, evaluated_value] - }) - .collect::>()?; + RuntimeValue::Map(coll) => { + let mut evaluated_coll = PersistentMap::new(); + for (key, value) in coll { + let evaluated_key = self.evaluate_analyzed_form(key)?; + let evaluated_value = self.evaluate_analyzed_form(value)?; + evaluated_coll.insert_mut(evaluated_key, evaluated_value); + } RuntimeValue::Map(evaluated_coll) } - AnalyzedForm::Set(coll) => { - let evaluated_coll = coll - .into_iter() - .map(|form| self.evaluate_analyzed_form(form)) - .collect::>()?; + RuntimeValue::Set(coll) => { + let mut evaluated_coll = PersistentSet::new(); + for elem in coll { + let analyzed_elem = self.evaluate_analyzed_form(elem)?; + evaluated_coll.insert_mut(analyzed_elem); + } RuntimeValue::Set(evaluated_coll) } + RuntimeValue::SpecialForm(form) => self.evaluate_special_form(form)?, + RuntimeValue::Fn(..) => { + // TODO? + form.clone() + } + RuntimeValue::Primitive(f) => { + // TODO? + form.clone() + } + RuntimeValue::Exception(exc) => { + // TODO? + form.clone() + } }; Ok(value) } - fn analyze_and_evaluate(&mut self, form: &Form) -> EvaluationResult { - let analyzer = Analyzer::new(&self.namespaces); + pub(crate) fn analyze_and_evaluate(&mut self, form: &Form) -> EvaluationResult { + let mut analyzer = Analyzer::new(&self.namespaces); let analyzed_form = analyzer.analyze(form)?; - self.evaluate_analyzed_form(analyzed_form) + self.evaluate_analyzed_form(&analyzed_form) } - pub fn interpret(&mut self, source: &str) -> EvaluationResult> { + pub fn interpret(&mut self, source: &str) -> EvaluationResult> { read(source) .map_err(|err| EvaluationError::ReaderError(err, source.to_string()))? .iter() .map(|form| self.analyze_and_evaluate(form)) - .collect::>()?; - // TODO fix return - Ok(vec![Value::Nil]) + .collect::, _>>() } } #[cfg(test)] mod test { - use crate::collections::{PersistentList, PersistentMap, PersistentVector}; - use crate::reader; - use crate::testing::run_eval_test; - use crate::value::{ - atom_with_value, exception, list_with_values, map_with_values, var_with_value, - vector_with_values, - Value::{self, *}, - }; - - const DEFAULT_NAMESPACE: &str = "core"; - - fn read_one_value(input: &str) -> Value { - let form = reader::read(input) - .expect("is valid") - .into_iter() - .nth(0) - .expect("some"); - - (&form).into() - } + // use crate::collections::{PersistentList, PersistentMap, PersistentVector}; + // use crate::reader; + // use crate::testing::run_eval_test; + // use crate::value::{ + // atom_with_value, exception, list_with_values, map_with_values, var_with_value, + // vector_with_values, + // Value::{self, *}, + // }; + + // const DEFAULT_NAMESPACE: &str = "core"; + + // fn read_one_value(input: &str) -> Value { + // let form = reader::read(input) + // .expect("is valid") + // .into_iter() + // .nth(0) + // .expect("some"); + + // (&form).into() + // } - #[test] - fn test_basic_self_evaluating() { - let test_cases = vec![ - ("nil", Nil), - ("true", Bool(true)), - ("false", Bool(false)), - ("1337", Number(1337)), - ("-1337", Number(-1337)), - ("\"hi\"", String("hi".to_string())), - (r#""""#, String("".to_string())), - ("\"abc\"", String("abc".to_string())), - ("\"abc def\"", String("abc def".to_string())), - ("\"abc\\ndef\\nghi\"", String("abc\ndef\nghi".to_string())), - ("\"abc\\def\\ghi\"", String("abc\\def\\ghi".to_string())), - ("\" \\\\n \"", String(" \\n ".to_string())), - (":hi", Keyword("hi".to_string(), None)), - ( - ":foo/hi", - Keyword("hi".to_string(), Some("foo".to_string())), - ), - ("()", List(PersistentList::new())), - ("[]", Vector(PersistentVector::new())), - ("{}", Map(PersistentMap::new())), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_self_evaluating() { + // let test_cases = vec![ + // ("nil", Nil), + // ("true", Bool(true)), + // ("false", Bool(false)), + // ("1337", Number(1337)), + // ("-1337", Number(-1337)), + // ("\"hi\"", String("hi".to_string())), + // (r#""""#, String("".to_string())), + // ("\"abc\"", String("abc".to_string())), + // ("\"abc def\"", String("abc def".to_string())), + // ("\"abc\\ndef\\nghi\"", String("abc\ndef\nghi".to_string())), + // ("\"abc\\def\\ghi\"", String("abc\\def\\ghi".to_string())), + // ("\" \\\\n \"", String(" \\n ".to_string())), + // (":hi", Keyword("hi".to_string(), None)), + // ( + // ":foo/hi", + // Keyword("hi".to_string(), Some("foo".to_string())), + // ), + // ("()", List(PersistentList::new())), + // ("[]", Vector(PersistentVector::new())), + // ("{}", Map(PersistentMap::new())), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_apply() { - let test_cases = vec![ - ("(+)", Number(0)), - ("(+ 1)", Number(1)), - ("(+ 1 10)", Number(11)), - ("(+ 1 10 2)", Number(13)), - ("(- 1)", Number(-1)), - ("(- 10 9)", Number(1)), - ("(- 10 20)", Number(-10)), - ("(- 10 20 10)", Number(-20)), - ("(*)", Number(1)), - ("(* 2)", Number(2)), - ("(* 2 3)", Number(6)), - ("(* 2 3 1 1 1)", Number(6)), - ("(/ 2)", Number(0)), - ("(/ 1)", Number(1)), - ("(/ 22 2)", Number(11)), - ("(/ 22 2 1 1 1)", Number(11)), - ("(/ 22 2 1 1 1)", Number(11)), - ("(+ 2 (* 3 4))", Number(14)), - ("(+ 5 (* 2 3))", Number(11)), - ("(- (+ 5 (* 2 3)) 3)", Number(8)), - ("(/ (- (+ 5 (* 2 3)) 3) 4)", Number(2)), - ("(/ (- (+ 515 (* 87 311)) 302) 27)", Number(1010)), - ("(* -3 6)", Number(-18)), - ("(/ (- (+ 515 (* -87 311)) 296) 27)", Number(-994)), - ( - "[1 2 (+ 1 2)]", - vector_with_values(vec![Number(1), Number(2), Number(3)]), - ), - ( - "{\"a\" (+ 7 8)}", - map_with_values(vec![(String("a".to_string()), Number(15))]), - ), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_apply() { + // let test_cases = vec![ + // ("(+)", Number(0)), + // ("(+ 1)", Number(1)), + // ("(+ 1 10)", Number(11)), + // ("(+ 1 10 2)", Number(13)), + // ("(- 1)", Number(-1)), + // ("(- 10 9)", Number(1)), + // ("(- 10 20)", Number(-10)), + // ("(- 10 20 10)", Number(-20)), + // ("(*)", Number(1)), + // ("(* 2)", Number(2)), + // ("(* 2 3)", Number(6)), + // ("(* 2 3 1 1 1)", Number(6)), + // ("(/ 2)", Number(0)), + // ("(/ 1)", Number(1)), + // ("(/ 22 2)", Number(11)), + // ("(/ 22 2 1 1 1)", Number(11)), + // ("(/ 22 2 1 1 1)", Number(11)), + // ("(+ 2 (* 3 4))", Number(14)), + // ("(+ 5 (* 2 3))", Number(11)), + // ("(- (+ 5 (* 2 3)) 3)", Number(8)), + // ("(/ (- (+ 5 (* 2 3)) 3) 4)", Number(2)), + // ("(/ (- (+ 515 (* 87 311)) 302) 27)", Number(1010)), + // ("(* -3 6)", Number(-18)), + // ("(/ (- (+ 515 (* -87 311)) 296) 27)", Number(-994)), + // ( + // "[1 2 (+ 1 2)]", + // vector_with_values(vec![Number(1), Number(2), Number(3)]), + // ), + // ( + // "{\"a\" (+ 7 8)}", + // map_with_values(vec![(String("a".to_string()), Number(15))]), + // ), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_do() { - let test_cases = vec![ - ("(do )", Nil), - ("(do 1 2 3)", Number(3)), - ("(do (do 1 2))", Number(2)), - ("(do (prn 101))", Nil), - ("(do (prn 101) 7)", Number(7)), - ("(do (prn 101) (prn 102) (+ 1 2))", Number(3)), - ("(do (def! a 6) 7 (+ a 8))", Number(14)), - ("(do (def! a 6) 7 (+ a 8) a)", Number(6)), - ("(def! DO (fn* [a] 7)) (DO 3)", Number(7)), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_do() { + // let test_cases = vec![ + // ("(do )", Nil), + // ("(do 1 2 3)", Number(3)), + // ("(do (do 1 2))", Number(2)), + // ("(do (prn 101))", Nil), + // ("(do (prn 101) 7)", Number(7)), + // ("(do (prn 101) (prn 102) (+ 1 2))", Number(3)), + // ("(do (def! a 6) 7 (+ a 8))", Number(14)), + // ("(do (def! a 6) 7 (+ a 8) a)", Number(6)), + // ("(def! DO (fn* [a] 7)) (DO 3)", Number(7)), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_def() { - let test_cases = vec![ - ( - "(def! a 3)", - var_with_value(Number(3), DEFAULT_NAMESPACE, "a"), - ), - ("(def! a 3) (+ a 1)", Number(4)), - ("(def! a (+ 1 7)) (+ a 1)", Number(9)), - ( - "(def! some-num 3)", - var_with_value(Number(3), DEFAULT_NAMESPACE, "some-num"), - ), - ( - "(def! SOME-NUM 4)", - var_with_value(Number(4), DEFAULT_NAMESPACE, "SOME-NUM"), - ), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_def() { + // let test_cases = vec![ + // ( + // "(def! a 3)", + // var_with_value(Number(3), DEFAULT_NAMESPACE, "a"), + // ), + // ("(def! a 3) (+ a 1)", Number(4)), + // ("(def! a (+ 1 7)) (+ a 1)", Number(9)), + // ( + // "(def! some-num 3)", + // var_with_value(Number(3), DEFAULT_NAMESPACE, "some-num"), + // ), + // ( + // "(def! SOME-NUM 4)", + // var_with_value(Number(4), DEFAULT_NAMESPACE, "SOME-NUM"), + // ), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_let() { - let test_cases = - vec![ - ("(let* [] )", Nil), - ("(let* [a 1] )", Nil), - ("(let* [a 3] a)", Number(3)), - ("(let* [_ 30 a _] a)", Number(30)), - ("(let* [b 3] (+ b 5))", Number(8)), - ("(let* [a 3] (+ a (let* [c 5] c)))", Number(8)), - ("(let* [a (+ 1 2)] (+ a (let* [c 5] c)))", Number(8)), - ("(let* [a (+ 1 2)] (+ a (let* [a 5] a)))", Number(8)), - ("(let* [p (+ 2 3) q (+ 2 p)] (+ p q))", Number(12)), - ("(let* [a 3] (+ a (let* [a 5] a)))", Number(8)), - ("(let* [a 3 b a] (+ b 5))", Number(8)), - ( - "(let* [a 3 b 33] (+ a (let* [c 4] (+ c 1)) b 5))", - Number(46), - ), - ("(def! a 1) (let* [a 3] a)", Number(3)), - ("(def! a (let* [z 33] z)) a", Number(33)), - ("(def! a (let* [z 33] z)) (let* [a 3] a)", Number(3)), - ("(def! a (let* [z 33] z)) (let* [a 3] a) a", Number(33)), - ("(def! a 1) (let* [a 3] a) a", Number(1)), - ("(def! b 1) (let* [a 3] (+ a b))", Number(4)), - ( - "(let* [a 5 b 6] [3 4 a [b 7] 8])", - vector_with_values(vec![ - Number(3), - Number(4), - Number(5), - vector_with_values(vec![Number(6), Number(7)]), - Number(8), - ]), - ), - ( - "(let* [cst (fn* [n] (if (= n 0) :success (cst (- n 1))))] (cst 1))", - Keyword("success".to_string(), None), - ), - ( - "(let* [f (fn* [n] (if (= n 0) :success (g (- n 1)))) g (fn* [n] (f n))] (f 2))", - Keyword("success".to_string(), None), - ), - // test captures inside `let*` - ("(let* [y (let* [x 12] (fn* [] x))] (y))", Number(12)), - ("(let* [y (let* [x 12] (fn* [] (fn* [] x)))] ((y)))", Number(12)), - ("(let* [y (let* [x 12] ((fn* [x] (fn* [] (inc x))) x))] (y))", Number(13)), - ("(let* [y (let* [y 12] ((fn* [y] (fn* [] (inc y))) y))] (y))", Number(13)), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_let() { + // let test_cases = + // vec![ + // ("(let* [] )", Nil), + // ("(let* [a 1] )", Nil), + // ("(let* [a 3] a)", Number(3)), + // ("(let* [_ 30 a _] a)", Number(30)), + // ("(let* [b 3] (+ b 5))", Number(8)), + // ("(let* [a 3] (+ a (let* [c 5] c)))", Number(8)), + // ("(let* [a (+ 1 2)] (+ a (let* [c 5] c)))", Number(8)), + // ("(let* [a (+ 1 2)] (+ a (let* [a 5] a)))", Number(8)), + // ("(let* [p (+ 2 3) q (+ 2 p)] (+ p q))", Number(12)), + // ("(let* [a 3] (+ a (let* [a 5] a)))", Number(8)), + // ("(let* [a 3 b a] (+ b 5))", Number(8)), + // ( + // "(let* [a 3 b 33] (+ a (let* [c 4] (+ c 1)) b 5))", + // Number(46), + // ), + // ("(def! a 1) (let* [a 3] a)", Number(3)), + // ("(def! a (let* [z 33] z)) a", Number(33)), + // ("(def! a (let* [z 33] z)) (let* [a 3] a)", Number(3)), + // ("(def! a (let* [z 33] z)) (let* [a 3] a) a", Number(33)), + // ("(def! a 1) (let* [a 3] a) a", Number(1)), + // ("(def! b 1) (let* [a 3] (+ a b))", Number(4)), + // ( + // "(let* [a 5 b 6] [3 4 a [b 7] 8])", + // vector_with_values(vec![ + // Number(3), + // Number(4), + // Number(5), + // vector_with_values(vec![Number(6), Number(7)]), + // Number(8), + // ]), + // ), + // ( + // "(let* [cst (fn* [n] (if (= n 0) :success (cst (- n 1))))] (cst 1))", + // Keyword("success".to_string(), None), + // ), + // ( + // "(let* [f (fn* [n] (if (= n 0) :success (g (- n 1)))) g (fn* [n] (f n))] (f 2))", + // Keyword("success".to_string(), None), + // ), + // // test captures inside `let*` + // ("(let* [y (let* [x 12] (fn* [] x))] (y))", Number(12)), + // ("(let* [y (let* [x 12] (fn* [] (fn* [] x)))] ((y)))", Number(12)), + // ("(let* [y (let* [x 12] ((fn* [x] (fn* [] (inc x))) x))] (y))", Number(13)), + // ("(let* [y (let* [y 12] ((fn* [y] (fn* [] (inc y))) y))] (y))", Number(13)), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_if() { - let test_cases = vec![ - ("(if true 1 2)", Number(1)), - ("(if true 1)", Number(1)), - ("(if false 1 2)", Number(2)), - ("(if false 7 false)", Bool(false)), - ("(if true (+ 1 7) (+ 1 8))", Number(8)), - ("(if false (+ 1 7) (+ 1 8))", Number(9)), - ("(if false 2)", Nil), - ("(if false (+ 1 7))", Nil), - ("(if false (/ 1 0))", Nil), - ("(if nil 1 2)", Number(2)), - ("(if 0 1 2)", Number(1)), - ("(if (list) 1 2)", Number(1)), - ("(if (list 1 2 3) 1 2)", Number(1)), - ("(= (list) nil)", Bool(false)), - ("(if nil 2)", Nil), - ("(if true 2)", Number(2)), - ("(if false (/ 1 0))", Nil), - ("(if nil (/ 1 0))", Nil), - ("(let* [b nil] (if b 2 3))", Number(3)), - ("(if (> (count (list 1 2 3)) 3) 89 78)", Number(78)), - ("(if (>= (count (list 1 2 3)) 3) 89 78)", Number(89)), - ("(if \"\" 7 8)", Number(7)), - ("(if [] 7 8)", Number(7)), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_if() { + // let test_cases = vec![ + // ("(if true 1 2)", Number(1)), + // ("(if true 1)", Number(1)), + // ("(if false 1 2)", Number(2)), + // ("(if false 7 false)", Bool(false)), + // ("(if true (+ 1 7) (+ 1 8))", Number(8)), + // ("(if false (+ 1 7) (+ 1 8))", Number(9)), + // ("(if false 2)", Nil), + // ("(if false (+ 1 7))", Nil), + // ("(if false (/ 1 0))", Nil), + // ("(if nil 1 2)", Number(2)), + // ("(if 0 1 2)", Number(1)), + // ("(if (list) 1 2)", Number(1)), + // ("(if (list 1 2 3) 1 2)", Number(1)), + // ("(= (list) nil)", Bool(false)), + // ("(if nil 2)", Nil), + // ("(if true 2)", Number(2)), + // ("(if false (/ 1 0))", Nil), + // ("(if nil (/ 1 0))", Nil), + // ("(let* [b nil] (if b 2 3))", Number(3)), + // ("(if (> (count (list 1 2 3)) 3) 89 78)", Number(78)), + // ("(if (>= (count (list 1 2 3)) 3) 89 78)", Number(89)), + // ("(if \"\" 7 8)", Number(7)), + // ("(if [] 7 8)", Number(7)), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_fn() { - let test_cases = vec![ - ("((fn* []))", Nil), - ("((fn* [a] (+ a 1)) 23)", Number(24)), - ("((fn* [a b] (+ a b)) 23 1)", Number(24)), - ("((fn* [] (+ 4 3)) )", Number(7)), - ("((fn* [f x] (f x)) (fn* [a] (+ 1 a)) 7)", Number(8)), - ("((fn* [a] (+ a 1) 25) 23)", Number(25)), - ("((fn* [a] (let* [b 2] (+ a b))) 23)", Number(25)), - ("((fn* [a] (let* [a 2] (+ a a))) 23)", Number(4)), - ( - "(def! inc (fn* [a] (+ a 1))) ((fn* [a] (inc a)) 1)", - Number(2), - ), - ("((fn* [a] ((fn* [b] (+ b 1)) a)) 1)", Number(2)), - ("((fn* [a] ((fn* [a] (+ a 1)) a)) 1)", Number(2)), - ("((fn* [] ((fn* [] ((fn* [] 13))))))", Number(13)), - ( - "(def! factorial (fn* [n] (if (< n 2) 1 (* n (factorial (- n 1)))))) (factorial 8)", - Number(40320), - ), - ( - "(def! fibo (fn* [N] (if (= N 0) 1 (if (= N 1) 1 (+ (fibo (- N 1)) (fibo (- N 2))))))) (fibo 1)", - Number(1), - ), - ( - "(def! fibo (fn* [N] (if (= N 0) 1 (if (= N 1) 1 (+ (fibo (- N 1)) (fibo (- N 2))))))) (fibo 2)", - Number(2), - ), - ( - "(def! fibo (fn* [N] (if (= N 0) 1 (if (= N 1) 1 (+ (fibo (- N 1)) (fibo (- N 2))))))) (fibo 4)", - Number(5), - ), - ("(def! f (fn* [a] (+ a 1))) (f 23)", Number(24)), - ( - "(def! b 12) (def! f (fn* [a] (+ a b))) (def! b 22) (f 1)", - Number(23), - ), - ( - "(def! b 12) (def! f (fn* [a] ((fn* [] (+ a b))))) (def! b 22) (f 1)", - Number(23), - ), - ( - "(def! gen-plus5 (fn* [] (fn* [b] (+ 5 b)))) (def! plus5 (gen-plus5)) (plus5 7)", - Number(12), - ), - ("(((fn* [a] (fn* [b] (+ a b))) 5) 7)", Number(12)), - ("(def! gen-plus-x (fn* [x] (fn* [b] (+ x b)))) (def! plus7 (gen-plus-x 7)) (plus7 8)", Number(15)), - ("((((fn* [a] (fn* [b] (fn* [c] (+ a b c)))) 1) 2) 3)", Number(6)), - ("(((fn* [a] (fn* [b] (* b ((fn* [c] (+ a c)) 32)))) 1) 2)", Number(66)), - ("(def! f (fn* [a] (fn* [b] (+ a b)))) ((first (let* [x 12] (map (fn* [_] (f x)) '(10000000)))) 27)", Number(39)), - // test `let*` bindings inside a `fn*` - ( - "(defn f [] (let* [cst (fn* [n] (if (= n 0) :success (cst (- n 1))))] (cst 10))) (f)", - Keyword("success".to_string(), None), - ), - ( - "(def! f (fn* [ast] (let* [ast ast] ast))) (f 22)", - Number(22), - ), - ("(def! f (fn* [ast] (let* [ast (inc ast) bar (inc ast)] bar))) (f 22)", Number(24)), - // test capturing let* bindings - ("(def f (fn* [x] (let* [x x] (if (list? (first x)) (f (first x)) (fn* [] x))))) (first ((eval (f '(3)))))", Number(3)), - ("(def f (fn* [x] (let* [x '((fn* [] 4))] (if (list? (first x)) (f (first x)) (fn* [] x))))) ((first ((eval (f '((fn* [] 3)))))))", Number(4)), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_fn() { + // let test_cases = vec![ + // ("((fn* []))", Nil), + // ("((fn* [a] (+ a 1)) 23)", Number(24)), + // ("((fn* [a b] (+ a b)) 23 1)", Number(24)), + // ("((fn* [] (+ 4 3)) )", Number(7)), + // ("((fn* [f x] (f x)) (fn* [a] (+ 1 a)) 7)", Number(8)), + // ("((fn* [a] (+ a 1) 25) 23)", Number(25)), + // ("((fn* [a] (let* [b 2] (+ a b))) 23)", Number(25)), + // ("((fn* [a] (let* [a 2] (+ a a))) 23)", Number(4)), + // ( + // "(def! inc (fn* [a] (+ a 1))) ((fn* [a] (inc a)) 1)", + // Number(2), + // ), + // ("((fn* [a] ((fn* [b] (+ b 1)) a)) 1)", Number(2)), + // ("((fn* [a] ((fn* [a] (+ a 1)) a)) 1)", Number(2)), + // ("((fn* [] ((fn* [] ((fn* [] 13))))))", Number(13)), + // ( + // "(def! factorial (fn* [n] (if (< n 2) 1 (* n (factorial (- n 1)))))) (factorial 8)", + // Number(40320), + // ), + // ( + // "(def! fibo (fn* [N] (if (= N 0) 1 (if (= N 1) 1 (+ (fibo (- N 1)) (fibo (- N 2))))))) (fibo 1)", + // Number(1), + // ), + // ( + // "(def! fibo (fn* [N] (if (= N 0) 1 (if (= N 1) 1 (+ (fibo (- N 1)) (fibo (- N 2))))))) (fibo 2)", + // Number(2), + // ), + // ( + // "(def! fibo (fn* [N] (if (= N 0) 1 (if (= N 1) 1 (+ (fibo (- N 1)) (fibo (- N 2))))))) (fibo 4)", + // Number(5), + // ), + // ("(def! f (fn* [a] (+ a 1))) (f 23)", Number(24)), + // ( + // "(def! b 12) (def! f (fn* [a] (+ a b))) (def! b 22) (f 1)", + // Number(23), + // ), + // ( + // "(def! b 12) (def! f (fn* [a] ((fn* [] (+ a b))))) (def! b 22) (f 1)", + // Number(23), + // ), + // ( + // "(def! gen-plus5 (fn* [] (fn* [b] (+ 5 b)))) (def! plus5 (gen-plus5)) (plus5 7)", + // Number(12), + // ), + // ("(((fn* [a] (fn* [b] (+ a b))) 5) 7)", Number(12)), + // ("(def! gen-plus-x (fn* [x] (fn* [b] (+ x b)))) (def! plus7 (gen-plus-x 7)) (plus7 8)", Number(15)), + // ("((((fn* [a] (fn* [b] (fn* [c] (+ a b c)))) 1) 2) 3)", Number(6)), + // ("(((fn* [a] (fn* [b] (* b ((fn* [c] (+ a c)) 32)))) 1) 2)", Number(66)), + // ("(def! f (fn* [a] (fn* [b] (+ a b)))) ((first (let* [x 12] (map (fn* [_] (f x)) '(10000000)))) 27)", Number(39)), + // // test `let*` bindings inside a `fn*` + // ( + // "(defn f [] (let* [cst (fn* [n] (if (= n 0) :success (cst (- n 1))))] (cst 10))) (f)", + // Keyword("success".to_string(), None), + // ), + // ( + // "(def! f (fn* [ast] (let* [ast ast] ast))) (f 22)", + // Number(22), + // ), + // ("(def! f (fn* [ast] (let* [ast (inc ast) bar (inc ast)] bar))) (f 22)", Number(24)), + // // test capturing let* bindings + // ("(def f (fn* [x] (let* [x x] (if (list? (first x)) (f (first x)) (fn* [] x))))) (first ((eval (f '(3)))))", Number(3)), + // ("(def f (fn* [x] (let* [x '((fn* [] 4))] (if (list? (first x)) (f (first x)) (fn* [] x))))) ((first ((eval (f '((fn* [] 3)))))))", Number(4)), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_loop_recur() { - let test_cases = vec![ - ("(loop* [i 12] i)", Number(12)), - ("(loop* [i 12])", Nil), - ("(loop* [])", Nil), - ("(loop* [i 0] (if (< i 5) (recur (+ i 1)) i))", Number(5)), - ("(def! factorial (fn* [n] (loop* [n n acc 1] (if (< n 1) acc (recur (- n 1) (* acc n)))))) (factorial 20)", Number(2432902008176640000)), - ( - "(def! inc (fn* [a] (+ a 1))) (loop* [i 0] (if (< i 5) (recur (inc i)) i))", - Number(5), - ), - // // NOTE: the following will overflow the stack - // ( - // "(def! f (fn* [i] (if (< i 400) (f (+ 1 i)) i))) (f 0)", - // Number(400), - // ), - // // but, the loop/recur form is stack efficient - ( - "(def! f (fn* [i] (loop* [n i] (if (< n 400) (recur (+ 1 n)) n)))) (f 0)", - Number(400), - ), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_loop_recur() { + // let test_cases = vec![ + // ("(loop* [i 12] i)", Number(12)), + // ("(loop* [i 12])", Nil), + // ("(loop* [])", Nil), + // ("(loop* [i 0] (if (< i 5) (recur (+ i 1)) i))", Number(5)), + // ("(def! factorial (fn* [n] (loop* [n n acc 1] (if (< n 1) acc (recur (- n 1) (* acc n)))))) (factorial 20)", Number(2432902008176640000)), + // ( + // "(def! inc (fn* [a] (+ a 1))) (loop* [i 0] (if (< i 5) (recur (inc i)) i))", + // Number(5), + // ), + // // // NOTE: the following will overflow the stack + // // ( + // // "(def! f (fn* [i] (if (< i 400) (f (+ 1 i)) i))) (f 0)", + // // Number(400), + // // ), + // // // but, the loop/recur form is stack efficient + // ( + // "(def! f (fn* [i] (loop* [n i] (if (< n 400) (recur (+ 1 n)) n)))) (f 0)", + // Number(400), + // ), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_atoms() { - let test_cases = vec![ - ("(atom 5)", atom_with_value(Number(5))), - ("(atom? (atom 5))", Bool(true)), - ("(atom? nil)", Bool(false)), - ("(atom? 1)", Bool(false)), - ("(def! a (atom 5)) (deref a)", Number(5)), - ("(def! a (atom 5)) @a", Number(5)), - ("(def! a (atom (fn* [a] (+ a 1)))) (@a 4)", Number(5)), - ("(def! a (atom 5)) (reset! a 10)", Number(10)), - ("(def! a (atom 5)) (reset! a 10) @a", Number(10)), - ( - "(def! a (atom 5)) (def! inc (fn* [x] (+ x 1))) (swap! a inc)", - Number(6), - ), - ("(def! a (atom 5)) (swap! a + 1 2 3 4 5)", Number(20)), - ( - "(def! a (atom 5)) (swap! a + 1 2 3 4 5) (deref a)", - Number(20), - ), - ( - "(def! a (atom 5)) (swap! a + 1 2 3 4 5) (reset! a 10)", - Number(10), - ), - ( - "(def! a (atom 5)) (swap! a + 1 2 3 4 5) (reset! a 10) (deref a)", - Number(10), - ), - ( - "(def! a (atom 7)) (def! f (fn* [] (swap! a inc))) (f) (f)", - Number(9), - ), - ( - "(def! g (let* [a (atom 0)] (fn* [] (swap! a inc)))) (def! a (atom 1)) (g) (g) (g)", - Number(3), - ), - ( - "(def! e (atom {:+ +})) (swap! e assoc :- -) ((get @e :+) 7 8)", - Number(15), - ), - ( - "(def! e (atom {:+ +})) (swap! e assoc :- -) ((get @e :-) 11 8)", - Number(3), - ), - ( - "(def! e (atom {:+ +})) (swap! e assoc :- -) (swap! e assoc :foo ()) (get @e :foo)", - list_with_values(vec![]), - ), - ( - "(def! e (atom {:+ +})) (swap! e assoc :- -) (swap! e assoc :bar '(1 2 3)) (get @e :bar)", - list_with_values(vec![Number(1), Number(2), Number(3)]), - ), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_atoms() { + // let test_cases = vec![ + // ("(atom 5)", atom_with_value(Number(5))), + // ("(atom? (atom 5))", Bool(true)), + // ("(atom? nil)", Bool(false)), + // ("(atom? 1)", Bool(false)), + // ("(def! a (atom 5)) (deref a)", Number(5)), + // ("(def! a (atom 5)) @a", Number(5)), + // ("(def! a (atom (fn* [a] (+ a 1)))) (@a 4)", Number(5)), + // ("(def! a (atom 5)) (reset! a 10)", Number(10)), + // ("(def! a (atom 5)) (reset! a 10) @a", Number(10)), + // ( + // "(def! a (atom 5)) (def! inc (fn* [x] (+ x 1))) (swap! a inc)", + // Number(6), + // ), + // ("(def! a (atom 5)) (swap! a + 1 2 3 4 5)", Number(20)), + // ( + // "(def! a (atom 5)) (swap! a + 1 2 3 4 5) (deref a)", + // Number(20), + // ), + // ( + // "(def! a (atom 5)) (swap! a + 1 2 3 4 5) (reset! a 10)", + // Number(10), + // ), + // ( + // "(def! a (atom 5)) (swap! a + 1 2 3 4 5) (reset! a 10) (deref a)", + // Number(10), + // ), + // ( + // "(def! a (atom 7)) (def! f (fn* [] (swap! a inc))) (f) (f)", + // Number(9), + // ), + // ( + // "(def! g (let* [a (atom 0)] (fn* [] (swap! a inc)))) (def! a (atom 1)) (g) (g) (g)", + // Number(3), + // ), + // ( + // "(def! e (atom {:+ +})) (swap! e assoc :- -) ((get @e :+) 7 8)", + // Number(15), + // ), + // ( + // "(def! e (atom {:+ +})) (swap! e assoc :- -) ((get @e :-) 11 8)", + // Number(3), + // ), + // ( + // "(def! e (atom {:+ +})) (swap! e assoc :- -) (swap! e assoc :foo ()) (get @e :foo)", + // list_with_values(vec![]), + // ), + // ( + // "(def! e (atom {:+ +})) (swap! e assoc :- -) (swap! e assoc :bar '(1 2 3)) (get @e :bar)", + // list_with_values(vec![Number(1), Number(2), Number(3)]), + // ), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_quote() { - let test_cases = vec![ - ("(quote 5)", Number(5)), - ( - "(quote (1 2 3))", - list_with_values([Number(1), Number(2), Number(3)].iter().cloned()), - ), - ( - "(quote (1 2 (into+ [] foo :baz/bar)))", - list_with_values( - [ - Number(1), - Number(2), - list_with_values( - [ - Symbol("into+".to_string(), None), - Vector(PersistentVector::new()), - Symbol("foo".to_string(), None), - Keyword("bar".to_string(), Some("baz".to_string())), - ] - .iter() - .cloned(), - ), - ] - .iter() - .cloned(), - ), - ), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_quote() { + // let test_cases = vec![ + // ("(quote 5)", Number(5)), + // ( + // "(quote (1 2 3))", + // list_with_values([Number(1), Number(2), Number(3)].iter().cloned()), + // ), + // ( + // "(quote (1 2 (into+ [] foo :baz/bar)))", + // list_with_values( + // [ + // Number(1), + // Number(2), + // list_with_values( + // [ + // Symbol("into+".to_string(), None), + // Vector(PersistentVector::new()), + // Symbol("foo".to_string(), None), + // Keyword("bar".to_string(), Some("baz".to_string())), + // ] + // .iter() + // .cloned(), + // ), + // ] + // .iter() + // .cloned(), + // ), + // ), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_quasiquote() { - let test_cases = vec![ - ("(quasiquote nil)", Nil), - ("(quasiquote ())", list_with_values(vec![])), - ("(quasiquote 7)", Number(7)), - ("(quasiquote a)", Symbol("a".to_string(), None)), - ( - "(quasiquote {:a b})", - map_with_values(vec![( - Keyword("a".to_string(), None), - Symbol("b".to_string(), None), - )]), - ), - ( - "(def! lst '(b c)) `(a lst d)", - read_one_value("(a lst d)"), - ), - ( - "`(1 2 (3 4))", - read_one_value("(1 2 (3 4))"), - ), - ( - "`(nil)", - read_one_value("(nil)"), - ), - ( - "`(1 ())", - read_one_value("(1 ())"), - ), - ( - "`(() 1)", - read_one_value("(() 1)"), - ), - ( - "`(2 () 1)", - read_one_value("(2 () 1)"), - ), - ( - "`(())", - read_one_value("(())"), - ), - ( - "`(f () g (h) i (j k) l)", - read_one_value("(f () g (h) i (j k) l)"), - ), - ("`~7", Number(7)), - ("(def! a 8) `a", Symbol("a".to_string(), None)), - ("(def! a 8) `~a", Number(8)), - ( - "`(1 a 3)", - read_one_value("(1 a 3)"), - ), - ( - "(def! a 8) `(1 ~a 3)", - read_one_value("(1 8 3)"), - ), - ( - "(def! b '(1 :b :d)) `(1 b 3)", - read_one_value("(1 b 3)"), - ), - ( - "(def! b '(1 :b :d)) `(1 ~b 3)", - read_one_value("(1 (1 :b :d) 3)"), - ), - ( - "`(~1 ~2)", - read_one_value("(1 2)"), - ), - ("(let* [x 0] `~x)", Number(0)), - ( - "(def! lst '(b c)) `(a ~lst d)", - read_one_value("(a (b c) d)"), - ), - ( - "(def! lst '(b c)) `(a ~@lst d)", - read_one_value("(a b c d)"), - ), - ( - "(def! lst '(b c)) `(a ~@lst)", - read_one_value("(a b c)"), - ), - ( - "(def! lst '(b c)) `(~@lst 2)", - read_one_value("(b c 2)"), - ), - ( - "(def! lst '(b c)) `(~@lst ~@lst)", - read_one_value("(b c b c)"), - ), - ( - "((fn* [q] (quasiquote ((unquote q) (quote (unquote q))))) (quote (fn* [q] (quasiquote ((unquote q) (quote (unquote q)))))))", - read_one_value("((fn* [q] (quasiquote ((unquote q) (quote (unquote q))))) (quote (fn* [q] (quasiquote ((unquote q) (quote (unquote q)))))))"), - ), - ( - "`[]", - read_one_value("[]"), - ), - ( - "`[[]]", - read_one_value("[[]]"), - ), - ( - "`[()]", - read_one_value("[()]"), - ), - ( - "`([])", - read_one_value("([])"), - ), - ( - "(def! a 8) `[1 a 3]", - read_one_value("[1 a 3]"), - ), - ( - "`[a [] b [c] d [e f] g]", - read_one_value("[a [] b [c] d [e f] g]"), - ), - ( - "(def! a 8) `[~a]", - read_one_value("[8]"), - ), - ( - "(def! a 8) `[(~a)]", - read_one_value("[(8)]"), - ), - ( - "(def! a 8) `([~a])", - read_one_value("([8])"), - ), - ( - "(def! a 8) `[a ~a a]", - read_one_value("[a 8 a]"), - ), - ( - "(def! a 8) `([a ~a a])", - read_one_value("([a 8 a])"), - ), - ( - "(def! a 8) `[(a ~a a)]", - read_one_value("[(a 8 a)]"), - ), - ( - "(def! c '(1 :b :d)) `[~@c]", - read_one_value("[1 :b :d]"), - ), - ( - "(def! c '(1 :b :d)) `[(~@c)]", - read_one_value("[(1 :b :d)]"), - ), - ( - "(def! c '(1 :b :d)) `([~@c])", - read_one_value("([1 :b :d])"), - ), - ( - "(def! c '(1 :b :d)) `[1 ~@c 3]", - read_one_value("[1 1 :b :d 3]"), - ), - ( - "(def! c '(1 :b :d)) `([1 ~@c 3])", - read_one_value("([1 1 :b :d 3])"), - ), - ( - "(def! c '(1 :b :d)) `[(1 ~@c 3)]", - read_one_value("[(1 1 :b :d 3)]"), - ), - ( - "`(0 unquote)", - read_one_value("(0 unquote)"), - ), - ( - "`(0 splice-unquote)", - read_one_value("(0 splice-unquote)"), - ), - ( - "`[unquote 0]", - read_one_value("[unquote 0]"), - ), - ( - "`[splice-unquote 0]", - read_one_value("[splice-unquote 0]"), - ), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_quasiquote() { + // let test_cases = vec![ + // ("(quasiquote nil)", Nil), + // ("(quasiquote ())", list_with_values(vec![])), + // ("(quasiquote 7)", Number(7)), + // ("(quasiquote a)", Symbol("a".to_string(), None)), + // ( + // "(quasiquote {:a b})", + // map_with_values(vec![( + // Keyword("a".to_string(), None), + // Symbol("b".to_string(), None), + // )]), + // ), + // ( + // "(def! lst '(b c)) `(a lst d)", + // read_one_value("(a lst d)"), + // ), + // ( + // "`(1 2 (3 4))", + // read_one_value("(1 2 (3 4))"), + // ), + // ( + // "`(nil)", + // read_one_value("(nil)"), + // ), + // ( + // "`(1 ())", + // read_one_value("(1 ())"), + // ), + // ( + // "`(() 1)", + // read_one_value("(() 1)"), + // ), + // ( + // "`(2 () 1)", + // read_one_value("(2 () 1)"), + // ), + // ( + // "`(())", + // read_one_value("(())"), + // ), + // ( + // "`(f () g (h) i (j k) l)", + // read_one_value("(f () g (h) i (j k) l)"), + // ), + // ("`~7", Number(7)), + // ("(def! a 8) `a", Symbol("a".to_string(), None)), + // ("(def! a 8) `~a", Number(8)), + // ( + // "`(1 a 3)", + // read_one_value("(1 a 3)"), + // ), + // ( + // "(def! a 8) `(1 ~a 3)", + // read_one_value("(1 8 3)"), + // ), + // ( + // "(def! b '(1 :b :d)) `(1 b 3)", + // read_one_value("(1 b 3)"), + // ), + // ( + // "(def! b '(1 :b :d)) `(1 ~b 3)", + // read_one_value("(1 (1 :b :d) 3)"), + // ), + // ( + // "`(~1 ~2)", + // read_one_value("(1 2)"), + // ), + // ("(let* [x 0] `~x)", Number(0)), + // ( + // "(def! lst '(b c)) `(a ~lst d)", + // read_one_value("(a (b c) d)"), + // ), + // ( + // "(def! lst '(b c)) `(a ~@lst d)", + // read_one_value("(a b c d)"), + // ), + // ( + // "(def! lst '(b c)) `(a ~@lst)", + // read_one_value("(a b c)"), + // ), + // ( + // "(def! lst '(b c)) `(~@lst 2)", + // read_one_value("(b c 2)"), + // ), + // ( + // "(def! lst '(b c)) `(~@lst ~@lst)", + // read_one_value("(b c b c)"), + // ), + // ( + // "((fn* [q] (quasiquote ((unquote q) (quote (unquote q))))) (quote (fn* [q] (quasiquote ((unquote q) (quote (unquote q)))))))", + // read_one_value("((fn* [q] (quasiquote ((unquote q) (quote (unquote q))))) (quote (fn* [q] (quasiquote ((unquote q) (quote (unquote q)))))))"), + // ), + // ( + // "`[]", + // read_one_value("[]"), + // ), + // ( + // "`[[]]", + // read_one_value("[[]]"), + // ), + // ( + // "`[()]", + // read_one_value("[()]"), + // ), + // ( + // "`([])", + // read_one_value("([])"), + // ), + // ( + // "(def! a 8) `[1 a 3]", + // read_one_value("[1 a 3]"), + // ), + // ( + // "`[a [] b [c] d [e f] g]", + // read_one_value("[a [] b [c] d [e f] g]"), + // ), + // ( + // "(def! a 8) `[~a]", + // read_one_value("[8]"), + // ), + // ( + // "(def! a 8) `[(~a)]", + // read_one_value("[(8)]"), + // ), + // ( + // "(def! a 8) `([~a])", + // read_one_value("([8])"), + // ), + // ( + // "(def! a 8) `[a ~a a]", + // read_one_value("[a 8 a]"), + // ), + // ( + // "(def! a 8) `([a ~a a])", + // read_one_value("([a 8 a])"), + // ), + // ( + // "(def! a 8) `[(a ~a a)]", + // read_one_value("[(a 8 a)]"), + // ), + // ( + // "(def! c '(1 :b :d)) `[~@c]", + // read_one_value("[1 :b :d]"), + // ), + // ( + // "(def! c '(1 :b :d)) `[(~@c)]", + // read_one_value("[(1 :b :d)]"), + // ), + // ( + // "(def! c '(1 :b :d)) `([~@c])", + // read_one_value("([1 :b :d])"), + // ), + // ( + // "(def! c '(1 :b :d)) `[1 ~@c 3]", + // read_one_value("[1 1 :b :d 3]"), + // ), + // ( + // "(def! c '(1 :b :d)) `([1 ~@c 3])", + // read_one_value("([1 1 :b :d 3])"), + // ), + // ( + // "(def! c '(1 :b :d)) `[(1 ~@c 3)]", + // read_one_value("[(1 1 :b :d 3)]"), + // ), + // ( + // "`(0 unquote)", + // read_one_value("(0 unquote)"), + // ), + // ( + // "`(0 splice-unquote)", + // read_one_value("(0 splice-unquote)"), + // ), + // ( + // "`[unquote 0]", + // read_one_value("[unquote 0]"), + // ), + // ( + // "`[splice-unquote 0]", + // read_one_value("[splice-unquote 0]"), + // ), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_macros() { - let test_cases = vec![ - ("(defmacro! one (fn* [] 1)) (one)", Number(1)), - ("(defmacro! two (fn* [] 2)) (two)", Number(2)), - ("(defmacro! unless (fn* [pred a b] `(if ~pred ~b ~a))) (unless false 7 8)", Number(7)), - ("(defmacro! unless (fn* [pred a b] `(if ~pred ~b ~a))) (unless true 7 8)", Number(8)), - ("(defmacro! unless (fn* [pred a b] (list 'if (list 'not pred) a b))) (unless false 7 8)", Number(7)), - ("(defmacro! unless (fn* [pred a b] (list 'if (list 'not pred) a b))) (unless true 7 8)", Number(8)), - ("(defmacro! one (fn* [] 1)) (macroexpand (one))", Number(1)), - ("(defmacro! unless (fn* [pred a b] `(if ~pred ~b ~a))) (macroexpand '(unless PRED A B))", - read_one_value("(if PRED B A)") - ), - ("(defmacro! unless (fn* [pred a b] (list 'if (list 'not pred) a b))) (macroexpand '(unless PRED A B))", - read_one_value("(if (not PRED) A B)") - ), - ("(defmacro! unless (fn* [pred a b] (list 'if (list 'not pred) a b))) (macroexpand '(unless 2 3 4))", - read_one_value("(if (not 2) 3 4)") - ), - ("(defmacro! identity (fn* [x] x)) (let* [a 123] (macroexpand (identity a)))", - Number(123), - ), - ("(defmacro! identity (fn* [x] x)) (let* [a 123] (identity a))", - Number(123), - ), - ("(macroexpand (cond))", Nil), - ("(cond)", Nil), - ("(macroexpand '(cond X Y))", - read_one_value("(if X Y (cond))") - ), - ("(cond true 7)", Number(7)), - ("(cond true 7 true 8)", Number(7)), - ("(cond false 7)", Nil), - ("(cond false 7 true 8)", Number(8)), - ("(cond false 7 false 8 :else 9)", Number(9)), - ("(cond false 7 (= 2 2) 8 :else 9)", Number(8)), - ("(cond false 7 false 8 false 9)", Nil), - ("(let* [x (cond false :no true :yes)] x)", Keyword("yes".to_string(), None)), - ("(macroexpand '(cond X Y Z T))", - read_one_value("(if X Y (cond Z T))") - ), - ("(def! x 2) (defmacro! a (fn* [] x)) (a)", Number(2)), - ("(def! x 2) (defmacro! a (fn* [] x)) (let* [x 3] (a))", Number(2)), - ("(def! f (fn* [x] (number? x))) (defmacro! m f) [(f (+ 1 1)) (m (+ 1 1))]", vector_with_values(vec![Bool(true), Bool(false)])), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_macros() { + // let test_cases = vec![ + // ("(defmacro! one (fn* [] 1)) (one)", Number(1)), + // ("(defmacro! two (fn* [] 2)) (two)", Number(2)), + // ("(defmacro! unless (fn* [pred a b] `(if ~pred ~b ~a))) (unless false 7 8)", Number(7)), + // ("(defmacro! unless (fn* [pred a b] `(if ~pred ~b ~a))) (unless true 7 8)", Number(8)), + // ("(defmacro! unless (fn* [pred a b] (list 'if (list 'not pred) a b))) (unless false 7 8)", Number(7)), + // ("(defmacro! unless (fn* [pred a b] (list 'if (list 'not pred) a b))) (unless true 7 8)", Number(8)), + // ("(defmacro! one (fn* [] 1)) (macroexpand (one))", Number(1)), + // ("(defmacro! unless (fn* [pred a b] `(if ~pred ~b ~a))) (macroexpand '(unless PRED A B))", + // read_one_value("(if PRED B A)") + // ), + // ("(defmacro! unless (fn* [pred a b] (list 'if (list 'not pred) a b))) (macroexpand '(unless PRED A B))", + // read_one_value("(if (not PRED) A B)") + // ), + // ("(defmacro! unless (fn* [pred a b] (list 'if (list 'not pred) a b))) (macroexpand '(unless 2 3 4))", + // read_one_value("(if (not 2) 3 4)") + // ), + // ("(defmacro! identity (fn* [x] x)) (let* [a 123] (macroexpand (identity a)))", + // Number(123), + // ), + // ("(defmacro! identity (fn* [x] x)) (let* [a 123] (identity a))", + // Number(123), + // ), + // ("(macroexpand (cond))", Nil), + // ("(cond)", Nil), + // ("(macroexpand '(cond X Y))", + // read_one_value("(if X Y (cond))") + // ), + // ("(cond true 7)", Number(7)), + // ("(cond true 7 true 8)", Number(7)), + // ("(cond false 7)", Nil), + // ("(cond false 7 true 8)", Number(8)), + // ("(cond false 7 false 8 :else 9)", Number(9)), + // ("(cond false 7 (= 2 2) 8 :else 9)", Number(8)), + // ("(cond false 7 false 8 false 9)", Nil), + // ("(let* [x (cond false :no true :yes)] x)", Keyword("yes".to_string(), None)), + // ("(macroexpand '(cond X Y Z T))", + // read_one_value("(if X Y (cond Z T))") + // ), + // ("(def! x 2) (defmacro! a (fn* [] x)) (a)", Number(2)), + // ("(def! x 2) (defmacro! a (fn* [] x)) (let* [x 3] (a))", Number(2)), + // ("(def! f (fn* [x] (number? x))) (defmacro! m f) [(f (+ 1 1)) (m (+ 1 1))]", vector_with_values(vec![Bool(true), Bool(false)])), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_try_catch() { - fn exception_value(msg: &str, data: &Value) -> Value { - Value::Exception(exception(msg, data)) - } + // #[test] + // fn test_basic_try_catch() { + // fn exception_value(msg: &str, data: &Value) -> Value { + // Value::Exception(exception(msg, data)) + // } - let exc = exception_value( - "test", - &map_with_values(vec![( - Keyword("cause".to_string(), None), - String("no memory".to_string()), - )]), - ); - let test_cases = vec![ - // NOTE: these are errors from uncaught exceptions now... - // TODO: map to evaluation error test cases - // let basic_exc = exception_value("", &String("test".to_string())); - // ( "(throw \"test\")", basic_exc), - // ( "(throw {:msg :foo})", exception_value("", &map_with_values(vec![(Keyword("msg".to_string(), None), Keyword("foo".to_string(), None))]))), - ( - "(try* (throw '(1 2 3)) (catch* e e))", - exception_value("", &list_with_values(vec![Number(1), Number(2), Number(3)])), - ), - ("(try* 22)", Number(22)), - ("(try* (prn 222) 22)", Number(22)), - ( - "(try* (ex-info \"test\" {:cause \"no memory\"}))", - exc.clone(), - ), - ("(try* 123 (catch* e 0))", Number(123)), - ( - "(try* (ex-info \"test\" {:cause \"no memory\"}) (catch* e 0))", - exc, - ), - ( - "(try* (throw (ex-info \"test\" {:cause \"no memory\"})) (catch* e (str e)))", - String("test, {:cause \"no memory\"}".to_string()), - ), - ( - "(try* (throw (ex-info \"test\" {:cause \"no memory\"})) (catch* e 999))", - Number(999), - ), - ( - // must throw exception to change control flow - "(try* (ex-info \"first\" {}) (ex-info \"test\" {:cause \"no memory\"}) 22 (catch* e e))", - Number(22), - ), - ( - // must throw exception to change control flow - "(try* (ex-info \"first\" {}) (ex-info \"test\" {:cause \"no memory\"}) (catch* e 22))", - exception_value( - "test", - &map_with_values( - [( - Keyword("cause".to_string(), None), - String("no memory".to_string()), - )] - .iter() - .cloned(), - ), - ), - ), - ( - "(try* (throw (ex-info \"first\" {})) (ex-info \"test\" {:cause \"no memory\"}) (catch* e e))", - exception_value( - "first", - &Map(PersistentMap::new()), - ), - ), - ( - "(try* (throw (ex-info \"first\" {})) (ex-info \"test\" {:cause \"no memory\"}) (catch* e (prn e) 22))", - Number(22), - ), - ( - "(def! f (fn* [] (try* (throw (ex-info \"test\" {:cause 22})) (catch* e (prn e) 22)))) (f)", - Number(22), - ), - ( - "(def! f (fn* [] (try* (throw (ex-info \"test\" {:cause 'foo})) (catch* e (prn e) 22)))) (f)", - Number(22), - ), - ( - "(try* (do 1 2 (try* (do 3 4 (throw :e1)) (catch* e (throw (ex-info \"foo\" :bar))))) (catch* e :outer))", - Keyword("outer".to_string(), None), - ), - ( - "(try* (do (try* \"t1\" (catch* e \"c1\")) (throw \"e1\")) (catch* e \"c2\"))", - String("c2".to_string()), - ), - ( - "(try* (try* (throw \"e1\") (catch* e (throw \"e2\"))) (catch* e \"c2\"))", - String("c2".to_string()), - ), - ( - "(def! f (fn* [a] ((fn* [] (try* (throw (ex-info \"test\" {:cause 22})) (catch* e (prn e) a)))))) (f 2222)", - Number(2222), - ), - ( - "(((fn* [a] (fn* [] (try* (throw (ex-info \"\" {:foo 2})) (catch* e (prn e) a)))) 2222))", - Number(2222), - ), - ( - "(try* abc (catch* exc (prn exc) 2222))", - Number(2222), - ), - ( - "(try* (abc 1 2) (catch* exc (prn exc)))", - Nil, - ), - ( - "(try* (nth () 1) (catch* exc (prn exc)))", - Nil, - ), - ( - "(try* (try* (nth () 1) (catch* exc (prn exc) (throw exc))) (catch* exc (prn exc) 33))", - Number(33), - ), - ]; - run_eval_test(&test_cases); - } + // let exc = exception_value( + // "test", + // &map_with_values(vec![( + // Keyword("cause".to_string(), None), + // String("no memory".to_string()), + // )]), + // ); + // let test_cases = vec![ + // // NOTE: these are errors from uncaught exceptions now... + // // TODO: map to evaluation error test cases + // // let basic_exc = exception_value("", &String("test".to_string())); + // // ( "(throw \"test\")", basic_exc), + // // ( "(throw {:msg :foo})", exception_value("", &map_with_values(vec![(Keyword("msg".to_string(), None), Keyword("foo".to_string(), None))]))), + // ( + // "(try* (throw '(1 2 3)) (catch* e e))", + // exception_value("", &list_with_values(vec![Number(1), Number(2), Number(3)])), + // ), + // ("(try* 22)", Number(22)), + // ("(try* (prn 222) 22)", Number(22)), + // ( + // "(try* (ex-info \"test\" {:cause \"no memory\"}))", + // exc.clone(), + // ), + // ("(try* 123 (catch* e 0))", Number(123)), + // ( + // "(try* (ex-info \"test\" {:cause \"no memory\"}) (catch* e 0))", + // exc, + // ), + // ( + // "(try* (throw (ex-info \"test\" {:cause \"no memory\"})) (catch* e (str e)))", + // String("test, {:cause \"no memory\"}".to_string()), + // ), + // ( + // "(try* (throw (ex-info \"test\" {:cause \"no memory\"})) (catch* e 999))", + // Number(999), + // ), + // ( + // // must throw exception to change control flow + // "(try* (ex-info \"first\" {}) (ex-info \"test\" {:cause \"no memory\"}) 22 (catch* e e))", + // Number(22), + // ), + // ( + // // must throw exception to change control flow + // "(try* (ex-info \"first\" {}) (ex-info \"test\" {:cause \"no memory\"}) (catch* e 22))", + // exception_value( + // "test", + // &map_with_values( + // [( + // Keyword("cause".to_string(), None), + // String("no memory".to_string()), + // )] + // .iter() + // .cloned(), + // ), + // ), + // ), + // ( + // "(try* (throw (ex-info \"first\" {})) (ex-info \"test\" {:cause \"no memory\"}) (catch* e e))", + // exception_value( + // "first", + // &Map(PersistentMap::new()), + // ), + // ), + // ( + // "(try* (throw (ex-info \"first\" {})) (ex-info \"test\" {:cause \"no memory\"}) (catch* e (prn e) 22))", + // Number(22), + // ), + // ( + // "(def! f (fn* [] (try* (throw (ex-info \"test\" {:cause 22})) (catch* e (prn e) 22)))) (f)", + // Number(22), + // ), + // ( + // "(def! f (fn* [] (try* (throw (ex-info \"test\" {:cause 'foo})) (catch* e (prn e) 22)))) (f)", + // Number(22), + // ), + // ( + // "(try* (do 1 2 (try* (do 3 4 (throw :e1)) (catch* e (throw (ex-info \"foo\" :bar))))) (catch* e :outer))", + // Keyword("outer".to_string(), None), + // ), + // ( + // "(try* (do (try* \"t1\" (catch* e \"c1\")) (throw \"e1\")) (catch* e \"c2\"))", + // String("c2".to_string()), + // ), + // ( + // "(try* (try* (throw \"e1\") (catch* e (throw \"e2\"))) (catch* e \"c2\"))", + // String("c2".to_string()), + // ), + // ( + // "(def! f (fn* [a] ((fn* [] (try* (throw (ex-info \"test\" {:cause 22})) (catch* e (prn e) a)))))) (f 2222)", + // Number(2222), + // ), + // ( + // "(((fn* [a] (fn* [] (try* (throw (ex-info \"\" {:foo 2})) (catch* e (prn e) a)))) 2222))", + // Number(2222), + // ), + // ( + // "(try* abc (catch* exc (prn exc) 2222))", + // Number(2222), + // ), + // ( + // "(try* (abc 1 2) (catch* exc (prn exc)))", + // Nil, + // ), + // ( + // "(try* (nth () 1) (catch* exc (prn exc)))", + // Nil, + // ), + // ( + // "(try* (try* (nth () 1) (catch* exc (prn exc) (throw exc))) (catch* exc (prn exc) 33))", + // Number(33), + // ), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_var_args() { - let test_cases = vec![ - ("((fn* [& rest] (first rest)))", Nil), - ("((fn* [& rest] (first rest)) 5)", Number(5)), - ("((fn* [& rest] (first rest)) 5 6 7)", Number(5)), - ("((fn* [& rest] (last rest)) 5 6 7)", Number(7)), - ("((fn* [& rest] (nth rest 1)) 5 6 7)", Number(6)), - ("((fn* [& rest] (count rest)))", Number(0)), - ("((fn* [& rest] (count rest)) 1)", Number(1)), - ("((fn* [& rest] (count rest)) 1 2 3)", Number(3)), - ("((fn* [& rest] (list? rest)) 1 2 3)", Bool(true)), - ("((fn* [& rest] (list? rest)))", Bool(true)), - ("((fn* [a & rest] (count rest)) 1 2 3)", Number(2)), - ("((fn* [a & rest] (count rest)) 3)", Number(0)), - ("((fn* [a & rest] (list? rest)) 3)", Bool(true)), - ("((fn* [a b & rest] (apply + a b rest)) 1 2 3)", Number(6)), - ( - "(def! f (fn* [a & rest] (count rest))) (f 1 2 3)", - Number(2), - ), - ( - "(def! f (fn* [a b & rest] (apply + a b rest))) (f 1 2 3 4)", - Number(10), - ), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_var_args() { + // let test_cases = vec![ + // ("((fn* [& rest] (first rest)))", Nil), + // ("((fn* [& rest] (first rest)) 5)", Number(5)), + // ("((fn* [& rest] (first rest)) 5 6 7)", Number(5)), + // ("((fn* [& rest] (last rest)) 5 6 7)", Number(7)), + // ("((fn* [& rest] (nth rest 1)) 5 6 7)", Number(6)), + // ("((fn* [& rest] (count rest)))", Number(0)), + // ("((fn* [& rest] (count rest)) 1)", Number(1)), + // ("((fn* [& rest] (count rest)) 1 2 3)", Number(3)), + // ("((fn* [& rest] (list? rest)) 1 2 3)", Bool(true)), + // ("((fn* [& rest] (list? rest)))", Bool(true)), + // ("((fn* [a & rest] (count rest)) 1 2 3)", Number(2)), + // ("((fn* [a & rest] (count rest)) 3)", Number(0)), + // ("((fn* [a & rest] (list? rest)) 3)", Bool(true)), + // ("((fn* [a b & rest] (apply + a b rest)) 1 2 3)", Number(6)), + // ( + // "(def! f (fn* [a & rest] (count rest))) (f 1 2 3)", + // Number(2), + // ), + // ( + // "(def! f (fn* [a b & rest] (apply + a b rest))) (f 1 2 3 4)", + // Number(10), + // ), + // ]; + // run_eval_test(&test_cases); + // } - #[test] - fn test_basic_interpreter() { - let test_cases = vec![ - ("(list? *command-line-args*)", Bool(true)), - ("*command-line-args*", list_with_values(vec![])), - ]; - run_eval_test(&test_cases); - } + // #[test] + // fn test_basic_interpreter() { + // let test_cases = vec![ + // ("(list? *command-line-args*)", Bool(true)), + // ("*command-line-args*", list_with_values(vec![])), + // ]; + // run_eval_test(&test_cases); + // } } diff --git a/src/lang/core.rs b/src/lang/core.rs index baf8b46..7f074d7 100644 --- a/src/lang/core.rs +++ b/src/lang/core.rs @@ -1,18 +1,15 @@ -use crate::collections::{PersistentList, PersistentSet, PersistentVector}; +use crate::collections::{PersistentList, PersistentMap, PersistentSet, PersistentVector}; use crate::interpreter::{EvaluationError, EvaluationResult, Interpreter, InterpreterError}; -use crate::namespace::Namespace; -use crate::reader::read; -use crate::value::{ - atom_impl_into_inner, atom_with_value, exception, list_with_values, map_with_values, - set_with_values, var_impl_into_inner, vector_with_values, FnWithCapturesImpl, NativeFn, Value, -}; +use crate::namespace::{Namespace, NamespaceDesc, DEFAULT_NAME}; +use crate::reader::{read, Identifier, Symbol}; +use crate::value::{exception, NativeFn, RuntimeValue}; use itertools::Itertools; use std::fmt::Write; use std::io::{BufRead, Write as IOWrite}; use std::time::{SystemTime, UNIX_EPOCH}; use std::{fs, io}; -const SOURCE: &str = include_str!("./core.sigil"); +pub const SOURCE: &str = include_str!("./core.sigil"); const BINDINGS: &[(&str, NativeFn)] = &[ ("+", plus), ("-", subtract), @@ -76,9 +73,9 @@ const BINDINGS: &[(&str, NativeFn)] = &[ ("last", last), ("string?", is_string), ("number?", is_number), - ("fn?", is_fn), + // ("fn?", is_fn), ("conj", conj), - ("macro?", is_macro), + // ("macro?", is_macro), ("time-ms", time_in_millis), ("seq", to_seq), ("readline", readline), @@ -87,28 +84,25 @@ const BINDINGS: &[(&str, NativeFn)] = &[ ("zero?", is_zero), ]; -// loads the namespace represented by this Rust module into `interpreter` -pub fn loader(interpreter: &mut Interpreter) -> EvaluationResult<()> { +pub fn namespace() -> NamespaceDesc<'static> { let mut namespace = Namespace::default(); for (k, f) in BINDINGS.iter() { - let value = Value::Primitive(*f); - namespace.intern(k, &value).expect("can intern"); + let name = k.to_string(); + let value = RuntimeValue::Primitive(f.into()); + namespace.intern(&name, Some(value)).expect("can intern"); } - // TODO: remove once we can determine namespace from source - interpreter.set_namespace(&namespace); - - interpreter.load_namespace(namespace)?; - - interpreter.interpret(SOURCE).expect("is valid"); - - Ok(()) + NamespaceDesc { + name: Identifier::from(DEFAULT_NAME), + namespace, + source: Some(SOURCE), + } } -fn plus(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn plus(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { args.iter() .try_fold(i64::default(), |acc, x| match x { - Value::Number(n) => acc + RuntimeValue::Number(n) => acc .checked_add(*n) .ok_or_else(|| EvaluationError::Overflow(acc, *n)), other => Err(EvaluationError::WrongType { @@ -116,20 +110,20 @@ fn plus(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { realized: other.clone(), }), }) - .map(Value::Number) + .map(RuntimeValue::Number) } -fn subtract(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn subtract(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { match args.len() { 0 => Err(EvaluationError::WrongArity { expected: 1, realized: 0, }), 1 => match &args[0] { - Value::Number(first) => first + RuntimeValue::Number(first) => first .checked_neg() .ok_or_else(|| EvaluationError::Negation(*first)) - .map(Value::Number), + .map(RuntimeValue::Number), other => Err(EvaluationError::WrongType { expected: "Number", realized: other.clone(), @@ -139,10 +133,10 @@ fn subtract(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { let first_value = &args[0]; let rest_values = &args[1..]; match first_value { - Value::Number(first) => rest_values + RuntimeValue::Number(first) => rest_values .iter() .try_fold(*first, |acc, x| match x { - Value::Number(next) => acc + RuntimeValue::Number(next) => acc .checked_sub(*next) .ok_or_else(|| EvaluationError::Underflow(acc, *next)), other => Err(EvaluationError::WrongType { @@ -150,7 +144,7 @@ fn subtract(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { realized: other.clone(), }), }) - .map(Value::Number), + .map(RuntimeValue::Number), other => Err(EvaluationError::WrongType { expected: "Number", realized: other.clone(), @@ -160,10 +154,10 @@ fn subtract(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn multiply(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn multiply(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { args.iter() .try_fold(1_i64, |acc, x| match x { - Value::Number(n) => acc + RuntimeValue::Number(n) => acc .checked_mul(*n) .ok_or_else(|| EvaluationError::Overflow(acc, *n)), other => Err(EvaluationError::WrongType { @@ -171,20 +165,20 @@ fn multiply(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { realized: other.clone(), }), }) - .map(Value::Number) + .map(RuntimeValue::Number) } -fn divide(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn divide(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { match args.len() { 0 => Err(EvaluationError::WrongArity { expected: 1, realized: 0, }), 1 => match &args[0] { - Value::Number(first) => 1_i64 + RuntimeValue::Number(first) => 1_i64 .checked_div_euclid(*first) .ok_or_else(|| EvaluationError::Overflow(1, *first)) - .map(Value::Number), + .map(RuntimeValue::Number), other => Err(EvaluationError::WrongType { expected: "Number", realized: other.clone(), @@ -194,10 +188,10 @@ fn divide(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { let first_value = &args[0]; let rest_values = &args[1..]; match first_value { - Value::Number(first) => rest_values + RuntimeValue::Number(first) => rest_values .iter() .try_fold(*first, |acc, x| match x { - Value::Number(next) => acc + RuntimeValue::Number(next) => acc .checked_div_euclid(*next) .ok_or_else(|| EvaluationError::Overflow(acc, *next)), other => Err(EvaluationError::WrongType { @@ -205,7 +199,7 @@ fn divide(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { realized: other.clone(), }), }) - .map(Value::Number), + .map(RuntimeValue::Number), other => Err(EvaluationError::WrongType { expected: "Number", realized: other.clone(), @@ -215,46 +209,48 @@ fn divide(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn pr(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn pr(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { let result = args.iter().map(|arg| arg.to_readable_string()).join(" "); print!("{}", result); io::stdout().flush().unwrap(); - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } -fn prn(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn prn(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { let result = args.iter().map(|arg| arg.to_readable_string()).join(" "); println!("{}", result); - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } -fn pr_str(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn pr_str(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { let result = args.iter().map(|arg| arg.to_readable_string()).join(" "); - Ok(Value::String(result)) + Ok(RuntimeValue::String(result)) } -fn print_(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn print_(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { print!("{}", args.iter().format(" ")); io::stdout().flush().unwrap(); - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } -fn println(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn println(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { println!("{}", args.iter().format(" ")); - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } -fn print_str(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn print_str(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { let mut result = String::new(); write!(&mut result, "{}", args.iter().format(" ")).expect("can write to string"); - Ok(Value::String(result)) + Ok(RuntimeValue::String(result)) } -fn list(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { - Ok(list_with_values(args.iter().cloned())) +fn list(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { + Ok(RuntimeValue::List(PersistentList::from_iter( + args.iter().cloned(), + ))) } -fn is_list(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn is_list(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -262,12 +258,12 @@ fn is_list(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match args[0] { - Value::List(_) => Ok(Value::Bool(true)), - _ => Ok(Value::Bool(false)), + RuntimeValue::List(_) => Ok(RuntimeValue::Bool(true)), + _ => Ok(RuntimeValue::Bool(false)), } } -fn is_empty(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn is_empty(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -275,12 +271,12 @@ fn is_empty(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Nil => Ok(Value::Bool(true)), - Value::String(s) => Ok(Value::Bool(s.is_empty())), - Value::List(elems) => Ok(Value::Bool(elems.is_empty())), - Value::Vector(elems) => Ok(Value::Bool(elems.is_empty())), - Value::Map(elems) => Ok(Value::Bool(elems.is_empty())), - Value::Set(elems) => Ok(Value::Bool(elems.is_empty())), + RuntimeValue::Nil => Ok(RuntimeValue::Bool(true)), + RuntimeValue::String(s) => Ok(RuntimeValue::Bool(s.is_empty())), + RuntimeValue::List(elems) => Ok(RuntimeValue::Bool(elems.is_empty())), + RuntimeValue::Vector(elems) => Ok(RuntimeValue::Bool(elems.is_empty())), + RuntimeValue::Map(elems) => Ok(RuntimeValue::Bool(elems.is_empty())), + RuntimeValue::Set(elems) => Ok(RuntimeValue::Bool(elems.is_empty())), other => Err(EvaluationError::WrongType { expected: "Nil, String, List, Vector, Map, Set", realized: other.clone(), @@ -288,7 +284,7 @@ fn is_empty(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn count(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn count(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -296,12 +292,12 @@ fn count(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Nil => Ok(Value::Number(0)), - Value::String(s) => Ok(Value::Number(s.len() as i64)), - Value::List(elems) => Ok(Value::Number(elems.len() as i64)), - Value::Vector(elems) => Ok(Value::Number(elems.len() as i64)), - Value::Map(elems) => Ok(Value::Number(elems.size() as i64)), - Value::Set(elems) => Ok(Value::Number(elems.size() as i64)), + RuntimeValue::Nil => Ok(RuntimeValue::Number(0)), + RuntimeValue::String(s) => Ok(RuntimeValue::Number(s.len() as i64)), + RuntimeValue::List(elems) => Ok(RuntimeValue::Number(elems.len() as i64)), + RuntimeValue::Vector(elems) => Ok(RuntimeValue::Number(elems.len() as i64)), + RuntimeValue::Map(elems) => Ok(RuntimeValue::Number(elems.size() as i64)), + RuntimeValue::Set(elems) => Ok(RuntimeValue::Number(elems.size() as i64)), other => Err(EvaluationError::WrongType { expected: "Nil, String, List, Vector, Map, Set", realized: other.clone(), @@ -311,7 +307,7 @@ fn count(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { macro_rules! comparator { ($name:ident, $comparison:tt) => { - fn $name(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { + fn $name(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -319,8 +315,8 @@ macro_rules! comparator { }); } match &args[0] { - Value::Number(a) => match &args[1] { - Value::Number(b) => Ok(Value::Bool(a $comparison b)), + RuntimeValue::Number(a) => match &args[1] { + RuntimeValue::Number(b) => Ok(RuntimeValue::Bool(a $comparison b)), other => Err(EvaluationError::WrongType { expected: "Number", realized: other.clone(), @@ -340,17 +336,17 @@ comparator!(less_eq, <=); comparator!(greater, >); comparator!(greater_eq, >=); -fn equal(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn equal(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, realized: args.len(), }); } - Ok(Value::Bool(args[0] == args[1])) + Ok(RuntimeValue::Bool(args[0] == args[1])) } -fn read_string(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn read_string(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -358,16 +354,17 @@ fn read_string(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::String(s) => { + RuntimeValue::String(s) => { let mut forms = read(s).map_err(|err| { let context = err.context(s); EvaluationError::ReaderError(err, context.to_string()) })?; if forms.is_empty() { - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } else { let form = forms.pop().unwrap(); - Ok((&form).into()) + // TODO fix + Ok(RuntimeValue::Nil) } } other => Err(EvaluationError::WrongType { @@ -377,7 +374,7 @@ fn read_string(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn spit(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn spit(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -385,11 +382,11 @@ fn spit(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::String(path) => { + RuntimeValue::String(path) => { let mut contents = String::new(); let _ = write!(&mut contents, "{}", &args[1]); let _ = fs::write(path, contents).map_err(|err| -> InterpreterError { err.into() })?; - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } other => Err(EvaluationError::WrongType { expected: "String", @@ -398,7 +395,7 @@ fn spit(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn slurp(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn slurp(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -406,10 +403,10 @@ fn slurp(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::String(path) => { + RuntimeValue::String(path) => { let contents = fs::read_to_string(path).map_err(|err| -> InterpreterError { err.into() })?; - Ok(Value::String(contents)) + Ok(RuntimeValue::String(contents)) } other => Err(EvaluationError::WrongType { expected: "String", @@ -418,7 +415,7 @@ fn slurp(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn eval(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn eval(interpreter: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -429,33 +426,35 @@ fn eval(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult EvaluationResult { - if args.len() == 1 && matches!(&args[0], Value::Nil) { - return Ok(Value::String("".to_string())); +fn to_str(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { + if args.len() == 1 && matches!(&args[0], RuntimeValue::Nil) { + return Ok(RuntimeValue::String("".to_string())); } let mut result = String::new(); for arg in args { match arg { - Value::String(s) => { + RuntimeValue::String(s) => { write!(result, "{}", s).expect("can write to string"); } _ => write!(result, "{}", arg.to_readable_string()).expect("can write to string"), } } - Ok(Value::String(result)) + Ok(RuntimeValue::String(result)) } -fn to_atom(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn to_atom(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, realized: args.len(), }); } - Ok(atom_with_value(args[0].clone())) + // TODO + // Ok(atom_with_value(args[0].clone())) + Ok(RuntimeValue::Nil) } -fn is_atom(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn is_atom(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -463,12 +462,13 @@ fn is_atom(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match args[0] { - Value::Atom(_) => Ok(Value::Bool(true)), - _ => Ok(Value::Bool(false)), + // TODO + // RuntimeValue::Atom(_) => Ok(RuntimeValue::Bool(true)), + _ => Ok(RuntimeValue::Bool(false)), } } -fn deref(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn deref(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -476,9 +476,10 @@ fn deref(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Atom(inner) => Ok(atom_impl_into_inner(inner)), - Value::Var(var) => var_impl_into_inner(var) - .ok_or_else(|| EvaluationError::CannotDerefUnboundVar(Value::Var(var.clone()))), + // TODO + // RuntimeValue::Atom(inner) => Ok(atom_impl_into_inner(inner)), + // RuntimeValue::Var(var) => var_impl_into_inner(var) + // .ok_or_else(|| EvaluationError::CannotDerefUnboundVar(RuntimeValue::Var(var.clone()))), other => Err(EvaluationError::WrongType { expected: "Atom, Var", realized: other.clone(), @@ -486,7 +487,7 @@ fn deref(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn reset_atom(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn reset_atom(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -494,11 +495,12 @@ fn reset_atom(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Atom(inner) => { - let value = args[1].clone(); - *inner.borrow_mut() = value.clone(); - Ok(value) - } + // TODO + // RuntimeValue::Atom(inner) => { + // let value = args[1].clone(); + // *inner.borrow_mut() = value.clone(); + // Ok(value) + // } other => Err(EvaluationError::WrongType { expected: "Atom", realized: other.clone(), @@ -506,7 +508,10 @@ fn reset_atom(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn swap_atom(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn swap_atom( + interpreter: &mut Interpreter, + args: &[RuntimeValue], +) -> EvaluationResult { if args.len() < 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -514,43 +519,44 @@ fn swap_atom(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult< }); } match &args[0] { - Value::Atom(cell) => match &args[1] { - Value::Fn(f) => { - let mut inner = cell.borrow_mut(); - let original_value = inner.clone(); - let mut fn_args = vec![original_value]; - fn_args.extend_from_slice(&args[2..]); - let new_value = interpreter.apply_fn_inner(f, &fn_args, fn_args.len())?; - *inner = new_value.clone(); - Ok(new_value) - } - Value::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { - interpreter.extend_from_captures(captures)?; - let mut inner = cell.borrow_mut(); - let original_value = inner.clone(); - let mut fn_args = vec![original_value]; - fn_args.extend_from_slice(&args[2..]); - let new_value = interpreter.apply_fn_inner(f, &fn_args, fn_args.len()); - interpreter.leave_scope(); - - let new_value = new_value?; - *inner = new_value.clone(); - Ok(new_value) - } - Value::Primitive(native_fn) => { - let mut inner = cell.borrow_mut(); - let original_value = inner.clone(); - let mut fn_args = vec![original_value]; - fn_args.extend_from_slice(&args[2..]); - let new_value = native_fn(interpreter, &fn_args)?; - *inner = new_value.clone(); - Ok(new_value) - } - other => Err(EvaluationError::WrongType { - expected: "Fn, FnWithCaptures, Primitive", - realized: other.clone(), - }), - }, + // TODO + // RuntimeValue::Atom(cell) => match &args[1] { + // RuntimeValue::Fn(f) => { + // let mut inner = cell.borrow_mut(); + // let original_value = inner.clone(); + // let mut fn_args = vec![original_value]; + // fn_args.extend_from_slice(&args[2..]); + // let new_value = interpreter.apply_fn_inner(f, &fn_args, fn_args.len())?; + // *inner = new_value.clone(); + // Ok(new_value) + // } + // RuntimeValue::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { + // interpreter.extend_from_captures(captures)?; + // let mut inner = cell.borrow_mut(); + // let original_value = inner.clone(); + // let mut fn_args = vec![original_value]; + // fn_args.extend_from_slice(&args[2..]); + // let new_value = interpreter.apply_fn_inner(f, &fn_args, fn_args.len()); + // interpreter.leave_scope(); + + // let new_value = new_value?; + // *inner = new_value.clone(); + // Ok(new_value) + // } + // RuntimeValue::Primitive(native_fn) => { + // let mut inner = cell.borrow_mut(); + // let original_value = inner.clone(); + // let mut fn_args = vec![original_value]; + // fn_args.extend_from_slice(&args[2..]); + // let new_value = native_fn(interpreter, &fn_args)?; + // *inner = new_value.clone(); + // Ok(new_value) + // } + // other => Err(EvaluationError::WrongType { + // expected: "Fn, FnWithCaptures, Primitive", + // realized: other.clone(), + // }), + // }, other => Err(EvaluationError::WrongType { expected: "Atom", realized: other.clone(), @@ -558,7 +564,7 @@ fn swap_atom(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult< } } -fn cons(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn cons(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -566,14 +572,14 @@ fn cons(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[1] { - Value::List(seq) => Ok(Value::List(seq.push_front(args[0].clone()))), - Value::Vector(seq) => { + RuntimeValue::List(seq) => Ok(RuntimeValue::List(seq.push_front(args[0].clone()))), + RuntimeValue::Vector(seq) => { let mut inner = PersistentList::new(); for elem in seq.iter().rev() { inner.push_front_mut(elem.clone()); } inner.push_front_mut(args[0].clone()); - Ok(Value::List(inner)) + Ok(RuntimeValue::List(inner)) } other => Err(EvaluationError::WrongType { expected: "List, Vector", @@ -582,12 +588,12 @@ fn cons(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn concat(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn concat(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { let mut elems = vec![]; for arg in args { match arg { - Value::List(seq) => elems.extend(seq.iter().cloned()), - Value::Vector(seq) => elems.extend(seq.iter().cloned()), + RuntimeValue::List(seq) => elems.extend(seq.iter().cloned()), + RuntimeValue::Vector(seq) => elems.extend(seq.iter().cloned()), other => { return Err(EvaluationError::WrongType { expected: "List, Vector", @@ -596,10 +602,10 @@ fn concat(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } } - Ok(list_with_values(elems)) + Ok(RuntimeValue::List(PersistentList::from_iter(elems))) } -fn vec(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn vec(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -607,9 +613,15 @@ fn vec(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::List(elems) => Ok(vector_with_values(elems.iter().cloned())), - Value::Vector(elems) => Ok(vector_with_values(elems.iter().cloned())), - Value::Nil => Ok(vector_with_values([].iter().cloned())), + RuntimeValue::List(elems) => Ok(RuntimeValue::Vector(PersistentVector::from_iter( + elems.iter().cloned(), + ))), + RuntimeValue::Vector(elems) => Ok(RuntimeValue::Vector(PersistentVector::from_iter( + elems.iter().cloned(), + ))), + RuntimeValue::Nil => Ok(RuntimeValue::Vector(PersistentVector::from_iter( + [].iter().cloned(), + ))), other => Err(EvaluationError::WrongType { expected: "List, Vector, Nil", realized: other.clone(), @@ -617,7 +629,7 @@ fn vec(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn nth(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn nth(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -625,15 +637,15 @@ fn nth(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[1] { - Value::Number(index) if *index >= 0 => { + RuntimeValue::Number(index) if *index >= 0 => { let index = *index as usize; match &args[0] { - Value::List(seq) => seq + RuntimeValue::List(seq) => seq .iter() .nth(index) .ok_or_else(|| EvaluationError::IndexOutOfBounds(index, seq.len())) .map(|elem| elem.clone()), - Value::Vector(seq) => seq + RuntimeValue::Vector(seq) => seq .iter() .nth(index) .ok_or_else(|| EvaluationError::IndexOutOfBounds(index, seq.len())) @@ -651,7 +663,7 @@ fn nth(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn first(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn first(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -659,21 +671,21 @@ fn first(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::List(elems) => { + RuntimeValue::List(elems) => { if let Some(first) = elems.first() { Ok(first.clone()) } else { - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } } - Value::Vector(elems) => { + RuntimeValue::Vector(elems) => { if let Some(first) = elems.first() { Ok(first.clone()) } else { - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } } - Value::Nil => Ok(Value::Nil), + RuntimeValue::Nil => Ok(RuntimeValue::Nil), other => Err(EvaluationError::WrongType { expected: "List, Vector, Nil", realized: other.clone(), @@ -681,7 +693,7 @@ fn first(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn rest(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn rest(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -689,21 +701,21 @@ fn rest(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::List(elems) => { + RuntimeValue::List(elems) => { if let Some(rest) = elems.drop_first() { - Ok(Value::List(rest)) + Ok(RuntimeValue::List(rest)) } else { - Ok(Value::List(PersistentList::new())) + Ok(RuntimeValue::List(PersistentList::new())) } } - Value::Vector(elems) => { + RuntimeValue::Vector(elems) => { let mut result = PersistentList::new(); for elem in elems.iter().skip(1).rev() { result.push_front_mut(elem.clone()) } - Ok(Value::List(result)) + Ok(RuntimeValue::List(result)) } - Value::Nil => Ok(Value::List(PersistentList::new())), + RuntimeValue::Nil => Ok(RuntimeValue::List(PersistentList::new())), other => Err(EvaluationError::WrongType { expected: "List, Vector, Nil", realized: other.clone(), @@ -711,7 +723,7 @@ fn rest(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn ex_info(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn ex_info(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -719,7 +731,7 @@ fn ex_info(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::String(msg) => Ok(Value::Exception(exception(msg, &args[1]))), + RuntimeValue::String(msg) => Ok(RuntimeValue::Exception(exception(msg, args[1].clone()))), other => Err(EvaluationError::WrongType { expected: "String", realized: other.clone(), @@ -727,7 +739,7 @@ fn ex_info(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn throw(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn throw(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -735,18 +747,18 @@ fn throw(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } let exception = - match &args[0] { - n @ Value::Nil => exception("", n), - b @ Value::Bool(_) => exception("", b), - n @ Value::Number(_) => exception("", n), - s @ Value::String(_) => exception("", s), - k @ Value::Keyword(..) => exception("", k), - s @ Value::Symbol(..) => exception("", s), - coll @ Value::List(_) => exception("", coll), - coll @ Value::Vector(_) => exception("", coll), - coll @ Value::Map(_) => exception("", coll), - coll @ Value::Set(_) => exception("", coll), - Value::Exception(e) => e.clone(), + match args[0].clone() { + n @ RuntimeValue::Nil => exception("", n), + b @ RuntimeValue::Bool(_) => exception("", b), + n @ RuntimeValue::Number(_) => exception("", n), + s @ RuntimeValue::String(_) => exception("", s), + k @ RuntimeValue::Keyword(..) => exception("", k), + s @ RuntimeValue::Symbol(..) => exception("", s), + coll @ RuntimeValue::List(_) => exception("", coll), + coll @ RuntimeValue::Vector(_) => exception("", coll), + coll @ RuntimeValue::Map(_) => exception("", coll), + coll @ RuntimeValue::Set(_) => exception("", coll), + RuntimeValue::Exception(e) => e.clone(), other => return Err(EvaluationError::WrongType { expected: "Nil, Bool, Number, String, Keyword, Symbol, List, Vector, Map, Set, Exception", @@ -756,7 +768,7 @@ fn throw(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { Err(EvaluationError::Exception(exception)) } -fn apply(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn apply(interpreter: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() < 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -766,14 +778,14 @@ fn apply(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult { + RuntimeValue::List(elems) => { let mut fn_args = Vec::with_capacity(middle.len() + elems.len()); for elem in middle.iter().chain(elems.iter()) { fn_args.push(elem.clone()) } fn_args } - Value::Vector(elems) => { + RuntimeValue::Vector(elems) => { let mut fn_args = Vec::with_capacity(middle.len() + elems.len()); for elem in middle.iter().chain(elems.iter()) { fn_args.push(elem.clone()) @@ -788,14 +800,15 @@ fn apply(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult interpreter.apply_fn_inner(f, &fn_args, fn_args.len()), - Value::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { - interpreter.extend_from_captures(captures)?; - let result = interpreter.apply_fn_inner(f, &fn_args, fn_args.len()); - interpreter.leave_scope(); - result - } - Value::Primitive(native_fn) => native_fn(interpreter, &fn_args), + // TODO + // RuntimeValue::Fn(f) => interpreter.apply_fn_inner(f, &fn_args, fn_args.len()), + // RuntimeValue::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { + // interpreter.extend_from_captures(captures)?; + // let result = interpreter.apply_fn_inner(f, &fn_args, fn_args.len()); + // interpreter.leave_scope(); + // result + // } + // RuntimeValue::Primitive(native_fn) => native_fn(interpreter, &fn_args), other => Err(EvaluationError::WrongType { expected: "Fn, FnWithCaptures, Primitive", realized: other.clone(), @@ -803,7 +816,7 @@ fn apply(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult EvaluationResult { +fn map(interpreter: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -811,9 +824,9 @@ fn map(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult }); } let fn_args: Vec<_> = match &args[1] { - Value::Nil => return Ok(Value::List(PersistentList::new())), - Value::List(elems) => elems.iter().collect(), - Value::Vector(elems) => elems.iter().collect(), + RuntimeValue::Nil => return Ok(RuntimeValue::List(PersistentList::new())), + RuntimeValue::List(elems) => elems.iter().collect(), + RuntimeValue::Vector(elems) => elems.iter().collect(), other => { return Err(EvaluationError::WrongType { expected: "Nil, List, Vector", @@ -823,26 +836,27 @@ fn map(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult }; let mut result = Vec::with_capacity(fn_args.len()); match &args[0] { - Value::Fn(f) => { - for arg in fn_args { - let mapped_arg = interpreter.apply_fn_inner(f, [arg], 1)?; - result.push(mapped_arg); - } - } - Value::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { - interpreter.extend_from_captures(captures)?; - for arg in fn_args { - let mapped_arg = interpreter.apply_fn_inner(f, [arg], 1)?; - result.push(mapped_arg); - } - interpreter.leave_scope(); - } - Value::Primitive(native_fn) => { - for arg in fn_args { - let mapped_arg = native_fn(interpreter, &[arg.clone()])?; - result.push(mapped_arg); - } - } + // TODO + // RuntimeValue::Fn(f) => { + // for arg in fn_args { + // let mapped_arg = interpreter.apply_fn_inner(f, [arg], 1)?; + // result.push(mapped_arg); + // } + // } + // RuntimeValue::FnWithCaptures(FnWithCapturesImpl { f, captures }) => { + // interpreter.extend_from_captures(captures)?; + // for arg in fn_args { + // let mapped_arg = interpreter.apply_fn_inner(f, [arg], 1)?; + // result.push(mapped_arg); + // } + // interpreter.leave_scope(); + // } + // RuntimeValue::Primitive(native_fn) => { + // for arg in fn_args { + // let mapped_arg = native_fn(interpreter, &[arg.clone()])?; + // result.push(mapped_arg); + // } + // } other => { return Err(EvaluationError::WrongType { expected: "Fn, FnWithCaptures, Primitive", @@ -850,12 +864,12 @@ fn map(interpreter: &mut Interpreter, args: &[Value]) -> EvaluationResult }); } }; - Ok(Value::List(result.into_iter().collect())) + Ok(RuntimeValue::List(result.into_iter().collect())) } macro_rules! is_type { ($name:ident, $($target_type:pat) ,*) => { - fn $name(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { + fn $name(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -863,34 +877,38 @@ macro_rules! is_type { }); } match &args[0] { - $($target_type) |* => Ok(Value::Bool(true)), - _ => Ok(Value::Bool(false)), + $($target_type) |* => Ok(RuntimeValue::Bool(true)), + _ => Ok(RuntimeValue::Bool(false)), } } }; } -is_type!(is_nil, Value::Nil); -is_type!(is_true, Value::Bool(true)); -is_type!(is_false, Value::Bool(false)); -is_type!(is_symbol, Value::Symbol(..)); -is_type!(is_keyword, Value::Keyword(..)); -is_type!(is_vector, Value::Vector(..)); -is_type!(is_sequential, Value::List(..), Value::Vector(..)); -is_type!(is_map, Value::Map(..)); -is_type!(is_set, Value::Set(..)); -is_type!(is_string, Value::String(..)); -is_type!(is_number, Value::Number(..)); +is_type!(is_nil, RuntimeValue::Nil); +is_type!(is_true, RuntimeValue::Bool(true)); +is_type!(is_false, RuntimeValue::Bool(false)); +is_type!(is_symbol, RuntimeValue::Symbol(..)); +is_type!(is_keyword, RuntimeValue::Keyword(..)); +is_type!(is_vector, RuntimeValue::Vector(..)); is_type!( - is_fn, - Value::Fn(..), - Value::FnWithCaptures(..), - Value::Primitive(..), - Value::Macro(..) + is_sequential, + RuntimeValue::List(..), + RuntimeValue::Vector(..) ); -is_type!(is_macro, Value::Macro(..)); - -fn to_symbol(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +is_type!(is_map, RuntimeValue::Map(..)); +is_type!(is_set, RuntimeValue::Set(..)); +is_type!(is_string, RuntimeValue::String(..)); +is_type!(is_number, RuntimeValue::Number(..)); +// is_type!( +// is_fn, +// // RuntimeValue::Fn(..), +// // RuntimeValue::FnWithCaptures(..), +// RuntimeValue::Primitive(..), +// RuntimeValue::Macro(..) +// ); +// is_type!(is_macro, RuntimeValue::Macro(..)); + +fn to_symbol(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -898,7 +916,10 @@ fn to_symbol(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::String(name) => Ok(Value::Symbol(name.clone(), None)), + RuntimeValue::String(name) => Ok(RuntimeValue::Symbol(Symbol { + identifier: name.clone(), + namespace: None, + })), other => Err(EvaluationError::WrongType { expected: "String", realized: other.clone(), @@ -906,7 +927,7 @@ fn to_symbol(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn to_keyword(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn to_keyword(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -914,8 +935,11 @@ fn to_keyword(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::String(name) => Ok(Value::Keyword(name.clone(), None)), - k @ Value::Keyword(..) => Ok(k.clone()), + RuntimeValue::String(name) => Ok(RuntimeValue::Keyword(Symbol { + identifier: name.clone(), + namespace: None, + })), + k @ RuntimeValue::Keyword(..) => Ok(k.clone()), other => Err(EvaluationError::WrongType { expected: "String, Keyword", realized: other.clone(), @@ -923,21 +947,25 @@ fn to_keyword(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn to_vector(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { - Ok(vector_with_values(args.iter().cloned())) +fn to_vector(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { + Ok(RuntimeValue::Vector(PersistentVector::from_iter( + args.iter().cloned(), + ))) } -fn to_map(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn to_map(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() % 2 != 0 { return Err(EvaluationError::MapRequiresPairs( - vector_with_values(args.iter().cloned()), + RuntimeValue::Vector(PersistentVector::from_iter(args.iter().cloned())), args.len(), )); } - Ok(map_with_values(args.iter().cloned().tuples())) + Ok(RuntimeValue::Map(PersistentMap::from_iter( + args.iter().cloned().tuples(), + ))) } -fn to_set(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn to_set(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -945,19 +973,25 @@ fn to_set(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Nil => Ok(Value::Set(PersistentSet::new())), - Value::String(s) => Ok(set_with_values( - s.chars().map(|c| Value::String(c.to_string())), - )), - Value::List(coll) => Ok(set_with_values(coll.iter().cloned())), - Value::Vector(coll) => Ok(set_with_values(coll.iter().cloned())), - Value::Map(coll) => Ok(set_with_values(coll.iter().map(|(k, v)| { - let mut inner = PersistentVector::new(); - inner.push_back_mut(k.clone()); - inner.push_back_mut(v.clone()); - Value::Vector(inner) - }))), - s @ Value::Set(..) => Ok(s.clone()), + RuntimeValue::Nil => Ok(RuntimeValue::Set(PersistentSet::new())), + RuntimeValue::String(s) => Ok(RuntimeValue::Set(PersistentSet::from_iter( + s.chars().map(|c| RuntimeValue::String(c.to_string())), + ))), + RuntimeValue::List(coll) => Ok(RuntimeValue::Set(PersistentSet::from_iter( + coll.iter().cloned(), + ))), + RuntimeValue::Vector(coll) => Ok(RuntimeValue::Set(PersistentSet::from_iter( + coll.iter().cloned(), + ))), + RuntimeValue::Map(coll) => Ok(RuntimeValue::Set(PersistentSet::from_iter( + coll.iter().map(|(k, v)| { + let mut inner = PersistentVector::new(); + inner.push_back_mut(k.clone()); + inner.push_back_mut(v.clone()); + RuntimeValue::Vector(inner) + }), + ))), + s @ RuntimeValue::Set(..) => Ok(s.clone()), other => Err(EvaluationError::WrongType { expected: "Nil, String, List, Vector, Map, Set", realized: other.clone(), @@ -965,7 +999,7 @@ fn to_set(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn assoc(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn assoc(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() < 3 { return Err(EvaluationError::WrongArity { expected: 3, @@ -974,17 +1008,17 @@ fn assoc(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } if (args.len() - 1) % 2 != 0 { return Err(EvaluationError::MapRequiresPairs( - vector_with_values(args.iter().cloned()), + RuntimeValue::Vector(PersistentVector::from_iter(args.iter().cloned())), args.len(), )); } match &args[0] { - Value::Map(map) => { + RuntimeValue::Map(map) => { let mut result = map.clone(); for (key, val) in args.iter().skip(1).tuples() { result.insert_mut(key.clone(), val.clone()); } - Ok(Value::Map(result)) + Ok(RuntimeValue::Map(result)) } other => Err(EvaluationError::WrongType { expected: "Map", @@ -993,7 +1027,7 @@ fn assoc(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn dissoc(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn dissoc(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.is_empty() { return Err(EvaluationError::WrongArity { expected: 1, @@ -1001,12 +1035,12 @@ fn dissoc(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Map(map) => { + RuntimeValue::Map(map) => { let mut result = map.clone(); for key in args.iter().skip(1) { result.remove_mut(key); } - Ok(Value::Map(result)) + Ok(RuntimeValue::Map(result)) } other => Err(EvaluationError::WrongType { expected: "Map", @@ -1015,7 +1049,7 @@ fn dissoc(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn get(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn get(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -1023,12 +1057,12 @@ fn get(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Nil => Ok(Value::Nil), - Value::Map(map) => { + RuntimeValue::Nil => Ok(RuntimeValue::Nil), + RuntimeValue::Map(map) => { let result = if let Some(val) = map.get(&args[1]) { val.clone() } else { - Value::Nil + RuntimeValue::Nil }; Ok(result) } @@ -1039,7 +1073,7 @@ fn get(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn does_contain(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn does_contain(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -1047,10 +1081,10 @@ fn does_contain(_: &mut Interpreter, args: &[Value]) -> EvaluationResult }); } match &args[0] { - Value::Nil => Ok(Value::Bool(false)), - Value::Map(map) => { + RuntimeValue::Nil => Ok(RuntimeValue::Bool(false)), + RuntimeValue::Map(map) => { let contains = map.contains_key(&args[1]); - Ok(Value::Bool(contains)) + Ok(RuntimeValue::Bool(contains)) } other => Err(EvaluationError::WrongType { expected: "Nil, Map", @@ -1059,7 +1093,7 @@ fn does_contain(_: &mut Interpreter, args: &[Value]) -> EvaluationResult } } -fn to_keys(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn to_keys(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -1067,12 +1101,12 @@ fn to_keys(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } let result = match &args[0] { - Value::Nil => Value::Nil, - Value::Map(map) => { + RuntimeValue::Nil => RuntimeValue::Nil, + RuntimeValue::Map(map) => { if map.is_empty() { - Value::Nil + RuntimeValue::Nil } else { - list_with_values(map.keys().cloned()) + RuntimeValue::List(PersistentList::from_iter(map.keys().cloned())) } } other => { @@ -1085,7 +1119,7 @@ fn to_keys(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { Ok(result) } -fn to_vals(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn to_vals(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -1093,12 +1127,12 @@ fn to_vals(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } let result = match &args[0] { - Value::Nil => Value::Nil, - Value::Map(map) => { + RuntimeValue::Nil => RuntimeValue::Nil, + RuntimeValue::Map(map) => { if map.is_empty() { - Value::Nil + RuntimeValue::Nil } else { - list_with_values(map.values().cloned()) + RuntimeValue::List(PersistentList::from_iter(map.values().cloned())) } } other => { @@ -1111,7 +1145,7 @@ fn to_vals(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { Ok(result) } -fn last(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn last(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -1119,19 +1153,19 @@ fn last(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Nil => Ok(Value::Nil), - Value::List(elems) => { + RuntimeValue::Nil => Ok(RuntimeValue::Nil), + RuntimeValue::List(elems) => { if let Some(elem) = elems.last() { Ok(elem.clone()) } else { - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } } - Value::Vector(elems) => { + RuntimeValue::Vector(elems) => { if let Some(elem) = elems.last() { Ok(elem.clone()) } else { - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } } other => Err(EvaluationError::WrongType { @@ -1141,7 +1175,7 @@ fn last(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn conj(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn conj(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() < 2 { return Err(EvaluationError::WrongArity { expected: 2, @@ -1149,31 +1183,33 @@ fn conj(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Nil => Ok(list_with_values(args[1..].iter().cloned())), - Value::List(seq) => { + RuntimeValue::Nil => Ok(RuntimeValue::List(PersistentList::from_iter( + args[1..].iter().cloned(), + ))), + RuntimeValue::List(seq) => { let mut inner = seq.clone(); for elem in &args[1..] { inner.push_front_mut(elem.clone()); } - Ok(Value::List(inner)) + Ok(RuntimeValue::List(inner)) } - Value::Vector(seq) => { + RuntimeValue::Vector(seq) => { let mut inner = seq.clone(); for elem in &args[1..] { inner.push_back_mut(elem.clone()); } - Ok(Value::Vector(inner)) + Ok(RuntimeValue::Vector(inner)) } - Value::Map(seq) => { + RuntimeValue::Map(seq) => { let mut inner = seq.clone(); for elem in &args[1..] { match elem { - Value::Vector(kv) if kv.len() == 2 => { + RuntimeValue::Vector(kv) if kv.len() == 2 => { let k = &kv[0]; let v = &kv[1]; inner.insert_mut(k.clone(), v.clone()); } - Value::Map(elems) => { + RuntimeValue::Map(elems) => { for (k, v) in elems { inner.insert_mut(k.clone(), v.clone()); } @@ -1186,14 +1222,14 @@ fn conj(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } } - Ok(Value::Map(inner)) + Ok(RuntimeValue::Map(inner)) } - Value::Set(seq) => { + RuntimeValue::Set(seq) => { let mut inner = seq.clone(); for elem in &args[1..] { inner.insert_mut(elem.clone()); } - Ok(Value::Set(inner)) + Ok(RuntimeValue::Set(inner)) } other => Err(EvaluationError::WrongType { expected: "Nil, List, Vector, Map, Set", @@ -1202,7 +1238,7 @@ fn conj(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn time_in_millis(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn time_in_millis(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if !args.is_empty() { return Err(EvaluationError::WrongArity { expected: 0, @@ -1212,10 +1248,10 @@ fn time_in_millis(_: &mut Interpreter, args: &[Value]) -> EvaluationResult EvaluationError { InterpreterError::SystemTimeError(err).into() })?; - Ok(Value::Number(duration.as_millis() as i64)) + Ok(RuntimeValue::Number(duration.as_millis() as i64)) } -fn to_seq(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn to_seq(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -1223,24 +1259,30 @@ fn to_seq(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Nil => Ok(Value::Nil), - Value::String(s) if s.is_empty() => Ok(Value::Nil), - Value::String(s) => Ok(list_with_values( - s.chars().map(|c| Value::String(c.to_string())), - )), - Value::List(coll) if coll.is_empty() => Ok(Value::Nil), - l @ Value::List(..) => Ok(l.clone()), - Value::Vector(coll) if coll.is_empty() => Ok(Value::Nil), - Value::Vector(coll) => Ok(list_with_values(coll.iter().cloned())), - Value::Map(coll) if coll.is_empty() => Ok(Value::Nil), - Value::Map(coll) => Ok(list_with_values(coll.iter().map(|(k, v)| { - let mut inner = PersistentVector::new(); - inner.push_back_mut(k.clone()); - inner.push_back_mut(v.clone()); - Value::Vector(inner) - }))), - Value::Set(coll) if coll.is_empty() => Ok(Value::Nil), - Value::Set(coll) => Ok(list_with_values(coll.iter().cloned())), + RuntimeValue::Nil => Ok(RuntimeValue::Nil), + RuntimeValue::String(s) if s.is_empty() => Ok(RuntimeValue::Nil), + RuntimeValue::String(s) => Ok(RuntimeValue::List(PersistentList::from_iter( + s.chars().map(|c| RuntimeValue::String(c.to_string())), + ))), + RuntimeValue::List(coll) if coll.is_empty() => Ok(RuntimeValue::Nil), + l @ RuntimeValue::List(..) => Ok(l.clone()), + RuntimeValue::Vector(coll) if coll.is_empty() => Ok(RuntimeValue::Nil), + RuntimeValue::Vector(coll) => Ok(RuntimeValue::List(PersistentList::from_iter( + coll.iter().cloned(), + ))), + RuntimeValue::Map(coll) if coll.is_empty() => Ok(RuntimeValue::Nil), + RuntimeValue::Map(coll) => Ok(RuntimeValue::List(PersistentList::from_iter( + coll.iter().map(|(k, v)| { + let mut inner = PersistentVector::new(); + inner.push_back_mut(k.clone()); + inner.push_back_mut(v.clone()); + RuntimeValue::Vector(inner) + }), + ))), + RuntimeValue::Set(coll) if coll.is_empty() => Ok(RuntimeValue::Nil), + RuntimeValue::Set(coll) => Ok(RuntimeValue::List(PersistentList::from_iter( + coll.iter().cloned(), + ))), other => Err(EvaluationError::WrongType { expected: "Nil, String, List, Vector, Map, Set", realized: other.clone(), @@ -1248,7 +1290,7 @@ fn to_seq(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn readline(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn readline(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -1256,7 +1298,7 @@ fn readline(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::String(s) => { + RuntimeValue::String(s) => { let stdout = io::stdout(); let stdin = io::stdin(); let mut stdout = stdout.lock(); @@ -1286,12 +1328,12 @@ fn readline(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { let interpreter_error: InterpreterError = err.into(); interpreter_error.into() })?; - Ok(Value::Nil) + Ok(RuntimeValue::Nil) } else { if input.ends_with('\n') { input.pop(); } - Ok(Value::String(input)) + Ok(RuntimeValue::String(input)) } } other => Err(EvaluationError::WrongType { @@ -1301,15 +1343,15 @@ fn readline(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { } } -fn to_meta(_: &mut Interpreter, _args: &[Value]) -> EvaluationResult { - Ok(Value::Nil) +fn to_meta(_: &mut Interpreter, _args: &[RuntimeValue]) -> EvaluationResult { + Ok(RuntimeValue::Nil) } -fn with_meta(_: &mut Interpreter, _args: &[Value]) -> EvaluationResult { - Ok(Value::Nil) +fn with_meta(_: &mut Interpreter, _args: &[RuntimeValue]) -> EvaluationResult { + Ok(RuntimeValue::Nil) } -fn is_zero(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { +fn is_zero(_: &mut Interpreter, args: &[RuntimeValue]) -> EvaluationResult { if args.len() != 1 { return Err(EvaluationError::WrongArity { expected: 1, @@ -1317,7 +1359,7 @@ fn is_zero(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { }); } match &args[0] { - Value::Number(n) => Ok(Value::Bool(*n == 0)), + RuntimeValue::Number(n) => Ok(RuntimeValue::Bool(*n == 0)), other => Err(EvaluationError::WrongType { expected: "Number", realized: other.clone(), @@ -1327,752 +1369,750 @@ fn is_zero(_: &mut Interpreter, args: &[Value]) -> EvaluationResult { #[cfg(test)] mod tests { - use crate::collections::{PersistentList, PersistentMap, PersistentSet, PersistentVector}; - use crate::testing::run_eval_test; - use crate::value::{ - list_with_values, map_with_values, set_with_values, vector_with_values, Value::*, - }; - - #[test] - fn test_basic_prelude() { - let test_cases = vec![ - ("(list)", list_with_values(vec![])), - ( - "(list 1 2)", - list_with_values([Number(1), Number(2)].iter().cloned()), - ), - ("(list? (list 1))", Bool(true)), - ("(list? (list))", Bool(true)), - ("(list? [1 2])", Bool(false)), - ("(empty? (list))", Bool(true)), - ("(empty? (list 1))", Bool(false)), - ("(empty? [1 2 3])", Bool(false)), - ("(empty? [])", Bool(true)), - ("(count nil)", Number(0)), - ("(count \"hi\")", Number(2)), - ("(count \"\")", Number(0)), - ("(count (list))", Number(0)), - ("(count (list 44 42 41))", Number(3)), - ("(count [])", Number(0)), - ("(count [1 2 3])", Number(3)), - ("(count {})", Number(0)), - ("(count {:a 1 :b 2})", Number(2)), - ("(count #{})", Number(0)), - ("(count #{:a 1 :b 2})", Number(4)), - ("(if (< 2 3) 12 13)", Number(12)), - ("(> 13 12)", Bool(true)), - ("(> 13 13)", Bool(false)), - ("(> 12 13)", Bool(false)), - ("(< 13 12)", Bool(false)), - ("(< 13 13)", Bool(false)), - ("(< 12 13)", Bool(true)), - ("(<= 12 12)", Bool(true)), - ("(<= 13 12)", Bool(false)), - ("(<= 12 13)", Bool(true)), - ("(>= 13 12)", Bool(true)), - ("(>= 13 13)", Bool(true)), - ("(>= 13 14)", Bool(false)), - ("(= 12 12)", Bool(true)), - ("(= 12 13)", Bool(false)), - ("(= 13 12)", Bool(false)), - ("(= 0 0)", Bool(true)), - ("(= 1 0)", Bool(false)), - ("(= true true)", Bool(true)), - ("(= true false)", Bool(false)), - ("(= false false)", Bool(true)), - ("(= nil nil)", Bool(true)), - ("(= (list) (list))", Bool(true)), - ("(= (list) ())", Bool(true)), - ("(= (list 1 2) '(1 2))", Bool(true)), - ("(= (list 1 ) ())", Bool(false)), - ("(= (list ) '(1))", Bool(false)), - ("(= 0 (list))", Bool(false)), - ("(= (list) 0)", Bool(false)), - ("(= (list nil) (list))", Bool(false)), - ("(= 1 (+ 1 1))", Bool(false)), - ("(= 2 (+ 1 1))", Bool(true)), - ("(= nil (+ 1 1))", Bool(false)), - ("(= nil nil)", Bool(true)), - ("(= \"\" \"\")", Bool(true)), - ("(= \"abc\" \"abc\")", Bool(true)), - ("(= \"\" \"abc\")", Bool(false)), - ("(= \"abc\" \"\")", Bool(false)), - ("(= \"abc\" \"def\")", Bool(false)), - ("(= \"abc\" \"ABC\")", Bool(false)), - ("(= (list) \"\")", Bool(false)), - ("(= \"\" (list))", Bool(false)), - ("(= :abc :abc)", Bool(true)), - ("(= :abc :def)", Bool(false)), - ("(= :abc \":abc\")", Bool(false)), - ("(= (list :abc) (list :abc))", Bool(true)), - ("(= [] (list))", Bool(true)), - ("(= [7 8] [7 8])", Bool(true)), - ("(= [:abc] [:abc])", Bool(true)), - ("(= (list 1 2) [1 2])", Bool(true)), - ("(= (list 1) [])", Bool(false)), - ("(= [] (list 1))", Bool(false)), - ("(= [] [1])", Bool(false)), - ("(= 0 [])", Bool(false)), - ("(= [] 0)", Bool(false)), - ("(= [] \"\")", Bool(false)), - ("(= \"\" [])", Bool(false)), - ("(= [(list)] (list []))", Bool(true)), - ("(= 'abc 'abc)", Bool(true)), - ("(= 'abc 'abdc)", Bool(false)), - ("(= 'abc \"abc\")", Bool(false)), - ("(= \"abc\" 'abc)", Bool(false)), - ("(= \"abc\" (str 'abc))", Bool(true)), - ("(= 'abc nil)", Bool(false)), - ("(= nil 'abc)", Bool(false)), - ("(= {} {})", Bool(true)), - ("(= {} (hash-map))", Bool(true)), - ("(= {:a 11 :b 22} (hash-map :b 22 :a 11))", Bool(true)), - ( - "(= {:a 11 :b [22 33]} (hash-map :b [22 33] :a 11))", - Bool(true), - ), - ( - "(= {:a 11 :b {:c 22}} (hash-map :b (hash-map :c 22) :a 11))", - Bool(true), - ), - ("(= {:a 11 :b 22} (hash-map :b 23 :a 11))", Bool(false)), - ("(= {:a 11 :b 22} (hash-map :a 11))", Bool(false)), - ("(= {:a [11 22]} {:a (list 11 22)})", Bool(true)), - ("(= {:a 11 :b 22} (list :a 11 :b 22))", Bool(false)), - ("(= {} [])", Bool(false)), - ("(= [] {})", Bool(false)), - ( - "(= [1 2 (list 3 4 [5 6])] (list 1 2 [3 4 (list 5 6)]))", - Bool(true), - ), - ( - "(read-string \"(+ 1 2)\")", - List(PersistentList::from_iter(vec![ - Symbol("+".to_string(), None), - Number(1), - Number(2), - ])), - ), - ( - "(read-string \"(1 2 (3 4) nil)\")", - List(PersistentList::from_iter(vec![ - Number(1), - Number(2), - List(PersistentList::from_iter(vec![Number(3), Number(4)])), - Nil, - ])), - ), - ("(= nil (read-string \"nil\"))", Bool(true)), - ("(read-string \"7 ;; comment\")", Number(7)), - ("(read-string \"7;;!\")", Number(7)), - ("(read-string \"7;;#\")", Number(7)), - ("(read-string \"7;;$\")", Number(7)), - ("(read-string \"7;;%\")", Number(7)), - ("(read-string \"7;;'\")", Number(7)), - ("(read-string \"7;;\\\\\")", Number(7)), - ("(read-string \"7;;////////\")", Number(7)), - ("(read-string \"7;;`\")", Number(7)), - ("(read-string \"7;; &()*+,-./:;<=>?@[]^_{|}~\")", Number(7)), - ("(read-string \";; comment\")", Nil), - ("(eval (list + 1 2 3))", Number(6)), - ("(eval (read-string \"(+ 2 3)\"))", Number(5)), - ( - "(def! a 1) (let* [a 12] (eval (read-string \"a\")))", - Number(1), - ), - ( - "(let* [b 12] (do (eval (read-string \"(def! aa 7)\")) aa))", - Number(7), - ), - ("(str)", String("".to_string())), - ("(str \"\")", String("".to_string())), - ("(str \"hi\" 3 :foo)", String("hi3:foo".to_string())), - ("(str \"hi \" 3 :foo)", String("hi 3:foo".to_string())), - ("(str [])", String("[]".to_string())), - ("(str [\"hi\"])", String("[\"hi\"]".to_string())), - ( - "(str \"A\" {:abc \"val\"} \"Z\")", - String("A{:abc \"val\"}Z".to_string()), - ), - ( - "(str true \".\" false \".\" nil \".\" :keyw \".\" 'symb)", - String("true.false.nil.:keyw.symb".to_string()), - ), - ( - "(str true \".\" false \".\" nil \".\" :keyw \".\" 'symb)", - String("true.false.nil.:keyw.symb".to_string()), - ), - ( - "(pr-str \"A\" {:abc \"val\"} \"Z\")", - String("\"A\" {:abc \"val\"} \"Z\"".to_string()), - ), - ( - "(pr-str true \".\" false \".\" nil \".\" :keyw \".\" 'symb)", - String("true \".\" false \".\" nil \".\" :keyw \".\" symb".to_string()), - ), - ( - "(cons 1 (list))", - list_with_values([Number(1)].iter().cloned()), - ), - ("(cons 1 [])", list_with_values([Number(1)].iter().cloned())), - ( - "(cons 1 (list 2))", - list_with_values([Number(1), Number(2)].iter().cloned()), - ), - ( - "(cons 1 (list 2 3))", - list_with_values([Number(1), Number(2), Number(3)].iter().cloned()), - ), - ( - "(cons 1 [2 3])", - list_with_values([Number(1), Number(2), Number(3)].iter().cloned()), - ), - ( - "(cons [1] [2 3])", - list_with_values( - [vector_with_values(vec![Number(1)]), Number(2), Number(3)] - .iter() - .cloned(), - ), - ), - ( - "(def! a [2 3]) (cons 1 a)", - list_with_values([Number(1), Number(2), Number(3)].iter().cloned()), - ), - ( - "(def! a [2 3]) (cons 1 a) a", - vector_with_values(vec![Number(2), Number(3)]), - ), - ( - "(cons (list 1) (list 2 3))", - list_with_values( - [ - list_with_values([Number(1)].iter().cloned()), - Number(2), - Number(3), - ] - .iter() - .cloned(), - ), - ), - ("(concat)", List(PersistentList::new())), - ("(concat (concat))", List(PersistentList::new())), - ("(concat (list) (list))", List(PersistentList::new())), - ("(= () (concat))", Bool(true)), - ( - "(concat (list 1 2))", - list_with_values([Number(1), Number(2)].iter().cloned()), - ), - ( - "(concat (list 1) (list 2 3))", - list_with_values([Number(1), Number(2), Number(3)].iter().cloned()), - ), - ( - "(concat (list 1) [3 3] (list 2 3))", - list_with_values( - [Number(1), Number(3), Number(3), Number(2), Number(3)] - .iter() - .cloned(), - ), - ), - ( - "(concat [1 2] '(3 4) [5 6])", - list_with_values( - [ - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6), - ] - .iter() - .cloned(), - ), - ), - ( - "(concat (list 1) (list 2 3) (list (list 4 5) 6))", - list_with_values( - [ - Number(1), - Number(2), - Number(3), - list_with_values([Number(4), Number(5)].iter().cloned()), - Number(6), - ] - .iter() - .cloned(), - ), - ), - ( - "(def! a (list 1 2)) (def! b (list 3 4)) (concat a b (list 5 6))", - list_with_values( - [ - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6), - ] - .iter() - .cloned(), - ), - ), - ( - "(def! a (list 1 2)) (def! b (list 3 4)) (concat a b (list 5 6)) a", - list_with_values([Number(1), Number(2)].iter().cloned()), - ), - ( - "(def! a (list 1 2)) (def! b (list 3 4)) (concat a b (list 5 6)) b", - list_with_values([Number(3), Number(4)].iter().cloned()), - ), - ( - "(concat [1 2])", - list_with_values([Number(1), Number(2)].iter().cloned()), - ), - ( - "(vec '(1 2 3))", - vector_with_values([Number(1), Number(2), Number(3)].iter().cloned()), - ), - ( - "(vec [1 2 3])", - vector_with_values([Number(1), Number(2), Number(3)].iter().cloned()), - ), - ("(vec nil)", vector_with_values([].iter().cloned())), - ("(vec '())", vector_with_values([].iter().cloned())), - ("(vec [])", vector_with_values([].iter().cloned())), - ( - "(def! a '(1 2)) (vec a)", - vector_with_values([Number(1), Number(2)].iter().cloned()), - ), - ( - "(def! a '(1 2)) (vec a) a", - list_with_values([Number(1), Number(2)].iter().cloned()), - ), - ( - "(vec '(1))", - vector_with_values([Number(1)].iter().cloned()), - ), - ("(nth [1 2 3] 2)", Number(3)), - ("(nth [1] 0)", Number(1)), - ("(nth [1 2 nil] 2)", Nil), - ("(nth '(1 2 3) 1)", Number(2)), - ("(nth '(1 2 3) 0)", Number(1)), - ("(nth '(1 2 nil) 2)", Nil), - ("(first '(1 2 3))", Number(1)), - ("(first '())", Nil), - ("(first [1 2 3])", Number(1)), - ("(first [10])", Number(10)), - ("(first [])", Nil), - ("(first nil)", Nil), - ( - "(rest '(1 2 3))", - list_with_values([Number(2), Number(3)].iter().cloned()), - ), - ("(rest '(1))", list_with_values(vec![])), - ("(rest '())", List(PersistentList::new())), - ( - "(rest [1 2 3])", - list_with_values([Number(2), Number(3)].iter().cloned()), - ), - ("(rest [])", List(PersistentList::new())), - ("(rest nil)", List(PersistentList::new())), - ("(rest [10])", List(PersistentList::new())), - ( - "(rest [10 11 12])", - list_with_values(vec![Number(11), Number(12)]), - ), - ( - "(rest (cons 10 [11 12]))", - list_with_values(vec![Number(11), Number(12)]), - ), - ("(apply str [1 2 3])", String("123".to_string())), - ("(apply str '(1 2 3))", String("123".to_string())), - ("(apply str 0 1 2 '(1 2 3))", String("012123".to_string())), - ("(apply + '(2 3))", Number(5)), - ("(apply + 4 '(5))", Number(9)), - ("(apply + 4 [5])", Number(9)), - ("(apply list ())", list_with_values(vec![])), - ("(apply list [])", list_with_values(vec![])), - ("(apply symbol? (list 'two))", Bool(true)), - ("(apply (fn* [a b] (+ a b)) '(2 3))", Number(5)), - ("(apply (fn* [a b] (+ a b)) 4 '(5))", Number(9)), - ("(apply (fn* [a b] (+ a b)) [2 3])", Number(5)), - ("(apply (fn* [a b] (+ a b)) 4 [5])", Number(9)), - ("(apply (fn* [& rest] (list? rest)) [1 2 3])", Bool(true)), - ("(apply (fn* [& rest] (list? rest)) [])", Bool(true)), - ("(apply (fn* [a & rest] (list? rest)) [1])", Bool(true)), - ( - "(def! inc (fn* [a] (+ a 1))) (map inc [1 2 3])", - list_with_values(vec![Number(2), Number(3), Number(4)]), - ), - ( - "(map inc '(1 2 3))", - list_with_values(vec![Number(2), Number(3), Number(4)]), - ), - ( - "(map (fn* [x] (* 2 x)) [1 2 3])", - list_with_values(vec![Number(2), Number(4), Number(6)]), - ), - ( - "(map (fn* [& args] (list? args)) [1 2])", - list_with_values(vec![Bool(true), Bool(true)]), - ), - ( - "(map symbol? '(nil false true))", - list_with_values(vec![Bool(false), Bool(false), Bool(false)]), - ), - ( - "(def! f (fn* [a] (fn* [b] (+ a b)))) (map (f 23) (list 1 2))", - list_with_values(vec![Number(24), Number(25)]), - ), - ( - "(def! state (atom 0)) (def! f (fn* [a] (swap! state (fn* [state a] (let [x (+ a state)] (/ 1 x))) a))) (map f '(1 0))", - list_with_values(vec![Number(1), Number(1)]), - ), - ("(= () (map str ()))", Bool(true)), - ("(nil? nil)", Bool(true)), - ("(nil? true)", Bool(false)), - ("(nil? false)", Bool(false)), - ("(nil? [1 2 3])", Bool(false)), - ("(true? true)", Bool(true)), - ("(true? nil)", Bool(false)), - ("(true? false)", Bool(false)), - ("(true? true?)", Bool(false)), - ("(true? [1 2 3])", Bool(false)), - ("(false? false)", Bool(true)), - ("(false? nil)", Bool(false)), - ("(false? true)", Bool(false)), - ("(false? [1 2 3])", Bool(false)), - ("(symbol? 'a)", Bool(true)), - ("(symbol? 'foo/a)", Bool(true)), - ("(symbol? :foo/a)", Bool(false)), - ("(symbol? :a)", Bool(false)), - ("(symbol? false)", Bool(false)), - ("(symbol? true)", Bool(false)), - ("(symbol? nil)", Bool(false)), - ("(symbol? (symbol \"abc\"))", Bool(true)), - ("(symbol? [1 2 3])", Bool(false)), - ("(symbol \"hi\")", Symbol("hi".to_string(), None)), - ("(keyword \"hi\")", Keyword("hi".to_string(), None)), - ("(keyword :hi)", Keyword("hi".to_string(), None)), - ("(keyword? :a)", Bool(true)), - ("(keyword? false)", Bool(false)), - ("(keyword? 'abc)", Bool(false)), - ("(keyword? \"hi\")", Bool(false)), - ("(keyword? \"\")", Bool(false)), - ("(keyword? (keyword \"abc\"))", Bool(true)), - ( - "(keyword? (first (keys {\":abc\" 123 \":def\" 456})))", - Bool(false), - ), - ("(vector)", Vector(PersistentVector::new())), - ( - "(vector 1)", - vector_with_values([Number(1)].iter().cloned()), - ), - ( - "(vector 1 2 3)", - vector_with_values([Number(1), Number(2), Number(3)].iter().cloned()), - ), - ("(vector? [1 2])", Bool(true)), - ("(vector? '(1 2))", Bool(false)), - ("(vector? :hi)", Bool(false)), - ("(= [] (vector))", Bool(true)), - ("(sequential? '(1 2))", Bool(true)), - ("(sequential? [1 2])", Bool(true)), - ("(sequential? :hi)", Bool(false)), - ("(sequential? nil)", Bool(false)), - ("(sequential? \"abc\")", Bool(false)), - ("(sequential? sequential?)", Bool(false)), - ("(hash-map)", Map(PersistentMap::new())), - ( - "(hash-map :a 2)", - map_with_values( - [(Keyword("a".to_string(), None), Number(2))] - .iter() - .cloned(), - ), - ), - ("(map? {:a 1 :b 2})", Bool(true)), - ("(map? {})", Bool(true)), - ("(map? '())", Bool(false)), - ("(map? [])", Bool(false)), - ("(map? 'abc)", Bool(false)), - ("(map? :abc)", Bool(false)), - ("(map? [1 2])", Bool(false)), - ( - "(assoc {} :a 1)", - map_with_values( - [(Keyword("a".to_string(), None), Number(1))] - .iter() - .cloned(), - ), - ), - ( - "(assoc {} :a 1 :b 3)", - map_with_values( - [ - (Keyword("a".to_string(), None), Number(1)), - (Keyword("b".to_string(), None), Number(3)), - ] - .iter() - .cloned(), - ), - ), - ( - "(assoc {:a 1} :b 3)", - map_with_values( - [ - (Keyword("a".to_string(), None), Number(1)), - (Keyword("b".to_string(), None), Number(3)), - ] - .iter() - .cloned(), - ), - ), - ( - "(assoc {:a 1} :a 3 :c 33)", - map_with_values(vec![ - (Keyword("a".to_string(), None), Number(3)), - (Keyword("c".to_string(), None), Number(33)), - ]), - ), - ( - "(assoc {} :a nil)", - map_with_values(vec![(Keyword("a".to_string(), None), Nil)]), - ), - ("(dissoc {})", map_with_values([].iter().cloned())), - ("(dissoc {} :a)", map_with_values([].iter().cloned())), - ( - "(dissoc {:a 1 :b 3} :a)", - map_with_values( - [(Keyword("b".to_string(), None), Number(3))] - .iter() - .cloned(), - ), - ), - ( - "(dissoc {:a 1 :b 3} :a :b :c)", - map_with_values([].iter().cloned()), - ), - ("(count (keys (assoc {} :b 2 :c 3)))", Number(2)), - ("(get {:a 1} :a)", Number(1)), - ("(get {:a 1} :b)", Nil), - ("(get nil :b)", Nil), - ("(contains? {:a 1} :b)", Bool(false)), - ("(contains? {:a 1} :a)", Bool(true)), - ("(contains? {:abc nil} :abc)", Bool(true)), - ("(contains? nil :abc)", Bool(false)), - ("(contains? nil 'abc)", Bool(false)), - ("(contains? nil [1 2 3])", Bool(false)), - ("(keyword? (nth (keys {:abc 123 :def 456}) 0))", Bool(true)), - ("(keyword? (nth (vals {123 :abc 456 :def}) 0))", Bool(true)), - ("(keys {})", Nil), - ("(keys nil)", Nil), - ( - "(= (set '(:a :b :c)) (set (keys {:a 1 :b 2 :c 3})))", - Bool(true), - ), - ( - "(= (set '(:a :c)) (set (keys {:a 1 :b 2 :c 3})))", - Bool(false), - ), - ("(vals {})", Nil), - ("(vals nil)", Nil), - ( - "(= (set '(1 2 3)) (set (vals {:a 1 :b 2 :c 3})))", - Bool(true), - ), - ( - "(= (set '(1 2)) (set (vals {:a 1 :b 2 :c 3})))", - Bool(false), - ), - ("(last '(1 2 3))", Number(3)), - ("(last [1 2 3])", Number(3)), - ("(last '())", Nil), - ("(last [])", Nil), - ("(not [])", Bool(false)), - ("(not '(1 2 3))", Bool(false)), - ("(not nil)", Bool(true)), - ("(not true)", Bool(false)), - ("(not false)", Bool(true)), - ("(not 1)", Bool(false)), - ("(not 0)", Bool(false)), - ("(not :foo)", Bool(false)), - ("(not \"a\")", Bool(false)), - ("(not \"\")", Bool(false)), - ("(not (= 1 1))", Bool(false)), - ("(not (= 1 2))", Bool(true)), - ("(set nil)", Set(PersistentSet::new())), - // NOTE: these all rely on an _unguaranteed_ insertion order... - ( - "(set \"hi\")", - set_with_values(vec![String("h".to_string()), String("i".to_string())]), - ), - ("(set '(1 2))", set_with_values(vec![Number(1), Number(2)])), - ( - "(set '(1 2 1 2 1 2 2 2 2))", - set_with_values(vec![Number(1), Number(2)]), - ), - ( - "(set [1 2 1 2 1 2 2 2 2])", - set_with_values(vec![Number(1), Number(2)]), - ), - ( - "(set {1 2 3 4})", - set_with_values(vec![ - vector_with_values(vec![Number(1), Number(2)]), - vector_with_values(vec![Number(3), Number(4)]), - ]), - ), - ( - "(set #{1 2 3 4})", - set_with_values(vec![Number(1), Number(2), Number(3), Number(4)]), - ), - ("(set? #{1 2 3 4})", Bool(true)), - ("(set? nil)", Bool(false)), - ("(set? '())", Bool(false)), - ("(set? [])", Bool(false)), - ("(set? {})", Bool(false)), - ("(set? #{})", Bool(true)), - ("(set? \"a\")", Bool(false)), - ("(set? :a)", Bool(false)), - ("(set? 'a)", Bool(false)), - ("(string? nil)", Bool(false)), - ("(string? true)", Bool(false)), - ("(string? false)", Bool(false)), - ("(string? [1 2 3])", Bool(false)), - ("(string? 1)", Bool(false)), - ("(string? :hi)", Bool(false)), - ("(string? \"hi\")", Bool(true)), - ("(string? string?)", Bool(false)), - ("(number? nil)", Bool(false)), - ("(number? true)", Bool(false)), - ("(number? false)", Bool(false)), - ("(number? [1 2 3])", Bool(false)), - ("(number? 1)", Bool(true)), - ("(number? -1)", Bool(true)), - ("(number? :hi)", Bool(false)), - ("(number? \"hi\")", Bool(false)), - ("(number? string?)", Bool(false)), - ("(fn? nil)", Bool(false)), - ("(fn? true)", Bool(false)), - ("(fn? false)", Bool(false)), - ("(fn? [1 2 3])", Bool(false)), - ("(fn? 1)", Bool(false)), - ("(fn? -1)", Bool(false)), - ("(fn? :hi)", Bool(false)), - ("(fn? \"hi\")", Bool(false)), - ("(fn? string?)", Bool(true)), - ("(fn? (fn* [a] a))", Bool(true)), - ("(def! foo (fn* [a] a)) (fn? foo)", Bool(true)), - ("(defmacro! foo (fn* [a] a)) (fn? foo)", Bool(true)), - ("(conj (list) 1)", list_with_values(vec![Number(1)])), - ( - "(conj (list 1) 2)", - list_with_values(vec![Number(2), Number(1)]), - ), - ( - "(conj (list 1 2) 3)", - list_with_values(vec![Number(3), Number(1), Number(2)]), - ), - ( - "(conj (list 2 3) 4 5 6)", - list_with_values(vec![Number(6), Number(5), Number(4), Number(2), Number(3)]), - ), - ( - "(conj (list 1) (list 2 3))", - list_with_values(vec![ - list_with_values(vec![Number(2), Number(3)]), - Number(1), - ]), - ), - ("(conj [] 1)", vector_with_values(vec![Number(1)])), - ( - "(conj [1] 2)", - vector_with_values(vec![Number(1), Number(2)]), - ), - ( - "(conj [1 2 3] 4)", - vector_with_values(vec![Number(1), Number(2), Number(3), Number(4)]), - ), - ( - "(conj [1 2 3] 4 5)", - vector_with_values(vec![Number(1), Number(2), Number(3), Number(4), Number(5)]), - ), - ( - "(conj '(1 2 3) 4 5)", - list_with_values(vec![Number(5), Number(4), Number(1), Number(2), Number(3)]), - ), - ( - "(conj [3] [4 5])", - vector_with_values(vec![ - Number(3), - vector_with_values(vec![Number(4), Number(5)]), - ]), - ), - ( - "(conj {:c :d} [1 2] {:a :b :c :e})", - map_with_values(vec![ - ( - Keyword("c".to_string(), None), - Keyword("e".to_string(), None), - ), - ( - Keyword("a".to_string(), None), - Keyword("b".to_string(), None), - ), - (Number(1), Number(2)), - ]), - ), - ( - "(conj #{1 2} 1 3 2 2 2 2 1)", - set_with_values(vec![Number(1), Number(2), Number(3)]), - ), - ("(macro? nil)", Bool(false)), - ("(macro? true)", Bool(false)), - ("(macro? false)", Bool(false)), - ("(macro? [1 2 3])", Bool(false)), - ("(macro? 1)", Bool(false)), - ("(macro? -1)", Bool(false)), - ("(macro? :hi)", Bool(false)), - ("(macro? \"hi\")", Bool(false)), - ("(macro? string?)", Bool(false)), - ("(macro? {})", Bool(false)), - ("(macro? (fn* [a] a))", Bool(false)), - ("(def! foo (fn* [a] a)) (macro? foo)", Bool(false)), - ("(defmacro! foo (fn* [a] a)) (macro? foo)", Bool(true)), - ("(number? (time-ms))", Bool(true)), - ("(seq nil)", Nil), - ("(seq \"\")", Nil), - ( - "(seq \"ab\")", - list_with_values(vec![String("a".to_string()), String("b".to_string())]), - ), - ("(apply str (seq \"ab\"))", String("ab".to_string())), - ("(seq '())", Nil), - ("(seq '(1 2))", list_with_values(vec![Number(1), Number(2)])), - ("(seq [])", Nil), - ("(seq [1 2])", list_with_values(vec![Number(1), Number(2)])), - ("(seq {})", Nil), - ( - "(seq {1 2})", - list_with_values(vec![vector_with_values(vec![Number(1), Number(2)])]), - ), - ("(seq #{})", Nil), - ("(= (set '(1 2)) (set (seq #{1 2})))", Bool(true)), - ("(zero? 0)", Bool(true)), - ("(zero? 10)", Bool(false)), - ("(zero? -10)", Bool(false)), - ]; - run_eval_test(&test_cases); - } - - #[test] - fn test_core_macros() { - let test_cases = &[("(defn f [x] (let [y 29] (+ x y))) (f 1)", Number(30))]; - run_eval_test(test_cases); - } + // use crate::collections::{PersistentList, PersistentMap, PersistentSet, PersistentVector}; + // use crate::testing::run_eval_test; + // use crate::value::RuntimeValue::*; + + // #[test] + // fn test_basic_prelude() { + // let test_cases = vec![ + // ("(list)", RuntimeValue::List(PersistentList::from_iter(vec![])), + // ( + // "(list 1 2)", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2)].iter().cloned()), + // ), + // ("(list? (list 1))", Bool(true)), + // ("(list? (list))", Bool(true)), + // ("(list? [1 2])", Bool(false)), + // ("(empty? (list))", Bool(true)), + // ("(empty? (list 1))", Bool(false)), + // ("(empty? [1 2 3])", Bool(false)), + // ("(empty? [])", Bool(true)), + // ("(count nil)", Number(0)), + // ("(count \"hi\")", Number(2)), + // ("(count \"\")", Number(0)), + // ("(count (list))", Number(0)), + // ("(count (list 44 42 41))", Number(3)), + // ("(count [])", Number(0)), + // ("(count [1 2 3])", Number(3)), + // ("(count {})", Number(0)), + // ("(count {:a 1 :b 2})", Number(2)), + // ("(count #{})", Number(0)), + // ("(count #{:a 1 :b 2})", Number(4)), + // ("(if (< 2 3) 12 13)", Number(12)), + // ("(> 13 12)", Bool(true)), + // ("(> 13 13)", Bool(false)), + // ("(> 12 13)", Bool(false)), + // ("(< 13 12)", Bool(false)), + // ("(< 13 13)", Bool(false)), + // ("(< 12 13)", Bool(true)), + // ("(<= 12 12)", Bool(true)), + // ("(<= 13 12)", Bool(false)), + // ("(<= 12 13)", Bool(true)), + // ("(>= 13 12)", Bool(true)), + // ("(>= 13 13)", Bool(true)), + // ("(>= 13 14)", Bool(false)), + // ("(= 12 12)", Bool(true)), + // ("(= 12 13)", Bool(false)), + // ("(= 13 12)", Bool(false)), + // ("(= 0 0)", Bool(true)), + // ("(= 1 0)", Bool(false)), + // ("(= true true)", Bool(true)), + // ("(= true false)", Bool(false)), + // ("(= false false)", Bool(true)), + // ("(= nil nil)", Bool(true)), + // ("(= (list) (list))", Bool(true)), + // ("(= (list) ())", Bool(true)), + // ("(= (list 1 2) '(1 2))", Bool(true)), + // ("(= (list 1 ) ())", Bool(false)), + // ("(= (list ) '(1))", Bool(false)), + // ("(= 0 (list))", Bool(false)), + // ("(= (list) 0)", Bool(false)), + // ("(= (list nil) (list))", Bool(false)), + // ("(= 1 (+ 1 1))", Bool(false)), + // ("(= 2 (+ 1 1))", Bool(true)), + // ("(= nil (+ 1 1))", Bool(false)), + // ("(= nil nil)", Bool(true)), + // ("(= \"\" \"\")", Bool(true)), + // ("(= \"abc\" \"abc\")", Bool(true)), + // ("(= \"\" \"abc\")", Bool(false)), + // ("(= \"abc\" \"\")", Bool(false)), + // ("(= \"abc\" \"def\")", Bool(false)), + // ("(= \"abc\" \"ABC\")", Bool(false)), + // ("(= (list) \"\")", Bool(false)), + // ("(= \"\" (list))", Bool(false)), + // ("(= :abc :abc)", Bool(true)), + // ("(= :abc :def)", Bool(false)), + // ("(= :abc \":abc\")", Bool(false)), + // ("(= (list :abc) (list :abc))", Bool(true)), + // ("(= [] (list))", Bool(true)), + // ("(= [7 8] [7 8])", Bool(true)), + // ("(= [:abc] [:abc])", Bool(true)), + // ("(= (list 1 2) [1 2])", Bool(true)), + // ("(= (list 1) [])", Bool(false)), + // ("(= [] (list 1))", Bool(false)), + // ("(= [] [1])", Bool(false)), + // ("(= 0 [])", Bool(false)), + // ("(= [] 0)", Bool(false)), + // ("(= [] \"\")", Bool(false)), + // ("(= \"\" [])", Bool(false)), + // ("(= [(list)] (list []))", Bool(true)), + // ("(= 'abc 'abc)", Bool(true)), + // ("(= 'abc 'abdc)", Bool(false)), + // ("(= 'abc \"abc\")", Bool(false)), + // ("(= \"abc\" 'abc)", Bool(false)), + // ("(= \"abc\" (str 'abc))", Bool(true)), + // ("(= 'abc nil)", Bool(false)), + // ("(= nil 'abc)", Bool(false)), + // ("(= {} {})", Bool(true)), + // ("(= {} (hash-map))", Bool(true)), + // ("(= {:a 11 :b 22} (hash-map :b 22 :a 11))", Bool(true)), + // ( + // "(= {:a 11 :b [22 33]} (hash-map :b [22 33] :a 11))", + // Bool(true), + // ), + // ( + // "(= {:a 11 :b {:c 22}} (hash-map :b (hash-map :c 22) :a 11))", + // Bool(true), + // ), + // ("(= {:a 11 :b 22} (hash-map :b 23 :a 11))", Bool(false)), + // ("(= {:a 11 :b 22} (hash-map :a 11))", Bool(false)), + // ("(= {:a [11 22]} {:a (list 11 22)})", Bool(true)), + // ("(= {:a 11 :b 22} (list :a 11 :b 22))", Bool(false)), + // ("(= {} [])", Bool(false)), + // ("(= [] {})", Bool(false)), + // ( + // "(= [1 2 (list 3 4 [5 6])] (list 1 2 [3 4 (list 5 6)]))", + // Bool(true), + // ), + // ( + // "(read-string \"(+ 1 2)\")", + // List(PersistentList::from_iter(vec![ + // Symbol("+".to_string(), None), + // Number(1), + // Number(2), + // ])), + // ), + // ( + // "(read-string \"(1 2 (3 4) nil)\")", + // List(PersistentList::from_iter(vec![ + // Number(1), + // Number(2), + // List(PersistentList::from_iter(vec![Number(3), Number(4)])), + // Nil, + // ])), + // ), + // ("(= nil (read-string \"nil\"))", Bool(true)), + // ("(read-string \"7 ;; comment\")", Number(7)), + // ("(read-string \"7;;!\")", Number(7)), + // ("(read-string \"7;;#\")", Number(7)), + // ("(read-string \"7;;$\")", Number(7)), + // ("(read-string \"7;;%\")", Number(7)), + // ("(read-string \"7;;'\")", Number(7)), + // ("(read-string \"7;;\\\\\")", Number(7)), + // ("(read-string \"7;;////////\")", Number(7)), + // ("(read-string \"7;;`\")", Number(7)), + // ("(read-string \"7;; &()*+,-./:;<=>?@[]^_{|}~\")", Number(7)), + // ("(read-string \";; comment\")", Nil), + // ("(eval (list + 1 2 3))", Number(6)), + // ("(eval (read-string \"(+ 2 3)\"))", Number(5)), + // ( + // "(def! a 1) (let* [a 12] (eval (read-string \"a\")))", + // Number(1), + // ), + // ( + // "(let* [b 12] (do (eval (read-string \"(def! aa 7)\")) aa))", + // Number(7), + // ), + // ("(str)", String("".to_string())), + // ("(str \"\")", String("".to_string())), + // ("(str \"hi\" 3 :foo)", String("hi3:foo".to_string())), + // ("(str \"hi \" 3 :foo)", String("hi 3:foo".to_string())), + // ("(str [])", String("[]".to_string())), + // ("(str [\"hi\"])", String("[\"hi\"]".to_string())), + // ( + // "(str \"A\" {:abc \"val\"} \"Z\")", + // String("A{:abc \"val\"}Z".to_string()), + // ), + // ( + // "(str true \".\" false \".\" nil \".\" :keyw \".\" 'symb)", + // String("true.false.nil.:keyw.symb".to_string()), + // ), + // ( + // "(str true \".\" false \".\" nil \".\" :keyw \".\" 'symb)", + // String("true.false.nil.:keyw.symb".to_string()), + // ), + // ( + // "(pr-str \"A\" {:abc \"val\"} \"Z\")", + // String("\"A\" {:abc \"val\"} \"Z\"".to_string()), + // ), + // ( + // "(pr-str true \".\" false \".\" nil \".\" :keyw \".\" 'symb)", + // String("true \".\" false \".\" nil \".\" :keyw \".\" symb".to_string()), + // ), + // ( + // "(cons 1 (list))", + // RuntimeValue::List(PersistentList::from_iter([Number(1)].iter().cloned()), + // ), + // ("(cons 1 [])", RuntimeValue::List(PersistentList::from_iter([Number(1)].iter().cloned())), + // ( + // "(cons 1 (list 2))", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2)].iter().cloned()), + // ), + // ( + // "(cons 1 (list 2 3))", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2), Number(3)].iter().cloned()), + // ), + // ( + // "(cons 1 [2 3])", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2), Number(3)].iter().cloned()), + // ), + // ( + // "(cons [1] [2 3])", + // RuntimeValue::List(PersistentList::from_iter( + // [RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(1)]), Number(2), Number(3)] + // .iter() + // .cloned(), + // ), + // ), + // ( + // "(def! a [2 3]) (cons 1 a)", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2), Number(3)].iter().cloned()), + // ), + // ( + // "(def! a [2 3]) (cons 1 a) a", + // RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(2), Number(3)]), + // ), + // ( + // "(cons (list 1) (list 2 3))", + // RuntimeValue::List(PersistentList::from_iter( + // [ + // RuntimeValue::List(PersistentList::from_iter([Number(1)].iter().cloned()), + // Number(2), + // Number(3), + // ] + // .iter() + // .cloned(), + // ), + // ), + // ("(concat)", List(PersistentList::new())), + // ("(concat (concat))", List(PersistentList::new())), + // ("(concat (list) (list))", List(PersistentList::new())), + // ("(= () (concat))", Bool(true)), + // ( + // "(concat (list 1 2))", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2)].iter().cloned()), + // ), + // ( + // "(concat (list 1) (list 2 3))", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2), Number(3)].iter().cloned()), + // ), + // ( + // "(concat (list 1) [3 3] (list 2 3))", + // RuntimeValue::List(PersistentList::from_iter( + // [Number(1), Number(3), Number(3), Number(2), Number(3)] + // .iter() + // .cloned(), + // ), + // ), + // ( + // "(concat [1 2] '(3 4) [5 6])", + // RuntimeValue::List(PersistentList::from_iter( + // [ + // Number(1), + // Number(2), + // Number(3), + // Number(4), + // Number(5), + // Number(6), + // ] + // .iter() + // .cloned(), + // ), + // ), + // ( + // "(concat (list 1) (list 2 3) (list (list 4 5) 6))", + // RuntimeValue::List(PersistentList::from_iter( + // [ + // Number(1), + // Number(2), + // Number(3), + // RuntimeValue::List(PersistentList::from_iter([Number(4), Number(5)].iter().cloned()), + // Number(6), + // ] + // .iter() + // .cloned(), + // ), + // ), + // ( + // "(def! a (list 1 2)) (def! b (list 3 4)) (concat a b (list 5 6))", + // RuntimeValue::List(PersistentList::from_iter( + // [ + // Number(1), + // Number(2), + // Number(3), + // Number(4), + // Number(5), + // Number(6), + // ] + // .iter() + // .cloned(), + // ), + // ), + // ( + // "(def! a (list 1 2)) (def! b (list 3 4)) (concat a b (list 5 6)) a", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2)].iter().cloned()), + // ), + // ( + // "(def! a (list 1 2)) (def! b (list 3 4)) (concat a b (list 5 6)) b", + // RuntimeValue::List(PersistentList::from_iter([Number(3), Number(4)].iter().cloned()), + // ), + // ( + // "(concat [1 2])", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2)].iter().cloned()), + // ), + // ( + // "(vec '(1 2 3))", + // RuntimeValue::Vector(PersistentVector::from_iter([Number(1), Number(2), Number(3)].iter().cloned()), + // ), + // ( + // "(vec [1 2 3])", + // RuntimeValue::Vector(PersistentVector::from_iter([Number(1), Number(2), Number(3)].iter().cloned()), + // ), + // ("(vec nil)", RuntimeValue::Vector(PersistentVector::from_iter([].iter().cloned())), + // ("(vec '())", RuntimeValue::Vector(PersistentVector::from_iter([].iter().cloned())), + // ("(vec [])", RuntimeValue::Vector(PersistentVector::from_iter([].iter().cloned())), + // ( + // "(def! a '(1 2)) (vec a)", + // RuntimeValue::Vector(PersistentVector::from_iter([Number(1), Number(2)].iter().cloned()), + // ), + // ( + // "(def! a '(1 2)) (vec a) a", + // RuntimeValue::List(PersistentList::from_iter([Number(1), Number(2)].iter().cloned()), + // ), + // ( + // "(vec '(1))", + // RuntimeValue::Vector(PersistentVector::from_iter([Number(1)].iter().cloned()), + // ), + // ("(nth [1 2 3] 2)", Number(3)), + // ("(nth [1] 0)", Number(1)), + // ("(nth [1 2 nil] 2)", Nil), + // ("(nth '(1 2 3) 1)", Number(2)), + // ("(nth '(1 2 3) 0)", Number(1)), + // ("(nth '(1 2 nil) 2)", Nil), + // ("(first '(1 2 3))", Number(1)), + // ("(first '())", Nil), + // ("(first [1 2 3])", Number(1)), + // ("(first [10])", Number(10)), + // ("(first [])", Nil), + // ("(first nil)", Nil), + // ( + // "(rest '(1 2 3))", + // RuntimeValue::List(PersistentList::from_iter([Number(2), Number(3)].iter().cloned()), + // ), + // ("(rest '(1))", RuntimeValue::List(PersistentList::from_iter(vec![])), + // ("(rest '())", List(PersistentList::new())), + // ( + // "(rest [1 2 3])", + // RuntimeValue::List(PersistentList::from_iter([Number(2), Number(3)].iter().cloned()), + // ), + // ("(rest [])", List(PersistentList::new())), + // ("(rest nil)", List(PersistentList::new())), + // ("(rest [10])", List(PersistentList::new())), + // ( + // "(rest [10 11 12])", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(11), Number(12)]), + // ), + // ( + // "(rest (cons 10 [11 12]))", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(11), Number(12)]), + // ), + // ("(apply str [1 2 3])", String("123".to_string())), + // ("(apply str '(1 2 3))", String("123".to_string())), + // ("(apply str 0 1 2 '(1 2 3))", String("012123".to_string())), + // ("(apply + '(2 3))", Number(5)), + // ("(apply + 4 '(5))", Number(9)), + // ("(apply + 4 [5])", Number(9)), + // ("(apply list ())", RuntimeValue::List(PersistentList::from_iter(vec![])), + // ("(apply list [])", RuntimeValue::List(PersistentList::from_iter(vec![])), + // ("(apply symbol? (list 'two))", Bool(true)), + // ("(apply (fn* [a b] (+ a b)) '(2 3))", Number(5)), + // ("(apply (fn* [a b] (+ a b)) 4 '(5))", Number(9)), + // ("(apply (fn* [a b] (+ a b)) [2 3])", Number(5)), + // ("(apply (fn* [a b] (+ a b)) 4 [5])", Number(9)), + // ("(apply (fn* [& rest] (list? rest)) [1 2 3])", Bool(true)), + // ("(apply (fn* [& rest] (list? rest)) [])", Bool(true)), + // ("(apply (fn* [a & rest] (list? rest)) [1])", Bool(true)), + // ( + // "(def! inc (fn* [a] (+ a 1))) (map inc [1 2 3])", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(2), Number(3), Number(4)]), + // ), + // ( + // "(map inc '(1 2 3))", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(2), Number(3), Number(4)]), + // ), + // ( + // "(map (fn* [x] (* 2 x)) [1 2 3])", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(2), Number(4), Number(6)]), + // ), + // ( + // "(map (fn* [& args] (list? args)) [1 2])", + // RuntimeValue::List(PersistentList::from_iter(vec![Bool(true), Bool(true)]), + // ), + // ( + // "(map symbol? '(nil false true))", + // RuntimeValue::List(PersistentList::from_iter(vec![Bool(false), Bool(false), Bool(false)]), + // ), + // ( + // "(def! f (fn* [a] (fn* [b] (+ a b)))) (map (f 23) (list 1 2))", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(24), Number(25)]), + // ), + // ( + // "(def! state (atom 0)) (def! f (fn* [a] (swap! state (fn* [state a] (let [x (+ a state)] (/ 1 x))) a))) (map f '(1 0))", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(1), Number(1)]), + // ), + // ("(= () (map str ()))", Bool(true)), + // ("(nil? nil)", Bool(true)), + // ("(nil? true)", Bool(false)), + // ("(nil? false)", Bool(false)), + // ("(nil? [1 2 3])", Bool(false)), + // ("(true? true)", Bool(true)), + // ("(true? nil)", Bool(false)), + // ("(true? false)", Bool(false)), + // ("(true? true?)", Bool(false)), + // ("(true? [1 2 3])", Bool(false)), + // ("(false? false)", Bool(true)), + // ("(false? nil)", Bool(false)), + // ("(false? true)", Bool(false)), + // ("(false? [1 2 3])", Bool(false)), + // ("(symbol? 'a)", Bool(true)), + // ("(symbol? 'foo/a)", Bool(true)), + // ("(symbol? :foo/a)", Bool(false)), + // ("(symbol? :a)", Bool(false)), + // ("(symbol? false)", Bool(false)), + // ("(symbol? true)", Bool(false)), + // ("(symbol? nil)", Bool(false)), + // ("(symbol? (symbol \"abc\"))", Bool(true)), + // ("(symbol? [1 2 3])", Bool(false)), + // ("(symbol \"hi\")", Symbol("hi".to_string(), None)), + // ("(keyword \"hi\")", Keyword("hi".to_string(), None)), + // ("(keyword :hi)", Keyword("hi".to_string(), None)), + // ("(keyword? :a)", Bool(true)), + // ("(keyword? false)", Bool(false)), + // ("(keyword? 'abc)", Bool(false)), + // ("(keyword? \"hi\")", Bool(false)), + // ("(keyword? \"\")", Bool(false)), + // ("(keyword? (keyword \"abc\"))", Bool(true)), + // ( + // "(keyword? (first (keys {\":abc\" 123 \":def\" 456})))", + // Bool(false), + // ), + // ("(vector)", Vector(PersistentVector::new())), + // ( + // "(vector 1)", + // RuntimeValue::Vector(PersistentVector::from_iter([Number(1)].iter().cloned()), + // ), + // ( + // "(vector 1 2 3)", + // RuntimeValue::Vector(PersistentVector::from_iter([Number(1), Number(2), Number(3)].iter().cloned()), + // ), + // ("(vector? [1 2])", Bool(true)), + // ("(vector? '(1 2))", Bool(false)), + // ("(vector? :hi)", Bool(false)), + // ("(= [] (vector))", Bool(true)), + // ("(sequential? '(1 2))", Bool(true)), + // ("(sequential? [1 2])", Bool(true)), + // ("(sequential? :hi)", Bool(false)), + // ("(sequential? nil)", Bool(false)), + // ("(sequential? \"abc\")", Bool(false)), + // ("(sequential? sequential?)", Bool(false)), + // ("(hash-map)", Map(PersistentMap::new())), + // ( + // "(hash-map :a 2)", + // map_with_values( + // [(Keyword("a".to_string(), None), Number(2))] + // .iter() + // .cloned(), + // ), + // ), + // ("(map? {:a 1 :b 2})", Bool(true)), + // ("(map? {})", Bool(true)), + // ("(map? '())", Bool(false)), + // ("(map? [])", Bool(false)), + // ("(map? 'abc)", Bool(false)), + // ("(map? :abc)", Bool(false)), + // ("(map? [1 2])", Bool(false)), + // ( + // "(assoc {} :a 1)", + // map_with_values( + // [(Keyword("a".to_string(), None), Number(1))] + // .iter() + // .cloned(), + // ), + // ), + // ( + // "(assoc {} :a 1 :b 3)", + // map_with_values( + // [ + // (Keyword("a".to_string(), None), Number(1)), + // (Keyword("b".to_string(), None), Number(3)), + // ] + // .iter() + // .cloned(), + // ), + // ), + // ( + // "(assoc {:a 1} :b 3)", + // map_with_values( + // [ + // (Keyword("a".to_string(), None), Number(1)), + // (Keyword("b".to_string(), None), Number(3)), + // ] + // .iter() + // .cloned(), + // ), + // ), + // ( + // "(assoc {:a 1} :a 3 :c 33)", + // map_with_values(vec![ + // (Keyword("a".to_string(), None), Number(3)), + // (Keyword("c".to_string(), None), Number(33)), + // ]), + // ), + // ( + // "(assoc {} :a nil)", + // map_with_values(vec![(Keyword("a".to_string(), None), Nil)]), + // ), + // ("(dissoc {})", map_with_values([].iter().cloned())), + // ("(dissoc {} :a)", map_with_values([].iter().cloned())), + // ( + // "(dissoc {:a 1 :b 3} :a)", + // map_with_values( + // [(Keyword("b".to_string(), None), Number(3))] + // .iter() + // .cloned(), + // ), + // ), + // ( + // "(dissoc {:a 1 :b 3} :a :b :c)", + // map_with_values([].iter().cloned()), + // ), + // ("(count (keys (assoc {} :b 2 :c 3)))", Number(2)), + // ("(get {:a 1} :a)", Number(1)), + // ("(get {:a 1} :b)", Nil), + // ("(get nil :b)", Nil), + // ("(contains? {:a 1} :b)", Bool(false)), + // ("(contains? {:a 1} :a)", Bool(true)), + // ("(contains? {:abc nil} :abc)", Bool(true)), + // ("(contains? nil :abc)", Bool(false)), + // ("(contains? nil 'abc)", Bool(false)), + // ("(contains? nil [1 2 3])", Bool(false)), + // ("(keyword? (nth (keys {:abc 123 :def 456}) 0))", Bool(true)), + // ("(keyword? (nth (vals {123 :abc 456 :def}) 0))", Bool(true)), + // ("(keys {})", Nil), + // ("(keys nil)", Nil), + // ( + // "(= (set '(:a :b :c)) (set (keys {:a 1 :b 2 :c 3})))", + // Bool(true), + // ), + // ( + // "(= (set '(:a :c)) (set (keys {:a 1 :b 2 :c 3})))", + // Bool(false), + // ), + // ("(vals {})", Nil), + // ("(vals nil)", Nil), + // ( + // "(= (set '(1 2 3)) (set (vals {:a 1 :b 2 :c 3})))", + // Bool(true), + // ), + // ( + // "(= (set '(1 2)) (set (vals {:a 1 :b 2 :c 3})))", + // Bool(false), + // ), + // ("(last '(1 2 3))", Number(3)), + // ("(last [1 2 3])", Number(3)), + // ("(last '())", Nil), + // ("(last [])", Nil), + // ("(not [])", Bool(false)), + // ("(not '(1 2 3))", Bool(false)), + // ("(not nil)", Bool(true)), + // ("(not true)", Bool(false)), + // ("(not false)", Bool(true)), + // ("(not 1)", Bool(false)), + // ("(not 0)", Bool(false)), + // ("(not :foo)", Bool(false)), + // ("(not \"a\")", Bool(false)), + // ("(not \"\")", Bool(false)), + // ("(not (= 1 1))", Bool(false)), + // ("(not (= 1 2))", Bool(true)), + // ("(set nil)", Set(PersistentSet::new())), + // // NOTE: these all rely on an _unguaranteed_ insertion order... + // ( + // "(set \"hi\")", + // RuntimeValue::Set(PersistentSet::from_iter(vec![String("h".to_string()), String("i".to_string())]), + // ), + // ("(set '(1 2))", RuntimeValue::Set(PersistentSet::from_iter(vec![Number(1), Number(2)])), + // ( + // "(set '(1 2 1 2 1 2 2 2 2))", + // RuntimeValue::Set(PersistentSet::from_iter(vec![Number(1), Number(2)]), + // ), + // ( + // "(set [1 2 1 2 1 2 2 2 2])", + // RuntimeValue::Set(PersistentSet::from_iter(vec![Number(1), Number(2)]), + // ), + // ( + // "(set {1 2 3 4})", + // RuntimeValue::Set(PersistentSet::from_iter(vec![ + // RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(1), Number(2)]), + // RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(3), Number(4)]), + // ]), + // ), + // ( + // "(set #{1 2 3 4})", + // RuntimeValue::Set(PersistentSet::from_iter(vec![Number(1), Number(2), Number(3), Number(4)]), + // ), + // ("(set? #{1 2 3 4})", Bool(true)), + // ("(set? nil)", Bool(false)), + // ("(set? '())", Bool(false)), + // ("(set? [])", Bool(false)), + // ("(set? {})", Bool(false)), + // ("(set? #{})", Bool(true)), + // ("(set? \"a\")", Bool(false)), + // ("(set? :a)", Bool(false)), + // ("(set? 'a)", Bool(false)), + // ("(string? nil)", Bool(false)), + // ("(string? true)", Bool(false)), + // ("(string? false)", Bool(false)), + // ("(string? [1 2 3])", Bool(false)), + // ("(string? 1)", Bool(false)), + // ("(string? :hi)", Bool(false)), + // ("(string? \"hi\")", Bool(true)), + // ("(string? string?)", Bool(false)), + // ("(number? nil)", Bool(false)), + // ("(number? true)", Bool(false)), + // ("(number? false)", Bool(false)), + // ("(number? [1 2 3])", Bool(false)), + // ("(number? 1)", Bool(true)), + // ("(number? -1)", Bool(true)), + // ("(number? :hi)", Bool(false)), + // ("(number? \"hi\")", Bool(false)), + // ("(number? string?)", Bool(false)), + // ("(fn? nil)", Bool(false)), + // ("(fn? true)", Bool(false)), + // ("(fn? false)", Bool(false)), + // ("(fn? [1 2 3])", Bool(false)), + // ("(fn? 1)", Bool(false)), + // ("(fn? -1)", Bool(false)), + // ("(fn? :hi)", Bool(false)), + // ("(fn? \"hi\")", Bool(false)), + // ("(fn? string?)", Bool(true)), + // ("(fn? (fn* [a] a))", Bool(true)), + // ("(def! foo (fn* [a] a)) (fn? foo)", Bool(true)), + // ("(defmacro! foo (fn* [a] a)) (fn? foo)", Bool(true)), + // ("(conj (list) 1)", RuntimeValue::List(PersistentList::from_iter(vec![Number(1)])), + // ( + // "(conj (list 1) 2)", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(2), Number(1)]), + // ), + // ( + // "(conj (list 1 2) 3)", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(3), Number(1), Number(2)]), + // ), + // ( + // "(conj (list 2 3) 4 5 6)", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(6), Number(5), Number(4), Number(2), Number(3)]), + // ), + // ( + // "(conj (list 1) (list 2 3))", + // RuntimeValue::List(PersistentList::from_iter(vec![ + // RuntimeValue::List(PersistentList::from_iter(vec![Number(2), Number(3)]), + // Number(1), + // ]), + // ), + // ("(conj [] 1)", RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(1)])), + // ( + // "(conj [1] 2)", + // RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(1), Number(2)]), + // ), + // ( + // "(conj [1 2 3] 4)", + // RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(1), Number(2), Number(3), Number(4)]), + // ), + // ( + // "(conj [1 2 3] 4 5)", + // RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(1), Number(2), Number(3), Number(4), Number(5)]), + // ), + // ( + // "(conj '(1 2 3) 4 5)", + // RuntimeValue::List(PersistentList::from_iter(vec![Number(5), Number(4), Number(1), Number(2), Number(3)]), + // ), + // ( + // "(conj [3] [4 5])", + // RuntimeValue::Vector(PersistentVector::from_iter(vec![ + // Number(3), + // RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(4), Number(5)]), + // ]), + // ), + // ( + // "(conj {:c :d} [1 2] {:a :b :c :e})", + // map_with_values(vec![ + // ( + // Keyword("c".to_string(), None), + // Keyword("e".to_string(), None), + // ), + // ( + // Keyword("a".to_string(), None), + // Keyword("b".to_string(), None), + // ), + // (Number(1), Number(2)), + // ]), + // ), + // ( + // "(conj #{1 2} 1 3 2 2 2 2 1)", + // RuntimeValue::Set(PersistentSet::from_iter(vec![Number(1), Number(2), Number(3)]), + // ), + // ("(macro? nil)", Bool(false)), + // ("(macro? true)", Bool(false)), + // ("(macro? false)", Bool(false)), + // ("(macro? [1 2 3])", Bool(false)), + // ("(macro? 1)", Bool(false)), + // ("(macro? -1)", Bool(false)), + // ("(macro? :hi)", Bool(false)), + // ("(macro? \"hi\")", Bool(false)), + // ("(macro? string?)", Bool(false)), + // ("(macro? {})", Bool(false)), + // ("(macro? (fn* [a] a))", Bool(false)), + // ("(def! foo (fn* [a] a)) (macro? foo)", Bool(false)), + // ("(defmacro! foo (fn* [a] a)) (macro? foo)", Bool(true)), + // ("(number? (time-ms))", Bool(true)), + // ("(seq nil)", Nil), + // ("(seq \"\")", Nil), + // ( + // "(seq \"ab\")", + // RuntimeValue::List(PersistentList::from_iter(vec![String("a".to_string()), String("b".to_string())]), + // ), + // ("(apply str (seq \"ab\"))", String("ab".to_string())), + // ("(seq '())", Nil), + // ("(seq '(1 2))", RuntimeValue::List(PersistentList::from_iter(vec![Number(1), Number(2)])), + // ("(seq [])", Nil), + // ("(seq [1 2])", RuntimeValue::List(PersistentList::from_iter(vec![Number(1), Number(2)])), + // ("(seq {})", Nil), + // ( + // "(seq {1 2})", + // RuntimeValue::List(PersistentList::from_iter(vec![RuntimeValue::Vector(PersistentVector::from_iter(vec![Number(1), Number(2)])]), + // ), + // ("(seq #{})", Nil), + // ("(= (set '(1 2)) (set (seq #{1 2})))", Bool(true)), + // ("(zero? 0)", Bool(true)), + // ("(zero? 10)", Bool(false)), + // ("(zero? -10)", Bool(false)), + // ]; + // run_eval_test(&test_cases); + // } + + // #[test] + // fn test_core_macros() { + // let test_cases = &[("(defn f [x] (let [y 29] (+ x y))) (f 1)", Number(30))]; + // run_eval_test(test_cases); + // } } diff --git a/src/namespace/mod.rs b/src/namespace/mod.rs index ed653ac..a468b94 100644 --- a/src/namespace/mod.rs +++ b/src/namespace/mod.rs @@ -1,14 +1,14 @@ mod var; use crate::reader::{Identifier, Symbol}; -use crate::value::{unbound_var, var_with_value, RuntimeValue, Value}; +use crate::value::RuntimeValue; use std::collections::HashMap; use thiserror::Error; use var::new_var; pub use var::Var; -const DEFAULT_NAME: Identifier = Identifier::from("core"); +pub const DEFAULT_NAME: &str = "core"; // `Context` maps global names to namespaces // and also tracks a "current" namespace, the one which @@ -24,8 +24,9 @@ pub struct Context { impl Default for Context { fn default() -> Self { let current_namespace = 0; - let names = HashMap::from([(DEFAULT_NAME, current_namespace)]); - let name_lookup = HashMap::from([(current_namespace, DEFAULT_NAME.clone())]); + let default_identifier = Identifier::from(DEFAULT_NAME); + let names = HashMap::from([(default_identifier.clone(), current_namespace)]); + let name_lookup = HashMap::from([(current_namespace, default_identifier)]); let namespaces = vec![Namespace::default()]; Self { @@ -42,9 +43,31 @@ impl Context { &self.namespaces[self.current_namespace] } - fn get_namespace(&self, identifier: &Identifier) -> &Namespace { - let index = self.names[identifier]; - &self.namespaces[index] + pub fn current_namespace_mut(&mut self) -> &mut Namespace { + &mut self.namespaces[self.current_namespace] + } + + pub fn current_namespace_name(&self) -> &Identifier { + self.name_lookup.get(&self.current_namespace).unwrap() + } + + fn create_if_missing(&mut self, identifier: &Identifier) -> usize { + *self.names.entry(identifier.clone()).or_insert_with(|| { + self.namespaces.push(Namespace::default()); + let index = self.namespaces.len() - 1; + self.name_lookup.insert(index, identifier.clone()); + index + }) + } + + pub fn get_namespace_mut(&mut self, name: &Identifier) -> &mut Namespace { + let index = self.create_if_missing(name); + &mut self.namespaces[index] + } + + pub fn intern_namespace(&mut self, name: &Identifier, namespace: Namespace) { + let ns = self.get_namespace_mut(name); + ns.merge(namespace); } pub fn resolve_symbol(&self, symbol: &Symbol) -> Result { @@ -122,18 +145,23 @@ impl Namespace { Ok(var.clone()) } - pub fn remove(&mut self, identifier: &str) { + pub fn remove(&mut self, identifier: &Identifier) { self.bindings.remove(identifier); } - // pub fn merge(&mut self, other: &Namespace) -> Result<(), NamespaceError> { - // for (identifier, value) in &other.bindings { - // self.intern(identifier, value)?; - // } - // Ok(()) - // } + fn merge(&mut self, other: Namespace) { + for (identifier, value) in other.bindings { + self.bindings.insert(identifier, value); + } + } - pub fn symbols(&self) -> impl Iterator { + pub fn symbols(&self) -> impl Iterator { self.bindings.keys() } } + +pub struct NamespaceDesc<'a> { + pub name: Identifier, + pub namespace: Namespace, + pub source: Option<&'a str>, +} diff --git a/src/namespace/var.rs b/src/namespace/var.rs index 05b2ace..cf9e65e 100644 --- a/src/namespace/var.rs +++ b/src/namespace/var.rs @@ -1,8 +1,10 @@ use crate::value::RuntimeValue; use std::cell::RefCell; +use std::hash::{Hash, Hasher}; +use std::mem::discriminant; use std::rc::Rc; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum Var { Bound(Rc>), Unbound, @@ -11,3 +13,17 @@ pub enum Var { pub fn new_var(value: RuntimeValue) -> Var { Var::Bound(Rc::new(RefCell::new(value))) } + +impl Hash for Var { + fn hash(&self, state: &mut H) { + discriminant(self).hash(state); + + match self { + Var::Bound(cell) => { + let value = cell.borrow(); + value.hash(state); + } + Var::Unbound => {} + } + } +} diff --git a/src/reader/form.rs b/src/reader/form.rs index fd2506d..8dbdb1e 100644 --- a/src/reader/form.rs +++ b/src/reader/form.rs @@ -4,21 +4,6 @@ use crate::writer::{ }; use std::fmt; -pub(super) fn list_from(elems: Vec) -> Form { - Form::List(elems) -} - -pub(super) fn vector_from(elems: Vec) -> Form { - Form::Vector(elems) -} -pub(super) fn map_from(elems: Vec<(Form, Form)>) -> Form { - Form::Map(elems) -} - -pub(super) fn set_from(elems: Vec) -> Form { - Form::Set(elems) -} - #[derive(Clone, PartialEq, Eq, Debug)] pub enum Form { Atom(Atom), @@ -28,7 +13,7 @@ pub enum Form { Set(Vec), } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Atom { Nil, Bool(bool), @@ -40,7 +25,7 @@ pub enum Atom { pub type Identifier = String; -#[derive(Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] pub struct Symbol { pub identifier: Identifier, pub namespace: Option, @@ -65,7 +50,7 @@ impl fmt::Display for Form { }, Form::List(elems) => write_list(f, elems), Form::Vector(elems) => write_vector(f, elems), - Form::Map(elems) => write_map(f, elems), + Form::Map(elems) => write_map(f, elems.iter().map(|(a, b)| (a, b))), Form::Set(elems) => write_set(f, elems), } } diff --git a/src/reader/mod.rs b/src/reader/mod.rs index 891feb1..c18a62c 100644 --- a/src/reader/mod.rs +++ b/src/reader/mod.rs @@ -2,7 +2,6 @@ mod form; pub use form::{Atom, Form, Identifier, Symbol}; -use form::{list_from, map_from, set_from, vector_from}; use itertools::Itertools; use std::num::ParseIntError; use std::{iter::Peekable, str::CharIndices}; @@ -568,7 +567,7 @@ impl<'a> Reader<'a> { let (_, next_ch) = stream.peek().ok_or(ReaderError::ExpectedMoreInput)?; match *next_ch { '{' => { - self.read_collection('}', stream, |elems| Ok(set_from(elems))) + self.read_collection('}', stream, |elems| Ok(Form::Set(elems))) .map_err(|err| { self.cursor = start; err @@ -595,7 +594,7 @@ impl<'a> Reader<'a> { let span = self.spans.pop().expect("just ranged symbol"); match symbol { symbol @ Form::Atom(Atom::Symbol(..)) => { - let expansion = list_from(vec![ + let expansion = Form::List(vec![ Form::Atom(Atom::Symbol(Symbol { identifier: "var".to_string(), namespace: None, @@ -680,7 +679,7 @@ impl<'a> Reader<'a> { })), form, ]; - self.values.push(list_from(expansion)); + self.values.push(Form::List(expansion)); let span = self.spans.pop().expect("just ranged form"); let span = match span { @@ -712,13 +711,13 @@ impl<'a> Reader<'a> { ) -> Result<(), ReaderError> { match next_char { '(' => { - self.read_collection(')', stream, |elems| Ok(list_from(elems)))?; + self.read_collection(')', stream, |elems| Ok(Form::List(elems)))?; } ')' => { self.parse_state = ParseState::Exiting; } '[' => { - self.read_collection(']', stream, |elems| Ok(vector_from(elems)))?; + self.read_collection(']', stream, |elems| Ok(Form::Vector(elems)))?; } ']' => { self.parse_state = ParseState::Exiting; @@ -728,7 +727,7 @@ impl<'a> Reader<'a> { if elems.len() % 2 != 0 { Err(ReaderError::MapLiteralWithUnpairedElements) } else { - Ok(map_from(elems.into_iter().tuples().collect::>())) + Ok(Form::Map(elems.into_iter().tuples().collect::>())) } })?; } @@ -809,10 +808,7 @@ pub fn read(input: &str) -> Result, ReadError> { #[cfg(test)] mod tests { - use super::{ - list_from, map_from, read, set_from, vector_from, Atom, Form, ReadError, ReaderError, - Symbol, - }; + use super::{read, Atom, Form, ReadError, ReaderError, Symbol}; use itertools::Itertools; #[test] @@ -1306,10 +1302,10 @@ mod tests { ("1;\\\\", vec![number(1)], "1"), ("1;\\\\\\", vec![number(1)], "1"), ("1; &()*+,-./:;<=>?@[]^_{|}~", vec![number(1)], "1"), - ("()", vec![list_from(vec![])], "()"), + ("()", vec![Form::List(vec![])], "()"), ( "(a b c)", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("a".into(), None), symbol("b".into(), None), symbol("c".into(), None), @@ -1318,7 +1314,7 @@ mod tests { ), ( "(a b, c,,,,),,", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("a".into(), None), symbol("b".into(), None), symbol("c".into(), None), @@ -1327,17 +1323,17 @@ mod tests { ), ( "(12 :foo/bar \"extra\")", - vec![list_from(vec![ + vec![Form::List(vec![ number(12), keyword("bar".into(), Some("foo".into())), string("extra".into()), ])], "(12 :foo/bar \"extra\")", ), - ("[]", vec![vector_from(vec![])], "[]"), + ("[]", vec![Form::Vector(vec![])], "[]"), ( "[a b c]", - vec![vector_from(vec![ + vec![Form::Vector(vec![ symbol("a".into(), None), symbol("b".into(), None), symbol("c".into(), None), @@ -1346,17 +1342,17 @@ mod tests { ), ( "[12 :foo/bar \"extra\"]", - vec![vector_from(vec![ + vec![Form::Vector(vec![ number(12), keyword("bar".into(), Some("foo".into())), string("extra".into()), ])], "[12 :foo/bar \"extra\"]", ), - ("{}", vec![map_from(vec![])], "{}"), + ("{}", vec![Form::Map(vec![])], "{}"), ( "{a b c d}", - vec![map_from(vec![ + vec![Form::Map(vec![ (symbol("a".into(), None), symbol("b".into(), None)), (symbol("c".into(), None), symbol("d".into(), None)), ])], @@ -1364,7 +1360,7 @@ mod tests { ), ( "{12 13 :foo/bar \"extra\"}", - vec![map_from(vec![ + vec![Form::Map(vec![ (number(12), number(13)), ( keyword("bar".into(), Some("foo".into())), @@ -1375,67 +1371,70 @@ mod tests { ), ( "() []", - vec![list_from(vec![]), vector_from(vec![])], + vec![Form::List(vec![]), Form::Vector(vec![])], "() []", ), ( "()\n[]", - vec![list_from(vec![]), vector_from(vec![])], + vec![Form::List(vec![]), Form::Vector(vec![])], "() []", ), - ("(())", vec![list_from(vec![list_from(vec![])])], "(())"), + ("(())", vec![Form::List(vec![Form::List(vec![])])], "(())"), ( "(([]))", - vec![list_from(vec![list_from(vec![vector_from(vec![])])])], + vec![Form::List(vec![Form::List(vec![Form::Vector(vec![])])])], "(([]))", ), ( "(([]))()", vec![ - list_from(vec![list_from(vec![vector_from(vec![])])]), - list_from(vec![]), + Form::List(vec![Form::List(vec![Form::Vector(vec![])])]), + Form::List(vec![]), ], "(([])) ()", ), ( "(12 (true [34 false]))(), (7)", vec![ - list_from(vec![ + Form::List(vec![ number(12), - list_from(vec![bool(true), vector_from(vec![number(34), bool(false)])]), + Form::List(vec![ + bool(true), + Form::Vector(vec![number(34), bool(false)]), + ]), ]), - list_from(vec![]), - list_from(vec![number(7)]), + Form::List(vec![]), + Form::List(vec![number(7)]), ], "(12 (true [34 false])) () (7)", ), ( " [ + 1 [+ 2 3 ] ] ", - vec![vector_from(vec![ + vec![Form::Vector(vec![ symbol("+".to_string(), None), number(1), - vector_from(vec![symbol("+".to_string(), None), number(2), number(3)]), + Form::Vector(vec![symbol("+".to_string(), None), number(2), number(3)]), ])], "[+ 1 [+ 2 3]]", ), - ("#{}", vec![set_from(vec![])], "#{}"), - ("#{1}", vec![set_from(vec![number(1)])], "#{1}"), - ("#{ 1}", vec![set_from(vec![number(1)])], "#{1}"), - ("#{ 1 }", vec![set_from(vec![number(1)])], "#{1}"), + ("#{}", vec![Form::Set(vec![])], "#{}"), + ("#{1}", vec![Form::Set(vec![number(1)])], "#{1}"), + ("#{ 1}", vec![Form::Set(vec![number(1)])], "#{1}"), + ("#{ 1 }", vec![Form::Set(vec![number(1)])], "#{1}"), ( "#{ \"hi\" }", - vec![set_from(vec![string("hi".to_string())])], + vec![Form::Set(vec![string("hi".to_string())])], "#{\"hi\"}", ), ( "#{1 2 3}", - vec![set_from(vec![number(1), number(2), number(3)])], + vec![Form::Set(vec![number(1), number(2), number(3)])], "", ), ( "#{(1 3) :foo}", - vec![set_from(vec![ - list_from(vec![number(1), number(3)]), + vec![Form::Set(vec![ + Form::List(vec![number(1), number(3)]), keyword("foo".into(), None), ])], "", @@ -1451,11 +1450,11 @@ mod tests { ), ( "(defn foo [a] (+ a 1))", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("defn".into(), None), symbol("foo".into(), None), - vector_from(vec![symbol("a".into(), None)]), - list_from(vec![ + Form::Vector(vec![symbol("a".into(), None)]), + Form::List(vec![ symbol("+".into(), None), symbol("a".into(), None), number(1), @@ -1465,11 +1464,11 @@ mod tests { ), ( "(defn foo\n [a]\n (+ a 1))", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("defn".into(), None), symbol("foo".into(), None), - vector_from(vec![symbol("a".into(), None)]), - list_from(vec![ + Form::Vector(vec![symbol("a".into(), None)]), + Form::List(vec![ symbol("+".into(), None), symbol("a".into(), None), number(1), @@ -1483,11 +1482,11 @@ mod tests { [a] ; another comment (+ a 1)) ; one final comment "#, - vec![list_from(vec![ + vec![Form::List(vec![ symbol("defn".into(), None), symbol("foo".into(), None), - vector_from(vec![symbol("a".into(), None)]), - list_from(vec![ + Form::Vector(vec![symbol("a".into(), None)]), + Form::List(vec![ symbol("+".into(), None), symbol("a".into(), None), number(1), @@ -1497,7 +1496,7 @@ mod tests { ), ( "@a", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("deref".into(), None), symbol("a".into(), None), ])], @@ -1505,7 +1504,7 @@ mod tests { ), ( "@ a", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("deref".into(), None), symbol("a".into(), None), ])], @@ -1513,7 +1512,7 @@ mod tests { ), ( "@,,,,,a", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("deref".into(), None), symbol("a".into(), None), ])], @@ -1521,7 +1520,7 @@ mod tests { ), ( "@ ,, , a", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("deref".into(), None), symbol("a".into(), None), ])], @@ -1529,20 +1528,20 @@ mod tests { ), ( "'1", - vec![list_from(vec![symbol("quote".into(), None), number(1)])], + vec![Form::List(vec![symbol("quote".into(), None), number(1)])], "(quote 1)", ), ( "'(1 2 3)", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("quote".into(), None), - list_from(vec![number(1), number(2), number(3)]), + Form::List(vec![number(1), number(2), number(3)]), ])], "(quote (1 2 3))", ), ( "`1", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("quasiquote".into(), None), number(1), ])], @@ -1550,32 +1549,32 @@ mod tests { ), ( "`(1 2 3)", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("quasiquote".into(), None), - list_from(vec![number(1), number(2), number(3)]), + Form::List(vec![number(1), number(2), number(3)]), ])], "(quasiquote (1 2 3))", ), ( "~1", - vec![list_from(vec![symbol("unquote".into(), None), number(1)])], + vec![Form::List(vec![symbol("unquote".into(), None), number(1)])], "(unquote 1)", ), ( "~(1 2 3)", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("unquote".into(), None), - list_from(vec![number(1), number(2), number(3)]), + Form::List(vec![number(1), number(2), number(3)]), ])], "(unquote (1 2 3))", ), ( "`(1 ~a 3)", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("quasiquote".into(), None), - list_from(vec![ + Form::List(vec![ number(1), - list_from(vec![ + Form::List(vec![ symbol("unquote".into(), None), symbol("a".into(), None), ]), @@ -1586,50 +1585,50 @@ mod tests { ), ( "~@(1 2 3)", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("splice-unquote".into(), None), - list_from(vec![number(1), number(2), number(3)]), + Form::List(vec![number(1), number(2), number(3)]), ])], "(splice-unquote (1 2 3))", ), ( "~@,,,,,(1 2 3)", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("splice-unquote".into(), None), - list_from(vec![number(1), number(2), number(3)]), + Form::List(vec![number(1), number(2), number(3)]), ])], "(splice-unquote (1 2 3))", ), ( "~@, ,,(1 2 3)", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("splice-unquote".into(), None), - list_from(vec![number(1), number(2), number(3)]), + Form::List(vec![number(1), number(2), number(3)]), ])], "(splice-unquote (1 2 3))", ), ( "~@ (1 2 3)", - vec![list_from(vec![ + vec![Form::List(vec![ symbol("splice-unquote".into(), None), - list_from(vec![number(1), number(2), number(3)]), + Form::List(vec![number(1), number(2), number(3)]), ])], "(splice-unquote (1 2 3))", ), ("1 #_(1 2 3) 3", vec![number(1), number(3)], "1 3"), ( "1 (1 2 #_[1 2 3 :keyw]) 3", - vec![number(1), list_from(vec![number(1), number(2)]), number(3)], + vec![number(1), Form::List(vec![number(1), number(2)]), number(3)], "1 (1 2) 3", ), ( "1 (1 2 #_[1 2 3 :keyw]) ,,,,,,, #_3", - vec![number(1), list_from(vec![number(1), number(2)])], + vec![number(1), Form::List(vec![number(1), number(2)])], "1 (1 2)", ), ( "1 (1 2 #_[1 2 3 :keyw]) ,,,,,,, #_3 \n\n4", - vec![number(1), list_from(vec![number(1), number(2)]), number(4)], + vec![number(1), Form::List(vec![number(1), number(2)]), number(4)], "1 (1 2) 4", ), ]; diff --git a/src/repl.rs b/src/repl.rs index 66da693..739c642 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -1,6 +1,6 @@ use crate::interpreter::{EvaluationError, Interpreter, SymbolIndex}; -use crate::reader::{is_structural, is_symbolic, is_token, read, ReadError}; -use crate::value::Value; +use crate::reader::{is_structural, is_symbolic, is_token, ReadError}; +use crate::value::RuntimeValue; use rustyline::completion::{Completer, Pair}; use rustyline::error::ReadlineError; use rustyline::highlight::{Highlighter, MatchingBracketHighlighter}; @@ -25,13 +25,16 @@ pub enum ReplError<'a> { #[error("error reading: {0}")] Read(ReadError, &'a str), #[error("error evaluating: {0}")] - Eval(EvaluationError, Value), + Eval(EvaluationError, RuntimeValue), #[error("error with I/O: {0}")] IO(#[from] io::Error), #[error("error with formatting: {0}")] Fmt(#[from] fmt::Error), #[error("error with readline: {0}")] Readline(#[from] ReadlineError), + // TODO: fixme + #[error("error interpreting: {0}")] + Tmp(#[from] EvaluationError), } pub struct StdRepl> { @@ -154,20 +157,8 @@ impl> StdRepl

{ self } - pub fn run_from_source<'a>(&mut self, source: &'a str) -> Result, ReplError<'a>> { - let forms = read(source).map_err(|err| ReplError::Read(err, source))?; - let mut results = vec![]; - for form in forms.iter() { - match self.interpreter.evaluate(&form.into()) { - Ok(result) => { - results.push(result); - } - Err(err) => { - return Err(ReplError::Eval(err, form.into())); - } - } - } - Ok(results) + pub fn run_from_source(&mut self, source: &str) -> Result, ReplError> { + self.interpreter.interpret(source).map_err(ReplError::Tmp) } pub fn run_from_file>(&mut self, path: Q) -> Result<(), ReplError> { diff --git a/src/testing.rs b/src/testing.rs index a6b1480..0a20941 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -1,10 +1,10 @@ use crate::interpreter::Interpreter; use crate::reader::read; -use crate::value::Value; +use crate::value::RuntimeValue; const EXPECTED_STARTING_SCOPE_LEN: usize = 1; -pub fn run_eval_test(test_cases: &[(&str, Value)]) { +pub fn run_eval_test(test_cases: &[(&str, RuntimeValue)]) { let mut has_err = false; for (input, expected) in test_cases { let forms = match read(input) { @@ -21,12 +21,12 @@ pub fn run_eval_test(test_cases: &[(&str, Value)]) { }; let mut interpreter = Interpreter::default(); - let mut final_result: Option = None; + let mut final_result: Option = None; let original_scope_len = interpreter.scopes.len(); assert!(original_scope_len == EXPECTED_STARTING_SCOPE_LEN); - assert!(interpreter.apply_stack.is_empty()); + // assert!(interpreter.apply_stack.is_empty()); for form in &forms { - match interpreter.evaluate(&form.into()) { + match interpreter.analyze_and_evaluate(form) { Ok(result) => { final_result = Some(result); } @@ -44,7 +44,7 @@ pub fn run_eval_test(test_cases: &[(&str, Value)]) { continue; } assert!(interpreter.scopes.len() == original_scope_len); - assert!(interpreter.apply_stack.is_empty()); + // assert!(interpreter.apply_stack.is_empty()); if let Some(final_result) = final_result { if final_result != *expected { has_err = true; diff --git a/src/value.rs b/src/value.rs index c49a113..187f161 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,240 +1,215 @@ -use crate::analyzer::{AnalyzedForm, FnForm}; use crate::collections::{PersistentList, PersistentMap, PersistentSet, PersistentVector}; use crate::interpreter::{EvaluationError, EvaluationResult, Interpreter}; use crate::namespace::Var; -use crate::reader::{Atom, Form, Symbol}; -use crate::writer::unescape_string; -use itertools::{join, sorted, Itertools}; -use std::cell::RefCell; -use std::cmp::{Eq, Ord, Ordering, PartialEq}; -use std::collections::HashMap; -use std::fmt; -use std::fmt::Write; +use crate::reader::{Atom, Form, Identifier, Symbol}; +use crate::writer::{ + unescape_string, write_bool, write_fn, write_identifer, write_keyword, write_list, write_map, + write_nil, write_number, write_primitive, write_set, write_string, write_symbol, write_var, + write_vector, +}; +use itertools::{sorted, Itertools}; +use std::cmp::Ordering; +use std::collections::HashSet; +use std::fmt::{self, Write}; use std::hash::{Hash, Hasher}; -use std::iter::{FromIterator, IntoIterator}; use std::mem::discriminant; -use std::rc::Rc; -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum RuntimeValue { - Nil, - Bool(bool), - Number(i64), - String(String), - Keyword(Symbol), - Symbol(Symbol), - Var(Var), - List(PersistentList), - Vector(PersistentVector), - Map(PersistentMap), - Set(PersistentSet), - Fn(FnForm<'_>), -} - -impl From<&Atom> for RuntimeValue { - fn from(atom: &Atom) -> Self { - match atom { - Atom::Nil => RuntimeValue::Nil, - Atom::Bool(b) => RuntimeValue::Bool(*b), - Atom::Number(n) => RuntimeValue::Number(*n), - Atom::String(s) => RuntimeValue::String(s.clone()), - Atom::Keyword(k) => RuntimeValue::Keyword(k.clone()), - Atom::Symbol(s) => RuntimeValue::Symbol(s.clone()), - } - } -} - -impl<'a> From<&AnalyzedForm<'a>> for RuntimeValue { - fn from(form: &AnalyzedForm<'a>) -> Self { - // TODO finish - match form { - AnalyzedForm::LexicalSymbol(identifier) => RuntimeValue::Symbol(Symbol { - identifier, - namespace: None, - }), - AnalyzedForm::Var(var) => RuntimeValue::Var(var), - AnalyzedForm::Atom(atom) => atom.into(), - AnalyzedForm::List(list) => {} - AnalyzedForm::Vector(coll) => {} - AnalyzedForm::Map(coll) => {} - AnalyzedForm::Set(coll) => {} - } - } -} +// pub fn list_with_values(values: impl IntoIterator) -> RuntimeValue { +// RuntimeValue::List(PersistentList::from_iter(values)) +// } -impl Hash for RuntimeValue { - fn hash(&self, state: &mut H) { - // TODO - } -} +// pub fn vector_with_values(values: impl IntoIterator) -> RuntimeValue { +// RuntimeValue::Vector(PersistentVector::from_iter(values)) +// } -impl From<&Form> for Value { - fn from(form: &Form) -> Self { - match form { - Form::Atom(atom) => match atom { - Atom::Nil => Value::Nil, - Atom::Bool(b) => Value::Bool(*b), - Atom::Number(n) => Value::Number(*n), - Atom::String(s) => Value::String(s.clone()), - Atom::Keyword(Symbol { - identifier: id, - namespace: ns_opt, - }) => Value::Keyword(id.clone(), ns_opt.clone()), - Atom::Symbol(Symbol { - identifier: id, - namespace: ns_opt, - }) => Value::Symbol(id.clone(), ns_opt.clone()), - }, - Form::List(elems) => list_with_values(elems.iter().map(|e| -> Value { e.into() })), - Form::Vector(elems) => vector_with_values(elems.iter().map(|e| -> Value { e.into() })), - Form::Map(elems) => map_with_values( - elems - .iter() - .map(|(x, y)| -> (Value, Value) { (x.into(), y.into()) }), - ), - Form::Set(elems) => set_with_values(elems.iter().map(|e| -> Value { e.into() })), - } - } -} +// pub fn map_with_values( +// values: impl IntoIterator, +// ) -> RuntimeValue { +// RuntimeValue::Map(PersistentMap::from_iter(values)) +// } -pub fn list_with_values(values: impl IntoIterator) -> Value { - Value::List(PersistentList::from_iter(values)) -} +// pub fn set_with_values(values: impl IntoIterator) -> RuntimeValue { +// RuntimeValue::Set(PersistentSet::from_iter(values)) +// } -pub fn vector_with_values(values: impl IntoIterator) -> Value { - Value::Vector(PersistentVector::from_iter(values)) -} +// pub fn var_with_value(value: RuntimeValue, namespace: &str, identifier: &str) -> RuntimeValue { +// RuntimeValue::Var(VarImpl { +// data: Rc::new(RefCell::new(Some(value))), +// namespace: namespace.to_string(), +// identifier: identifier.to_string(), +// }) +// } -pub fn map_with_values(values: impl IntoIterator) -> Value { - Value::Map(PersistentMap::from_iter(values)) -} +// pub fn unbound_var(namespace: &str, identifier: &str) -> RuntimeValue { +// RuntimeValue::Var(VarImpl { +// data: Rc::new(RefCell::new(None)), +// namespace: namespace.to_string(), +// identifier: identifier.to_string(), +// }) +// } -pub fn set_with_values(values: impl IntoIterator) -> Value { - Value::Set(PersistentSet::from_iter(values)) -} +// pub fn atom_with_value(value: RuntimeValue) -> RuntimeValue { +// RuntimeValue::Atom(Rc::new(RefCell::new(value))) +// } -pub fn var_with_value(value: Value, namespace: &str, identifier: &str) -> Value { - Value::Var(VarImpl { - data: Rc::new(RefCell::new(Some(value))), - namespace: namespace.to_string(), - identifier: identifier.to_string(), - }) -} +// pub fn var_impl_into_inner(var: &VarImpl) -> Option { +// var.data.borrow().clone() +// } -pub fn unbound_var(namespace: &str, identifier: &str) -> Value { - Value::Var(VarImpl { - data: Rc::new(RefCell::new(None)), - namespace: namespace.to_string(), - identifier: identifier.to_string(), - }) -} - -pub fn atom_with_value(value: Value) -> Value { - Value::Atom(Rc::new(RefCell::new(value))) -} - -pub fn var_impl_into_inner(var: &VarImpl) -> Option { - var.data.borrow().clone() -} +// pub fn atom_impl_into_inner(atom: &AtomImpl) -> RuntimeValue { +// atom.borrow().clone() +// } -pub fn atom_impl_into_inner(atom: &AtomImpl) -> Value { - atom.borrow().clone() -} - -pub fn exception(msg: &str, data: &Value) -> ExceptionImpl { +pub fn exception(msg: &str, data: RuntimeValue) -> ExceptionImpl { ExceptionImpl::User(UserException { message: msg.to_string(), - data: Box::new(data.clone()), + data: Box::new(data), }) } -pub fn exception_from_system_err(err: EvaluationError) -> Value { +pub fn exception_from_system_err(err: EvaluationError) -> RuntimeValue { let inner = match err { EvaluationError::Exception(exc) => exc, err => ExceptionImpl::System(Box::new(err)), }; - Value::Exception(inner) + RuntimeValue::Exception(inner) } -pub type NativeFn = fn(&mut Interpreter, &[Value]) -> EvaluationResult; +pub type NativeFn = fn(&mut Interpreter, &[RuntimeValue]) -> EvaluationResult; -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct FnImpl { - pub body: PersistentList, - pub arity: usize, - // allow for nested fns - pub level: usize, - pub variadic: bool, -} +#[derive(Clone)] +pub struct Primitive(NativeFn); -#[derive(Debug, Clone, Eq)] -pub struct FnWithCapturesImpl { - pub f: FnImpl, - pub captures: HashMap>, +impl From<&NativeFn> for Primitive { + fn from(f: &NativeFn) -> Self { + Self(*f) + } } -impl PartialOrd for FnWithCapturesImpl { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) +impl fmt::Debug for Primitive { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "") } } -impl Ord for FnWithCapturesImpl { - fn cmp(&self, other: &Self) -> Ordering { - match self.f.cmp(&other.f) { - Ordering::Equal => { - let sorted_pairs = self.captures.iter().sorted(); - let other_sorted_pairs = other.captures.iter().sorted(); - sorted_pairs.cmp(other_sorted_pairs) - } - other => other, - } +impl PartialEq for Primitive { + fn eq(&self, other: &Self) -> bool { + let x = self as *const Primitive as usize; + let y = other as *const Primitive as usize; + x == y } } -impl PartialEq for FnWithCapturesImpl { - fn eq(&self, other: &Self) -> bool { - if self.f != other.f { - return false; - } +impl Eq for Primitive {} - self.captures - .iter() - .sorted() - .zip(other.captures.iter().sorted()) - .all(|((a, b), (c, d))| a == c && b == d) +impl Hash for Primitive { + fn hash(&self, state: &mut H) { + let x = self as *const Self as usize; + x.hash(state); } } -impl Hash for FnWithCapturesImpl { - fn hash(&self, state: &mut H) { - self.f.hash(state); - self.captures.iter().sorted().for_each(|(k, v)| { - k.hash(state); - v.hash(state); - }); +impl PartialOrd for Primitive { + fn partial_cmp(&self, other: &Self) -> Option { + let x = self as *const Primitive as usize; + let y = other as *const Primitive as usize; + x.partial_cmp(&y) } } -#[derive(Clone)] -pub struct VarImpl { - data: Rc>>, - namespace: String, - pub identifier: String, +impl Ord for Primitive { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } } -impl VarImpl { - pub fn update(&self, value: Value) { - *self.data.borrow_mut() = Some(value); +impl Primitive { + pub fn apply( + &self, + interpreter: &mut Interpreter, + args: &[RuntimeValue], + ) -> EvaluationResult { + self.0(interpreter, args) } } -type AtomImpl = Rc>; +// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +// pub struct FnImpl { +// pub body: PersistentList, +// pub arity: usize, +// // allow for nested fns +// pub level: usize, +// pub variadic: bool, +// } + +// #[derive(Debug, Clone, Eq)] +// pub struct FnWithCapturesImpl { +// pub f: FnImpl, +// pub captures: HashMap>, +// } + +// impl PartialOrd for FnWithCapturesImpl { +// fn partial_cmp(&self, other: &Self) -> Option { +// Some(self.cmp(other)) +// } +// } + +// impl Ord for FnWithCapturesImpl { +// fn cmp(&self, other: &Self) -> Ordering { +// match self.f.cmp(&other.f) { +// Ordering::Equal => { +// let sorted_pairs = self.captures.iter().sorted(); +// let other_sorted_pairs = other.captures.iter().sorted(); +// sorted_pairs.cmp(other_sorted_pairs) +// } +// other => other, +// } +// } +// } + +// impl PartialEq for FnWithCapturesImpl { +// fn eq(&self, other: &Self) -> bool { +// if self.f != other.f { +// return false; +// } + +// self.captures +// .iter() +// .sorted() +// .zip(other.captures.iter().sorted()) +// .all(|((a, b), (c, d))| a == c && b == d) +// } +// } + +// impl Hash for FnWithCapturesImpl { +// fn hash(&self, state: &mut H) { +// self.f.hash(state); +// self.captures.iter().sorted().for_each(|(k, v)| { +// k.hash(state); +// v.hash(state); +// }); +// } +// } + +// #[derive(Clone)] +// pub struct VarImpl { +// data: Rc>>, +// namespace: String, +// pub identifier: String, +// } + +// impl VarImpl { +// pub fn update(&self, value: RuntimeValue) { +// *self.data.borrow_mut() = Some(value); +// } +// } + +// type AtomImpl = Rc>; #[derive(Clone, Debug)] pub struct UserException { message: String, - data: Box, + data: Box, } impl UserException { @@ -273,7 +248,7 @@ impl ExceptionImpl { ExceptionImpl::System(err) => write!( &mut result, "{}", - Value::String(err.to_string()).to_readable_string() + RuntimeValue::String(err.to_string()).to_readable_string() ) .expect("can write to string"), } @@ -354,554 +329,725 @@ impl fmt::Display for ExceptionImpl { } } -#[derive(Clone)] -pub enum Value { - Nil, - Bool(bool), - Number(i64), - String(String), - // identifier with optional namespace - Keyword(String, Option), - // identifier with optional namespace - Symbol(String, Option), - List(PersistentList), - Vector(PersistentVector), - Map(PersistentMap), - Set(PersistentSet), - Fn(FnImpl), - FnWithCaptures(FnWithCapturesImpl), - Primitive(NativeFn), - Var(VarImpl), - Recur(PersistentVector), - Atom(AtomImpl), - Macro(FnImpl), - Exception(ExceptionImpl), +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum SpecialForm { + // (def! symbol form?) + Def(DefForm), + // (var symbol) + Var(Symbol), + // (let* [bindings*] form*) + Let(LetForm), + // (loop* [bindings*] form*) + Loop(LexicalForm), + // (recur form*) + Recur(BodyForm), + // (if predicate consequent alternate?) + If(IfForm), + // (do form*) + Do(BodyForm), + //(fn* [parameters*] form*) + Fn(FnForm), + // (quote form) + Quote(Box), + // (quasiquote form) + Quasiquote(Box), + // // (unquote form) + // Unquote(Box), + // // (splice-unquote form) + // SpliceUnquote(Box), + // (defmacro! symbol fn*-form) + Defmacro(Symbol, FnForm), + // (macroexpand macro-form) + Macroexpand(Box), + // (try* form* catch*-form?) + Try(TryForm), } -impl PartialEq for Value { - fn eq(&self, other: &Self) -> bool { - use Value::*; +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum DefForm { + Bound(Symbol, Box), + Unbound(Symbol), +} + +pub type LexicalBinding = (Identifier, Box); + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum LexicalBindings { + Bound(Vec), + Unbound(Vec), +} +impl LexicalBindings { + pub fn names(&self) -> Vec { match self { - Nil => matches!(other, Nil), - Bool(ref x) => match other { - Bool(ref y) => x == y, - _ => false, - }, - Number(ref x) => match other { - Number(ref y) => x == y, - _ => false, - }, - String(ref x) => match other { - String(ref y) => x == y, - _ => false, - }, - Keyword(ref x, ref x_ns_opt) => match other { - Keyword(ref y, ref y_ns_opt) => (x, x_ns_opt) == (y, y_ns_opt), - _ => false, - }, - Symbol(ref x, ref x_ns_opt) => match other { - Symbol(ref y, ref y_ns_opt) => (x, x_ns_opt) == (y, y_ns_opt), - _ => false, - }, - List(ref x) => match other { - List(ref y) => x == y, - Vector(ref y) => { - if x.len() == y.len() { - x.iter().zip(y.iter()).map(|(a, b)| a == b).all(|x| x) - } else { - false - } - } - _ => false, - }, - Vector(ref x) => match other { - Vector(ref y) => x == y, - List(ref y) => { - if x.len() == y.len() { - x.iter().zip(y.iter()).map(|(a, b)| a == b).all(|x| x) - } else { - false + LexicalBindings::Bound(bindings) => { + bindings.iter().map(|(name, _)| name.clone()).collect() + } + LexicalBindings::Unbound(bindings) => bindings.clone(), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct LexicalForm { + pub bindings: LexicalBindings, + pub body: BodyForm, +} + +fn is_forward_visible(form: &RuntimeValue) -> bool { + matches!(form, RuntimeValue::SpecialForm(SpecialForm::Fn(_))) +} + +impl LexicalForm { + pub(super) fn resolve_forward_declarations(&self) -> HashSet { + let mut result = HashSet::new(); + match &self.bindings { + LexicalBindings::Bound(bindings) => { + for (index, (name, value)) in bindings.iter().enumerate() { + if is_forward_visible(value.as_ref()) { + result.insert(index); } } - _ => false, - }, - Map(ref x) => match other { - Map(ref y) => x == y, - _ => false, - }, - Set(ref x) => match other { - Set(ref y) => x == y, - _ => false, - }, - Fn(ref x) => match other { - Fn(ref y) => x == y, - _ => false, - }, - FnWithCaptures(ref x) => match other { - FnWithCaptures(ref y) => x == y, - _ => false, - }, - Primitive(x) => match other { - Primitive(y) => { - let x_ptr = x as *const NativeFn; - let x_identifier = x_ptr as usize; - let y_ptr = y as *const NativeFn; - let y_identifier = y_ptr as usize; - x_identifier == y_identifier - } - _ => false, - }, - Var(VarImpl { - namespace: namespace_x, - identifier: identifier_x, - .. - }) => match other { - Var(VarImpl { - namespace: namespace_y, - identifier: identifier_y, - .. - }) => (namespace_x, identifier_x) == (namespace_y, identifier_y), - _ => false, - }, - Recur(ref x) => match other { - Recur(ref y) => x == y, - _ => false, - }, - Atom(ref x) => match other { - Atom(ref y) => x == y, - _ => false, - }, - Macro(ref x) => match other { - Macro(ref y) => x == y, - _ => false, - }, - Exception(ref x) => match other { - Exception(ref y) => x == y, - _ => false, - }, + } + LexicalBindings::Unbound(_) => unreachable!("only relevant for bound symbols"), } + result } } -impl Eq for Value {} +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct LetForm { + pub lexical_form: LexicalForm, + // `let*` can produce "forward declarations" where some names + // in `scope` can be seen by all other names + pub forward_declarations: HashSet, +} + +impl Hash for LetForm { + fn hash(&self, state: &mut H) { + self.lexical_form.hash(state); + let declarations = self.forward_declarations.iter().sorted(); + for declaration in declarations { + declaration.hash(state); + } + } +} -impl PartialOrd for Value { +impl PartialOrd for LetForm { fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) + match self.lexical_form.cmp(&other.lexical_form) { + Ordering::Equal => Some( + sorted(self.forward_declarations.iter()) + .cmp(sorted(other.forward_declarations.iter())), + ), + other => Some(other), + } } } -// NOTE: `Ord` is implemented to facilitate operations within the `Interpreter`, -// e.g. consistent hashing; this notion of order should not be exposed to users. -impl Ord for Value { +impl Ord for LetForm { fn cmp(&self, other: &Self) -> Ordering { - use Value::*; + self.partial_cmp(other).unwrap() + } +} - match self { - Nil => match other { - Nil => Ordering::Equal, - _ => Ordering::Less, - }, - Bool(ref x) => match other { - Nil => Ordering::Greater, - Bool(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - Number(ref x) => match other { - Nil | Bool(_) => Ordering::Greater, - Number(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - String(ref x) => match other { - Nil | Bool(_) | Number(_) => Ordering::Greater, - String(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - Keyword(ref x, ref x_ns_opt) => match other { - Nil | Bool(_) | Number(_) | String(_) => Ordering::Greater, - Keyword(ref y, ref y_ns_opt) => (x, x_ns_opt).cmp(&(y, y_ns_opt)), - _ => Ordering::Less, - }, - Symbol(ref x, ref x_ns_opt) => match other { - Nil | Bool(_) | Number(_) | String(_) | Keyword(_, _) => Ordering::Greater, - Symbol(ref y, ref y_ns_opt) => (x, x_ns_opt).cmp(&(y, y_ns_opt)), - _ => Ordering::Less, - }, - List(ref x) => match other { - Nil | Bool(_) | Number(_) | String(_) | Keyword(_, _) | Symbol(_, _) => { - Ordering::Greater - } - List(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - Vector(ref x) => match other { - Nil | Bool(_) | Number(_) | String(_) | Keyword(_, _) | Symbol(_, _) | List(_) => { - Ordering::Greater - } - Vector(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - Map(ref x) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) => Ordering::Greater, - Map(ref y) => sorted(x).cmp(sorted(y)), - _ => Ordering::Less, - }, - Set(ref x) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) - | Map(_) => Ordering::Greater, - Set(ref y) => sorted(x).cmp(sorted(y)), - _ => Ordering::Less, - }, - Fn(ref x) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) - | Map(_) - | Set(_) => Ordering::Greater, - Fn(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - FnWithCaptures(ref x) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) - | Map(_) - | Set(_) - | Fn(_) => Ordering::Greater, - FnWithCaptures(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - Primitive(x) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) - | Map(_) - | Set(_) - | Fn(_) - | FnWithCaptures(_) => Ordering::Greater, - Primitive(y) => { - let x_ptr = x as *const NativeFn; - let x_identifier = x_ptr as usize; - let y_ptr = y as *const NativeFn; - let y_identifier = y_ptr as usize; - x_identifier.cmp(&y_identifier) - } - _ => Ordering::Less, - }, - Var(VarImpl { - namespace: namespace_x, - identifier: identifier_x, - .. - }) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) - | Map(_) - | Set(_) - | Fn(_) - | FnWithCaptures(_) - | Primitive(_) => Ordering::Greater, - Var(VarImpl { - namespace: namespace_y, - identifier: identifier_y, - .. - }) => (namespace_x, identifier_x).cmp(&(namespace_y, identifier_y)), - _ => Ordering::Less, - }, - Recur(ref x) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) - | Map(_) - | Set(_) - | Fn(_) - | FnWithCaptures(_) - | Primitive(_) - | Var(_) => Ordering::Greater, - Recur(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - Atom(ref x) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) - | Map(_) - | Set(_) - | Fn(_) - | FnWithCaptures(_) - | Primitive(_) - | Var(_) - | Recur(_) => Ordering::Greater, - Atom(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - Macro(ref x) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) - | Map(_) - | Set(_) - | Fn(_) - | FnWithCaptures(_) - | Primitive(_) - | Var(_) - | Recur(_) - | Atom(_) => Ordering::Greater, - Macro(ref y) => x.cmp(y), - _ => Ordering::Less, - }, - Exception(ref x) => match other { - Nil - | Bool(_) - | Number(_) - | String(_) - | Keyword(_, _) - | Symbol(_, _) - | List(_) - | Vector(_) - | Map(_) - | Set(_) - | Fn(_) - | FnWithCaptures(_) - | Primitive(_) - | Var(_) - | Recur(_) - | Atom(_) - | Macro(_) => Ordering::Greater, - Exception(ref y) => x.cmp(y), - }, +impl LetForm { + pub fn identifier_for_binding(&self, index: usize) -> Option<&Identifier> { + match &self.lexical_form.bindings { + LexicalBindings::Bound(bindings) => bindings.get(index).map(|binding| &binding.0), + LexicalBindings::Unbound(bindings) => bindings.get(index), } } } -impl Hash for Value { - fn hash(&self, state: &mut H) { - use Value::*; +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct BodyForm { + pub body: Vec, +} - // mix in the particular variant - discriminant(self).hash(state); +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct IfForm { + pub predicate: Box, + pub consequent: Box, + pub alternate: Option>, +} - match self { - Nil => {} - Bool(b) => b.hash(state), - Number(n) => n.hash(state), - String(s) => s.hash(state), - Keyword(s, ns) => { - s.hash(state); - ns.hash(state); - } - Symbol(s, ns) => { - s.hash(state); - ns.hash(state); - } - List(l) => l.hash(state), - Vector(v) => v.hash(state), - Map(m) => { - m.size().hash(state); - sorted(m).for_each(|binding| binding.hash(state)); - } - Set(s) => { - s.size().hash(state); - sorted(s).for_each(|elem| elem.hash(state)); - } - Fn(lambda) => lambda.hash(state), - FnWithCaptures(lambda) => lambda.hash(state), - Primitive(f) => { - let ptr = f as *const NativeFn; - let identifier = ptr as usize; - identifier.hash(state); - } - Var(VarImpl { - data, - namespace, - identifier, - }) => { - data.borrow().hash(state); - namespace.hash(state); - identifier.hash(state); - } - Recur(v) => v.hash(state), - Atom(v) => { - (*v.borrow()).hash(state); - } - Macro(lambda) => lambda.hash(state), - Exception(e) => e.hash(state), - } +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct FnForm { + pub parameters: Vec, + pub variadic: Option, + pub body: BodyForm, +} + +impl FnForm { + // `arity` is the number of _fixed_ arguments `self` expects + pub fn arity(&self) -> usize { + self.parameters.len() + } + + pub fn variadic(&self) -> bool { + self.variadic.is_some() } } -impl fmt::Debug for Value { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use Value::*; +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct TryForm { + pub body: BodyForm, + pub catch: Option, +} - match self { - Nil => write!(f, "Nil"), - Bool(ref b) => write!(f, "Bool({:?})", b), - Number(ref n) => write!(f, "Number({:?})", n), - String(ref s) => write!(f, "String({:?})", s), - Keyword(ref id, ref ns_opt) => { - write!(f, "Keyword(\"")?; - if let Some(ns) = ns_opt { - write!(f, "{}/", ns)?; - } - write!(f, "{}\")", id) - } - Symbol(ref id, ref ns_opt) => { - write!(f, "Symbol(\"")?; - if let Some(ns) = ns_opt { - write!(f, "{}/", ns)?; - } - write!(f, "{}\")", id) - } - List(elems) => write!(f, "List({:?})", elems.iter().format(", ")), - Vector(elems) => write!(f, "Vector({:?})", elems.iter().format(", ")), - Map(elems) => { - let mut inner = vec![]; - for (k, v) in elems { - let mut buffer = std::string::String::new(); - write!(buffer, "{:?} {:?}", k, v)?; - inner.push(buffer); - } - write!(f, "Map({:?})", inner.iter().format(", ")) - } - Set(elems) => write!(f, "Set({:?})", elems.iter().format(", ")), - Fn(_) => write!(f, "Fn(..)"), - FnWithCaptures(..) => write!(f, "FnWithCaptures(..)",), - Primitive(_) => write!(f, "Primitive(..)"), - Var(VarImpl { - data, - namespace, - identifier, - }) => match data.borrow().as_ref() { - Some(inner) => { - write!(f, "Var({:?}/{:?}, {:?})", namespace, identifier, inner) - } - None => write!(f, "Var({:?}/{:?}, unbound)", namespace, identifier), - }, - Recur(elems) => write!(f, "Recur({:?})", elems.iter().format(" ")), - Atom(v) => write!(f, "Atom({:?})", *v.borrow()), - Macro(_) => write!(f, "Macro(..)"), - Exception(exception) => { - write!(f, "Exception({:?})", exception) +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct CatchForm { + pub exception_binding: Identifier, + pub body: BodyForm, +} + +impl From<&Atom> for RuntimeValue { + fn from(atom: &Atom) -> Self { + match atom { + Atom::Nil => RuntimeValue::Nil, + Atom::Bool(b) => RuntimeValue::Bool(*b), + Atom::Number(n) => RuntimeValue::Number(*n), + Atom::String(s) => RuntimeValue::String(s.clone()), + Atom::Keyword(k) => RuntimeValue::Keyword(k.clone()), + Atom::Symbol(s) => RuntimeValue::Symbol(s.clone()), + } + } +} + +// this `From` impl provides for a translation from a `Form` to an `RuntimeValue` +// without doing any actual analysis, e.g. when producing a `quote` form. +impl From<&Form> for RuntimeValue { + fn from(form: &Form) -> Self { + match form { + Form::Atom(atom) => atom.into(), + Form::List(coll) => RuntimeValue::List(coll.iter().map(From::from).collect()), + Form::Vector(coll) => RuntimeValue::Vector(coll.iter().map(From::from).collect()), + Form::Map(coll) => { + RuntimeValue::Map(coll.iter().map(|(k, v)| (k.into(), v.into())).collect()) } + Form::Set(coll) => RuntimeValue::Set(coll.iter().map(From::from).collect()), } } } -impl fmt::Display for Value { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use Value::*; +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum RuntimeValue { + Nil, + Bool(bool), + Number(i64), + String(String), + Keyword(Symbol), + Symbol(Symbol), + LexicalSymbol(Identifier), + Var(Var), + List(PersistentList), + Vector(PersistentVector), + Map(PersistentMap), + Set(PersistentSet), + SpecialForm(SpecialForm), + Fn(FnForm), + Primitive(Primitive), + Exception(ExceptionImpl), + // FnWithCaptures(FnWithCapturesImpl), + // Atom(AtomImpl), + // Macro(FnImpl), +} +// #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +// pub struct FnImpl { +// pub parameters: Vec, +// pub variadic: Option, +// pub body: Vec, +// } + +// impl PartialEq for RuntimeValue { +// fn eq(&self, other: &Self) -> bool { +// use RuntimeValue::*; + +// match self { +// Nil => matches!(other, Nil), +// Bool(ref x) => match other { +// Bool(ref y) => x == y, +// _ => false, +// }, +// Number(ref x) => match other { +// Number(ref y) => x == y, +// _ => false, +// }, +// String(ref x) => match other { +// String(ref y) => x == y, +// _ => false, +// }, +// Keyword(x) => match other { +// Keyword(y) => x == y, +// _ => false, +// }, +// Symbol(x) => match other { +// Symbol(y) => x == y, +// _ => false, +// }, +// List(ref x) => match other { +// List(ref y) => x == y, +// Vector(ref y) => { +// if x.len() == y.len() { +// x.iter().zip(y.iter()).map(|(a, b)| a == b).all(|x| x) +// } else { +// false +// } +// } +// _ => false, +// }, +// Vector(ref x) => match other { +// Vector(ref y) => x == y, +// List(ref y) => { +// if x.len() == y.len() { +// x.iter().zip(y.iter()).map(|(a, b)| a == b).all(|x| x) +// } else { +// false +// } +// } +// _ => false, +// }, +// Map(ref x) => match other { +// Map(ref y) => x == y, +// _ => false, +// }, +// Set(ref x) => match other { +// Set(ref y) => x == y, +// _ => false, +// }, +// Fn(x) => match other { +// Fn(y) => x == y, +// _ => false, +// }, +// // FnWithCaptures(ref x) => match other { +// // FnWithCaptures(ref y) => x == y, +// // _ => false, +// // }, +// Primitive(x) => match other { +// Primitive(y) => { +// let x_ptr = x as *const Primitive; +// let x_identifier = x_ptr as usize; +// let y_ptr = y as *const Primitive; +// let y_identifier = y_ptr as usize; +// x_identifier == y_identifier +// } +// _ => false, +// }, +// Var(VarImpl { +// namespace: namespace_x, +// identifier: identifier_x, +// .. +// }) => match other { +// Var(VarImpl { +// namespace: namespace_y, +// identifier: identifier_y, +// .. +// }) => (namespace_x, identifier_x) == (namespace_y, identifier_y), +// _ => false, +// }, +// // Recur(ref x) => match other { +// // Recur(ref y) => x == y, +// // _ => false, +// // }, +// // Atom(ref x) => match other { +// // Atom(ref y) => x == y, +// // _ => false, +// // }, +// // Macro(ref x) => match other { +// // Macro(ref y) => x == y, +// // _ => false, +// // }, +// Exception(ref x) => match other { +// Exception(ref y) => x == y, +// _ => false, +// }, +// } +// } +// } + +// impl PartialOrd for RuntimeValue { +// fn partial_cmp(&self, other: &Self) -> Option { +// Some(self.cmp(other)) +// } +// } + +// NOTE: `Ord` is implemented to facilitate operations within the `Interpreter`, +// e.g. consistent hashing; this notion of order should not be exposed to users. +// impl Ord for RuntimeValue { +// fn cmp(&self, other: &Self) -> Ordering { +// use RuntimeValue::*; + +// match self { +// Nil => match other { +// Nil => Ordering::Equal, +// _ => Ordering::Less, +// }, +// Bool(ref x) => match other { +// Nil => Ordering::Greater, +// Bool(ref y) => x.cmp(y), +// _ => Ordering::Less, +// }, +// Number(ref x) => match other { +// Nil | Bool(_) => Ordering::Greater, +// Number(ref y) => x.cmp(y), +// _ => Ordering::Less, +// }, +// String(ref x) => match other { +// Nil | Bool(_) | Number(_) => Ordering::Greater, +// String(ref y) => x.cmp(y), +// _ => Ordering::Less, +// }, +// Keyword(ref x, ref x_ns_opt) => match other { +// Nil | Bool(_) | Number(_) | String(_) => Ordering::Greater, +// Keyword(ref y, ref y_ns_opt) => (x, x_ns_opt).cmp(&(y, y_ns_opt)), +// _ => Ordering::Less, +// }, +// Symbol(ref x, ref x_ns_opt) => match other { +// Nil | Bool(_) | Number(_) | String(_) | Keyword(_, _) => Ordering::Greater, +// Symbol(ref y, ref y_ns_opt) => (x, x_ns_opt).cmp(&(y, y_ns_opt)), +// _ => Ordering::Less, +// }, +// List(ref x) => match other { +// Nil | Bool(_) | Number(_) | String(_) | Keyword(_, _) | Symbol(_, _) => { +// Ordering::Greater +// } +// List(ref y) => x.cmp(y), +// _ => Ordering::Less, +// }, +// Vector(ref x) => match other { +// Nil | Bool(_) | Number(_) | String(_) | Keyword(_, _) | Symbol(_, _) | List(_) => { +// Ordering::Greater +// } +// Vector(ref y) => x.cmp(y), +// _ => Ordering::Less, +// }, +// Map(ref x) => match other { +// Nil +// | Bool(_) +// | Number(_) +// | String(_) +// | Keyword(_, _) +// | Symbol(_, _) +// | List(_) +// | Vector(_) => Ordering::Greater, +// Map(ref y) => sorted(x).cmp(sorted(y)), +// _ => Ordering::Less, +// }, +// Set(ref x) => match other { +// Nil +// | Bool(_) +// | Number(_) +// | String(_) +// | Keyword(_, _) +// | Symbol(_, _) +// | List(_) +// | Vector(_) +// | Map(_) => Ordering::Greater, +// Set(ref y) => sorted(x).cmp(sorted(y)), +// _ => Ordering::Less, +// }, +// Fn(ref x) => match other { +// Nil +// | Bool(_) +// | Number(_) +// | String(_) +// | Keyword(_, _) +// | Symbol(_, _) +// | List(_) +// | Vector(_) +// | Map(_) +// | Set(_) => Ordering::Greater, +// Fn(ref y) => x.cmp(y), +// _ => Ordering::Less, +// }, +// // FnWithCaptures(ref x) => match other { +// // Nil +// // | Bool(_) +// // | Number(_) +// // | String(_) +// // | Keyword(_, _) +// // | Symbol(_, _) +// // | List(_) +// // | Vector(_) +// // | Map(_) +// // | Set(_) +// // | Fn(_) => Ordering::Greater, +// // FnWithCaptures(ref y) => x.cmp(y), +// // _ => Ordering::Less, +// // }, +// Primitive(x) => match other { +// Nil +// | Bool(_) +// | Number(_) +// | String(_) +// | Keyword(_, _) +// | Symbol(_, _) +// | List(_) +// | Vector(_) +// | Map(_) +// | Set(_) +// | Fn(_) +// | FnWithCaptures(_) => Ordering::Greater, +// Primitive(y) => { +// let x_ptr = x as *const NativeFn; +// let x_identifier = x_ptr as usize; +// let y_ptr = y as *const NativeFn; +// let y_identifier = y_ptr as usize; +// x_identifier.cmp(&y_identifier) +// } +// _ => Ordering::Less, +// }, +// Var(VarImpl { +// namespace: namespace_x, +// identifier: identifier_x, +// .. +// }) => match other { +// Nil +// | Bool(_) +// | Number(_) +// | String(_) +// | Keyword(_, _) +// | Symbol(_, _) +// | List(_) +// | Vector(_) +// | Map(_) +// | Set(_) +// | Fn(_) +// | FnWithCaptures(_) +// | Primitive(_) => Ordering::Greater, +// Var(VarImpl { +// namespace: namespace_y, +// identifier: identifier_y, +// .. +// }) => (namespace_x, identifier_x).cmp(&(namespace_y, identifier_y)), +// _ => Ordering::Less, +// }, +// Recur(ref x) => match other { +// Nil +// | Bool(_) +// | Number(_) +// | String(_) +// | Keyword(_, _) +// | Symbol(_, _) +// | List(_) +// | Vector(_) +// | Map(_) +// | Set(_) +// | Fn(_) +// | FnWithCaptures(_) +// | Primitive(_) +// | Var(_) => Ordering::Greater, +// Recur(ref y) => x.cmp(y), +// _ => Ordering::Less, +// }, +// Atom(ref x) => match other { +// Nil +// | Bool(_) +// | Number(_) +// | String(_) +// | Keyword(_, _) +// | Symbol(_, _) +// | List(_) +// | Vector(_) +// | Map(_) +// | Set(_) +// | Fn(_) +// | FnWithCaptures(_) +// | Primitive(_) +// | Var(_) +// | Recur(_) => Ordering::Greater, +// Atom(ref y) => x.cmp(y), +// _ => Ordering::Less, +// }, +// Macro(ref x) => match other { +// Nil +// | Bool(_) +// | Number(_) +// | String(_) +// | Keyword(_, _) +// | Symbol(_, _) +// | List(_) +// | Vector(_) +// | Map(_) +// | Set(_) +// | Fn(_) +// | FnWithCaptures(_) +// | Primitive(_) +// | Var(_) +// | Recur(_) +// | Atom(_) => Ordering::Greater, +// Macro(ref y) => x.cmp(y), +// _ => Ordering::Less, +// }, +// Exception(ref x) => match other { +// Nil +// | Bool(_) +// | Number(_) +// | String(_) +// | Keyword(_, _) +// | Symbol(_, _) +// | List(_) +// | Vector(_) +// | Map(_) +// | Set(_) +// | Fn(_) +// | FnWithCaptures(_) +// | Primitive(_) +// | Var(_) +// | Recur(_) +// | Atom(_) +// | Macro(_) => Ordering::Greater, +// Exception(ref y) => x.cmp(y), +// }, +// } +// } +// } + +// impl Hash for RuntimeValue { +// fn hash(&self, state: &mut H) { +// use RuntimeValue::*; + +// // mix in the particular variant +// discriminant(self).hash(state); + +// match self { +// Nil => {} +// Bool(b) => b.hash(state), +// Number(n) => n.hash(state), +// String(s) => s.hash(state), +// Keyword(s) => s.hash(state), +// Symbol(s) => s.hash(state), +// List(l) => l.hash(state), +// Vector(v) => v.hash(state), +// Map(m) => { +// m.size().hash(state); +// sorted(m).for_each(|binding| binding.hash(state)); +// } +// Set(s) => { +// s.size().hash(state); +// sorted(s).for_each(|elem| elem.hash(state)); +// } +// Fn(f) => f.hash(state), +// // FnWithCaptures(lambda) => lambda.hash(state), +// Primitive(f) => { +// let ptr = f as *const Primitive; +// let identifier = ptr as usize; +// identifier.hash(state); +// } +// Var(var) => { +// var.hash(state); +// // data.borrow().hash(state); +// // namespace.hash(state); +// // identifier.hash(state); +// } +// // Recur(v) => v.hash(state), +// // Atom(v) => { +// // (*v.borrow()).hash(state); +// // } +// // Macro(lambda) => lambda.hash(state), +// Exception(e) => e.hash(state), +// } +// } +// } + +// impl fmt::Debug for RuntimeValue { +// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// use RuntimeValue::*; + +// match self { +// Nil => write!(f, "Nil"), +// Bool(ref b) => write!(f, "Bool({:?})", b), +// Number(ref n) => write!(f, "Number({:?})", n), +// String(ref s) => write!(f, "String({:?})", s), +// Keyword(ref id, ref ns_opt) => { +// write!(f, "Keyword(\"")?; +// if let Some(ns) = ns_opt { +// write!(f, "{}/", ns)?; +// } +// write!(f, "{}\")", id) +// } +// Symbol(ref id, ref ns_opt) => { +// write!(f, "Symbol(\"")?; +// if let Some(ns) = ns_opt { +// write!(f, "{}/", ns)?; +// } +// write!(f, "{}\")", id) +// } +// List(elems) => write!(f, "List({:?})", elems.iter().format(", ")), +// Vector(elems) => write!(f, "Vector({:?})", elems.iter().format(", ")), +// Map(elems) => { +// let mut inner = vec![]; +// for (k, v) in elems { +// let mut buffer = std::string::String::new(); +// write!(buffer, "{:?} {:?}", k, v)?; +// inner.push(buffer); +// } +// write!(f, "Map({:?})", inner.iter().format(", ")) +// } +// Set(elems) => write!(f, "Set({:?})", elems.iter().format(", ")), +// Fn(_) => write!(f, "Fn(..)"), +// FnWithCaptures(..) => write!(f, "FnWithCaptures(..)",), +// Primitive(_) => write!(f, "Primitive(..)"), +// Var(VarImpl { +// data, +// namespace, +// identifier, +// }) => match data.borrow().as_ref() { +// Some(inner) => { +// write!(f, "Var({:?}/{:?}, {:?})", namespace, identifier, inner) +// } +// None => write!(f, "Var({:?}/{:?}, unbound)", namespace, identifier), +// }, +// Recur(elems) => write!(f, "Recur({:?})", elems.iter().format(" ")), +// Atom(v) => write!(f, "Atom({:?})", *v.borrow()), +// Macro(_) => write!(f, "Macro(..)"), +// Exception(exception) => { +// write!(f, "Exception({:?})", exception) +// } +// } +// } +// } + +impl fmt::Display for RuntimeValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Nil => write!(f, "nil"), - Bool(ref b) => write!(f, "{}", b), - Number(ref n) => write!(f, "{}", n), - String(ref s) => write!(f, "{}", s), - Keyword(ref id, ref ns_opt) => { - write!(f, ":")?; - if let Some(ns) = ns_opt { - write!(f, "{}/", ns)?; - } - write!(f, "{}", id) - } - Symbol(ref id, ref ns_opt) => { - if let Some(ns) = ns_opt { - write!(f, "{}/", ns)?; - } - write!(f, "{}", id) + RuntimeValue::Nil => write_nil(f), + RuntimeValue::Bool(b) => write_bool(f, *b), + RuntimeValue::Number(n) => write_number(f, *n), + RuntimeValue::String(s) => write_string(f, s), + RuntimeValue::LexicalSymbol(s) => write_identifer(f, s), + RuntimeValue::Keyword(symbol) => write_keyword(f, symbol), + RuntimeValue::Symbol(symbol) => write_symbol(f, symbol), + RuntimeValue::Var(var) => write_var(f, var), + RuntimeValue::List(elems) => write_list(f, elems), + RuntimeValue::Vector(elems) => write_vector(f, elems), + RuntimeValue::Map(elems) => write_map(f, elems), + RuntimeValue::Set(elems) => write_set(f, elems), + RuntimeValue::SpecialForm(_) => { + // TODO + // write_fn(f), + write_nil(f) } - List(elems) => write!(f, "({})", join(elems, " ")), - Vector(elems) => write!(f, "[{}]", join(elems, " ")), - Map(elems) => { - let mut inner = vec![]; - for (k, v) in elems { - let mut buffer = std::string::String::new(); - write!(buffer, "{} {}", k, v)?; - inner.push(buffer); - } - write!(f, "{{{}}}", join(inner, ", ")) - } - Set(elems) => write!(f, "#{{{}}}", join(elems, " ")), - Fn(_) => write!(f, ""), - FnWithCaptures(..) => write!(f, "",), - Primitive(_) => write!(f, ""), - Var(VarImpl { - data, - namespace, - identifier, - }) => { - if data.borrow().is_some() { - write!(f, "#'{}/{}", namespace, identifier) - } else { - write!(f, "#'{}/{} (unbound)", namespace, identifier) - } - } - Recur(elems) => write!(f, "[{}]", join(elems, " ")), - Atom(v) => write!(f, "(atom {})", *v.borrow()), - Macro(_) => write!(f, ""), - Exception(exception) => { + // FnWithCaptures(..) => write!(f, "",), + RuntimeValue::Fn(..) => write_fn(f), + RuntimeValue::Primitive(..) => write_primitive(f), + // Atom(v) => write!(f, "(atom {})", *v.borrow()), + // Macro(_) => write!(f, ""), + RuntimeValue::Exception(exception) => { write!(f, "{}", exception) } } } } -impl Value { +impl RuntimeValue { pub fn to_readable_string(&self) -> String { let mut f = String::new(); let _ = match self { - Value::List(elems) => { + RuntimeValue::List(elems) => { write!( &mut f, "({})", @@ -909,7 +1055,7 @@ impl Value { ) .expect("can write to string"); } - Value::Vector(elems) => { + RuntimeValue::Vector(elems) => { write!( &mut f, "[{}]", @@ -917,7 +1063,7 @@ impl Value { ) .expect("can write to string"); } - Value::Map(elems) => { + RuntimeValue::Map(elems) => { let mut inner = vec![]; for (k, v) in elems { let mut buffer = String::new(); @@ -932,7 +1078,7 @@ impl Value { } write!(&mut f, "{{{}}}", inner.iter().format(", ")).expect("can write to string"); } - Value::Set(elems) => write!( + RuntimeValue::Set(elems) => write!( &mut f, "#{{{}}}", elems @@ -941,28 +1087,63 @@ impl Value { .format(" ") ) .expect("can write to string"), - Value::String(s) => { + RuntimeValue::String(s) => { let unescaped_string = unescape_string(s); write!(&mut f, "\"{}\"", unescaped_string).expect("can write to string"); } - Value::Atom(v) => write!(&mut f, "(atom {})", v.borrow().to_readable_string()) - .expect("can write to string"), - Value::Exception(e) => { + RuntimeValue::Exception(e) => { write!(&mut f, "{}", e.to_readable_string()).expect("can write to string") } other => { write!(&mut f, "{}", other).expect("can write to string"); } }; - f } } +// this `From` impl is to facilitate lang fns like `read-string` so does a translation without any "analysis" +// impl From<&AnalyzedForm> for RuntimeValue { +// fn from(form: &AnalyzedForm) -> Self { +// match form { +// AnalyzedForm::LexicalSymbol(identifier) => { +// RuntimeValue::LexicalSymbol(identifier.clone()) +// } +// AnalyzedForm::Var(var) => RuntimeValue::Var(var.clone()), +// AnalyzedForm::Atom(atom) => atom.into(), +// AnalyzedForm::List(coll) => match coll { +// AnalyzedList::Def(form) => {} +// AnalyzedList::Var(symbol) => {} +// AnalyzedList::Let(form) => {} +// AnalyzedList::Loop(form) => {} +// AnalyzedList::Recur(form) => {} +// AnalyzedList::If(form) => {} +// AnalyzedList::Do(form) => {} +// AnalyzedList::Fn(form) => {} +// AnalyzedList::Quote(form) => {} +// AnalyzedList::Quasiquote(form) => {} +// AnalyzedList::Defmacro(symbol, form) => {} +// AnalyzedList::Macroexpand(form) => {} +// AnalyzedList::Try(form) => {} +// AnalyzedList::Form(coll) => { +// RuntimeValue::List(coll.iter().map(From::from).collect()) +// } +// }, +// AnalyzedForm::Vector(coll) => { +// RuntimeValue::Vector(coll.iter().map(From::from).collect()) +// } +// AnalyzedForm::Map(coll) => { +// RuntimeValue::Map(coll.iter().map(|(k, v)| (k.into(), v.into())).collect()) +// } +// AnalyzedForm::Set(coll) => RuntimeValue::Set(coll.iter().map(From::from).collect()), +// } +// } +// } + #[cfg(test)] mod tests { use super::*; - use Value::*; + use RuntimeValue::*; #[test] fn test_ord_provided() { diff --git a/src/writer.rs b/src/writer.rs index 029e5dd..b95ea1a 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1,9 +1,9 @@ +use crate::namespace::Var; +use crate::reader::{Identifier, Symbol}; use itertools::join; use std::fmt::{self, Display, Write}; use std::string::String as StdString; -use crate::reader::Symbol; - pub(crate) fn unescape_string(input: &str) -> String { let mut result = String::with_capacity(input.len()); let mut iter = input.chars().peekable(); @@ -50,6 +50,10 @@ pub(crate) fn write_string(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result { write!(f, "\"{}\"", unescape_string(s)) } +pub(crate) fn write_identifer(f: &mut fmt::Formatter<'_>, identifier: &Identifier) -> fmt::Result { + write!(f, "{}", identifier) +} + pub(crate) fn write_keyword(f: &mut fmt::Formatter<'_>, symbol: &Symbol) -> fmt::Result { write!(f, ":")?; write_symbol(f, symbol) @@ -65,7 +69,7 @@ pub(crate) fn write_symbol( if let Some(ns) = namespace { write!(f, "{}/", ns)?; } - write!(f, "{}", identifier) + write_identifer(f, identifier) } pub(crate) fn write_list(f: &mut fmt::Formatter<'_>, elems: I) -> fmt::Result @@ -86,7 +90,7 @@ where pub(crate) fn write_map<'a, I, E>(f: &'a mut fmt::Formatter<'_>, elems: I) -> fmt::Result where - I: IntoIterator, + I: IntoIterator, E: Display + 'a, { let mut inner = vec![]; @@ -105,3 +109,23 @@ where { write!(f, "#{{{}}}", join(elems, " ")) } + +pub(crate) fn write_fn(f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "") +} + +pub(crate) fn write_primitive(f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "") +} + +pub(crate) fn write_var(f: &mut fmt::Formatter<'_>, var: &Var) -> fmt::Result { + match var { + Var::Bound(data) => { + // TODO how to display name... + write!(f, "") + } + Var::Unbound => { + write!(f, "") + } + } +} diff --git a/tests/integration.rs b/tests/integration.rs index f661ce9..a43d4b3 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -13,7 +13,7 @@ fn run_tests_as_self_hosted() { let args = env::args().into_iter().chain(iter::once(arg)); interpreter.intern_args(args); interpreter - .evaluate_from_source(SELF_HOSTING_REPL_SOURCE) + .interpret(SELF_HOSTING_REPL_SOURCE) .expect("is valid source"); }