diff --git a/src/ast/eval.rs b/src/ast/eval.rs index abca8f2..de93df4 100644 --- a/src/ast/eval.rs +++ b/src/ast/eval.rs @@ -1,16 +1,76 @@ //! todo -use crate::continuation::*; +use std::collections::BTreeSet; + +use futures::future::BoxFuture; + use super::*; +use crate::{ + continuation::*, + proc::{PreparedCall, ProcCallDebugInfo, Procedure}, + util::{self, RequireOne}, +}; + +impl Definition { + pub async fn eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result<(), RuntimeError> { + match self { + Self::DefineVar(var) => var.eval(env, cont).await, + Self::DefineFunc(func_def) => func_def.eval(env).await, + } + } +} + +impl DefineVar { + pub(super) async fn eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result<(), RuntimeError> { + let cont = Arc::new(Continuation::new( + Arc::new(ResumableDefineVar::new(env, &self.name)), + cont, + )); + let val = self.val.eval(env, &Some(cont)).await?.require_one()?; + env.write().def_local_var(&self.name, val); + Ok(()) + } +} + +impl DefineFunc { + pub(super) async fn eval(&self, env: &Gc) -> Result<(), RuntimeError> { + let (args, remaining) = self.args.to_args_and_remaining(); + let func = Gc::new(Value::Procedure(Procedure { + up: env.clone(), + args, + remaining, + body: self.body.clone(), + is_variable_transformer: false, + })); + env.write().def_local_var(&self.name, func); + Ok(()) + } +} impl Body { - pub async fn tail_eval( + pub(crate) async fn eval( &self, - env: &Env, + env: &Gc, + cont: &Option>, + ) -> Result>, RuntimeError> { + self.tail_eval(env, cont).await?.eval(cont).await + } + + pub(crate) async fn tail_eval( + &self, + env: &Gc, cont: &Option>, ) -> Result { let Some(last) = self.forms.last() else { - return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Null)])); + return Ok(ValuesOrPreparedCall::Values(Vec::new())); }; for (form, tail) in self.forms.skip_last() { let cont = Some(Arc::new(Continuation::new( @@ -23,3 +83,265 @@ impl Body { last.tail_eval(env, cont).await } } + +impl Expression { + pub fn tail_eval<'a>( + &'a self, + env: &'a Gc, + cont: &'a Option>, + ) -> BoxFuture<'a, Result> { + Box::pin(async move { + match self { + Self::Undefined => val(Value::Undefined), + Self::Literal(literal) => val(Value::from_literal(literal)), + Self::Quote(quote) => val(quote.val.clone()), + Self::SyntaxQuote(syn_quote) => val(Value::Syntax(syn_quote.syn.clone())), + Self::SyntaxCase(syn_case) => vals(syn_case.eval(env, cont).await?), + Self::Call(call) => call.tail_eval(env, cont).await, + Self::Let(bind) => bind.tail_eval(env, cont).await, + Self::If(cond) => cond.tail_eval(env, cont).await, + Self::And(and) => and.tail_eval(env, cont).await, + Self::Or(or) => or.tail_eval(env, cont).await, + Self::Lambda(lambda) => val(lambda.eval(env)), + Self::Set(set) => { + set.eval(env, cont).await?; + no_vals() + } + Self::Vector(vec) => val(vec.eval()), + Self::Begin(body) => body.tail_eval(env, cont).await, + Self::Var(var) => Ok(ValuesOrPreparedCall::Values(vec![var + .fetch(env) + .await + .map_err(|ident| RuntimeError::undefined_variable(ident))?])), + } + }) + } + + pub async fn eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result>, RuntimeError> { + self.tail_eval(env, cont).await?.eval(cont).await + } +} + +fn no_vals() -> Result { + Ok(ValuesOrPreparedCall::Values(Vec::new())) +} + +fn val(value: Value) -> Result { + Ok(ValuesOrPreparedCall::Values(vec![Gc::new(value)])) +} + +fn vals(values: Vec>) -> Result { + Ok(ValuesOrPreparedCall::Values(values)) +} + +impl Call { + async fn tail_eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result { + let mut collected = Vec::new(); + for (arg, remaining) in self.args.iter() { + let cont = Arc::new(Continuation::new( + Arc::new(ResumableCall::new( + &self.proc_name, + &self.location, + env, + &collected, + remaining, + )), + cont, + )); + let arg = arg.eval(env, &Some(cont)).await?.require_one()?; + collected.push(arg); + } + Ok(ValuesOrPreparedCall::PreparedCall(PreparedCall::prepare( + collected, + Some(ProcCallDebugInfo::new(&self.proc_name, &self.location)), + ))) + } +} + +impl Lambda { + fn eval(&self, env: &Gc) -> Value { + let (args, remaining) = self.args.to_args_and_remaining(); + Value::Procedure(Procedure { + up: env.clone(), + args, + remaining, + body: self.body.clone(), + is_variable_transformer: false, + }) + } +} + +impl Let { + async fn tail_eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result { + let scope = Gc::new(env.read().new_lexical_contour()); + for ((ident, expr), remaining) in util::iter_arc(&self.bindings) { + let cont = Arc::new(Continuation::new( + Arc::new(ResumableLet::new(&scope, ident, remaining, &self.body)), + cont, + )); + let val = expr.eval(&scope, &Some(cont)).await?.require_one()?; + scope.write().def_local_var(ident, val); + } + self.body.tail_eval(&scope, cont).await + } +} + +impl If { + async fn tail_eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result { + let cond_cont = Arc::new(Continuation::new( + Arc::new(ResumableIf::new(env, &self.success, &self.failure)), + cont, + )); + let condition = self + .cond + .eval(env, &Some(cond_cont)) + .await? + .require_one()? + .read() + .is_true(); + if condition { + self.success.tail_eval(env, cont).await + } else if let Some(ref failure) = self.failure { + failure.tail_eval(env, cont).await + } else { + Ok(ValuesOrPreparedCall::Values(Vec::new())) + } + } +} + +impl And { + async fn tail_eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result { + let Some(last) = self.args.last() else { + return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean( + true, + ))])); + }; + for (arg, tail) in self.args.skip_last() { + let cont = Arc::new(Continuation::new( + Arc::new(ResumableAnd::new(env, &tail)), + cont, + )); + // If one of the arguments does not evaluate to true, then the result + // is false + if !arg + .eval(env, &Some(cont)) + .await? + .require_one()? + .read() + .is_true() + { + return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean( + false, + ))])); + } + } + // If all of the other arguments are true, then the result is the last expression + last.tail_eval(env, cont).await + } +} + +impl Or { + async fn tail_eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result { + let Some(last) = self.args.last() else { + return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean( + false, + ))])); + }; + for (arg, tail) in self.args.skip_last() { + let cont = Arc::new(Continuation::new( + Arc::new(ResumableOr::new(env, &tail)), + cont, + )); + // If one of the arguments evaluates to true, then the result is true + if arg + .eval(env, &Some(cont)) + .await? + .require_one()? + .read() + .is_true() + { + return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean( + true, + ))])); + } + } + // If all of the other arguments are false, then the result is the last expression + last.tail_eval(env, cont).await + } +} + +impl Set { + async fn eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result<(), RuntimeError> { + let new_cont = Arc::new(Continuation::new( + Arc::new(ResumableSet::new(env, &self.var)), + cont, + )); + // TODO: Add try_unwrap to GC to avoid the clone of the inner value + let val = self + .val + .eval(env, &Some(new_cont)) + .await? + .require_one()? + .read() + .clone(); + self.var.set(env, &Gc::new(val)); + Ok(()) + } +} + +impl SyntaxCase { + async fn eval( + &self, + env: &Gc, + cont: &Option>, + ) -> Result>, RuntimeError> { + let new_cont = Arc::new(Continuation::new( + Arc::new(ResumableSyntaxCase::new(env, &self.transformer)), + cont, + )); + let val = self.arg.eval(env, &Some(new_cont)).await?.require_one()?; + // This clones _all_ syntax objects; we should fix this to be more optimal. + let syntax = Syntax::from_datum(&BTreeSet::default(), &val); + let transformed = self.transformer.expand(&syntax).unwrap(); + let expansion_env = ExpansionEnv::from_env(env); + Expression::parse(transformed, &expansion_env, cont) + .await + .expect("fixme") + .eval(&env, cont) + .await + } +} + +impl Vector { + fn eval(&self) -> Value { + Value::Vector(self.vals.clone()) + } +} diff --git a/src/ast/mod.rs b/src/ast/mod.rs index ff05167..6d015a1 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -2,16 +2,17 @@ mod eval; pub mod parse; use nom::error::ParseError; +use parse::define_syntax; use crate::{ continuation::Continuation, - env::Env, + env::{Env, ExpansionEnv, Ref}, error::RuntimeError, expand::Transformer, gc::{Gc, Trace}, num::Number, proc::ValuesOrPreparedCall, - syntax::{ExpansionEnv, Identifier, Mark, Span, Syntax}, + syntax::{ExpansionCtx, FullyExpanded, Identifier, Mark, Span, Syntax}, util::ArcSlice, value::Value, }; @@ -26,7 +27,7 @@ pub enum AstNode { impl AstNode { pub async fn eval( &self, - env: &Env, + env: &Gc, cont: &Option>, ) -> Result>, RuntimeError> { match self { @@ -40,7 +41,7 @@ impl AstNode { pub async fn tail_eval( &self, - env: &Env, + env: &Gc, cont: &Option>, ) -> Result { match self { @@ -48,37 +49,53 @@ impl AstNode { def.eval(env, cont).await?; Ok(ValuesOrPreparedCall::Values(Vec::new())) } - Self::Expression(expr) => expr.tail_eval(env, cont).await + Self::Expression(expr) => expr.tail_eval(env, cont).await, } } -} - -#[derive(Debug, Clone, Trace)] -pub enum Definition { - DefineVar(DefineVar), - DefineFunc(DefineFunc), -} -impl Definition { - pub async fn eval( - &self, - env: &Env, + pub async fn from_syntax( + syn: Syntax, + env: &Gc, cont: &Option>, - ) -> Result<(), RuntimeError> { - todo!() + ) -> Result, parse::ParseAstError> { + let expansion_env = ExpansionEnv::from_env(env); + let FullyExpanded { + expanded, + expansion_envs, + } = syn.expand(&expansion_env, cont).await?; + let expansion_env = expansion_env.new_expansion_env(expansion_envs); + Self::from_syntax_with_expansion_env(expanded, &expansion_env, cont).await } - pub async fn parse( - syn: &Syntax, - env: &Env, + async fn from_syntax_with_expansion_env( + syn: Syntax, + env: &ExpansionEnv<'_>, cont: &Option>, - ) -> Result { - todo!() + ) -> Result, parse::ParseAstError> { + match syn.as_list() { + Some([Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }]) + if ident.name == "define-syntax" => + { + // TODO: Error if define syntax isn't proper, error. + define_syntax(ident, expr.clone(), &env.lexical_contour, cont).await?; + Ok(None) + } + Some(syn @ [Syntax::Identifier { ident, span, .. }, ..]) if ident.name == "define" => { + Ok(Some(Self::Definition( + Definition::parse(syn, env, cont, span).await?, + ))) + } + _ => Ok(Some(Self::Expression( + Expression::parse(syn, env, cont).await?, + ))), + } } +} - pub fn wrap(self, envs: Vec) -> Self { - todo!() - } +#[derive(Debug, Clone, Trace)] +pub enum Definition { + DefineVar(DefineVar), + DefineFunc(DefineFunc), } #[derive(Debug, Clone, Trace)] @@ -96,48 +113,26 @@ pub struct DefineFunc { #[derive(Debug, Clone, Trace)] pub enum Expression { + Undefined, Literal(Literal), Quote(Quote), SyntaxQuote(SyntaxQuote), + SyntaxCase(SyntaxCase), Call(Call), + Let(Let), + If(If), + And(And), + Or(Or), Lambda(Lambda), Set(Set), - MacroExpansionPoint(MacroExpansionPoint), + Var(Ref), + Vector(Vector), + Begin(Body), } -impl Expression { - pub async fn eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result>, RuntimeError> { - match self { - _ => todo!(), - } - } - - pub async fn tail_eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result { - todo!() - } - - pub async fn parse( - syn: &Syntax, - env: &Env, - cont: &Option>, - ) -> Result { - todo!() - } - - fn wrap(self, envs: Vec) -> Self { - todo!() - } -} #[derive(Debug, Clone, PartialEq, Trace)] +// Vector should be in here too. Oh well. pub enum Literal { Number(Number), Boolean(bool), @@ -154,12 +149,11 @@ pub struct Quote { #[derive(Debug, Clone, Trace)] pub struct SyntaxQuote { pub syn: Syntax, - pub env: Env, } #[derive(Debug, Clone, Trace)] pub struct Call { - pub args: ArcSlice>, + pub args: ArcSlice, pub location: Span, pub proc_name: String, } @@ -172,12 +166,12 @@ pub struct Lambda { #[derive(Debug, Clone, Trace)] pub struct Let { - pub bindings: Arc<[(Identifier, Arc)]>, + pub bindings: Arc<[(Identifier, Expression)]>, pub body: Body, } impl Let { - pub fn new(bindings: Vec<(Identifier, Arc)>, body: Body) -> Self { + pub fn new(bindings: Vec<(Identifier, Expression)>, body: Body) -> Self { Self { bindings: Arc::from(bindings), body, @@ -187,7 +181,7 @@ impl Let { #[derive(Debug, Clone, Trace)] pub struct Set { - pub var: Identifier, + pub var: Ref, pub val: Arc, } @@ -224,16 +218,17 @@ pub struct Body { impl Body { pub fn new(defs: Vec, exprs: Vec) -> Self { Self { - forms: ArcSlice::from(defs - .into_iter() - .map(AstNode::Definition) - .chain(exprs.into_iter().map(AstNode::Expression)) - .collect::>()), + forms: ArcSlice::from( + defs.into_iter() + .map(AstNode::Definition) + .chain(exprs.into_iter().map(AstNode::Expression)) + .collect::>(), + ), } } } -#[derive(Clone, Trace)] +#[derive(Debug, Clone, Trace)] pub struct And { pub args: ArcSlice, } @@ -246,7 +241,7 @@ impl And { } } -#[derive(Clone, Trace)] +#[derive(Debug, Clone, Trace)] pub struct Or { pub args: ArcSlice, } @@ -259,41 +254,13 @@ impl Or { } } -#[derive(Clone, Trace)] +#[derive(Debug, Clone, Trace)] pub struct Vector { - pub vals: Vec, + pub vals: Vec, } -#[derive(Clone, Trace)] +#[derive(Debug, Clone, Trace)] pub struct SyntaxCase { pub arg: Arc, pub transformer: Transformer, } - -#[derive(Clone, Trace)] -pub struct Var { - pub ident: Identifier, -} - -impl Var { - pub fn new(ident: Identifier) -> Self { - Self { ident } - } -} - -#[derive(Debug, Clone, Trace)] -pub struct MacroExpansionPoint { - pub mark: Mark, - pub macro_env: Env, - pub expr: Arc, -} - -impl MacroExpansionPoint { - pub fn new(mark: Mark, macro_env: Env, expr: Arc) -> Self { - Self { - mark, - macro_env, - expr, - } - } -} diff --git a/src/ast/parse.rs b/src/ast/parse.rs index d1a4777..48b0b88 100644 --- a/src/ast/parse.rs +++ b/src/ast/parse.rs @@ -30,19 +30,14 @@ pub enum ParseAstError { NotAVariableTransformer, EmptyBody(Span), DefInExprContext(Span), - /* - ParseLetError(ParseLetError), - ParseFuncCallError(ParseFuncCallError), - ParseIfError(ParseIfError), - ParseDefineError(ParseDefineError), - ParseDefineSyntaxError(ParseDefineSyntaxError), - ParseQuoteError(ParseQuoteError), - ParseSetError(ParseSetError), - ParseLambdaError(ParseLambdaError), - ParseSyntaxError(ParseSyntaxError), - ParseSyntaxCaseError(ParseSyntaxCaseError), - */ - // ParseDefineRecordTypeError(crate::records::ParseDefineRecordTypeError), + ExpectedIdentifier(Span), + NameBoundMultipleTimes { + ident: Identifier, + first: Span, + second: Span, + }, + ExpectedArgument(Span), + UnexpectedArgument(Span), } impl From for ParseAstError { @@ -51,50 +46,175 @@ impl From for ParseAstError { } } -impl Body { - async fn parse( - body: &[Syntax], - env: &Env, +impl Definition { + pub(super) async fn parse( + syn: &[Syntax], + env: &ExpansionEnv<'_>, cont: &Option>, span: &Span, ) -> Result { - let mut defs = Vec::new(); - let mut exprs = Vec::new(); + match syn { + [_, Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }] => { + Ok(Definition::DefineVar(DefineVar { + name: ident.clone(), + val: Arc::new(Expression::parse(expr.clone(), env, cont).await?), + })) + } + [_, Syntax::List { list, span }, body @ .., Syntax::Null { .. }] => { + if body.is_empty() { + return Err(ParseAstError::EmptyBody(span.clone())); + } + match list.as_slice() { + [Syntax::Identifier { + ident: func_name, + span: func_span, + .. + }, args @ ..] => { + let mut bound = HashMap::::new(); + let mut new_env = env.lexical_contour.read().new_lexical_contour(); + let mut fixed = Vec::new(); - splice_in(&mut defs, &mut exprs, body, env, cont, span).await?; + // Bind the arguments to a new environment: + for arg in &args[..args.len() - 1] { + match arg { + Syntax::Identifier { ident, span, .. } => { + if let Some(prev_span) = bound.get(ident) { + return Err(ParseAstError::NameBoundMultipleTimes { + ident: ident.clone(), + first: prev_span.clone(), + second: span.clone(), + }); + } + new_env.def_local_var(&ident, Gc::new(Value::Undefined)); + bound.insert(ident.clone(), span.clone()); + fixed.push(ident.clone()); + } + x => { + return Err(ParseAstError::ExpectedIdentifier(x.span().clone())) + } + } + } - let mut defs_parsed = Vec::new(); - let mut exprs_parsed = Vec::new(); + let args = if let Some(last) = args.last() { + match last { + Syntax::Null { .. } => { + Formals::FixedArgs(fixed.into_iter().collect()) + } + Syntax::Identifier { ident, span, .. } => { + if let Some(prev_span) = bound.get(ident) { + return Err(ParseAstError::NameBoundMultipleTimes { + ident: ident.clone(), + first: prev_span.clone(), + second: span.clone(), + }); + } + let remaining = ident.clone(); + new_env.def_local_var(&ident, Gc::new(Value::Undefined)); + bound.insert(remaining.clone(), span.clone()); + Formals::VarArgs { + fixed: fixed.into_iter().collect(), + remaining, + } + } + x => { + return Err(ParseAstError::ExpectedIdentifier(x.span().clone())) + } + } + } else { + // If there is no last argument, there are no arguments + Formals::FixedArgs(Vec::new()) + }; - for def in defs.into_iter() { - defs_parsed.push( - Definition::parse(&def.expanded, env, cont) - .await? - .wrap(def.expansion_envs), - ); - } + let new_env = env.new_lexical_contour(Gc::new(new_env)); - for expr in exprs.into_iter() { - exprs_parsed.push( - Expression::parse(&expr.expanded, env, cont) - .await? - .wrap(expr.expansion_envs), - ); - } + // Parse the body: + let body = Body::parse(body, &new_env, cont, func_span).await?; - Ok(Self::new(defs_parsed, exprs_parsed)) + Ok(Self::DefineFunc(DefineFunc { + name: func_name.clone(), + args, + body, + })) + } + _ => Err(ParseAstError::BadForm(span.clone())), + } + } + _ => Err(ParseAstError::BadForm(span.clone())), + } } } +impl Body { + /// Parse the body. body is expected to be a list of valid syntax objects, and should not include + /// _any_ nulls, including one at the end. + pub(super) fn parse<'a, 'b>( + body: &'a [Syntax], + env: &'a ExpansionEnv<'b>, + cont: &'a Option>, + span: &'a Span, + ) -> BoxFuture<'a, Result> + where + 'a: 'b, + { + Box::pin(async move { + let mut defs = Vec::::new(); + let mut exprs = Vec::::new(); + + splice_in(&mut defs, &mut exprs, body, env, cont, span).await?; + + let mut defs_parsed = Vec::new(); + let mut exprs_parsed = Vec::new(); + + for def in defs.into_iter() { + let new_expansion_env = env.new_expansion_env(def.expansion_envs); + defs_parsed.push( + Definition::parse( + def.expanded.as_list().unwrap(), + &new_expansion_env, + cont, + def.expanded.span(), + ) + .await?, + ); + } -fn splice_in<'a>( - defs: &'a mut Vec>, - exprs: &'a mut Vec>, + for expr in exprs.into_iter() { + let new_expansion_env = env.new_expansion_env(expr.expansion_envs); + exprs_parsed.push( + Expression::parse_expanded(expr.expanded, &new_expansion_env, cont).await?, + ); + } + + Ok(Self::new(defs_parsed, exprs_parsed)) + }) + } + + /// Differs from Body by being purely expression based. No definitions allowed. + pub(super) async fn parse_in_expr_context( + body: &[Syntax], + env: &ExpansionEnv<'_>, + cont: &Option>, + ) -> Result { + let mut forms = Vec::new(); + for sexpr in body { + let parsed = AstNode::Expression(Expression::parse(sexpr.clone(), env, cont).await?); + forms.push(parsed); + } + let forms = ArcSlice::from(forms); + Ok(Self { forms }) + } +} + +fn splice_in<'a, 'b>( + defs: &'a mut Vec, + exprs: &'a mut Vec, body: &'a [Syntax], - env: &'a Env, + env: &'a ExpansionEnv<'b>, cont: &'a Option>, span: &'a Span, ) -> BoxFuture<'a, Result<(), ParseAstError>> +where + 'a: 'b, { Box::pin(async move { if body.len() == 0 { @@ -103,14 +223,10 @@ fn splice_in<'a>( let mut expanded = Vec::new(); for unexpanded in body { - expanded.push(unexpanded.expand(env, cont).await?); + expanded.push(unexpanded.clone().expand(env, cont).await?); } for expanded in expanded.into_iter() { - /* - let mut is_def; - (defs, exprs, is_def) = body1(defs, exprs, expanded - */ let is_def = { match expanded.as_ref().as_list() { Some([Syntax::Identifier { ident, .. }, body @ .., Syntax::Null { .. }]) @@ -122,7 +238,7 @@ fn splice_in<'a>( Some([Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }]) if ident == "define-syntax" => { - define_syntax(ident, expr, env, cont).await?; + define_syntax(ident, expr.clone(), &env.lexical_contour, cont).await?; continue; } Some( @@ -138,7 +254,9 @@ fn splice_in<'a>( .as_ident() .ok_or(ParseAstError::BadForm(def.span().clone()))?, }; - env.def_var(ident, Gc::new(Value::Undefined)); + env.lexical_contour + .write() + .def_local_var(ident, Gc::new(Value::Undefined)); true } _ => false, @@ -146,9 +264,9 @@ fn splice_in<'a>( }; if is_def { - defs.push(expanded.to_owned()); + defs.push(expanded); } else { - exprs.push(expanded.to_owned()); + exprs.push(expanded); } } @@ -156,107 +274,305 @@ fn splice_in<'a>( }) } -async fn define_syntax( +pub(super) async fn define_syntax( ident: &Identifier, - expr: &Syntax, - env: &Env, + expr: Syntax, + env: &Gc, cont: &Option>, ) -> Result<(), ParseAstError> { - env.def_macro( - ident, - Expression::parse(expr, env, cont) - .await? - .eval(cont) - .await? - .require_one()?, - ); + let expansion_env = ExpansionEnv::from_env(env); + let FullyExpanded { + expanded, + expansion_envs, + } = expr.expand(&expansion_env, cont).await?; + let expansion_env = expansion_env.new_expansion_env(expansion_envs); + let value = Expression::parse(expanded, &expansion_env, cont) + .await? + .eval(env, cont) + .await? + .require_one()?; + env.write().def_local_macro(ident, value); Ok(()) } -/* -#[async_trait] -impl Parse for ast::Body { - type Error = ParseBodyError; +impl Expression { + pub(crate) async fn parse( + syn: Syntax, + env: &ExpansionEnv<'_>, + cont: &Option>, + ) -> Result { + let FullyExpanded { + expanded, + expansion_envs, + } = syn.expand(&env, cont).await?; + let expansion_env = env.new_expansion_env(expansion_envs); + Self::parse_expanded(expanded, &expansion_env, cont).await + } - async fn compile( - exprs: &[Syntax], - env: &Env, + fn parse_expanded<'a, 'b>( + syn: Syntax, + env: &'a ExpansionEnv<'b>, + cont: &'a Option>, + ) -> BoxFuture<'a, Result> + where + 'a: 'b, + { + Box::pin(async move { + match syn { + Syntax::Null { span } => Err(ParseAstError::UnexpectedEmptyList(span)), + + // Special Identifiers: + Syntax::Identifier { ident, .. } if ident.name == "" => { + Ok(Self::Undefined) + } + + // Regular identifiers: + Syntax::Identifier { ident, .. } => Ok(Self::Var(env.fetch_var_ref(&ident))), + + // Literals: + Syntax::Literal { literal, .. } => Ok(Self::Literal(literal)), + + // Vector literals: + Syntax::Vector { vector, .. } => Ok(Self::Vector(Vector::parse(&vector))), + + // Functional forms: + Syntax::List { list: exprs, span, .. } => match exprs.as_slice() { + // Special forms: + [Syntax::Identifier { ident, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "begin" => + { + Body::parse_in_expr_context(tail, env, cont) + .await + .map(Expression::Begin) + } + [Syntax::Identifier { ident, span, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "lambda" => + { + Lambda::parse(tail, env, cont, span) + .await + .map(Expression::Lambda) + } + [Syntax::Identifier { ident, span, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "let" => + { + Let::parse(tail, env, cont, span).await.map(Expression::Let) + } + [Syntax::Identifier { ident, span, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "if" => + { + If::parse(tail, env, cont, span).await.map(Expression::If) + } + [Syntax::Identifier { ident, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "and" => + { + And::parse(tail, env, cont).await.map(Expression::And) + } + [Syntax::Identifier { ident, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "or" => + { + Or::parse(tail, env, cont).await.map(Expression::Or) + } + [Syntax::Identifier { ident, span, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "quote" => + { + Quote::parse(tail, span).await.map(Expression::Quote) + } + [Syntax::Identifier { ident, span, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "syntax-quote" => + { + SyntaxQuote::parse(tail, span).await.map(Expression::SyntaxQuote) + } + [Syntax::Identifier { ident, span, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "syntax-case" => + { + SyntaxCase::parse(tail, env, cont, span).await.map(Expression::SyntaxCase) + } + + // Extra special form (set!): + [Syntax::Identifier { ident, span, .. }, tail @ .., Syntax::Null { .. }] + if ident.name == "set!" => + { + Set::parse(tail, env, cont, span).await.map(Expression::Set) + } + + // Definition in expression context is illegal: + [Syntax::Identifier { ident, span, .. }, .., Syntax::Null { .. }] + if ident.name == "define" => + { + return Err(ParseAstError::DefInExprContext(span.clone())); + } + + // Regular old function call: + [operator, args @ .., Syntax::Null { .. }] => { + Call::parse(operator.clone(), args, env, cont).await.map(Expression::Call) + } + + _ => return Err(ParseAstError::BadForm(span.clone())), + }, + } + }) + } +} + +impl Call { + async fn parse( + operator: Syntax, + args: &[Syntax], + env: &ExpansionEnv<'_>, cont: &Option>, - span: &Span, - ) -> Result { - if exprs.is_empty() { - return Err(ParseBodyError::EmptyBody(span.clone())); - } - let mut output = Vec::new(); - for expr in &exprs[..exprs.len() - 1] { - output.push(expr.compile(env, cont).await?); + ) -> Result { + let location = operator.span().clone(); + let proc_name = match operator { + Syntax::Identifier { ref ident, .. } => ident.name.clone(), + _ => String::from(""), + }; + let operator = Expression::parse(operator, env, cont).await?; + let mut compiled_args = vec![operator]; + for arg in args { + compiled_args.push(Expression::parse(arg.clone(), env, cont).await?); } - // TODO: what if the body isn't a proper list? - Ok(ast::Body::new(output)) + Ok(Call { + args: ArcSlice::from(compiled_args), + location, + proc_name, + }) } } -#[derive(Debug, Clone)] -pub enum ParseLetError { - BadForm(Span), - ParseBodyError(ParseBodyError), - ParseLetBindingError(ParseLetBindingError), +impl Lambda { + async fn parse( + sexprs: &[Syntax], + env: &ExpansionEnv<'_>, + cont: &Option>, + span: &Span, + ) -> Result { + match sexprs { + [Syntax::Null { .. }, body @ ..] => parse_lambda(&[], body, env, cont, span).await, + [Syntax::List { list: args, .. }, body @ ..] => { + parse_lambda(args, body, env, cont, span).await + } + [ident @ Syntax::Identifier { .. }, body @ ..] => { + let args = &[ident.clone()]; + parse_lambda(args, body, env, cont, span).await + } + _ => Err(ParseAstError::BadForm(span.clone())), + } + } } -#[async_trait] -impl Parse for ast::Let { - type Error = ParseLetError; +async fn parse_lambda( + args: &[Syntax], + body: &[Syntax], + env: &ExpansionEnv<'_>, + cont: &Option>, + span: &Span, +) -> Result { + let mut bound = HashMap::::new(); + let mut fixed = Vec::new(); + let mut new_contour = env.lexical_contour.read().new_lexical_contour(); + + if !args.is_empty() { + for arg in &args[..args.len() - 1] { + match arg { + Syntax::Identifier { ident, span, .. } => { + if let Some(prev_span) = bound.get(ident) { + return Err(ParseAstError::NameBoundMultipleTimes { + ident: ident.clone(), + first: prev_span.clone(), + second: span.clone(), + }); + } + new_contour.def_local_var(&ident, Gc::new(Value::Undefined)); + bound.insert(ident.clone(), span.clone()); + fixed.push(ident.clone()); + } + x => return Err(ParseAstError::ExpectedIdentifier(x.span().clone())), + } + } + } + + let args = if let Some(last) = args.last() { + match last { + Syntax::Null { .. } => Formals::FixedArgs(fixed.into_iter().collect()), + Syntax::Identifier { ident, span, .. } => { + if let Some(prev_span) = bound.get(ident) { + return Err(ParseAstError::NameBoundMultipleTimes { + ident: ident.clone(), + first: prev_span.clone(), + second: span.clone(), + }); + } + new_contour.def_local_var(&ident, Gc::new(Value::Undefined)); + let remaining = ident.clone(); + Formals::VarArgs { + fixed: fixed.into_iter().collect(), + remaining, + } + } + x => return Err(ParseAstError::ExpectedIdentifier(x.span().clone())), + } + } else { + // If there is no last argument, there are no arguments + Formals::FixedArgs(Vec::new()) + }; - async fn compile( - expr: &[Syntax], - env: &Env, + let new_env = env.new_lexical_contour(Gc::new(new_contour)); + let body = Body::parse(body, &new_env, cont, span).await?; + + Ok(Lambda { args, body }) +} + +impl Let { + async fn parse( + syn: &[Syntax], + env: &ExpansionEnv<'_>, cont: &Option>, span: &Span, - ) -> Result { - match expr { - [Syntax::Null { .. }, body @ ..] => compile_let(None, &[], body, env, cont, span).await, + ) -> Result { + match syn { + [Syntax::Null { .. }, body @ ..] => parse_let(None, &[], body, env, cont, span).await, [Syntax::List { list: bindings, .. }, body @ ..] => { - compile_let(None, bindings, body, env, cont, span).await + parse_let(None, bindings, body, env, cont, span).await } // Named let: [Syntax::Identifier { ident, .. }, Syntax::List { list: bindings, .. }, body @ ..] => { - compile_let(Some(ident), bindings, body, env, cont, span).await + parse_let(Some(ident), bindings, body, env, cont, span).await } [Syntax::Identifier { ident, .. }, Syntax::Null { .. }, body @ ..] => { - compile_let(Some(ident), &[], body, env, cont, span).await + parse_let(Some(ident), &[], body, env, cont, span).await } - _ => Err(ParseLetError::BadForm(span.clone())), + _ => Err(ParseAstError::BadForm(span.clone())), } } } -async fn compile_let( +async fn parse_let( name: Option<&Identifier>, bindings: &[Syntax], body: &[Syntax], - env: &Env, + env: &ExpansionEnv<'_>, cont: &Option>, span: &Span, -) -> Result { +) -> Result { let mut previously_bound = HashMap::new(); - let mut new_contour = env.new_lexical_contour(); + let mut new_contour = env.lexical_contour.read().new_lexical_contour(); let mut compiled_bindings = Vec::new(); - // TODO: Check that the list of bindings is proper - if !bindings.is_empty() { - for binding in &bindings[..bindings.len() - 1] { - let binding = LetBinding::compile(binding, env, cont, &previously_bound) - .await - .map_err(ParseLetError::ParseLetBindingError)?; - previously_bound.insert(binding.ident.clone(), binding.span.clone()); - new_contour.def_var(&binding.ident, Gc::new(Value::Undefined)); - compiled_bindings.push(binding); + + match bindings { + [Syntax::Null { .. }] => (), + [bindings @ .., Syntax::Null { .. }] => { + for binding in bindings { + let binding = LetBinding::parse(binding, env, cont, &previously_bound).await?; + previously_bound.insert(binding.ident.clone(), binding.span.clone()); + new_contour.def_local_var(&binding.ident, Gc::new(Value::Undefined)); + compiled_bindings.push(binding); + } } + _ => return Err(ParseAstError::BadForm(span.clone())), } - let env = Gc::new(new_contour); - let body = ast::Body::compile(body, &Env::from(env.clone()), cont, span) - .await - .map_err(ParseLetError::ParseBodyError)?; + let new_env = env.new_lexical_contour(Gc::new(new_contour)); + let body = Body::parse(body, &new_env, cont, span).await?; let mut bindings: Vec<_> = compiled_bindings .into_iter() @@ -264,585 +580,184 @@ async fn compile_let( .collect(); // If this is a named let, add a binding for a procedure with the same - // body and args of the formals: + // body and args of the formals. if let Some(name) = name { - let lambda = ast::Lambda { - args: ast::Formals::FixedArgs( - bindings.iter().map(|(ident, _)| ident.clone()).collect(), - ), + let lambda = Lambda { + args: Formals::FixedArgs(bindings.iter().map(|(ident, _)| ident.clone()).collect()), body: body.clone(), }; - bindings.push((name.clone(), Arc::new(lambda))); + bindings.push((name.clone(), Expression::Lambda(lambda))); } - Ok(ast::Let { + Ok(Let { bindings: Arc::from(bindings), body, }) } -#[derive(Debug, Clone)] -pub enum ParseLetBindingError { - BadForm(Span), - PreviouslyBound { - ident: Identifier, - first: Span, - second: Span, - }, - NotAList(Span), - ParseError(Box), -} - -impl_from_parse_error!(ParseLetBindingError); - struct LetBinding { ident: Identifier, span: Span, - expr: Arc, + expr: Expression, } impl LetBinding { - async fn compile( - expr: &Syntax, - env: &Env, + async fn parse( + form: &Syntax, + env: &ExpansionEnv<'_>, cont: &Option>, previously_bound: &HashMap, - ) -> Result { - match expr { - Syntax::List { list, span } => match &list[..] { - [Syntax::Identifier { - ident, - span: bind_span, - .. - }, expr, Syntax::Null { .. }] => { - if let Some(prev_bind) = previously_bound.get(ident) { - return Err(ParseLetBindingError::PreviouslyBound { - ident: ident.clone(), - first: prev_bind.clone(), - second: bind_span.clone(), - }); - } - - let expr = expr.compile(env, cont).await?; - - Ok(LetBinding { - ident: ident.clone(), - span: bind_span.clone(), - expr, - }) - } - _ => Err(ParseLetBindingError::BadForm(span.clone())), - }, - expr => Err(ParseLetBindingError::NotAList(expr.span().clone())), - } - } -} - -#[derive(From, Debug, Clone)] -pub enum ParseFuncCallError { - EmptyFunctionCall(Span), - ParseError(Box), -} - -impl_from_parse_error!(ParseFuncCallError); + ) -> Result { + if let Some( + [Syntax::Identifier { + ident, + span: bind_span, + .. + }, expr, Syntax::Null { .. }], + ) = form.as_list() + { + if let Some(prev_bind) = previously_bound.get(ident) { + return Err(ParseAstError::NameBoundMultipleTimes { + ident: ident.clone(), + first: prev_bind.clone(), + second: bind_span.clone(), + }); + } -#[async_trait] -impl Parse for ast::Call { - type Error = ParseFuncCallError; + let expr = Expression::parse(expr.clone(), env, cont).await?; - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result { - match exprs { - [operator, args @ ..] => { - // TODO: Support macro expansions in the call position that eventually - // resolve into an identifier, that is a macro (or function) - let proc_name = match operator { - Syntax::Identifier { ident, .. } => ident.name.clone(), - _ => String::from(""), - }; - let operator = operator.compile(env, cont).await?; - let mut compiled_args = vec![operator]; - for arg in &args[..args.len() - 1] { - compiled_args.push(arg.compile(env, cont).await?); - } - // TODO: what if it's not a proper list? - Ok(ast::Call { - // operator, - args: ArcSlice::from(compiled_args), - location: span.clone(), - proc_name, - }) - } - [] => Err(ParseFuncCallError::EmptyFunctionCall(span.clone())), + Ok(LetBinding { + ident: ident.clone(), + span: bind_span.clone(), + expr, + }) + } else { + Err(ParseAstError::BadForm(form.span().clone())) } } } -#[derive(Debug, Clone)] -pub enum ParseIfError { - ExpectedConditional(Span), - ExpectedArgumentAfterConditional(Span), - UnexpectedArgument(Span), - ParseError(Box), -} - -impl_from_parse_error!(ParseIfError); - -#[async_trait] -impl Parse for ast::If { - type Error = ParseIfError; - - async fn compile( +impl If { + async fn parse( exprs: &[Syntax], - env: &Env, + env: &ExpansionEnv<'_>, cont: &Option>, span: &Span, - ) -> Result { + ) -> Result { match exprs { - [cond, success, Syntax::Null { .. }] => Ok(ast::If { - cond: cond.compile(env, cont).await?, - success: success.compile(env, cont).await?, + [cond, success] => Ok(If { + cond: Arc::new(Expression::parse(cond.clone(), env, cont).await?), + success: Arc::new(Expression::parse(success.clone(), env, cont).await?), failure: None, }), - [cond, success, failure, Syntax::Null { .. }] => Ok(ast::If { - cond: cond.compile(env, cont).await?, - success: success.compile(env, cont).await?, - failure: Some(failure.compile(env, cont).await?), + [cond, success, failure] => Ok(If { + cond: Arc::new(Expression::parse(cond.clone(), env, cont).await?), + success: Arc::new(Expression::parse(success.clone(), env, cont).await?), + failure: Some(Arc::new( + Expression::parse(failure.clone(), env, cont).await?, + )), }), - [] => Err(ParseIfError::ExpectedConditional(span.clone())), - [a1] => Err(ParseIfError::ExpectedArgumentAfterConditional( - a1.span().clone(), - )), - [_, _, _, unexpected, ..] => Err(ParseIfError::UnexpectedArgument( - unexpected.span().clone(), - )), - _ => unreachable!(), - } - } -} - -#[derive(Debug, Clone)] -pub enum ParseDefineError { - ParameterDefinedMultipleTimes { - ident: Identifier, - first: Span, - second: Span, - }, - ExpectedIdentifier(Span), - ParseBodyError(ParseBodyError), - BadForm(Span), - ParseError(Box), -} - -impl_from_parse_error!(ParseDefineError); - -#[async_trait] -impl Parse for ast::Define { - type Error = ParseDefineError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result { - match exprs { - [Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }] => { - Ok(ast::Define::DefineVar(ast::DefineVar { - name: ident.clone(), - val: expr.compile(env, cont).await?, - })) + [] => Err(ParseAstError::ExpectedArgument(span.clone())), + [a1] => Err(ParseAstError::ExpectedArgument(a1.span().clone())), + [_, _, _, unexpected, ..] => { + Err(ParseAstError::UnexpectedArgument(unexpected.span().clone())) } - [Syntax::List { list, span }, body @ ..] => { - match &list[..] { - [] => Err(ParseDefineError::ExpectedIdentifier(span.clone())), - [Syntax::Identifier { - ident: func_name, - span: func_span, - .. - }, args @ ..] => { - let mut bound = HashMap::::new(); - let mut fixed = Vec::new(); - for arg in &args[..args.len() - 1] { - match arg { - Syntax::Identifier { ident, span, .. } => { - if let Some(prev_span) = bound.get(ident) { - return Err( - ParseDefineError::ParameterDefinedMultipleTimes { - ident: ident.clone(), - first: prev_span.clone(), - second: span.clone(), - }, - ); - } - bound.insert(ident.clone(), span.clone()); - fixed.push(ident.clone()); - } - x => { - return Err(ParseDefineError::ExpectedIdentifier( - x.span().clone(), - )) - } - } - } - - let args = if let Some(last) = args.last() { - match last { - Syntax::Null { .. } => { - ast::Formals::FixedArgs(fixed.into_iter().collect()) - } - Syntax::Identifier { ident, span, .. } => { - if let Some(prev_span) = bound.get(ident) { - return Err( - ParseDefineError::ParameterDefinedMultipleTimes { - ident: ident.clone(), - first: prev_span.clone(), - second: span.clone(), - }, - ); - } - let remaining = ident.clone(); - ast::Formals::VarArgs { - fixed: fixed.into_iter().collect(), - remaining, - } - } - x => { - return Err(ParseDefineError::ExpectedIdentifier( - x.span().clone(), - )) - } - } - } else { - // If there is no last argument, there are no arguments - ast::Formals::FixedArgs(Vec::new()) - }; - let body = ast::Body::compile(body, env, cont, func_span) - .await - .map_err(ParseDefineError::ParseBodyError)?; - Ok(ast::Define::DefineFunc(ast::DefineFunc { - name: func_name.clone(), - args, - body, - })) - } - [x, ..] => Err(ParseDefineError::BadForm(x.span().clone())), - } - } - _ => Err(ParseDefineError::BadForm(span.clone())), } } } -#[derive(Debug, Clone)] -pub enum ParseDefineSyntaxError { - BadForm(Span), - ParseError(Box), - RuntimeError(Box), -} - -impl_from_parse_error!(ParseDefineSyntaxError); - -impl From for ParseDefineSyntaxError { - fn from(value: RuntimeError) -> Self { - Self::RuntimeError(Box::new(value)) - } -} - -#[async_trait] -impl Parse for ast::DefineSyntax { - type Error = ParseDefineSyntaxError; - - async fn compile( - expr: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result { - match expr { - [Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }] => { - env.def_macro( - ident, - expr.compile(env, cont) - .await? - .eval(env, cont) - .await? - .require_one()?, - ); - Ok(ast::DefineSyntax) - } - _ => Err(ParseDefineSyntaxError::BadForm(span.clone())), - } - } -} - -#[derive(Debug, Clone)] -pub enum ParseQuoteError { - ExpectedArgument(Span), - UnexpectedArgument(Span), - BadForm(Span), -} - -#[async_trait] -impl Parse for ast::Quote { - type Error = ParseQuoteError; - - async fn compile( - exprs: &[Syntax], - _env: &Env, - _cont: &Option>, - span: &Span, - ) -> Result { - match exprs { - [] => Err(ParseQuoteError::ExpectedArgument(span.clone())), - [Syntax::Null { .. }] => Ok(ast::Quote { val: Value::Null }), - [expr, Syntax::Null { .. }] => Ok(ast::Quote { - val: Value::from_syntax(expr), - }), - [_, arg, ..] => Err(ParseQuoteError::UnexpectedArgument(arg.span().clone())), - _ => Err(ParseQuoteError::BadForm(span.clone())), - } - } -} - -#[async_trait] -impl Parse for ast::And { - type Error = ParseError; - - async fn compile( +impl And { + async fn parse( exprs: &[Syntax], - env: &Env, + env: &ExpansionEnv<'_>, cont: &Option>, - _span: &Span, - ) -> Result { + ) -> Result { let mut output = Vec::new(); - // TODO: what if the arguments aren't a proper list? - for expr in &exprs[..exprs.len() - 1] { - let expr = expr.compile(env, cont).await?; + for expr in exprs { + let expr = Expression::parse(expr.clone(), env, cont).await?; output.push(expr); } Ok(Self::new(output)) } } -#[async_trait] -impl Parse for ast::Or { - type Error = ParseError; - - async fn compile( +impl Or { + async fn parse( exprs: &[Syntax], - env: &Env, + env: &ExpansionEnv<'_>, cont: &Option>, - _span: &Span, - ) -> Result { + ) -> Result { let mut output = Vec::new(); - // TODO: what if the arguments aren't a proper list? - for expr in &exprs[..exprs.len() - 1] { - let expr = expr.compile(env, cont).await?; + for expr in exprs { + let expr = Expression::parse(expr.clone(), env, cont).await?; output.push(expr); } Ok(Self::new(output)) } } -#[derive(Debug, Clone)] -pub enum ParseSetError { - ExpectedArgument(Span), - ExpectedIdent(Span), - UnexpectedArgument(Span), - BadForm(Span), - ParseError(Box), -} - -impl_from_parse_error!(ParseSetError); - -#[async_trait] -impl Parse for ast::Set { - type Error = ParseSetError; - - async fn compile( +impl Set { + async fn parse( exprs: &[Syntax], - env: &Env, + env: &ExpansionEnv<'_>, cont: &Option>, span: &Span, - ) -> Result { - // TODO: We need to check if the identifier is defined as a variable transformer + ) -> Result { match exprs { - [] => Err(ParseSetError::ExpectedArgument(span.clone())), - [Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }] => Ok(ast::Set { - var: ident.clone(), - val: expr.compile(env, cont).await?, + [] => Err(ParseAstError::ExpectedArgument(span.clone())), + [Syntax::Identifier { ident, .. }, expr] => Ok(Set { + var: env.fetch_var_ref(ident), + val: Arc::new(Expression::parse(expr.clone(), env, cont).await?), }), - [arg1, _, Syntax::Null { .. }] => { - Err(ParseSetError::ExpectedIdent(arg1.span().clone())) - } - [_, _, arg3, ..] => Err(ParseSetError::UnexpectedArgument(arg3.span().clone())), - _ => Err(ParseSetError::BadForm(span.clone())), + [arg1, _] => Err(ParseAstError::ExpectedIdentifier(arg1.span().clone())), + [_, _, arg3, ..] => Err(ParseAstError::UnexpectedArgument(arg3.span().clone())), + _ => Err(ParseAstError::BadForm(span.clone())), } } } -#[derive(Debug, Clone)] -pub enum ParseSyntaxError { - ExpectedArgument(Span), - UnexpectedArgument(Span), - BadForm(Span), -} - -#[async_trait] -impl Parse for ast::SyntaxQuote { - type Error = ParseSyntaxError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - _cont: &Option>, - span: &Span, - ) -> Result { +impl Quote { + async fn parse(exprs: &[Syntax], span: &Span) -> Result { match exprs { - [] => Err(ParseSyntaxError::ExpectedArgument(span.clone())), - [expr, Syntax::Null { .. }] => Ok(ast::SyntaxQuote { - syn: expr.clone(), - env: env.clone(), + [] => Err(ParseAstError::ExpectedArgument(span.clone())), + [expr] => Ok(Quote { + val: Value::from_syntax(expr), }), - [_, arg, ..] => Err(ParseSyntaxError::UnexpectedArgument(arg.span().clone())), - _ => Err(ParseSyntaxError::BadForm(span.clone())), + [_, arg, ..] => Err(ParseAstError::UnexpectedArgument(arg.span().clone())), } } } -#[derive(Debug, Clone)] -pub enum ParseLambdaError { - ExpectedList(Span), - ExpectedIdentifier(Span), - ParseBodyError(ParseBodyError), - ParameterDefinedMultipleTimes { - ident: Identifier, - first: Span, - second: Span, - }, -} - -#[async_trait] -impl Parse for ast::Lambda { - type Error = ParseLambdaError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result { - match exprs { - [Syntax::Null { .. }, body @ ..] => compile_lambda(&[], body, env, cont, span).await, - [Syntax::List { list: args, .. }, body @ ..] => { - compile_lambda(args, body, env, cont, span).await - } - [Syntax::Identifier { ident, .. }, body @ ..] => { - let mut env = env.new_lexical_contour(); - env.def_var(ident, Gc::new(Value::Undefined)); - - let body = ast::Body::compile(body, &Env::from(Gc::new(env)), cont, span) - .await - .map_err(ParseLambdaError::ParseBodyError)?; - - Ok(ast::Lambda { - args: ast::Formals::VarArgs { - fixed: Vec::new(), - remaining: ident.clone(), - }, - body, - }) - } - _ => todo!(), +impl Vector { + fn parse(exprs: &[Syntax]) -> Self { + let mut vals = Vec::new(); + for expr in exprs { + vals.push(Value::from_syntax(expr)); } + Self { vals } } } -async fn compile_lambda( - args: &[Syntax], - body: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, -) -> Result { - let mut bound = HashMap::::new(); - let mut fixed = Vec::new(); - if !args.is_empty() { - for arg in &args[..args.len() - 1] { - match arg { - Syntax::Identifier { ident, span, .. } => { - if let Some(prev_span) = bound.get(ident) { - return Err(ParseLambdaError::ParameterDefinedMultipleTimes { - ident: ident.clone(), - first: prev_span.clone(), - second: span.clone(), - }); - } - bound.insert(ident.clone(), span.clone()); - fixed.push(ident.clone()); - } - x => return Err(ParseLambdaError::ExpectedIdentifier(x.span().clone())), - } - } - } - let args = if let Some(last) = args.last() { - match last { - Syntax::Null { .. } => ast::Formals::FixedArgs(fixed.into_iter().collect()), - Syntax::Identifier { ident, span, .. } => { - if let Some(prev_span) = bound.get(ident) { - return Err(ParseLambdaError::ParameterDefinedMultipleTimes { - ident: ident.clone(), - first: prev_span.clone(), - second: span.clone(), - }); - } - let remaining = ident.clone(); - ast::Formals::VarArgs { - fixed: fixed.into_iter().collect(), - remaining, - } - } - x => return Err(ParseLambdaError::ExpectedIdentifier(x.span().clone())), - } - } else { - // If there is no last argument, there are no arguments - ast::Formals::FixedArgs(Vec::new()) - }; - let mut env = env.new_lexical_contour(); - for bound in bound.into_keys() { - env.def_var(&bound, Gc::new(Value::Undefined)); +impl SyntaxQuote { + async fn parse(exprs: &[Syntax], span: &Span) -> Result { + match exprs { + [] => Err(ParseAstError::ExpectedArgument(span.clone())), + [expr] => Ok(SyntaxQuote { + syn: expr.clone(), + }), + [_, arg, ..] => Err(ParseAstError::UnexpectedArgument(arg.span().clone())), + } } - - let body = ast::Body::compile(body, &Env::from(Gc::new(env)), cont, span) - .await - .map_err(ParseLambdaError::ParseBodyError)?; - Ok(ast::Lambda { args, body }) } -#[derive(Debug, Clone)] -pub enum ParseSyntaxCaseError { - ParseError(Box), - BadForm(Span), -} - -impl_from_parse_error!(ParseSyntaxCaseError); - -#[async_trait] -impl Parse for ast::SyntaxCase { - type Error = ParseSyntaxCaseError; - - async fn compile( +impl SyntaxCase { + async fn parse( exprs: &[Syntax], - env: &Env, + env: &ExpansionEnv<'_>, cont: &Option>, span: &Span, - ) -> Result { + ) -> Result { let (arg, keywords, mut rules) = match exprs { [arg, Syntax::List { list, .. }, rules @ ..] => { let mut keywords = HashSet::default(); @@ -851,30 +766,30 @@ impl Parse for ast::SyntaxCase { if let Syntax::Identifier { ident, .. } = keyword { keywords.insert(ident.name.clone()); } else { - return Err(ParseSyntaxCaseError::BadForm(keyword.span().clone())); + return Err(ParseAstError::BadForm(keyword.span().clone())); } } (arg, keywords, rules) } [arg, Syntax::Null { .. }, rules @ ..] => (arg, HashSet::default(), rules), - _ => return Err(ParseSyntaxCaseError::BadForm(span.clone())), + _ => return Err(ParseAstError::BadForm(span.clone())), }; let mut syntax_rules = Vec::new(); loop { match rules { - [Syntax::Null { .. }] => break, + [] => break, [Syntax::List { list, .. }, tail @ ..] => match &list[..] { [pattern, template, Syntax::Null { .. }] => { syntax_rules.push(SyntaxRule::compile(&keywords, pattern, template)); rules = tail; } - _ => return Err(ParseSyntaxCaseError::BadForm(span.clone())), + _ => return Err(ParseAstError::BadForm(span.clone())), }, - _ => return Err(ParseSyntaxCaseError::BadForm(span.clone())), + _ => return Err(ParseAstError::BadForm(span.clone())), } } - Ok(ast::SyntaxCase { - arg: arg.compile(env, cont).await?, + Ok(SyntaxCase { + arg: Arc::new(Expression::parse(arg.clone(), env, cont).await?), transformer: Transformer { rules: syntax_rules, is_variable_transformer: false, @@ -882,5 +797,3 @@ impl Parse for ast::SyntaxCase { }) } } - -*/ diff --git a/src/builtin.rs b/src/builtin.rs index d62ce91..c9e702e 100644 --- a/src/builtin.rs +++ b/src/builtin.rs @@ -1,6 +1,5 @@ use crate::{ - continuation::Continuation, env::LexicalContour, error::RuntimeError, - proc::ValuesOrPreparedCall, gc::Gc, proc::ExternalFn, syntax::Identifier, value::Value, + continuation::Continuation, env::Env, error::RuntimeError, gc::Gc, proc::{ExternalFn, ValuesOrPreparedCall}, syntax::Identifier, value::Value }; use futures::future::BoxFuture; use std::sync::Arc; @@ -29,8 +28,8 @@ impl Builtin { } } - pub fn install(&self, into: &mut LexicalContour) { - into.def_var( + pub fn install(&self, into: &mut Env) { + into.def_local_var( &Identifier::new(self.name.to_string()), Gc::new(Value::from(ExternalFn { name: self.name, diff --git a/src/continuation.rs b/src/continuation.rs index f996f13..809acf6 100644 --- a/src/continuation.rs +++ b/src/continuation.rs @@ -2,8 +2,8 @@ use async_trait::async_trait; use proc_macros::builtin; use crate::{ - ast::{self, AstNode}, - env::{Env, LexicalContour}, + ast::{self, AstNode, Body, Expression}, + env::{Env, ExpansionEnv, Ref}, error::{RuntimeError, RuntimeErrorKind}, expand::Transformer, gc::{Gc, Trace}, @@ -141,16 +141,54 @@ impl Eval for CatchContinuationCall { inner } } -*/ + */ + +#[derive(Trace)] +pub struct ResumableDefineVar { + env: Gc, + name: Identifier, +} + +impl ResumableDefineVar { + pub fn new(env: &Gc, name: &Identifier) -> Self { + Self { + env: env.clone(), + name: name.clone(), + } + } +} + +#[async_trait] +impl Resumable for ResumableDefineVar { + async fn resume( + &self, + args: Vec>, + _cont: &Option>, + ) -> Result>, RuntimeError> { + let arg = args.require_one()?; + self.env.write().def_local_var(&self.name, arg); + Ok(vec![]) + } + + fn clone_stack(&self) -> Arc { + /* + Arc::new(Self { + env: self.env.deep_clone(), + name: self.name.clone(), + }) + */ + todo!() + } +} #[derive(Trace)] pub struct ResumableBody { - env: Env, + env: Gc, remaining: ArcSlice, } impl ResumableBody { - pub fn new(env: &Env, remaining: &ArcSlice) -> Self { + pub fn new(env: &Gc, remaining: &ArcSlice) -> Self { Self { env: env.clone(), remaining: remaining.clone(), @@ -179,108 +217,135 @@ impl Resumable for ResumableBody { } fn clone_stack(&self) -> Arc { + /* Arc::new(Self { env: self.env.deep_clone(), remaining: self.remaining.clone(), }) + */ + todo!() } } -/* #[derive(Trace)] -pub struct ResumableSyntaxCase { - env: Env, - transformer: Transformer, +pub struct ResumableLet { + scope: Gc, + curr: Identifier, + remaining_bindings: ArcSlice<(Identifier, Expression)>, + body: Body, } -impl ResumableSyntaxCase { - pub fn new(env: &Env, transformer: &Transformer) -> Self { +impl ResumableLet { + pub fn new( + scope: &Gc, + curr: &Identifier, + remaining_bindings: ArcSlice<(Identifier, Expression)>, + body: &Body, + ) -> Self { Self { - env: env.clone(), - transformer: transformer.clone(), + scope: scope.clone(), + curr: curr.clone(), + remaining_bindings, + body: body.clone(), } } } #[async_trait] -impl Resumable for ResumableSyntaxCase { +impl Resumable for ResumableLet { async fn resume( &self, args: Vec>, cont: &Option>, ) -> Result>, RuntimeError> { let arg = args.require_one()?; - let transformed = { - let arg = arg.read(); - match &*arg { - Value::Syntax(syntax) => self.transformer.expand(syntax).unwrap(), - _ => todo!(), - } + let up = { + let mut scope = self.scope.write(); + scope.def_local_var(&self.curr, arg); + scope.up.as_ref().unwrap().clone() }; - transformed - .compile(&self.env, cont) - .await? - .eval(&self.env, cont) - .await + for ((ident, expr), remaining) in self.remaining_bindings.iter() { + let cont = Arc::new(Continuation::new( + Arc::new(ResumableLet::new(&self.scope, ident, remaining, &self.body)), + cont, + )); + let val = expr.eval(&up, &Some(cont)).await?.require_one()?; + self.scope.write().def_local_var(ident, val); + } + self.body.eval(&self.scope, cont).await } fn clone_stack(&self) -> Arc { + /* Arc::new(Self { - env: self.env.deep_clone(), - transformer: self.transformer.clone(), + scope: Gc::new(self.scope.read().deep_clone()), + curr: self.curr.clone(), + remaining_bindings: self.remaining_bindings.clone(), + body: self.body.clone(), }) + */ + todo!() } } #[derive(Trace)] -pub struct ResumableSet { - env: Env, - var: Identifier, +pub struct ResumableIf { + env: Gc, + success: Arc, + failure: Option>, } -impl ResumableSet { - pub fn new(env: &Env, var: &Identifier) -> Self { +impl ResumableIf { + pub fn new( + env: &Gc, + success: &Arc, + failure: &Option>, + ) -> Self { Self { env: env.clone(), - var: var.clone(), + success: success.clone(), + failure: failure.clone(), } } } #[async_trait] -impl Resumable for ResumableSet { +impl Resumable for ResumableIf { async fn resume( &self, args: Vec>, - _cont: &Option>, + cont: &Option>, ) -> Result>, RuntimeError> { - // TODO: Add try_unwrap to GC to avoid the clone of the inner value let arg = args.require_one()?; - let val = arg.read().clone(); - *self - .env - .fetch_var(&self.var) - .ok_or_else(|| RuntimeError::undefined_variable(self.var.clone()))? - .write() = val; - Ok(vec![Gc::new(Value::Null)]) + if arg.read().is_true() { + self.success.eval(&self.env, cont).await + } else if let Some(ref failure) = self.failure { + failure.eval(&self.env, cont).await + } else { + Ok(Vec::new()) + } } fn clone_stack(&self) -> Arc { + /* Arc::new(Self { env: self.env.deep_clone(), - var: self.var.clone(), + success: self.success.clone(), + failure: self.failure.clone(), }) + */ + todo!() } } #[derive(Trace)] pub struct ResumableAnd { - env: Env, - args: ArcSlice>, + env: Gc, + args: ArcSlice, } impl ResumableAnd { - pub fn new(env: &Env, args: &ArcSlice>) -> Self { + pub fn new(env: &Gc, args: &ArcSlice) -> Self { Self { env: env.clone(), args: args.clone(), @@ -323,21 +388,23 @@ impl Resumable for ResumableAnd { } fn clone_stack(&self) -> Arc { - Arc::new(Self { - env: self.env.deep_clone(), - args: self.args.clone(), - }) + /* + Arc::new(Self { + env: self.env.deep_clone(), + args: self.args.clone(), + })*/ + todo!() } } #[derive(Trace)] pub struct ResumableOr { - env: Env, - args: ArcSlice>, + env: Gc, + args: ArcSlice, } impl ResumableOr { - pub fn new(env: &Env, args: &ArcSlice>) -> Self { + pub fn new(env: &Gc, args: &ArcSlice) -> Self { Self { env: env.clone(), args: args.clone(), @@ -363,7 +430,7 @@ impl Resumable for ResumableOr { } for (arg, tail) in self.args.skip_last() { let cont = Arc::new(Continuation::new( - Arc::new(ResumableAnd::new(&self.env, &tail)), + Arc::new(ResumableOr::new(&self.env, &tail)), cont, )); if arg @@ -380,156 +447,111 @@ impl Resumable for ResumableOr { } fn clone_stack(&self) -> Arc { - Arc::new(Self { - env: self.env.deep_clone(), - args: self.args.clone(), - }) - } -} - -#[derive(Trace)] -pub struct ResumableLet { - scope: Gc, - curr: Identifier, - remaining_bindings: ArcSlice<(Identifier, Arc)>, - body: ast::Body, -} - -impl ResumableLet { - pub fn new( - scope: &Gc, - curr: &Identifier, - remaining_bindings: ArcSlice<(Identifier, Arc)>, - body: &ast::Body, - ) -> Self { - Self { - scope: scope.clone(), - curr: curr.clone(), - remaining_bindings, - body: body.clone(), - } - } -} - -#[async_trait] -impl Resumable for ResumableLet { - async fn resume( - &self, - args: Vec>, - cont: &Option>, - ) -> Result>, RuntimeError> { - let arg = args.require_one()?; - let up = { - let mut scope = self.scope.write(); - scope.def_var(&self.curr, arg); - scope.up.clone() - }; - for ((ident, expr), remaining) in self.remaining_bindings.iter() { - let cont = Arc::new(Continuation::new( - Arc::new(ResumableLet::new(&self.scope, ident, remaining, &self.body)), - cont, - )); - let val = expr.eval(&up, &Some(cont)).await?.require_one()?; - self.scope.write().def_var(ident, val); - } - self.body.eval(&Env::from(self.scope.clone()), cont).await - } - - fn clone_stack(&self) -> Arc { - Arc::new(Self { - scope: Gc::new(self.scope.read().deep_clone()), - curr: self.curr.clone(), - remaining_bindings: self.remaining_bindings.clone(), - body: self.body.clone(), + /* + Arc::new(Self { + env: self.env.deep_clone(), + args: self.args.clone(), }) + */ + todo!() } } #[derive(Trace)] -pub struct ResumableIf { - env: Env, - success: Arc, - failure: Option>, +pub struct ResumableSet { + env: Gc, + var: Ref, } -impl ResumableIf { - pub fn new(env: &Env, success: &Arc, failure: &Option>) -> Self { +impl ResumableSet { + pub fn new(env: &Gc, var: &Ref) -> Self { Self { env: env.clone(), - success: success.clone(), - failure: failure.clone(), + var: var.clone(), } } } #[async_trait] -impl Resumable for ResumableIf { +impl Resumable for ResumableSet { async fn resume( &self, args: Vec>, - cont: &Option>, + _cont: &Option>, ) -> Result>, RuntimeError> { let arg = args.require_one()?; - if arg.read().is_true() { - self.success.eval(&self.env, cont).await - } else if let Some(ref failure) = self.failure { - failure.eval(&self.env, cont).await - } else { - Ok(vec![Gc::new(Value::Null)]) - } + let val = arg.read().clone(); + self.var.set(&self.env, &Gc::new(val)); + Ok(Vec::new()) } fn clone_stack(&self) -> Arc { - Arc::new(Self { - env: self.env.deep_clone(), - success: self.success.clone(), - failure: self.failure.clone(), + /* + Arc::new(Self { + env: self.env.deep_clone(), + var: self.var.clone(), }) + */ + todo!() } } #[derive(Trace)] -pub struct ResumableDefineVar { - env: Env, - name: Identifier, +pub struct ResumableSyntaxCase { + env: Gc, + transformer: Transformer, } -impl ResumableDefineVar { - pub fn new(env: &Env, name: &Identifier) -> Self { +impl ResumableSyntaxCase { + pub fn new(env: &Gc, transformer: &Transformer) -> Self { Self { env: env.clone(), - name: name.clone(), + transformer: transformer.clone(), } } } #[async_trait] -impl Resumable for ResumableDefineVar { +impl Resumable for ResumableSyntaxCase { async fn resume( &self, args: Vec>, - _cont: &Option>, + cont: &Option>, ) -> Result>, RuntimeError> { let arg = args.require_one()?; - self.env.def_var(&self.name, arg); - Ok(vec![Gc::new(Value::Null)]) + let transformed = { + let arg = arg.read(); + match &*arg { + Value::Syntax(syntax) => self.transformer.expand(syntax).unwrap(), + _ => todo!(), + } + }; + let expansion_env = ExpansionEnv::from_env(&self.env); + Expression::parse(transformed, &expansion_env, cont) + .await + .expect("fixme") + .eval(&self.env, cont) + .await } fn clone_stack(&self) -> Arc { + /* Arc::new(Self { env: self.env.deep_clone(), - name: self.name.clone(), + transformer: self.transformer.clone(), }) + */ + todo!() } } #[derive(Trace)] pub struct ResumableCall { - env: Env, + env: Gc, // TODO: Making this a SmallVec of around 10 would probably be a // performance improvement. collected: Vec>, - remaining: ArcSlice>, + remaining: ArcSlice, proc_name: String, location: Span, } @@ -538,9 +560,9 @@ impl ResumableCall { pub fn new( proc_name: &str, location: &Span, - env: &Env, + env: &Gc, collected: &[Gc], - remaining: ArcSlice>, + remaining: ArcSlice, ) -> Self { Self { env: env.clone(), @@ -592,6 +614,7 @@ impl Resumable for ResumableCall { } fn clone_stack(&self) -> Arc { + /* Arc::new(Self { env: self.env.deep_clone(), collected: self.collected.clone(), @@ -599,6 +622,8 @@ impl Resumable for ResumableCall { proc_name: self.proc_name.clone(), location: self.location.clone(), }) + */ + todo!() } } @@ -624,6 +649,7 @@ pub async fn call_cc( .await } + #[derive(Clone, Trace)] pub struct CallWithValues { min_args: usize, @@ -696,4 +722,3 @@ pub async fn call_with_values( .eval(cont) .await } -*/ diff --git a/src/env.rs b/src/env.rs index 5b4caa9..2fae7cf 100644 --- a/src/env.rs +++ b/src/env.rs @@ -1,16 +1,365 @@ +use indexmap::IndexSet; use proc_macros::Trace; -use std::collections::HashMap; +use std::{borrow::Cow, collections::HashMap}; +use tokio::sync::OnceCell; use crate::{ + ast::{parse::ParseAstError, AstNode}, builtin::Builtin, error::RuntimeError, gc::{init_gc, Gc}, lex::{LexError, Token}, parse::ParseError, - syntax::{Identifier, Mark}, + syntax::{ExpansionCtx, Identifier, Mark, ParsedSyntax}, value::Value, }; +/// An Environment, or store of variables and macros with a reference to its containing +/// lexical scope. +#[derive(Debug, Default, Trace)] +pub struct Env { + /// The containing environment of this environment, or None if this is a top level + /// environment. + pub up: Option>, + /// Variables stored in this environment. Variables are referenced via their index + /// into an array. This array is dynamic only because a top level environment + /// (i.e. a REPL) can define new variables over the course of evaluation. + vars: Vec>, + /// Names of the variables, used during parsing and compute the reference of the + /// variable. + var_names: IndexSet, + /// Macros stored in the scope. Macros can only be used in the expansion process, so + /// there's no reason to precompute faster lookups for thme. + macros: HashMap>, +} + +static TOP_LEVEL_ENV: OnceCell> = OnceCell::const_new(); + +impl Env { + pub async fn top() -> Gc { + TOP_LEVEL_ENV + .get_or_init(|| async { + let mut top = Env::default(); + + // Install the builtins: + for builtin in inventory::iter:: { + builtin.install(&mut top); + } + + // Install the stdlib: + let top = Gc::new(top); + let _ = top.eval(include_str!("stdlib.scm")).await.unwrap(); + + top + }) + .await + .clone() + } + + pub fn new_lexical_contour(&self) -> Self { + todo!() + } + + /// Compute the reference of the variable. If no such reference exists, the variable + /// is either undefined or a global. + pub fn fetch_var_ref(&self, ident: &Identifier) -> Option { + self.var_names.get_index_of(ident).map_or_else( + || { + self.up + .as_ref() + .map(|up| up.read().fetch_var_ref(ident).map(VarRef::inc_depth)) + .flatten() + }, + |offset| Some(VarRef { depth: 0, offset }), + ) + } + + /// Fetch the value of the variable. Will panic if no variable exists. + pub fn fetch_var(&self, var_ref: VarRef) -> Gc { + // TODO: Convert this to an iterative function. + if var_ref.depth == 0 { + self.vars[var_ref.offset].clone() + } else { + self.up + .as_ref() + .unwrap() + .read() + .fetch_var(var_ref.dec_depth()) + } + } + + /// Define a variable local to this scope. + pub fn def_local_var(&mut self, ident: &Identifier, val: Gc) { + let (idx, exists) = self.var_names.insert_full(ident.clone()); + if exists { + self.vars[idx] = val; + } else { + self.vars.push(val); + } + } + + /// Set the value of the variable. Will panic if no variable exists. + pub fn set_var(&mut self, var_ref: VarRef, new_val: Gc) { + // TODO: Convert this to an iterative function. + if var_ref.depth == 0 { + self.vars[var_ref.offset] = new_val; + } else { + self.up + .as_ref() + .unwrap() + .write() + .set_var(var_ref.dec_depth(), new_val) + } + } + + /// Fetch a macro, along with its containing environment. + fn fetch_macro(&self, ident: &Identifier) -> Option { + match self.macros.get(ident) { + Some(mac) => Some(MacroLookup::WithoutEnv(mac.clone())), + None => match self.up.as_ref().map(|up| up.read().fetch_macro(ident))?? { + wenv @ MacroLookup::WithEnv { .. } => Some(wenv), + MacroLookup::WithoutEnv(value) => Some(MacroLookup::WithEnv { + env: self.up.as_ref().unwrap().clone(), + value, + }), + }, + } + } + + /// Fetch a macro, along with its containing environment. + pub fn def_local_macro(&mut self, ident: &Identifier, val: Gc) { + self.macros.insert(ident.clone(), val); + } +} + +impl Gc { + /// Evaluate a string, returning all of the results in a Vec + pub async fn eval<'e>(&self, exprs: &'e str) -> Result>>, EvalError<'e>> { + let tokens = Token::tokenize_str(exprs)?; + let sexprs = ParsedSyntax::parse(&tokens)?; + let mut results = Vec::new(); + for sexpr in sexprs { + let Some(result) = AstNode::from_syntax(sexpr.syntax, self, &None).await? else { + continue; + }; + // TODO: Catch continuation calls + let vals = result.eval(self, &None).await?; + results.push(vals); + } + Ok(results) + } +} + +#[derive(derive_more::From, Debug)] +pub enum EvalError<'e> { + LexError(LexError<'e>), + ParseError(ParseError<'e>), + ParseAstError(ParseAstError), + RuntimeError(RuntimeError), +} + +/// Reference to a variable that is accessible via the current environment. Could be +/// local or non-local depending on the depth field. +#[derive(Debug, Copy, Clone, Trace)] +pub struct VarRef { + /// Number of up environments we need to traverse in order to reach the defining + /// scope of the variable. Variables with a depth of 0 are local. + depth: usize, + /// Offset into the `vars` field of the environment. + offset: usize, +} + +impl VarRef { + fn inc_depth(self) -> Self { + Self { + depth: self.depth + 1, + offset: self.offset, + } + } + + fn dec_depth(self) -> Self { + Self { + depth: self.depth - 1, + offset: self.offset, + } + } + + pub fn fetch(&self, env: &Gc) -> Gc { + env.read().fetch_var(*self) + } +} + +/// Reference to a bound variable that has been introduced as part of a macro. +#[derive(Debug, Clone, Trace)] +pub struct MacroVarRef { + /// The environment that the macro was defined in. + env: Gc, + /// Reference to the variable from within that macro. + var_ref: VarRef, +} + +impl MacroVarRef { + pub fn fetch(&self) -> Gc { + self.env.read().fetch_var(self.var_ref) + } +} + +/// References a variable in the global scope. Essentially, any variable that is +/// undefined must be a global. +#[derive(Debug, Clone, Trace)] +pub struct GlobalRef { + name: Identifier, + // TODO: Add span for debug info +} + +impl GlobalRef { + pub fn new(name: Identifier) -> Self { + Self { name } + } + + // Throw error when variable is undefined + pub async fn fetch(&self) -> Option> { + todo!() + } +} + +/// A reference that can either be global, macro, or regular +#[derive(Debug, Clone, Trace)] +pub enum Ref { + Macro(MacroVarRef), + Global(GlobalRef), + Regular(VarRef), +} + +impl Ref { + pub fn set(&self, env: &Gc, value: &Gc) { + todo!() + } + + pub async fn fetch(&self, env: &Gc) -> Result, Identifier> { + todo!() + } +} + +/// The result of looking up a macro. If the macro is present in the local environment, +/// `WithoutEnv` is returned (this is because we do not have the Gc of the env). +enum MacroLookup { + WithEnv { env: Gc, value: Gc }, + WithoutEnv(Gc), +} + +pub struct ExpansionEnv<'a> { + up: Option<&'a ExpansionEnv<'a>>, + expansion_ctxs: Vec, + pub lexical_contour: Gc, +} + +impl ExpansionEnv<'static> { + pub async fn top() -> Self { + Self { + up: None, + expansion_ctxs: Vec::new(), + lexical_contour: Env::top().await, + } + } + + pub fn from_env(env: &Gc) -> Self { + Self { + up: None, + expansion_ctxs: Vec::new(), + lexical_contour: env.clone(), + } + } +} + +impl ExpansionEnv<'_> { + pub fn is_bound(&self, ident: &Identifier) -> bool { + !matches!(self.fetch_var_ref(ident), Ref::Global(_)) + } + + pub fn new_expansion_env<'a>(&'a self, ctxs: Vec) -> ExpansionEnv<'a> { + todo!() + } + + pub fn new_lexical_contour<'a>(&'a self, gc: Gc) -> ExpansionEnv<'a> { + todo!() + } + + pub fn fetch_var_ref(&self, ident: &Identifier) -> Ref { + // The very first thing we do is check the current lexical contour. We do not + // need to do anything special here; any marks introduced via a macro expansion + // can only be used to define variables in more local lexical contours. + // + // After we check the lexical scope, we can check the macro expansion contexts. + // If any of them contain the mark of an expansion context, it belongs to that + // macro environment. + self.lexical_contour + .read() + .fetch_var_ref(ident) + .map_or_else(|| self.fetch_macro_var_ref(ident), Ref::Regular) + } + + /// Lexical environments are separately linked, so when we know that a variable is + /// free in the current lexical environment, we can just check the macro envs. + fn fetch_macro_var_ref(&self, ident: &Identifier) -> Ref { + for expansion_ctx in &self.expansion_ctxs { + if ident.marks.contains(&expansion_ctx.mark) { + // Strip the mark and check the macro environment + let mut ident = ident.clone(); + ident.mark(expansion_ctx.mark); + // Fetch the var from the macro env: + let Some(var_ref) = expansion_ctx.env.read().fetch_var_ref(&ident) else { + return Ref::Global(GlobalRef::new(ident)); + }; + return Ref::Macro(MacroVarRef { + env: expansion_ctx.env.clone(), + var_ref, + }); + } + } + + if let Some(up) = self.up { + up.fetch_macro_var_ref(ident) + } else { + Ref::Global(GlobalRef::new(ident.clone())) + } + } + + pub fn fetch_macro(&self, ident: &Identifier) -> Option<(Gc, Gc)> { + // Mechanically this works exactly the same as fetch_var_ref. + self.lexical_contour.read().fetch_macro(ident).map_or_else( + || self.fetch_macro_macro(ident), + |ml| match ml { + MacroLookup::WithEnv { env, value } => Some((env, value)), + MacroLookup::WithoutEnv(value) => Some((self.lexical_contour.clone(), value)), + }, + ) + } + + // Terrible name, but it's the same thing going on as `fetch_macro_var_ref` + fn fetch_macro_macro(&self, ident: &Identifier) -> Option<(Gc, Gc)> { + for expansion_ctx in &self.expansion_ctxs { + if ident.marks.contains(&expansion_ctx.mark) { + // Strip the mark and check the macro environment + let mut ident = ident.clone(); + ident.mark(expansion_ctx.mark); + // Fetch the macro from the macro env: + return match expansion_ctx.env.read().fetch_macro(&ident)? { + MacroLookup::WithEnv { env, value } => Some((env, value)), + MacroLookup::WithoutEnv(value) => Some((expansion_ctx.env.clone(), value)), + }; + } + } + + if let Some(up) = self.up { + up.fetch_macro_macro(ident) + } else { + None + } + } +} + +/* #[derive(derive_more::Debug, Trace)] pub struct LexicalContour { #[debug(skip)] @@ -257,3 +606,4 @@ pub enum EvalError<'e> { // CompileError(CompileError), RuntimeError(RuntimeError), } +*/ diff --git a/src/error.rs b/src/error.rs index 96ab470..f5ae0a7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,9 +1,9 @@ use crate::{ + ast::parse::ParseAstError, continuation::Continuation, gc::Gc, syntax::{Identifier, Span}, value::Value, - ast::parse::ParseAstError, }; use derivative::Derivative; use std::sync::Arc; @@ -34,6 +34,7 @@ pub enum RuntimeErrorKind { expected: String, actual: String, }, + NotAVariableTransformer, DivisionByZero, ParseAstError(ParseAstError), AbandonCurrentContinuation { @@ -132,6 +133,13 @@ impl RuntimeError { } } + pub fn not_a_variable_transformer() -> Self { + Self { + backtrace: Vec::new(), + kind: RuntimeErrorKind::NotAVariableTransformer, + } + } + pub fn no_patterns_match() -> Self { Self { backtrace: Vec::new(), diff --git a/src/eval.rs b/src/eval.rs deleted file mode 100644 index fab479a..0000000 --- a/src/eval.rs +++ /dev/null @@ -1,440 +0,0 @@ -use crate::{ - ast, - continuation::{ - Continuation, ResumableAnd, ResumableBody, ResumableCall, ResumableDefineVar, ResumableIf, - ResumableLet, ResumableOr, ResumableSet, ResumableSyntaxCase, - }, - env::Env, - error::RuntimeError, - gc::{Gc, Trace}, - proc::{PreparedCall, ProcDebugInfo, Procedure}, - syntax::Syntax, - util::{self, RequireOne}, - value::Value, -}; -use async_trait::async_trait; -use std::{collections::BTreeSet, sync::Arc}; - -/// Core evaulation trait for expressions. -/// -/// Any struct implementing this trait must either implement `eval`, `tail_eval`, or -/// both, even though both methods are provided. -#[async_trait] -pub trait Eval: Trace + Send + Sync + 'static { - async fn eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result>, RuntimeError> { - self.tail_eval(env, cont).await?.eval(cont).await - } - - /// Evaluate the expression in a tail environment - async fn tail_eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result { - Ok(ValuesOrPreparedCall::Values(self.eval(env, cont).await?)) - } -} - -#[async_trait] -impl Eval for Value { - async fn eval( - &self, - _env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - Ok(vec![Gc::new(self.clone())]) - } -} - -#[async_trait] -impl Eval for Vec> { - async fn eval( - &self, - _env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - Ok(self.clone()) - } -} - -#[async_trait] -impl Eval for ast::Literal { - async fn eval( - &self, - _env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - Ok(vec![Gc::new(Value::from_literal(self))]) - } -} - -#[async_trait] -impl Eval for ast::Quote { - async fn eval( - &self, - _env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - Ok(vec![Gc::new(self.val.clone())]) - } -} - -#[async_trait] -impl Eval for ast::Body { - async fn tail_eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result { - let Some(last) = self.exprs.last() else { - return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Null)])); - }; - for (expr, tail) in self.exprs.skip_last() { - let cont = Some(Arc::new(Continuation::new( - Arc::new(ResumableBody::new(env, &tail)), - cont, - ))); - // Discard values that aren't returned - expr.eval(env, &cont).await?; - } - last.tail_eval(env, cont).await - } -} - -#[async_trait] -impl Eval for ast::Let { - async fn tail_eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result { - let scope = Gc::new(env.new_lexical_contour()); - for ((ident, expr), remaining) in util::iter_arc(&self.bindings) { - let cont = Arc::new(Continuation::new( - Arc::new(ResumableLet::new(&scope, ident, remaining, &self.body)), - cont, - )); - let val = expr - .eval(&Env::from(scope.clone()), &Some(cont)) - .await? - .require_one()?; - scope.write().def_var(ident, val); - } - self.body.tail_eval(&Env::from(scope), cont).await - } -} - -#[async_trait] -impl Eval for ast::Call { - async fn tail_eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result { - let mut collected = Vec::new(); - for (arg, remaining) in self.args.iter() { - let cont = Arc::new(Continuation::new( - Arc::new(ResumableCall::new( - &self.proc_name, - &self.location, - env, - &collected, - remaining, - )), - cont, - )); - let arg = arg.eval(env, &Some(cont)).await?.require_one()?; - collected.push(arg); - } - Ok(ValuesOrPreparedCall::PreparedCall(PreparedCall::prepare( - collected, - Some(ProcDebugInfo::new(&self.proc_name, &self.location)), - ))) - } -} - -#[async_trait] -impl Eval for ast::If { - async fn tail_eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result { - let cond_cont = Arc::new(Continuation::new( - Arc::new(ResumableIf::new(env, &self.success, &self.failure)), - cont, - )); - let condition = self - .cond - .eval(env, &Some(cond_cont)) - .await? - .require_one()? - .read() - .is_true(); - if condition { - self.success.tail_eval(env, cont).await - } else if let Some(ref failure) = self.failure { - failure.tail_eval(env, cont).await - } else { - Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Null)])) - } - } -} - -#[async_trait] -impl Eval for ast::DefineFunc { - async fn eval( - &self, - env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - let (args, remaining) = self.args.to_args_and_remaining(); - let func = Gc::new(Value::Procedure(Procedure { - up: env.clone(), - args, - remaining, - // mark: self.mark, - body: self.body.clone(), - is_variable_transformer: false, - })); - env.def_var(&self.name, func); - Ok(vec![]) - } -} - -#[async_trait] -impl Eval for ast::DefineVar { - async fn eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result>, RuntimeError> { - let cont = Arc::new(Continuation::new( - Arc::new(ResumableDefineVar::new(env, &self.name)), - cont, - )); - let val = self.val.eval(env, &Some(cont)).await?.require_one()?; - env.def_var(&self.name, val); - Ok(vec![]) - } -} - -#[async_trait] -impl Eval for ast::Define { - async fn eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result>, RuntimeError> { - match self { - ast::Define::DefineFunc(define_func) => define_func.eval(env, cont).await, - ast::Define::DefineVar(define_var) => define_var.eval(env, cont).await, - } - } -} - -#[async_trait] -impl Eval for ast::DefineSyntax { - async fn eval( - &self, - _env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - Ok(vec![]) - } -} - -#[async_trait] -impl Eval for ast::And { - async fn tail_eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result { - let Some(last) = self.args.last() else { - return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean( - true, - ))])); - }; - for (arg, tail) in self.args.skip_last() { - let cont = Arc::new(Continuation::new( - Arc::new(ResumableAnd::new(env, &tail)), - cont, - )); - // If one of the arguments does not evaluate to true, then the result - // is false - if !arg - .eval(env, &Some(cont)) - .await? - .require_one()? - .read() - .is_true() - { - return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean( - false, - ))])); - } - } - // If all of the other arguments are true, then the result is the last expression - last.tail_eval(env, cont).await - } -} - -#[async_trait] -impl Eval for ast::Or { - async fn tail_eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result { - let Some(last) = self.args.last() else { - return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean( - false, - ))])); - }; - for (arg, tail) in self.args.skip_last() { - let cont = Arc::new(Continuation::new( - Arc::new(ResumableOr::new(env, &tail)), - cont, - )); - // If one of the arguments evaluates to true, then the result is true - if arg - .eval(env, &Some(cont)) - .await? - .require_one()? - .read() - .is_true() - { - return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean( - true, - ))])); - } - } - // If all of the other arguments are false, then the result is the last expression - last.tail_eval(env, cont).await - } -} - -#[async_trait] -impl Eval for ast::Vector { - async fn eval( - &self, - _env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - /* - let mut output = Vec::new(); - for item in &self.vals { - output.push(item.eval(env, cont.clone()).await?); - } - Ok(Gc::new(Value::Vector(output))) - */ - todo!("FIXME: Vectors don't evaluate their arguments, take the literals") - } -} - -#[async_trait] -impl Eval for ast::Set { - async fn eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result>, RuntimeError> { - let new_cont = Arc::new(Continuation::new( - Arc::new(ResumableSet::new(env, &self.var)), - cont, - )); - // TODO: Add try_unwrap to GC to avoid the clone of the inner value - let val = self - .val - .eval(env, &Some(new_cont)) - .await? - .require_one()? - .read() - .clone(); - *env.fetch_var(&self.var) - .ok_or_else(|| RuntimeError::undefined_variable(self.var.clone()))? - .write() = val; - Ok(vec![]) - } -} - -#[async_trait] -impl Eval for ast::Lambda { - async fn eval( - &self, - env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - // TODO: Optimize the AST with smart pointers to prevent constantly - // cloning. - - let (args, remaining) = self.args.to_args_and_remaining(); - Ok(vec![Gc::new(Value::Procedure(Procedure { - up: env.clone(), - args, - remaining, - body: self.body.clone(), - is_variable_transformer: false, - }))]) - } -} - -#[async_trait] -impl Eval for ast::SyntaxQuote { - async fn eval( - &self, - _env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - Ok(vec![Gc::new(Value::Syntax(self.syn.clone()))]) - } -} - -#[async_trait] -impl Eval for ast::SyntaxCase { - async fn eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result>, RuntimeError> { - let new_cont = Arc::new(Continuation::new( - Arc::new(ResumableSyntaxCase::new(env, &self.transformer)), - cont, - )); - let val = self.arg.eval(env, &Some(new_cont)).await?.require_one()?; - // This clones _all_ syntax objects; we should fix this to be more optimal. - let syntax = Syntax::from_datum(&BTreeSet::default(), &val); - let result = self.transformer.expand(&syntax).unwrap(); - result.compile(env, cont).await?.eval(env, cont).await - } -} - -#[async_trait] -impl Eval for ast::Var { - async fn eval( - &self, - env: &Env, - _cont: &Option>, - ) -> Result>, RuntimeError> { - Ok(vec![env.fetch_var(&self.ident).ok_or_else(|| { - RuntimeError::undefined_variable(self.ident.clone()) - })?]) - } -} - -#[async_trait] -impl Eval for ast::MacroExpansionPoint { - async fn tail_eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result { - let env = Gc::new(env.new_expansion_context(self.mark, self.macro_env.clone())); - self.expr.tail_eval(&Env::from(env), cont).await - } -} diff --git a/src/expand.rs b/src/expand.rs index 9ed5035..86a9ee0 100644 --- a/src/expand.rs +++ b/src/expand.rs @@ -381,11 +381,6 @@ pub async fn make_variable_transformer( proc.is_variable_transformer = true; Ok(vec![Gc::new(Value::Procedure(proc))]) } - Value::Transformer(transformer) => { - let mut transformer = transformer.clone(); - transformer.is_variable_transformer = true; - Ok(vec![Gc::new(Value::Transformer(transformer))]) - } _ => todo!(), } } diff --git a/src/main.rs b/src/main.rs index 2e647a5..f5973b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,10 @@ -/* use reedline::{Reedline, Signal, ValidationResult, Validator}; -use scheme_rs::{env::Env, lex::Token, parse::ParseError}; +use scheme_rs::{env::Env, lex::Token, parse::ParseError, syntax::ParsedSyntax}; use std::{ borrow::Cow, - sync::{Arc, Mutex}, -};e -*/ +}; -/* -type ParsedResult = Option, String>>; - -struct InputParser { - parsed: Arc>, -} +struct InputParser; impl Validator for InputParser { fn validate(&self, line: &str) -> ValidationResult { @@ -22,10 +14,7 @@ impl Validator for InputParser { let syntax = ParsedSyntax::parse(&tokens); match syntax { Err(ParseError::UnclosedParen { .. }) => ValidationResult::Incomplete, - x => { - *self.parsed.lock().unwrap() = Some(x.map_err(|e| format!("{:?}", e))); - ValidationResult::Complete - } + _ => ValidationResult::Complete, } } } @@ -56,56 +45,27 @@ impl reedline::Prompt for Prompt { Cow::Borrowed("? ") } } -*/ #[tokio::main] async fn main() { - /* - let parsed = Arc::new(Mutex::new(None)); - let mut rl = Reedline::create().with_validator(Box::new(InputParser { - parsed: parsed.clone(), - })); + let mut rl = Reedline::create().with_validator(Box::new(InputParser)); let mut n_results = 1; let top = Env::top().await; loop { - match rl.read_line(&Prompt) { - Ok(Signal::Success(_)) => (), - _ => { - println!("exiting..."); - return; - } - } - let Some(parsed) = parsed.lock().unwrap().take() else { - continue; - }; - let parsed = match parsed { - Err(err) => { - println!("Error parsing: {err}"); - continue; - } - Ok(parsed) => parsed, + let Ok(Signal::Success(input)) = rl.read_line(&Prompt) else { + println!("exiting..."); + return; }; - for sexpr in parsed { - let compiled = match sexpr.compile(&top, &None).await { - Err(err) => { - println!("Error compiling: {err:?}"); - continue; - } - Ok(compiled) => compiled, - }; - match compiled.eval(&top, &None).await { - Err(err) => { - println!("Error: {err:?}"); - } - Ok(results) => { - for result in results { - println!("${n_results} = {}", result.read().fmt()); - n_results += 1; - } + match top.eval(&input).await { + Ok(results) => { + for result in results.into_iter().flatten() { + println!("${n_results} = {}", result.read().fmt()); + n_results += 1; } } + Err(err) => { + println!("Error: {err:?}"); + } } } - */ - todo!() } diff --git a/src/proc.rs b/src/proc.rs index 31d4339..5d08ac7 100644 --- a/src/proc.rs +++ b/src/proc.rs @@ -59,7 +59,7 @@ pub trait Callable: Send + Sync + 'static { #[derive(Clone, derive_more::Debug, Trace)] pub struct Procedure { #[debug(skip)] - pub up: Env, + pub up: Gc, pub args: Vec, pub remaining: Option, #[debug(skip)] @@ -82,7 +82,7 @@ impl Callable for Procedure { args: Vec>, cont: &Option>, ) -> Result { - let env = Gc::new(self.up.new_lexical_contour()); + let env = Gc::new(self.up.read().new_lexical_contour()); let provided = args.len(); let mut args_iter = args.iter().peekable(); @@ -92,11 +92,11 @@ impl Callable for Procedure { let Some(value) = args_iter.next().cloned() else { return Err(RuntimeError::wrong_num_of_args(self.args.len(), provided)); }; - env.write().def_var(required, value); + env.write().def_local_var(required, value); } if let Some(ref remaining) = self.remaining { - env.write().def_var( + env.write().def_local_var( remaining, Gc::new(Value::from(args_iter.cloned().collect::>())), ); @@ -104,7 +104,7 @@ impl Callable for Procedure { return Err(RuntimeError::wrong_num_of_args(self.args.len(), provided)); } - self.body.tail_eval(&Env::from(env.clone()), cont).await + self.body.tail_eval(&env, cont).await } } diff --git a/src/syntax.rs b/src/syntax.rs index 75a0844..e18cf15 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -1,8 +1,8 @@ use crate::{ - ast::{self, Var, Literal, MacroExpansionPoint}, + ast::{self, Literal}, // compile::{Compile, CompileError}, continuation::Continuation, - env::Env, + env::{Env, ExpansionEnv}, error::RuntimeError, // eval::Eval, gc::{Gc, Trace}, @@ -54,6 +54,7 @@ impl From> for Span { } #[derive(Clone, derive_more::Debug, Trace)] +// TODO: Make cloning this struct as fast as possible. pub enum Syntax { /// An empty list. Null { @@ -175,7 +176,7 @@ impl Syntax { } } - pub fn resolve_bindings(&mut self, env: &Env) { + pub fn resolve_bindings(&mut self, env: &ExpansionEnv<'_>) { match self { Self::List { ref mut list, .. } => { for item in list { @@ -198,8 +199,8 @@ impl Syntax { async fn apply_transformer( &self, - curr_env: &Env, - macro_env: Env, + env: &ExpansionEnv<'_>, + macro_env: Gc, cont: &Option>, transformer: Gc, ) -> Result { @@ -208,7 +209,7 @@ impl Syntax { // Apply the new mark to the input // TODO: Figure out a better way to do this without cloning so much let mut input = self.clone(); - input.resolve_bindings(curr_env); + input.resolve_bindings(env); input.mark(new_mark); // Call the transformer with the input: let transform = transformer.read().as_callable().unwrap(); @@ -234,16 +235,19 @@ impl Syntax { }) } - fn expand_once<'a>( + fn expand_once<'a, 'b>( &'a self, - env: &'a Env, + env: &'a ExpansionEnv<'b>, cont: &'a Option>, - ) -> BoxFuture<'a, Result> { + ) -> BoxFuture<'a, Result> + where + 'a: 'b, + { Box::pin(async move { match self { Self::List { list, .. } => { - // If the head is not an identifier, we leave the expression unexpanded - // for now. We will expand it later in the proc call + // TODO: If list head is a list, do we expand this in here or in proc call? + let ident = match list.first() { Some(Self::Identifier { ident, .. }) => ident, _ => return Ok(Expansion::Unexpanded), @@ -253,6 +257,22 @@ impl Syntax { .apply_transformer(env, macro_env, cont, transformer) .await; } + + // Check for set! macro + match list.as_slice() { + [Syntax::Identifier { ident, .. }, ..] if ident.name == "set!" => { + // Look for variable transformer: + if let Some((macro_env, transformer)) = env.fetch_macro(ident) { + if !transformer.read().is_variable_transformer() { + return Err(RuntimeError::not_a_variable_transformer()); + } + return self + .apply_transformer(env, macro_env, cont, transformer) + .await; + } + } + _ => (), + } } Self::Identifier { ident, .. } => { if let Some((macro_env, transformer)) = env.fetch_macro(ident) { @@ -267,6 +287,7 @@ impl Syntax { }) } + /* /// Fully expand the outermost syntax object. pub async fn expand<'a>(&'a self, env: &Env, cont: &Option>) -> Result, RuntimeError> { let mut expansion_envs = Vec::new(); @@ -280,12 +301,44 @@ impl Syntax { }) }, Expansion::Expanded { mark, macro_env, syntax } => { - expansion_envs.push(ExpansionEnv::new(mark, macro_env)); + expansion_envs.push(ExpansionCtx::new(mark, macro_env)); expansion = Cow::Owned(syntax); } } } } + */ + + /// Fully expand the outermost syntax object. + pub async fn expand( + mut self, + env: &ExpansionEnv<'_>, + cont: &Option>, + ) -> Result { + let mut expansion_envs = Vec::new(); + loop { + match self.expand_once(env, cont).await? { + Expansion::Unexpanded => { + return Ok(FullyExpanded { + expansion_envs, + expanded: self, + }) + } + Expansion::Expanded { + mark, + macro_env, + syntax, + } => { + expansion_envs.push(ExpansionCtx::new(mark, macro_env)); + self = syntax; + } + } + } + } + + pub async fn test(self: Arc) -> i32 { + todo!() + } pub fn as_list(&self) -> Option<&[Syntax]> { todo!() @@ -296,107 +349,107 @@ impl Syntax { } /* - pub async fn compile_expanded( - &self, - env: &Env, - cont: &Option>, - ) -> Result, CompileError> { - match self { - Self::Null { span } => Err(CompileError::UnexpectedEmptyList(span.clone())), - // Special identifiers: - Self::Identifier { ident, .. } if ident == "" => { - Ok(Arc::new(Value::Undefined)) - } - // Regular identifiers: - Self::Identifier { ident, .. } => { - Ok(Arc::new(Var::new(ident.clone())) as Arc) - } - Self::Literal { literal, .. } => Ok(Arc::new(literal.clone()) as Arc), - Self::List { list: exprs, span } => match &exprs[..] { - // Function call: - [Self::Identifier { ident, .. }, ..] if env.is_bound(ident) => { - ast::Call::compile_to_expr(exprs, env, cont, span).await - } - // Special forms: - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "quote" => { - ast::Quote::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "syntax" => { - ast::SyntaxQuote::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "begin" => { - ast::Body::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "let" => { - ast::Let::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "lambda" => { - ast::Lambda::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "if" => { - ast::If::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "and" => { - ast::And::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "or" => { - ast::Or::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "define" => { - ast::Define::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "define-syntax" => { - ast::DefineSyntax::compile_to_expr(tail, env, cont, span).await - } - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "syntax-case" => { - ast::SyntaxCase::compile_to_expr(tail, env, cont, span).await + pub async fn compile_expanded( + &self, + env: &Env, + cont: &Option>, + ) -> Result, CompileError> { + match self { + Self::Null { span } => Err(CompileError::UnexpectedEmptyList(span.clone())), + // Special identifiers: + Self::Identifier { ident, .. } if ident == "" => { + Ok(Arc::new(Value::Undefined)) } - [Self::Identifier { ident, span, .. }, tail @ ..] - if ident == "define-record-type" => - { - records::DefineRecordType::compile_to_expr(tail, env, cont, span).await + // Regular identifiers: + Self::Identifier { ident, .. } => { + Ok(Arc::new(Var::new(ident.clone())) as Arc) } - // Very special form: - [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "set!" => { - // Check for a variable transformer - if let Some(Syntax::Identifier { ident, .. }) = tail.first() { - if let Some((macro_env, transformer)) = env.fetch_macro(ident) { - if !transformer.read().is_variable_transformer() { - return Err(CompileError::NotVariableTransformer); + Self::Literal { literal, .. } => Ok(Arc::new(literal.clone()) as Arc), + Self::List { list: exprs, span } => match &exprs[..] { + // Function call: + [Self::Identifier { ident, .. }, ..] if env.is_bound(ident) => { + ast::Call::compile_to_expr(exprs, env, cont, span).await + } + // Special forms: + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "quote" => { + ast::Quote::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "syntax" => { + ast::SyntaxQuote::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "begin" => { + ast::Body::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "let" => { + ast::Let::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "lambda" => { + ast::Lambda::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "if" => { + ast::If::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "and" => { + ast::And::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "or" => { + ast::Or::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "define" => { + ast::Define::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "define-syntax" => { + ast::DefineSyntax::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "syntax-case" => { + ast::SyntaxCase::compile_to_expr(tail, env, cont, span).await + } + [Self::Identifier { ident, span, .. }, tail @ ..] + if ident == "define-record-type" => + { + records::DefineRecordType::compile_to_expr(tail, env, cont, span).await + } + // Very special form: + [Self::Identifier { ident, span, .. }, tail @ ..] if ident == "set!" => { + // Check for a variable transformer + if let Some(Syntax::Identifier { ident, .. }) = tail.first() { + if let Some((macro_env, transformer)) = env.fetch_macro(ident) { + if !transformer.read().is_variable_transformer() { + return Err(CompileError::NotVariableTransformer); + } + return self + .apply_transformer(env, macro_env, cont, transformer) + .await? + .compile(env, cont) + .await; } - return self - .apply_transformer(env, macro_env, cont, transformer) - .await? - .compile(env, cont) - .await; } + ast::Set::compile_to_expr(tail, env, cont, span).await } - ast::Set::compile_to_expr(tail, env, cont, span).await - } - // Special function call: - _ => ast::Call::compile_to_expr(exprs, env, cont, span).await, - }, - Self::Vector { vector, .. } => { - let mut vals = Vec::new(); - for item in vector { - match item { - Self::Null { .. } => vals.push(Arc::new(Value::Null) as Arc), - item => vals.push(item.compile(env, cont).await?), + // Special function call: + _ => ast::Call::compile_to_expr(exprs, env, cont, span).await, + }, + Self::Vector { vector, .. } => { + let mut vals = Vec::new(); + for item in vector { + match item { + Self::Null { .. } => vals.push(Arc::new(Value::Null) as Arc), + item => vals.push(item.compile(env, cont).await?), + } } + Ok(Arc::new(ast::Vector { vals }) as Arc) } - Ok(Arc::new(ast::Vector { vals }) as Arc) } } - } - pub async fn compile( - &self, - env: &Env, - cont: &Option>, - ) -> Result, CompileError> { - self.expand(env, cont).await?.compile(env, cont).await -} - */ + pub async fn compile( + &self, + env: &Env, + cont: &Option>, + ) -> Result, CompileError> { + self.expand(env, cont).await?.compile(env, cont).await + } + */ } pub enum Expansion { @@ -405,7 +458,7 @@ pub enum Expansion { /// Syntax was expanded, producing a new expansion context Expanded { mark: Mark, - macro_env: Env, + macro_env: Gc, syntax: Syntax, }, } @@ -422,34 +475,25 @@ impl Expansion<'_> { } */ -pub struct ExpansionEnv { - mark: Mark, - macro_env: Env, +pub struct ExpansionCtx { + pub mark: Mark, + pub env: Gc, } -impl ExpansionEnv { - fn new(mark: Mark, macro_env: Env) -> Self { - todo!() +impl ExpansionCtx { + fn new(mark: Mark, env: Gc) -> Self { + Self { mark, env } } } -pub struct FullyExpanded<'a> { - pub expansion_envs: Vec, - pub expanded: Cow<'a, Syntax>, +pub struct FullyExpanded { + pub expansion_envs: Vec, + pub expanded: Syntax, } -impl AsRef for FullyExpanded<'_> { +impl AsRef for FullyExpanded { fn as_ref(&self) -> &Syntax { - self.expanded.as_ref() - } -} - -impl FullyExpanded<'_> { - pub fn to_owned(self) -> FullyExpanded<'static> { - FullyExpanded { - expansion_envs: self.expansion_envs, - expanded: Cow::Owned(self.expanded.as_ref().clone()), - } + &self.expanded } } @@ -485,11 +529,10 @@ impl<'a> Expansion<'a> { */ -/* #[derive(Debug)] pub struct ParsedSyntax { pub doc_comment: Option, - syntax: Syntax, + pub syntax: Syntax, } impl ParsedSyntax { @@ -524,18 +567,7 @@ impl ParsedSyntax { } Ok(output) } - - pub async fn compile( - &self, - env: &Env, - cont: &Option>, - ) -> Result, CompileError> { - Ok(Arc::new(CatchContinuationCall::new( - self.syntax.compile(env, cont).await?, - ))) - } } -*/ #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Trace)] pub struct Mark(usize); diff --git a/src/value.rs b/src/value.rs index 0b929e4..4cc6789 100644 --- a/src/value.rs +++ b/src/value.rs @@ -24,12 +24,12 @@ pub enum Value { String(String), Symbol(String), Pair(Gc, Gc), - Vector(Vec>), + Vector(Vec), ByteVector(Vec), Syntax(Syntax), Procedure(Procedure), ExternalFn(ExternalFn), - Transformer(Transformer), + // Transformer(Transformer), Record(Record), RecordType(Gc), Future(#[debug(skip)] Shared>, RuntimeError>>>), @@ -40,7 +40,7 @@ impl Value { pub fn is_callable(&self) -> bool { matches!( self, - Self::Procedure(_) | Self::ExternalFn(_) | Self::Transformer(_) + Self::Procedure(_) | Self::ExternalFn(_) ) } @@ -52,7 +52,7 @@ impl Value { pub fn is_variable_transformer(&self) -> bool { match self { Self::Procedure(ref proc) => proc.is_variable_transformer, - Self::Transformer(ref trans) => trans.is_variable_transformer, + // Self::Transformer(ref trans) => trans.is_variable_transformer, _ => false, } } @@ -80,7 +80,7 @@ impl Value { let mut iter = vec.iter().peekable(); let mut output = String::from("#("); while let Some(item) = iter.next() { - output.push_str(&item.read().fmt()); + output.push_str(&item.fmt()); if iter.peek().is_some() { output.push(' '); } @@ -95,7 +95,7 @@ impl Value { Self::Procedure(proc) => format!("<{proc:?}>"), Self::ExternalFn(_) => "".to_string(), Self::Future(_) => "".to_string(), - Self::Transformer(_) => "".to_string(), + // Self::Transformer(_) => "".to_string(), Self::Continuation(_) => "".to_string(), Self::Record(_) => "".to_string(), Self::RecordType(_) => "".to_string(), @@ -123,7 +123,7 @@ impl Value { curr } Syntax::Vector { vector, .. } => { - Self::Vector(vector.iter().map(Self::from_syntax).map(Gc::new).collect()) + Self::Vector(vector.iter().map(Self::from_syntax).collect()) } Syntax::Literal { literal, .. } => Self::from_literal(literal), Syntax::Identifier { ident, .. } => Self::Symbol(ident.name.clone()), @@ -141,7 +141,7 @@ impl Value { Self::Vector(_) => "vector", Self::ByteVector(_) => "byte vector", Self::Syntax(_) => "syntax", - Self::Procedure(_) | Self::ExternalFn(_) | Self::Transformer(_) => "procedure", + Self::Procedure(_) | Self::ExternalFn(_) => "procedure", Self::Future(_) => "future", Self::Continuation(_) => "continuation", Self::Record(_) => "record", @@ -160,7 +160,7 @@ impl Value { (Self::Pair(a1, a2), Self::Pair(b1, b2)) => eqv(a1, b1) && eqv(a2, b2), (Self::Vector(a), Self::Vector(b)) => { for (a, b) in a.iter().zip(b.iter()) { - if !eqv(a, b) { + if !a.eqv(b) { return false; } } @@ -191,7 +191,6 @@ impl Clone for Value { Self::Procedure(proc) => Self::Procedure(proc.clone()), Self::ExternalFn(ext_fn) => Self::ExternalFn(*ext_fn), Self::Future(fut) => Self::Future(fut.clone()), - Self::Transformer(trans) => Self::Transformer(trans.clone()), Self::Continuation(cont) => Self::Continuation(cont.clone()), Self::Record(record) => Self::Record(record.clone()), Self::RecordType(rt) => Self::RecordType(rt.clone()), @@ -402,7 +401,7 @@ pub async fn procedure_pred( let arg = arg.read(); Ok(vec![Gc::new(Value::Boolean(matches!( &*arg, - Value::Procedure(_) | Value::ExternalFn(_) | Value::Transformer(_) | Value::Continuation(_) + Value::Procedure(_) | Value::ExternalFn(_) | Value::Continuation(_) )))]) } diff --git a/tests/r6rs.scm b/tests/r6rs.scm index a6d7933..bc3b3e1 100644 --- a/tests/r6rs.scm +++ b/tests/r6rs.scm @@ -201,3 +201,18 @@ ;; ((x y) (values a b))) ;; (list a b x y))) ;; (x y x y)) + +;; Scoping rules: +(define (f x) + (let ([y 1]) + (define (g h) + (* y x h)) + (let ([h 2]) + (g h)))) + +(define-syntax test + (lambda (i) + (let ([x 10]) + (syntax-case i () + ([_ from] + #'(define from x))))))