From f85ed8139a07a8f0b7c427380996eae11171fe48 Mon Sep 17 00:00:00 2001 From: Matthew Plant Date: Tue, 24 Dec 2024 20:55:38 -0500 Subject: [PATCH 1/7] Flesh out new structure for interpreter (and eventual comp) --- benches/fib.rs | 2 +- benches/fib.scm | 2 +- proc-macros/src/lib.rs | 8 +- src/ast.rs | 211 ---------- src/ast/eval.rs | 25 ++ src/ast/mod.rs | 299 ++++++++++++++ src/ast/mod.rs~ | 226 +++++++++++ src/ast/parse.rs | 886 +++++++++++++++++++++++++++++++++++++++++ src/builtin.rs | 2 +- src/compile.rs | 795 ------------------------------------ src/continuation.rs | 19 +- src/env.rs | 9 +- src/error.rs | 6 +- src/eval.rs | 31 +- src/lib.rs | 4 +- src/main.rs | 11 +- src/proc.rs | 40 +- src/records.rs | 8 +- src/syntax.rs | 99 ++++- 19 files changed, 1600 insertions(+), 1083 deletions(-) delete mode 100644 src/ast.rs create mode 100644 src/ast/eval.rs create mode 100644 src/ast/mod.rs create mode 100644 src/ast/mod.rs~ create mode 100644 src/ast/parse.rs diff --git a/benches/fib.rs b/benches/fib.rs index 40356d8..7076c5f 100644 --- a/benches/fib.rs +++ b/benches/fib.rs @@ -19,7 +19,7 @@ async fn fib() { } fn fib_benchmark(c: &mut Criterion) { - c.bench_function("fib 100", |b| { + c.bench_function("fib 10000", |b| { b.to_async(tokio::runtime::Runtime::new().unwrap()) .iter(fib) }); diff --git a/benches/fib.scm b/benches/fib.scm index 948ce1e..b3e70df 100644 --- a/benches/fib.scm +++ b/benches/fib.scm @@ -5,4 +5,4 @@ (iter b (+ a b) (- count 1)))) (iter 0 1 n)) -(fib 100) +(fib 10000) diff --git a/proc-macros/src/lib.rs b/proc-macros/src/lib.rs index 3d87bbc..a757e80 100644 --- a/proc-macros/src/lib.rs +++ b/proc-macros/src/lib.rs @@ -33,13 +33,13 @@ pub fn builtin(name: TokenStream, item: TokenStream) -> TokenStream { fn #wrapper_name( cont: Option>, args: Vec<::scheme_rs::gc::Gc<::scheme_rs::value::Value>> - ) -> futures::future::BoxFuture<'static, Result<::scheme_rs::eval::ValuesOrPreparedCall, ::scheme_rs::error::RuntimeError>> { + ) -> futures::future::BoxFuture<'static, Result<::scheme_rs::proc::ValuesOrPreparedCall, ::scheme_rs::error::RuntimeError>> { Box::pin( async move { #impl_name( &cont, #( &args[#arg_indices], )* - ).await.map(::scheme_rs::eval::ValuesOrPreparedCall::from) + ).await.map(::scheme_rs::proc::ValuesOrPreparedCall::from) } ) } @@ -50,7 +50,7 @@ pub fn builtin(name: TokenStream, item: TokenStream) -> TokenStream { fn #wrapper_name( cont: Option>, mut required_args: Vec<::scheme_rs::gc::Gc<::scheme_rs::value::Value>> - ) -> futures::future::BoxFuture<'static, Result<::scheme_rs::eval::ValuesOrPreparedCall, ::scheme_rs::error::RuntimeError>> { + ) -> futures::future::BoxFuture<'static, Result<::scheme_rs::proc::ValuesOrPreparedCall, ::scheme_rs::error::RuntimeError>> { let var_args = required_args.split_off(#num_args); Box::pin( async move { @@ -58,7 +58,7 @@ pub fn builtin(name: TokenStream, item: TokenStream) -> TokenStream { &cont, #( &required_args[#arg_indices], )* var_args - ).await.map(::scheme_rs::eval::ValuesOrPreparedCall::from) + ).await.map(::scheme_rs::proc::ValuesOrPreparedCall::from) } ) } diff --git a/src/ast.rs b/src/ast.rs deleted file mode 100644 index 3b16965..0000000 --- a/src/ast.rs +++ /dev/null @@ -1,211 +0,0 @@ -use crate::{ - env::Env, - eval::Eval, - expand::Transformer, - gc::Trace, - num::Number, - syntax::{Identifier, Mark, Span, Syntax}, - util::ArcSlice, - value::Value, -}; -use std::sync::Arc; - -#[derive(Debug, Clone, PartialEq, Trace)] -pub struct ByteVector(pub Vec); - -#[derive(Debug, Clone, PartialEq, Trace)] -pub enum Literal { - Number(Number), - Boolean(bool), - Character(char), - String(String), - ByteVector(ByteVector), -} - -#[derive(Clone, Trace)] -pub struct Quote { - pub val: Value, -} - -#[derive(Clone, Trace)] -pub struct SyntaxQuote { - pub syn: Syntax, - pub env: Env, -} - -#[derive(Clone, Trace)] -pub struct Call { - pub args: ArcSlice>, - pub location: Span, - pub proc_name: String, -} - -#[derive(Clone, Trace)] -pub struct DefineFunc { - pub name: Identifier, - pub args: Formals, - pub body: Body, -} - -#[derive(Clone, Trace, derive_more::Debug)] -pub struct DefineVar { - pub name: Identifier, - #[debug(skip)] - pub val: Arc, -} - -#[derive(Clone, Trace, derive_more::Debug)] -pub enum Define { - DefineVar(#[debug(skip)] DefineVar), - DefineFunc(#[debug(skip)] DefineFunc), -} - -#[derive(Clone, Trace)] -pub struct DefineSyntax; - -#[derive(Clone, Trace)] -pub struct Lambda { - pub args: Formals, - pub body: Body, -} - -#[derive(Debug, Clone, Trace)] -pub enum Formals { - FixedArgs(Vec), - VarArgs { - fixed: Vec, - remaining: Identifier, - }, -} - -impl Formals { - pub fn to_args_and_remaining(&self) -> (Vec, Option) { - match self { - Self::VarArgs { fixed, remaining } => (fixed.clone(), Some(remaining.clone())), - Self::FixedArgs(args) => (args.clone(), None), - } - } -} - -#[derive(Clone, Trace)] -pub struct Body { - pub exprs: ArcSlice>, -} - -impl Body { - pub fn new(exprs: Vec>) -> Self { - Self { - exprs: ArcSlice::from(exprs), - } - } -} - -#[derive(Clone, Trace)] -pub struct Let { - pub bindings: Arc<[(Identifier, Arc)]>, - pub body: Body, -} - -impl Let { - pub fn new(bindings: Vec<(Identifier, Arc)>, body: Body) -> Self { - Self { - bindings: Arc::from(bindings), - body, - } - } -} - -#[derive(Clone, Trace)] -pub struct Set { - pub var: Identifier, - pub val: Arc, -} - -#[derive(Clone, Trace)] -pub struct If { - pub cond: Arc, - pub success: Arc, - pub failure: Option>, -} - -#[derive(Clone, Trace)] -pub struct And { - pub args: ArcSlice>, -} - -impl And { - pub fn new(args: Vec>) -> Self { - Self { - args: ArcSlice::from(args), - } - } -} - -#[derive(Clone, Trace)] -pub struct Or { - pub args: ArcSlice>, -} - -impl Or { - pub fn new(args: Vec>) -> Self { - Self { - args: ArcSlice::from(args), - } - } -} - -#[derive(Clone, Trace)] -pub struct Vector { - pub vals: Vec>, -} - -#[derive(Clone, Trace)] -pub struct SyntaxCase { - pub arg: Arc, - pub transformer: Transformer, -} - -#[derive(Clone, Trace)] -pub struct FetchVar { - pub ident: Identifier, -} - -impl FetchVar { - pub fn new(ident: Identifier) -> Self { - Self { ident } - } -} - -#[derive(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, - } - } -} - -/* -struct Export {} - -struct Import {} - -struct Library { - imports: Vec, - exports: Vec, - library_body: Body, -} - -struct TopLevelProgram { - imports: Vec, - program_body: Body, -} -*/ diff --git a/src/ast/eval.rs b/src/ast/eval.rs new file mode 100644 index 0000000..abca8f2 --- /dev/null +++ b/src/ast/eval.rs @@ -0,0 +1,25 @@ +//! todo + +use crate::continuation::*; +use super::*; + +impl Body { + pub async fn tail_eval( + &self, + env: &Env, + cont: &Option>, + ) -> Result { + let Some(last) = self.forms.last() else { + return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Null)])); + }; + for (form, tail) in self.forms.skip_last() { + let cont = Some(Arc::new(Continuation::new( + Arc::new(ResumableBody::new(env, &tail)), + cont, + ))); + // Discard values that aren't returned + form.eval(env, &cont).await?; + } + last.tail_eval(env, cont).await + } +} diff --git a/src/ast/mod.rs b/src/ast/mod.rs new file mode 100644 index 0000000..ff05167 --- /dev/null +++ b/src/ast/mod.rs @@ -0,0 +1,299 @@ +mod eval; +pub mod parse; + +use nom::error::ParseError; + +use crate::{ + continuation::Continuation, + env::Env, + error::RuntimeError, + expand::Transformer, + gc::{Gc, Trace}, + num::Number, + proc::ValuesOrPreparedCall, + syntax::{ExpansionEnv, Identifier, Mark, Span, Syntax}, + util::ArcSlice, + value::Value, +}; +use std::sync::Arc; + +#[derive(Debug, Clone, Trace)] +pub enum AstNode { + Definition(Definition), + Expression(Expression), +} + +impl AstNode { + pub async fn eval( + &self, + env: &Env, + cont: &Option>, + ) -> Result>, RuntimeError> { + match self { + Self::Definition(def) => { + def.eval(env, cont).await?; + Ok(Vec::new()) + } + Self::Expression(expr) => expr.eval(env, cont).await, + } + } + + pub async fn tail_eval( + &self, + env: &Env, + cont: &Option>, + ) -> Result { + match self { + Self::Definition(def) => { + def.eval(env, cont).await?; + Ok(ValuesOrPreparedCall::Values(Vec::new())) + } + 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, + cont: &Option>, + ) -> Result<(), RuntimeError> { + todo!() + } + + pub async fn parse( + syn: &Syntax, + env: &Env, + cont: &Option>, + ) -> Result { + todo!() + } + + pub fn wrap(self, envs: Vec) -> Self { + todo!() + } +} + +#[derive(Debug, Clone, Trace)] +pub struct DefineVar { + pub name: Identifier, + pub val: Arc, +} + +#[derive(Debug, Clone, Trace)] +pub struct DefineFunc { + pub name: Identifier, + pub args: Formals, + pub body: Body, +} + +#[derive(Debug, Clone, Trace)] +pub enum Expression { + Literal(Literal), + Quote(Quote), + SyntaxQuote(SyntaxQuote), + Call(Call), + Lambda(Lambda), + Set(Set), + MacroExpansionPoint(MacroExpansionPoint), +} + +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)] +pub enum Literal { + Number(Number), + Boolean(bool), + Character(char), + String(String), + ByteVector(Vec), +} + +#[derive(Debug, Clone, Trace)] +pub struct Quote { + pub val: Value, +} + +#[derive(Debug, Clone, Trace)] +pub struct SyntaxQuote { + pub syn: Syntax, + pub env: Env, +} + +#[derive(Debug, Clone, Trace)] +pub struct Call { + pub args: ArcSlice>, + pub location: Span, + pub proc_name: String, +} + +#[derive(Debug, Clone, Trace)] +pub struct Lambda { + pub args: Formals, + pub body: Body, +} + +#[derive(Debug, Clone, Trace)] +pub struct Let { + pub bindings: Arc<[(Identifier, Arc)]>, + pub body: Body, +} + +impl Let { + pub fn new(bindings: Vec<(Identifier, Arc)>, body: Body) -> Self { + Self { + bindings: Arc::from(bindings), + body, + } + } +} + +#[derive(Debug, Clone, Trace)] +pub struct Set { + pub var: Identifier, + pub val: Arc, +} + +#[derive(Debug, Clone, Trace)] +pub struct If { + pub cond: Arc, + pub success: Arc, + pub failure: Option>, +} + +#[derive(Debug, Clone, Trace)] +pub enum Formals { + FixedArgs(Vec), + VarArgs { + fixed: Vec, + remaining: Identifier, + }, +} + +impl Formals { + pub fn to_args_and_remaining(&self) -> (Vec, Option) { + match self { + Self::VarArgs { fixed, remaining } => (fixed.clone(), Some(remaining.clone())), + Self::FixedArgs(args) => (args.clone(), None), + } + } +} + +#[derive(Debug, Clone, Trace)] +pub struct Body { + pub forms: ArcSlice, +} + +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::>()), + } + } +} + +#[derive(Clone, Trace)] +pub struct And { + pub args: ArcSlice, +} + +impl And { + pub fn new(args: Vec) -> Self { + Self { + args: ArcSlice::from(args), + } + } +} + +#[derive(Clone, Trace)] +pub struct Or { + pub args: ArcSlice, +} + +impl Or { + pub fn new(args: Vec) -> Self { + Self { + args: ArcSlice::from(args), + } + } +} + +#[derive(Clone, Trace)] +pub struct Vector { + pub vals: Vec, +} + +#[derive(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/mod.rs~ b/src/ast/mod.rs~ new file mode 100644 index 0000000..3ba1f32 --- /dev/null +++ b/src/ast/mod.rs~ @@ -0,0 +1,226 @@ +use crate::{ + continuation::Continuation, env::Env, error::RuntimeError, proc::ValuesOrPreparedCall, expand::Transformer, gc::{Gc, Trace}, num::Number, syntax::{Identifier, Mark, Span, Syntax}, util::ArcSlice, value::Value +}; +use std::sync::Arc; + +pub enum AstNode { + Definition(Definition), + Expression(Expression), +} + +impl AstNode { + async fn eval(&self, cont: &Option>) -> Result>, RuntimeError> { + match self { + Self::Definition(def) => todo!(), + Self::Expression(expr) => expr.eval(cont).await, + } + } +} + +#[derive(Debug, Clone, Trace)] +pub enum Definition { + DefineVar(DefineVar), + DefineFunc(DefineFunc), +} + +#[derive(Debug, Clone, Trace)] +pub struct DefineVar { + pub name: Identifier, + pub val: Arc, +} + +#[derive(Debug, Clone, Trace)] +pub struct DefineFunc { + pub name: Identifier, + pub args: Formals, + pub body: Body, +} + +#[derive(Debug, Clone, Trace)] +pub struct DefineSyntax { + pub name: Identifier, + pub expr: Arc +} + +#[derive(Debug, Clone, Trace)] +pub enum Expression { + Literal(Literal), + Quote(Quote), + SyntaxQuote(SyntaxQuote), + Call(Call), + Lambda(Lambda), + Set(Set), + MacroExpansionPoint(MacroExpansionPoint), +} + +impl Expression { + async fn eval(&self, cont: &Option>) -> Result>, RuntimeError> { + match self { + _ => todo!(), + } + } + + async fn tail_eval(&self, cont: &Option>) -> Result { + todo!() + } +} + +#[derive(Debug, Clone, PartialEq, Trace)] +pub enum Literal { + Number(Number), + Boolean(bool), + Character(char), + String(String), + ByteVector(Vec), +} + +#[derive(Debug, Clone, Trace)] +pub struct Quote { + pub val: Value, +} + +#[derive(Debug, Clone, Trace)] +pub struct SyntaxQuote { + pub syn: Syntax, + pub env: Env, +} + +#[derive(Debug, Clone, Trace)] +pub struct Call { + pub args: ArcSlice>, + pub location: Span, + pub proc_name: String, +} + +#[derive(Debug, Clone, Trace)] +pub struct Lambda { + pub args: Formals, + pub body: Body, +} + +#[derive(Debug, Clone, Trace)] +pub struct Let { + pub bindings: Arc<[(Identifier, Arc)]>, + pub body: Body, +} + +impl Let { + pub fn new(bindings: Vec<(Identifier, Arc)>, body: Body) -> Self { + Self { + bindings: Arc::from(bindings), + body, + } + } +} + +#[derive(Debug, Clone, Trace)] +pub struct Set { + pub var: Identifier, + pub val: Arc, +} + +#[derive(Debug, Clone, Trace)] +pub struct If { + pub cond: Arc, + pub success: Arc, + pub failure: Option>, +} + +#[derive(Debug, Clone, Trace)] +pub enum Formals { + FixedArgs(Vec), + VarArgs { + fixed: Vec, + remaining: Identifier, + }, +} + +impl Formals { + pub fn to_args_and_remaining(&self) -> (Vec, Option) { + match self { + Self::VarArgs { fixed, remaining } => (fixed.clone(), Some(remaining.clone())), + Self::FixedArgs(args) => (args.clone(), None), + } + } +} + +#[derive(Debug, Clone, Trace)] +pub struct Body { + pub defs: ArcSlice>, + pub exprs: ArcSlice>, +} + +impl Body { + pub fn new(defs: Vec>, exprs: Vec>) -> Self { + Self { + defs: ArcSlice::from(defs), + exprs: ArcSlice::from(exprs), + } + } +} + + +#[derive(Clone, Trace)] +pub struct And { + pub args: ArcSlice>, +} + +impl And { + pub fn new(args: Vec>) -> Self { + Self { + args: ArcSlice::from(args), + } + } +} + +#[derive(Clone, Trace)] +pub struct Or { + pub args: ArcSlice>, +} + +impl Or { + pub fn new(args: Vec>) -> Self { + Self { + args: ArcSlice::from(args), + } + } +} + +#[derive(Clone, Trace)] +pub struct Vector { + pub vals: Vec, +} + +#[derive(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 new file mode 100644 index 0000000..d1a4777 --- /dev/null +++ b/src/ast/parse.rs @@ -0,0 +1,886 @@ +//! todo + +use crate::{ + continuation::Continuation, + env::Env, + error::RuntimeError, + expand::{SyntaxRule, Transformer}, + gc::Gc, + syntax::{Expansion, FullyExpanded, Identifier, Span, Syntax}, + util::{ArcSlice, RequireOne}, + value::Value, +}; + +use super::*; + +use async_trait::async_trait; +use derive_more::From; +use futures::future::BoxFuture; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, +}; + +#[derive(Debug, Clone)] +pub enum ParseAstError { + BadForm(Span), + UnexpectedEmptyList(Span), + UndefinedVariable(Identifier), + RuntimeError(Box), + 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), +} + +impl From for ParseAstError { + fn from(re: RuntimeError) -> Self { + Self::RuntimeError(Box::new(re)) + } +} + +impl Body { + async fn parse( + body: &[Syntax], + env: &Env, + cont: &Option>, + span: &Span, + ) -> Result { + 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() { + defs_parsed.push( + Definition::parse(&def.expanded, env, cont) + .await? + .wrap(def.expansion_envs), + ); + } + + for expr in exprs.into_iter() { + exprs_parsed.push( + Expression::parse(&expr.expanded, env, cont) + .await? + .wrap(expr.expansion_envs), + ); + } + + Ok(Self::new(defs_parsed, exprs_parsed)) + } +} + + +fn splice_in<'a>( + defs: &'a mut Vec>, + exprs: &'a mut Vec>, + body: &'a [Syntax], + env: &'a Env, + cont: &'a Option>, + span: &'a Span, +) -> BoxFuture<'a, Result<(), ParseAstError>> +{ + Box::pin(async move { + if body.len() == 0 { + return Err(ParseAstError::EmptyBody(span.clone())); + } + + let mut expanded = Vec::new(); + for unexpanded in body { + expanded.push(unexpanded.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 { .. }]) + if ident == "begin" => + { + splice_in(defs, exprs, body, env, cont, span).await?; + continue; + } + Some([Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }]) + if ident == "define-syntax" => + { + define_syntax(ident, expr, env, cont).await?; + continue; + } + Some( + [Syntax::Identifier { ident, span, .. }, def, .., Syntax::Null { .. }], + ) if ident == "define" => { + if !exprs.is_empty() { + return Err(ParseAstError::DefInExprContext(span.clone())); + } + + let ident = match def.as_list() { + Some([Syntax::Identifier { ident, .. }, ..]) => ident, + _ => def + .as_ident() + .ok_or(ParseAstError::BadForm(def.span().clone()))?, + }; + env.def_var(ident, Gc::new(Value::Undefined)); + true + } + _ => false, + } + }; + + if is_def { + defs.push(expanded.to_owned()); + } else { + exprs.push(expanded.to_owned()); + } + } + + Ok(()) + }) +} + +async fn define_syntax( + ident: &Identifier, + expr: &Syntax, + env: &Env, + cont: &Option>, +) -> Result<(), ParseAstError> { + env.def_macro( + ident, + Expression::parse(expr, env, cont) + .await? + .eval(cont) + .await? + .require_one()?, + ); + Ok(()) +} + +/* +#[async_trait] +impl Parse for ast::Body { + type Error = ParseBodyError; + + async fn compile( + exprs: &[Syntax], + env: &Env, + 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?); + } + // TODO: what if the body isn't a proper list? + Ok(ast::Body::new(output)) + } +} + +#[derive(Debug, Clone)] +pub enum ParseLetError { + BadForm(Span), + ParseBodyError(ParseBodyError), + ParseLetBindingError(ParseLetBindingError), +} + +#[async_trait] +impl Parse for ast::Let { + type Error = ParseLetError; + + async fn compile( + expr: &[Syntax], + env: &Env, + cont: &Option>, + span: &Span, + ) -> Result { + match expr { + [Syntax::Null { .. }, body @ ..] => compile_let(None, &[], body, env, cont, span).await, + [Syntax::List { list: bindings, .. }, body @ ..] => { + compile_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 + } + [Syntax::Identifier { ident, .. }, Syntax::Null { .. }, body @ ..] => { + compile_let(Some(ident), &[], body, env, cont, span).await + } + _ => Err(ParseLetError::BadForm(span.clone())), + } + } +} + +async fn compile_let( + name: Option<&Identifier>, + bindings: &[Syntax], + body: &[Syntax], + env: &Env, + cont: &Option>, + span: &Span, +) -> Result { + let mut previously_bound = HashMap::new(); + let mut new_contour = env.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); + } + } + + let env = Gc::new(new_contour); + let body = ast::Body::compile(body, &Env::from(env.clone()), cont, span) + .await + .map_err(ParseLetError::ParseBodyError)?; + + let mut bindings: Vec<_> = compiled_bindings + .into_iter() + .map(|binding| (binding.ident, binding.expr)) + .collect(); + + // If this is a named let, add a binding for a procedure with the same + // 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(), + ), + body: body.clone(), + }; + bindings.push((name.clone(), Arc::new(lambda))); + } + + Ok(ast::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, +} + +impl LetBinding { + async fn compile( + expr: &Syntax, + env: &Env, + 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); + +#[async_trait] +impl Parse for ast::Call { + type Error = ParseFuncCallError; + + 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())), + } + } +} + +#[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( + exprs: &[Syntax], + env: &Env, + cont: &Option>, + span: &Span, + ) -> Result { + match exprs { + [cond, success, Syntax::Null { .. }] => Ok(ast::If { + cond: cond.compile(env, cont).await?, + success: success.compile(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?), + }), + [] => 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?, + })) + } + [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( + exprs: &[Syntax], + env: &Env, + cont: &Option>, + _span: &Span, + ) -> 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?; + output.push(expr); + } + Ok(Self::new(output)) + } +} + +#[async_trait] +impl Parse for ast::Or { + type Error = ParseError; + + async fn compile( + exprs: &[Syntax], + env: &Env, + cont: &Option>, + _span: &Span, + ) -> 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?; + 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( + exprs: &[Syntax], + env: &Env, + cont: &Option>, + span: &Span, + ) -> Result { + // TODO: We need to check if the identifier is defined as a variable transformer + 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?, + }), + [arg1, _, Syntax::Null { .. }] => { + Err(ParseSetError::ExpectedIdent(arg1.span().clone())) + } + [_, _, arg3, ..] => Err(ParseSetError::UnexpectedArgument(arg3.span().clone())), + _ => Err(ParseSetError::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 { + match exprs { + [] => Err(ParseSyntaxError::ExpectedArgument(span.clone())), + [expr, Syntax::Null { .. }] => Ok(ast::SyntaxQuote { + syn: expr.clone(), + env: env.clone(), + }), + [_, arg, ..] => Err(ParseSyntaxError::UnexpectedArgument(arg.span().clone())), + _ => Err(ParseSyntaxError::BadForm(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!(), + } + } +} + +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)); + } + + 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( + exprs: &[Syntax], + env: &Env, + cont: &Option>, + span: &Span, + ) -> Result { + let (arg, keywords, mut rules) = match exprs { + [arg, Syntax::List { list, .. }, rules @ ..] => { + let mut keywords = HashSet::default(); + // TODO: ensure keywords_list is proper + for keyword in &list[..list.len() - 1] { + if let Syntax::Identifier { ident, .. } = keyword { + keywords.insert(ident.name.clone()); + } else { + return Err(ParseSyntaxCaseError::BadForm(keyword.span().clone())); + } + } + (arg, keywords, rules) + } + [arg, Syntax::Null { .. }, rules @ ..] => (arg, HashSet::default(), rules), + _ => return Err(ParseSyntaxCaseError::BadForm(span.clone())), + }; + let mut syntax_rules = Vec::new(); + loop { + match rules { + [Syntax::Null { .. }] => 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(ParseSyntaxCaseError::BadForm(span.clone())), + } + } + Ok(ast::SyntaxCase { + arg: arg.compile(env, cont).await?, + transformer: Transformer { + rules: syntax_rules, + is_variable_transformer: false, + }, + }) + } +} + +*/ diff --git a/src/builtin.rs b/src/builtin.rs index 476a91e..d62ce91 100644 --- a/src/builtin.rs +++ b/src/builtin.rs @@ -1,6 +1,6 @@ use crate::{ continuation::Continuation, env::LexicalContour, error::RuntimeError, - eval::ValuesOrPreparedCall, gc::Gc, proc::ExternalFn, syntax::Identifier, value::Value, + proc::ValuesOrPreparedCall, gc::Gc, proc::ExternalFn, syntax::Identifier, value::Value, }; use futures::future::BoxFuture; use std::sync::Arc; diff --git a/src/compile.rs b/src/compile.rs index f856830..e69de29 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -1,795 +0,0 @@ -use crate::{ - ast, - continuation::Continuation, - env::Env, - error::RuntimeError, - eval::Eval, - expand::{SyntaxRule, Transformer}, - gc::Gc, - syntax::{Identifier, Span, Syntax}, - util::{ArcSlice, RequireOne}, - value::Value, -}; -use async_trait::async_trait; -use derive_more::From; -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, -}; - -#[derive(From, Debug, Clone)] -pub enum CompileError { - UnexpectedEmptyList(Span), - UndefinedVariable(Identifier), - RuntimeError(Box), - NotVariableTransformer, - CompileBodyError(CompileBodyError), - CompileLetError(CompileLetError), - CompileFuncCallError(CompileFuncCallError), - CompileIfError(CompileIfError), - CompileDefineError(CompileDefineError), - CompileDefineSyntaxError(CompileDefineSyntaxError), - CompileQuoteError(CompileQuoteError), - CompileSetError(CompileSetError), - CompileLambdaError(CompileLambdaError), - CompileSyntaxError(CompileSyntaxError), - CompileSyntaxCaseError(CompileSyntaxCaseError), - CompileDefineRecordTypeError(crate::records::CompileDefineRecordTypeError), -} - -impl From for CompileError { - fn from(re: RuntimeError) -> Self { - Self::RuntimeError(Box::new(re)) - } -} - -macro_rules! impl_from_compile_error { - ( $error:ident ) => { - impl From for $error { - fn from(ce: CompileError) -> Self { - Self::CompileError(Box::new(ce)) - } - } - }; -} - -#[async_trait] -pub trait Compile: Eval + Sized + 'static -where - CompileError: From, -{ - type Error; - - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result; - - async fn compile_to_expr( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result, CompileError> { - Ok(Arc::new(Self::compile(exprs, env, cont, span).await?)) - } -} - -#[derive(Debug, Clone)] -pub enum CompileBodyError { - EmptyBody(Span), - CompileError(Box), -} - -impl_from_compile_error!(CompileBodyError); - -#[async_trait] -impl Compile for ast::Body { - type Error = CompileBodyError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result { - if exprs.is_empty() { - return Err(CompileBodyError::EmptyBody(span.clone())); - } - let mut output = Vec::new(); - for expr in &exprs[..exprs.len() - 1] { - output.push(expr.compile(env, cont).await?); - } - // TODO: what if the body isn't a proper list? - Ok(ast::Body::new(output)) - } -} - -#[derive(Debug, Clone)] -pub enum CompileLetError { - BadForm(Span), - CompileBodyError(CompileBodyError), - CompileLetBindingError(CompileLetBindingError), -} - -#[async_trait] -impl Compile for ast::Let { - type Error = CompileLetError; - - async fn compile( - expr: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result { - match expr { - [Syntax::Null { .. }, body @ ..] => compile_let(None, &[], body, env, cont, span).await, - [Syntax::List { list: bindings, .. }, body @ ..] => { - compile_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 - } - [Syntax::Identifier { ident, .. }, Syntax::Null { .. }, body @ ..] => { - compile_let(Some(ident), &[], body, env, cont, span).await - } - _ => Err(CompileLetError::BadForm(span.clone())), - } - } -} - -async fn compile_let( - name: Option<&Identifier>, - bindings: &[Syntax], - body: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, -) -> Result { - let mut previously_bound = HashMap::new(); - let mut new_contour = env.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(CompileLetError::CompileLetBindingError)?; - previously_bound.insert(binding.ident.clone(), binding.span.clone()); - new_contour.def_var(&binding.ident, Gc::new(Value::Undefined)); - compiled_bindings.push(binding); - } - } - - let env = Gc::new(new_contour); - let body = ast::Body::compile(body, &Env::from(env.clone()), cont, span) - .await - .map_err(CompileLetError::CompileBodyError)?; - - let mut bindings: Vec<_> = compiled_bindings - .into_iter() - .map(|binding| (binding.ident, binding.expr)) - .collect(); - - // If this is a named let, add a binding for a procedure with the same - // 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(), - ), - body: body.clone(), - }; - bindings.push((name.clone(), Arc::new(lambda))); - } - - Ok(ast::Let { - bindings: Arc::from(bindings), - body, - }) -} - -#[derive(Debug, Clone)] -pub enum CompileLetBindingError { - BadForm(Span), - PreviouslyBound { - ident: Identifier, - first: Span, - second: Span, - }, - NotAList(Span), - CompileError(Box), -} - -impl_from_compile_error!(CompileLetBindingError); - -struct LetBinding { - ident: Identifier, - span: Span, - expr: Arc, -} - -impl LetBinding { - async fn compile( - expr: &Syntax, - env: &Env, - 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(CompileLetBindingError::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(CompileLetBindingError::BadForm(span.clone())), - }, - expr => Err(CompileLetBindingError::NotAList(expr.span().clone())), - } - } -} - -#[derive(From, Debug, Clone)] -pub enum CompileFuncCallError { - EmptyFunctionCall(Span), - CompileError(Box), -} - -impl_from_compile_error!(CompileFuncCallError); - -#[async_trait] -impl Compile for ast::Call { - type Error = CompileFuncCallError; - - 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(CompileFuncCallError::EmptyFunctionCall(span.clone())), - } - } -} - -#[derive(Debug, Clone)] -pub enum CompileIfError { - ExpectedConditional(Span), - ExpectedArgumentAfterConditional(Span), - UnexpectedArgument(Span), - CompileError(Box), -} - -impl_from_compile_error!(CompileIfError); - -#[async_trait] -impl Compile for ast::If { - type Error = CompileIfError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result { - match exprs { - [cond, success, Syntax::Null { .. }] => Ok(ast::If { - cond: cond.compile(env, cont).await?, - success: success.compile(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?), - }), - [] => Err(CompileIfError::ExpectedConditional(span.clone())), - [a1] => Err(CompileIfError::ExpectedArgumentAfterConditional( - a1.span().clone(), - )), - [_, _, _, unexpected, ..] => Err(CompileIfError::UnexpectedArgument( - unexpected.span().clone(), - )), - _ => unreachable!(), - } - } -} - -#[derive(Debug, Clone)] -pub enum CompileDefineError { - ParameterDefinedMultipleTimes { - ident: Identifier, - first: Span, - second: Span, - }, - ExpectedIdentifier(Span), - CompileBodyError(CompileBodyError), - BadForm(Span), - CompileError(Box), -} - -impl_from_compile_error!(CompileDefineError); - -#[async_trait] -impl Compile for ast::Define { - type Error = CompileDefineError; - - 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?, - })) - } - [Syntax::List { list, span }, body @ ..] => { - match &list[..] { - [] => Err(CompileDefineError::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( - CompileDefineError::ParameterDefinedMultipleTimes { - ident: ident.clone(), - first: prev_span.clone(), - second: span.clone(), - }, - ); - } - bound.insert(ident.clone(), span.clone()); - fixed.push(ident.clone()); - } - x => { - return Err(CompileDefineError::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( - CompileDefineError::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(CompileDefineError::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(CompileDefineError::CompileBodyError)?; - Ok(ast::Define::DefineFunc(ast::DefineFunc { - name: func_name.clone(), - args, - body, - })) - } - [x, ..] => Err(CompileDefineError::BadForm(x.span().clone())), - } - } - _ => Err(CompileDefineError::BadForm(span.clone())), - } - } -} - -#[derive(Debug, Clone)] -pub enum CompileDefineSyntaxError { - BadForm(Span), - CompileError(Box), - RuntimeError(Box), -} - -impl_from_compile_error!(CompileDefineSyntaxError); - -impl From for CompileDefineSyntaxError { - fn from(value: RuntimeError) -> Self { - Self::RuntimeError(Box::new(value)) - } -} - -#[async_trait] -impl Compile for ast::DefineSyntax { - type Error = CompileDefineSyntaxError; - - 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(CompileDefineSyntaxError::BadForm(span.clone())), - } - } -} - -#[derive(Debug, Clone)] -pub enum CompileQuoteError { - ExpectedArgument(Span), - UnexpectedArgument(Span), - BadForm(Span), -} - -#[async_trait] -impl Compile for ast::Quote { - type Error = CompileQuoteError; - - async fn compile( - exprs: &[Syntax], - _env: &Env, - _cont: &Option>, - span: &Span, - ) -> Result { - match exprs { - [] => Err(CompileQuoteError::ExpectedArgument(span.clone())), - [Syntax::Null { .. }] => Ok(ast::Quote { val: Value::Null }), - [expr, Syntax::Null { .. }] => Ok(ast::Quote { - val: Value::from_syntax(expr), - }), - [_, arg, ..] => Err(CompileQuoteError::UnexpectedArgument(arg.span().clone())), - _ => Err(CompileQuoteError::BadForm(span.clone())), - } - } -} - -#[async_trait] -impl Compile for ast::And { - type Error = CompileError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - _span: &Span, - ) -> 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?; - output.push(expr); - } - Ok(Self::new(output)) - } -} - -#[async_trait] -impl Compile for ast::Or { - type Error = CompileError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - _span: &Span, - ) -> 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?; - output.push(expr); - } - Ok(Self::new(output)) - } -} - -#[derive(Debug, Clone)] -pub enum CompileSetError { - ExpectedArgument(Span), - ExpectedIdent(Span), - UnexpectedArgument(Span), - BadForm(Span), - CompileError(Box), -} - -impl_from_compile_error!(CompileSetError); - -#[async_trait] -impl Compile for ast::Set { - type Error = CompileSetError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result { - // TODO: We need to check if the identifier is defined as a variable transformer - match exprs { - [] => Err(CompileSetError::ExpectedArgument(span.clone())), - [Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }] => Ok(ast::Set { - var: ident.clone(), - val: expr.compile(env, cont).await?, - }), - [arg1, _, Syntax::Null { .. }] => { - Err(CompileSetError::ExpectedIdent(arg1.span().clone())) - } - [_, _, arg3, ..] => Err(CompileSetError::UnexpectedArgument(arg3.span().clone())), - _ => Err(CompileSetError::BadForm(span.clone())), - } - } -} - -#[derive(Debug, Clone)] -pub enum CompileSyntaxError { - ExpectedArgument(Span), - UnexpectedArgument(Span), - BadForm(Span), -} - -#[async_trait] -impl Compile for ast::SyntaxQuote { - type Error = CompileSyntaxError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - _cont: &Option>, - span: &Span, - ) -> Result { - match exprs { - [] => Err(CompileSyntaxError::ExpectedArgument(span.clone())), - [expr, Syntax::Null { .. }] => Ok(ast::SyntaxQuote { - syn: expr.clone(), - env: env.clone(), - }), - [_, arg, ..] => Err(CompileSyntaxError::UnexpectedArgument(arg.span().clone())), - _ => Err(CompileSyntaxError::BadForm(span.clone())), - } - } -} - -#[derive(Debug, Clone)] -pub enum CompileLambdaError { - ExpectedList(Span), - ExpectedIdentifier(Span), - CompileBodyError(CompileBodyError), - ParameterDefinedMultipleTimes { - ident: Identifier, - first: Span, - second: Span, - }, -} - -#[async_trait] -impl Compile for ast::Lambda { - type Error = CompileLambdaError; - - 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(CompileLambdaError::CompileBodyError)?; - - Ok(ast::Lambda { - args: ast::Formals::VarArgs { - fixed: Vec::new(), - remaining: ident.clone(), - }, - body, - }) - } - _ => todo!(), - } - } -} - -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(CompileLambdaError::ParameterDefinedMultipleTimes { - ident: ident.clone(), - first: prev_span.clone(), - second: span.clone(), - }); - } - bound.insert(ident.clone(), span.clone()); - fixed.push(ident.clone()); - } - x => return Err(CompileLambdaError::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(CompileLambdaError::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(CompileLambdaError::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)); - } - - let body = ast::Body::compile(body, &Env::from(Gc::new(env)), cont, span) - .await - .map_err(CompileLambdaError::CompileBodyError)?; - Ok(ast::Lambda { args, body }) -} - -#[derive(Debug, Clone)] -pub enum CompileSyntaxCaseError { - CompileError(Box), - BadForm(Span), -} - -impl_from_compile_error!(CompileSyntaxCaseError); - -#[async_trait] -impl Compile for ast::SyntaxCase { - type Error = CompileSyntaxCaseError; - - async fn compile( - exprs: &[Syntax], - env: &Env, - cont: &Option>, - span: &Span, - ) -> Result { - let (arg, keywords, mut rules) = match exprs { - [arg, Syntax::List { list, .. }, rules @ ..] => { - let mut keywords = HashSet::default(); - // TODO: ensure keywords_list is proper - for keyword in &list[..list.len() - 1] { - if let Syntax::Identifier { ident, .. } = keyword { - keywords.insert(ident.name.clone()); - } else { - return Err(CompileSyntaxCaseError::BadForm(keyword.span().clone())); - } - } - (arg, keywords, rules) - } - [arg, Syntax::Null { .. }, rules @ ..] => (arg, HashSet::default(), rules), - _ => return Err(CompileSyntaxCaseError::BadForm(span.clone())), - }; - let mut syntax_rules = Vec::new(); - loop { - match rules { - [Syntax::Null { .. }] => break, - [Syntax::List { list, .. }, tail @ ..] => match &list[..] { - [pattern, template, Syntax::Null { .. }] => { - syntax_rules.push(SyntaxRule::compile(&keywords, pattern, template)); - rules = tail; - } - _ => return Err(CompileSyntaxCaseError::BadForm(span.clone())), - }, - _ => return Err(CompileSyntaxCaseError::BadForm(span.clone())), - } - } - Ok(ast::SyntaxCase { - arg: arg.compile(env, cont).await?, - transformer: Transformer { - rules: syntax_rules, - is_variable_transformer: false, - }, - }) - } -} diff --git a/src/continuation.rs b/src/continuation.rs index 3f8e48e..f996f13 100644 --- a/src/continuation.rs +++ b/src/continuation.rs @@ -2,13 +2,12 @@ use async_trait::async_trait; use proc_macros::builtin; use crate::{ - ast, + ast::{self, AstNode}, env::{Env, LexicalContour}, error::{RuntimeError, RuntimeErrorKind}, - eval::{Eval, ValuesOrPreparedCall}, expand::Transformer, gc::{Gc, Trace}, - proc::{Callable, PreparedCall, ProcDebugInfo}, + proc::{Callable, PreparedCall, ProcCallDebugInfo, ValuesOrPreparedCall}, syntax::{Identifier, Span}, util::{ArcSlice, RequireOne}, value::Value, @@ -105,6 +104,7 @@ impl Callable for Option> { } } +/* #[derive(Trace)] pub struct CatchContinuationCall { inner: Arc, @@ -141,15 +141,16 @@ impl Eval for CatchContinuationCall { inner } } +*/ #[derive(Trace)] pub struct ResumableBody { env: Env, - remaining: ArcSlice>, + remaining: ArcSlice, } impl ResumableBody { - pub fn new(env: &Env, remaining: &ArcSlice>) -> Self { + pub fn new(env: &Env, remaining: &ArcSlice) -> Self { Self { env: env.clone(), remaining: remaining.clone(), @@ -167,12 +168,12 @@ impl Resumable for ResumableBody { let Some(last) = self.remaining.last() else { return Ok(args); }; - for (expr, tail) in self.remaining.skip_last() { + for (form, tail) in self.remaining.skip_last() { let cont = Some(Arc::new(Continuation::new( Arc::new(ResumableBody::new(&self.env, &tail)), cont, ))); - expr.eval(&self.env, &cont).await?; + form.eval(&self.env, &cont).await?; } last.eval(&self.env, cont).await } @@ -185,6 +186,7 @@ impl Resumable for ResumableBody { } } +/* #[derive(Trace)] pub struct ResumableSyntaxCase { env: Env, @@ -583,7 +585,7 @@ impl Resumable for ResumableCall { } PreparedCall::prepare( collected, - Some(ProcDebugInfo::new(&self.proc_name, &self.location)), + Some(ProcCallDebugInfo::new(&self.proc_name, &self.location)), ) .eval(cont) .await @@ -694,3 +696,4 @@ pub async fn call_with_values( .eval(cont) .await } +*/ diff --git a/src/env.rs b/src/env.rs index f7462ce..5b4caa9 100644 --- a/src/env.rs +++ b/src/env.rs @@ -3,12 +3,11 @@ use std::collections::HashMap; use crate::{ builtin::Builtin, - compile::CompileError, error::RuntimeError, gc::{init_gc, Gc}, lex::{LexError, Token}, parse::ParseError, - syntax::{Identifier, Mark, ParsedSyntax}, + syntax::{Identifier, Mark}, value::Value, }; @@ -211,6 +210,7 @@ impl Env { /// 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(); @@ -219,8 +219,11 @@ impl Env { results.push(result); } Ok(results) + */ + todo!() } + pub fn deep_clone(&self) -> Self { match self { Self::Top => Self::Top, @@ -251,6 +254,6 @@ enum MacroLookup { pub enum EvalError<'e> { LexError(LexError<'e>), ParseError(ParseError<'e>), - CompileError(CompileError), + // CompileError(CompileError), RuntimeError(RuntimeError), } diff --git a/src/error.rs b/src/error.rs index 9ccb5bd..96ab470 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,9 +1,9 @@ use crate::{ - compile::CompileError, continuation::Continuation, gc::Gc, syntax::{Identifier, Span}, value::Value, + ast::parse::ParseAstError, }; use derivative::Derivative; use std::sync::Arc; @@ -35,7 +35,7 @@ pub enum RuntimeErrorKind { actual: String, }, DivisionByZero, - CompileError(CompileError), + ParseAstError(ParseAstError), AbandonCurrentContinuation { #[derivative(Debug = "ignore")] args: Vec>, @@ -140,6 +140,7 @@ impl RuntimeError { } } +/* impl From for RuntimeError { fn from(ce: CompileError) -> Self { Self { @@ -148,6 +149,7 @@ impl From for RuntimeError { } } } +*/ /* impl fmt::Debug for RuntimeError { diff --git a/src/eval.rs b/src/eval.rs index 7053961..fab479a 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -15,35 +15,6 @@ use crate::{ use async_trait::async_trait; use std::{collections::BTreeSet, sync::Arc}; -pub enum ValuesOrPreparedCall { - Values(Vec>), - PreparedCall(PreparedCall), -} - -impl From>> for ValuesOrPreparedCall { - fn from(values: Vec>) -> Self { - Self::Values(values) - } -} - -impl From for ValuesOrPreparedCall { - fn from(prepared_call: PreparedCall) -> ValuesOrPreparedCall { - Self::PreparedCall(prepared_call) - } -} - -impl ValuesOrPreparedCall { - pub async fn eval( - self, - cont: &Option>, - ) -> Result>, RuntimeError> { - match self { - Self::Values(val) => Ok(val), - Self::PreparedCall(prepared_call) => prepared_call.eval(cont).await, - } - } -} - /// Core evaulation trait for expressions. /// /// Any struct implementing this trait must either implement `eval`, `tail_eval`, or @@ -444,7 +415,7 @@ impl Eval for ast::SyntaxCase { } #[async_trait] -impl Eval for ast::FetchVar { +impl Eval for ast::Var { async fn eval( &self, env: &Env, diff --git a/src/lib.rs b/src/lib.rs index accc858..b12d22c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,11 +2,11 @@ extern crate self as scheme_rs; pub mod ast; pub mod builtin; -pub mod compile; +// pub mod compile; pub mod continuation; pub mod env; pub mod error; -pub mod eval; +// pub mod eval; pub mod expand; pub mod futures; pub mod gc; diff --git a/src/main.rs b/src/main.rs index 2fdc7a1..2e647a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,13 @@ +/* use reedline::{Reedline, Signal, ValidationResult, Validator}; -use scheme_rs::{env::Env, lex::Token, parse::ParseError, syntax::ParsedSyntax}; +use scheme_rs::{env::Env, lex::Token, parse::ParseError}; use std::{ borrow::Cow, sync::{Arc, Mutex}, -}; +};e +*/ +/* type ParsedResult = Option, String>>; struct InputParser { @@ -53,9 +56,11 @@ 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(), @@ -101,4 +106,6 @@ async fn main() { } } } + */ + todo!() } diff --git a/src/proc.rs b/src/proc.rs index b925f8c..31d4339 100644 --- a/src/proc.rs +++ b/src/proc.rs @@ -4,7 +4,6 @@ use crate::{ continuation::Continuation, env::Env, error::{Frame, RuntimeError}, - eval::{Eval, ValuesOrPreparedCall}, gc::Gc, lists::list_to_vec, syntax::{Identifier, Span}, @@ -15,6 +14,35 @@ use futures::future::BoxFuture; use proc_macros::Trace; use std::sync::Arc; +pub enum ValuesOrPreparedCall { + Values(Vec>), + PreparedCall(PreparedCall), +} + +impl From>> for ValuesOrPreparedCall { + fn from(values: Vec>) -> Self { + Self::Values(values) + } +} + +impl From for ValuesOrPreparedCall { + fn from(prepared_call: PreparedCall) -> ValuesOrPreparedCall { + Self::PreparedCall(prepared_call) + } +} + +impl ValuesOrPreparedCall { + pub async fn eval( + self, + cont: &Option>, + ) -> Result>, RuntimeError> { + match self { + Self::Values(val) => Ok(val), + Self::PreparedCall(prepared_call) => prepared_call.eval(cont).await, + } + } +} + #[async_trait] pub trait Callable: Send + Sync + 'static { fn min_args(&self) -> usize; @@ -111,7 +139,7 @@ impl Callable for ExternalFn { } pub struct PreparedCall { - proc_debug_info: Option, + proc_debug_info: Option, operator: Gc, args: Vec>, } @@ -125,7 +153,7 @@ impl PreparedCall { let mut bt = Vec::new(); loop { let proc = curr_proc.take().unwrap(); - if let Some(ProcDebugInfo { + if let Some(ProcCallDebugInfo { proc_name, location, }) = proc.proc_debug_info @@ -166,7 +194,7 @@ impl PreparedCall { } /// Such a strange interface. Whatever. FIXME - pub fn prepare(args: Vec>, proc_debug_info: Option) -> Self { + pub fn prepare(args: Vec>, proc_debug_info: Option) -> Self { let operator = args[0].clone(); let args = args[1..].to_owned(); Self { @@ -177,12 +205,12 @@ impl PreparedCall { } } -pub struct ProcDebugInfo { +pub struct ProcCallDebugInfo { proc_name: String, location: Span, } -impl ProcDebugInfo { +impl ProcCallDebugInfo { pub fn new(proc_name: &str, location: &Span) -> Self { Self { proc_name: proc_name.to_string(), diff --git a/src/records.rs b/src/records.rs index dea8375..3a514a7 100644 --- a/src/records.rs +++ b/src/records.rs @@ -4,11 +4,11 @@ use async_trait::async_trait; use crate::{ ast, - compile::Compile, + // compile::Compile, continuation::Continuation, env::Env, error::RuntimeError, - eval::Eval, + // eval::Eval, gc::{Gc, Trace}, proc::Procedure, syntax::{Identifier, Mark, Span, Syntax}, @@ -97,6 +97,7 @@ enum FieldDefinitionKind { Immutable, } +/* #[derive(Debug, Clone)] pub enum CompileDefineRecordTypeError { ParentSpecifiedMultiple { first: Span, second: Span }, @@ -374,7 +375,7 @@ impl Eval for DefineRecordType { // Append the return value setters.push( - Arc::new(ast::FetchVar::new(Identifier::new("this".to_string()))) as Arc, + Arc::new(ast::Var::new(Identifier::new("this".to_string()))) as Arc, ); let constructor = new_proc( @@ -604,3 +605,4 @@ impl Eval for RecordPredicate { )))]) } } +*/ diff --git a/src/syntax.rs b/src/syntax.rs index 334f9c9..75a0844 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -1,10 +1,10 @@ use crate::{ - ast::{self, FetchVar, Literal, MacroExpansionPoint}, - compile::{Compile, CompileError}, - continuation::{CatchContinuationCall, Continuation}, + ast::{self, Var, Literal, MacroExpansionPoint}, + // compile::{Compile, CompileError}, + continuation::Continuation, env::Env, error::RuntimeError, - eval::Eval, + // eval::Eval, gc::{Gc, Trace}, lex::{InputSpan, Lexeme, Token}, lists::list_to_vec_with_null, @@ -15,7 +15,7 @@ use crate::{ }; use futures::future::BoxFuture; use proc_macros::builtin; -use std::{collections::BTreeSet, fmt, sync::Arc}; +use std::{borrow::Cow, collections::BTreeSet, fmt, sync::Arc}; #[derive(Debug, Clone, PartialEq, Trace)] pub struct Span { @@ -202,7 +202,7 @@ impl Syntax { macro_env: Env, cont: &Option>, transformer: Gc, - ) -> Result, RuntimeError> { + ) -> Result { // Create a new mark for the expansion context let new_mark = Mark::new(); // Apply the new mark to the input @@ -234,11 +234,11 @@ impl Syntax { }) } - fn expand<'a>( + fn expand_once<'a>( &'a self, env: &'a Env, cont: &'a Option>, - ) -> BoxFuture<'a, Result, RuntimeError>> { + ) -> BoxFuture<'a, Result> { Box::pin(async move { match self { Self::List { list, .. } => { @@ -246,7 +246,7 @@ impl Syntax { // for now. We will expand it later in the proc call let ident = match list.first() { Some(Self::Identifier { ident, .. }) => ident, - _ => return Ok(Expansion::Unexpanded(self)), + _ => return Ok(Expansion::Unexpanded), }; if let Some((macro_env, transformer)) = env.fetch_macro(ident) { return self @@ -263,10 +263,39 @@ impl Syntax { } _ => (), } - Ok(Expansion::Unexpanded(self)) + Ok(Expansion::Unexpanded) }) } + /// 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(); + let mut expansion = Cow::Borrowed(self); + loop { + match expansion.expand_once(env, cont).await? { + Expansion::Unexpanded => { + return Ok(FullyExpanded { + expansion_envs, + expanded: expansion, + }) + }, + Expansion::Expanded { mark, macro_env, syntax } => { + expansion_envs.push(ExpansionEnv::new(mark, macro_env)); + expansion = Cow::Owned(syntax); + } + } + } + } + + pub fn as_list(&self) -> Option<&[Syntax]> { + todo!() + } + + pub fn as_ident(&self) -> Option<&Identifier> { + todo!() + } + + /* pub async fn compile_expanded( &self, env: &Env, @@ -280,7 +309,7 @@ impl Syntax { } // Regular identifiers: Self::Identifier { ident, .. } => { - Ok(Arc::new(FetchVar::new(ident.clone())) as Arc) + 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[..] { @@ -366,12 +395,13 @@ impl Syntax { cont: &Option>, ) -> Result, CompileError> { self.expand(env, cont).await?.compile(env, cont).await - } +} + */ } -pub enum Expansion<'a> { +pub enum Expansion { /// Syntax remained unchanged after expansion - Unexpanded(&'a Syntax), + Unexpanded, /// Syntax was expanded, producing a new expansion context Expanded { mark: Mark, @@ -380,6 +410,7 @@ pub enum Expansion<'a> { }, } +/* impl Expansion<'_> { pub fn is_expanded(&self) -> bool { matches!(self, Self::Expanded { .. }) @@ -389,7 +420,40 @@ impl Expansion<'_> { matches!(self, Self::Unexpanded(_)) } } + */ +pub struct ExpansionEnv { + mark: Mark, + macro_env: Env, +} + +impl ExpansionEnv { + fn new(mark: Mark, macro_env: Env) -> Self { + todo!() + } +} + +pub struct FullyExpanded<'a> { + pub expansion_envs: Vec, + pub expanded: Cow<'a, Syntax>, +} + +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()), + } + } +} + +/* impl<'a> Expansion<'a> { pub fn compile( self, @@ -419,6 +483,9 @@ impl<'a> Expansion<'a> { } } +*/ + +/* #[derive(Debug)] pub struct ParsedSyntax { pub doc_comment: Option, @@ -468,6 +535,7 @@ impl ParsedSyntax { ))) } } +*/ #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Trace)] pub struct Mark(usize); @@ -603,6 +671,8 @@ impl Syntax { } } +/* + #[builtin("syntax->datum")] pub async fn syntax_to_datum( _cont: &Option>, @@ -636,3 +706,4 @@ pub async fn datum_to_syntax( datum, )))]) } +*/ From e0f9b2262d225300b42080cbe6c4c2e97d67a8d9 Mon Sep 17 00:00:00 2001 From: Matthew Plant Date: Tue, 24 Dec 2024 21:05:09 -0500 Subject: [PATCH 2/7] Remove backup file --- src/ast/mod.rs~ | 226 ------------------------------------------------ 1 file changed, 226 deletions(-) delete mode 100644 src/ast/mod.rs~ diff --git a/src/ast/mod.rs~ b/src/ast/mod.rs~ deleted file mode 100644 index 3ba1f32..0000000 --- a/src/ast/mod.rs~ +++ /dev/null @@ -1,226 +0,0 @@ -use crate::{ - continuation::Continuation, env::Env, error::RuntimeError, proc::ValuesOrPreparedCall, expand::Transformer, gc::{Gc, Trace}, num::Number, syntax::{Identifier, Mark, Span, Syntax}, util::ArcSlice, value::Value -}; -use std::sync::Arc; - -pub enum AstNode { - Definition(Definition), - Expression(Expression), -} - -impl AstNode { - async fn eval(&self, cont: &Option>) -> Result>, RuntimeError> { - match self { - Self::Definition(def) => todo!(), - Self::Expression(expr) => expr.eval(cont).await, - } - } -} - -#[derive(Debug, Clone, Trace)] -pub enum Definition { - DefineVar(DefineVar), - DefineFunc(DefineFunc), -} - -#[derive(Debug, Clone, Trace)] -pub struct DefineVar { - pub name: Identifier, - pub val: Arc, -} - -#[derive(Debug, Clone, Trace)] -pub struct DefineFunc { - pub name: Identifier, - pub args: Formals, - pub body: Body, -} - -#[derive(Debug, Clone, Trace)] -pub struct DefineSyntax { - pub name: Identifier, - pub expr: Arc -} - -#[derive(Debug, Clone, Trace)] -pub enum Expression { - Literal(Literal), - Quote(Quote), - SyntaxQuote(SyntaxQuote), - Call(Call), - Lambda(Lambda), - Set(Set), - MacroExpansionPoint(MacroExpansionPoint), -} - -impl Expression { - async fn eval(&self, cont: &Option>) -> Result>, RuntimeError> { - match self { - _ => todo!(), - } - } - - async fn tail_eval(&self, cont: &Option>) -> Result { - todo!() - } -} - -#[derive(Debug, Clone, PartialEq, Trace)] -pub enum Literal { - Number(Number), - Boolean(bool), - Character(char), - String(String), - ByteVector(Vec), -} - -#[derive(Debug, Clone, Trace)] -pub struct Quote { - pub val: Value, -} - -#[derive(Debug, Clone, Trace)] -pub struct SyntaxQuote { - pub syn: Syntax, - pub env: Env, -} - -#[derive(Debug, Clone, Trace)] -pub struct Call { - pub args: ArcSlice>, - pub location: Span, - pub proc_name: String, -} - -#[derive(Debug, Clone, Trace)] -pub struct Lambda { - pub args: Formals, - pub body: Body, -} - -#[derive(Debug, Clone, Trace)] -pub struct Let { - pub bindings: Arc<[(Identifier, Arc)]>, - pub body: Body, -} - -impl Let { - pub fn new(bindings: Vec<(Identifier, Arc)>, body: Body) -> Self { - Self { - bindings: Arc::from(bindings), - body, - } - } -} - -#[derive(Debug, Clone, Trace)] -pub struct Set { - pub var: Identifier, - pub val: Arc, -} - -#[derive(Debug, Clone, Trace)] -pub struct If { - pub cond: Arc, - pub success: Arc, - pub failure: Option>, -} - -#[derive(Debug, Clone, Trace)] -pub enum Formals { - FixedArgs(Vec), - VarArgs { - fixed: Vec, - remaining: Identifier, - }, -} - -impl Formals { - pub fn to_args_and_remaining(&self) -> (Vec, Option) { - match self { - Self::VarArgs { fixed, remaining } => (fixed.clone(), Some(remaining.clone())), - Self::FixedArgs(args) => (args.clone(), None), - } - } -} - -#[derive(Debug, Clone, Trace)] -pub struct Body { - pub defs: ArcSlice>, - pub exprs: ArcSlice>, -} - -impl Body { - pub fn new(defs: Vec>, exprs: Vec>) -> Self { - Self { - defs: ArcSlice::from(defs), - exprs: ArcSlice::from(exprs), - } - } -} - - -#[derive(Clone, Trace)] -pub struct And { - pub args: ArcSlice>, -} - -impl And { - pub fn new(args: Vec>) -> Self { - Self { - args: ArcSlice::from(args), - } - } -} - -#[derive(Clone, Trace)] -pub struct Or { - pub args: ArcSlice>, -} - -impl Or { - pub fn new(args: Vec>) -> Self { - Self { - args: ArcSlice::from(args), - } - } -} - -#[derive(Clone, Trace)] -pub struct Vector { - pub vals: Vec, -} - -#[derive(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, - } - } -} From bd1602238a421f2443b1cf8989102f8ba3c0af57 Mon Sep 17 00:00:00 2001 From: Matthew Plant Date: Wed, 25 Dec 2024 20:08:36 -0500 Subject: [PATCH 3/7] Get everything building. This should be mostly correct --- src/ast/eval.rs | 330 ++++++++++++- src/ast/mod.rs | 169 +++---- src/ast/parse.rs | 1155 ++++++++++++++++++++----------------------- src/builtin.rs | 7 +- src/continuation.rs | 331 +++++++------ src/env.rs | 354 ++++++++++++- src/error.rs | 10 +- src/eval.rs | 440 ----------------- src/expand.rs | 5 - src/main.rs | 72 +-- src/proc.rs | 10 +- src/syntax.rs | 306 +++++++----- src/value.rs | 21 +- tests/r6rs.scm | 15 + 14 files changed, 1685 insertions(+), 1540 deletions(-) delete mode 100644 src/eval.rs 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)))))) From f5f474e021e141424ed04469b08da04dcf03904f Mon Sep 17 00:00:00 2001 From: Matthew Plant Date: Thu, 26 Dec 2024 10:46:45 -0500 Subject: [PATCH 4/7] Get most things back to working --- src/ast/eval.rs | 5 +- src/ast/mod.rs | 14 +- src/ast/parse.rs | 54 +++---- src/builtin.rs | 8 +- src/continuation.rs | 51 ++----- src/env.rs | 359 ++++++++++++-------------------------------- src/main.rs | 5 +- src/proc.rs | 2 +- src/records.rs | 4 +- src/syntax.rs | 207 +++---------------------- src/value.rs | 5 +- tests/r6rs.rs | 9 +- 12 files changed, 175 insertions(+), 548 deletions(-) diff --git a/src/ast/eval.rs b/src/ast/eval.rs index de93df4..c737e70 100644 --- a/src/ast/eval.rs +++ b/src/ast/eval.rs @@ -111,7 +111,6 @@ impl Expression { 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))?])), } }) @@ -185,7 +184,7 @@ impl Let { env: &Gc, cont: &Option>, ) -> Result { - let scope = Gc::new(env.read().new_lexical_contour()); + 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)), @@ -312,7 +311,7 @@ impl Set { .require_one()? .read() .clone(); - self.var.set(env, &Gc::new(val)); + self.var.set(env, &Gc::new(val)).await; Ok(()) } } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 6d015a1..0e429a1 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1,7 +1,6 @@ mod eval; pub mod parse; -use nom::error::ParseError; use parse::define_syntax; use crate::{ @@ -12,7 +11,7 @@ use crate::{ gc::{Gc, Trace}, num::Number, proc::ValuesOrPreparedCall, - syntax::{ExpansionCtx, FullyExpanded, Identifier, Mark, Span, Syntax}, + syntax::{FullyExpanded, Identifier, Span, Syntax}, util::ArcSlice, value::Value, }; @@ -63,7 +62,7 @@ impl AstNode { expanded, expansion_envs, } = syn.expand(&expansion_env, cont).await?; - let expansion_env = expansion_env.new_expansion_env(expansion_envs); + let expansion_env = expansion_env.push_expansion_env(expansion_envs); Self::from_syntax_with_expansion_env(expanded, &expansion_env, cont).await } @@ -73,11 +72,11 @@ impl AstNode { cont: &Option>, ) -> Result, parse::ParseAstError> { match syn.as_list() { - Some([Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }]) - if ident.name == "define-syntax" => - { + Some( + [Syntax::Identifier { ident, .. }, Syntax::Identifier { ident: name, .. }, 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?; + define_syntax(name, expr.clone(), &env.lexical_contour, cont).await?; Ok(None) } Some(syn @ [Syntax::Identifier { ident, span, .. }, ..]) if ident.name == "define" => { @@ -130,7 +129,6 @@ pub enum Expression { Begin(Body), } - #[derive(Debug, Clone, PartialEq, Trace)] // Vector should be in here too. Oh well. pub enum Literal { diff --git a/src/ast/parse.rs b/src/ast/parse.rs index 48b0b88..9b6d1f0 100644 --- a/src/ast/parse.rs +++ b/src/ast/parse.rs @@ -1,19 +1,16 @@ -//! todo - use crate::{ continuation::Continuation, env::Env, error::RuntimeError, expand::{SyntaxRule, Transformer}, gc::Gc, - syntax::{Expansion, FullyExpanded, Identifier, Span, Syntax}, + syntax::{FullyExpanded, Identifier, Span, Syntax}, util::{ArcSlice, RequireOne}, value::Value, }; use super::*; -use async_trait::async_trait; use derive_more::From; use futures::future::BoxFuture; use std::{ @@ -71,7 +68,7 @@ impl Definition { .. }, args @ ..] => { let mut bound = HashMap::::new(); - let mut new_env = env.lexical_contour.read().new_lexical_contour(); + let mut new_env = env.lexical_contour.new_lexical_contour(); let mut fixed = Vec::new(); // Bind the arguments to a new environment: @@ -125,7 +122,7 @@ impl Definition { Formals::FixedArgs(Vec::new()) }; - let new_env = env.new_lexical_contour(Gc::new(new_env)); + let new_env = env.push_lexical_contour(Gc::new(new_env)); // Parse the body: let body = Body::parse(body, &new_env, cont, func_span).await?; @@ -166,7 +163,7 @@ impl Body { let mut exprs_parsed = Vec::new(); for def in defs.into_iter() { - let new_expansion_env = env.new_expansion_env(def.expansion_envs); + let new_expansion_env = env.push_expansion_env(def.expansion_envs); defs_parsed.push( Definition::parse( def.expanded.as_list().unwrap(), @@ -179,7 +176,7 @@ impl Body { } for expr in exprs.into_iter() { - let new_expansion_env = env.new_expansion_env(expr.expansion_envs); + let new_expansion_env = env.push_expansion_env(expr.expansion_envs); exprs_parsed.push( Expression::parse_expanded(expr.expanded, &new_expansion_env, cont).await?, ); @@ -285,7 +282,7 @@ pub(super) async fn define_syntax( expanded, expansion_envs, } = expr.expand(&expansion_env, cont).await?; - let expansion_env = expansion_env.new_expansion_env(expansion_envs); + let expansion_env = expansion_env.push_expansion_env(expansion_envs); let value = Expression::parse(expanded, &expansion_env, cont) .await? .eval(env, cont) @@ -305,7 +302,7 @@ impl Expression { expanded, expansion_envs, } = syn.expand(&env, cont).await?; - let expansion_env = env.new_expansion_env(expansion_envs); + let expansion_env = env.push_expansion_env(expansion_envs); Self::parse_expanded(expanded, &expansion_env, cont).await } @@ -336,9 +333,11 @@ impl Expression { Syntax::Vector { vector, .. } => Ok(Self::Vector(Vector::parse(&vector))), // Functional forms: - Syntax::List { list: exprs, span, .. } => match exprs.as_slice() { + Syntax::List { + list: exprs, span, .. + } => match exprs.as_slice() { // Special forms: - [Syntax::Identifier { ident, .. }, tail @ .., Syntax::Null { .. }] + [Syntax::Identifier { ident, .. }, tail @ .., Syntax::Null { .. }] if ident.name == "begin" => { Body::parse_in_expr_context(tail, env, cont) @@ -378,14 +377,18 @@ impl Expression { Quote::parse(tail, span).await.map(Expression::Quote) } [Syntax::Identifier { ident, span, .. }, tail @ .., Syntax::Null { .. }] - if ident.name == "syntax-quote" => + if ident.name == "syntax" => { - SyntaxQuote::parse(tail, span).await.map(Expression::SyntaxQuote) + 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) + SyntaxCase::parse(tail, env, cont, span) + .await + .map(Expression::SyntaxCase) } // Extra special form (set!): @@ -396,7 +399,7 @@ impl Expression { } // Definition in expression context is illegal: - [Syntax::Identifier { ident, span, .. }, .., Syntax::Null { .. }] + [Syntax::Identifier { ident, span, .. }, .., Syntax::Null { .. }] if ident.name == "define" => { return Err(ParseAstError::DefInExprContext(span.clone())); @@ -404,7 +407,9 @@ impl Expression { // Regular old function call: [operator, args @ .., Syntax::Null { .. }] => { - Call::parse(operator.clone(), args, env, cont).await.map(Expression::Call) + Call::parse(operator.clone(), args, env, cont) + .await + .map(Expression::Call) } _ => return Err(ParseAstError::BadForm(span.clone())), @@ -469,7 +474,7 @@ async fn parse_lambda( ) -> Result { let mut bound = HashMap::::new(); let mut fixed = Vec::new(); - let mut new_contour = env.lexical_contour.read().new_lexical_contour(); + let mut new_contour = env.lexical_contour.new_lexical_contour(); if !args.is_empty() { for arg in &args[..args.len() - 1] { @@ -516,7 +521,7 @@ async fn parse_lambda( Formals::FixedArgs(Vec::new()) }; - let new_env = env.new_lexical_contour(Gc::new(new_contour)); + let new_env = env.push_lexical_contour(Gc::new(new_contour)); let body = Body::parse(body, &new_env, cont, span).await?; Ok(Lambda { args, body }) @@ -555,7 +560,7 @@ async fn parse_let( span: &Span, ) -> Result { let mut previously_bound = HashMap::new(); - let mut new_contour = env.lexical_contour.read().new_lexical_contour(); + let mut new_contour = env.lexical_contour.new_lexical_contour(); let mut compiled_bindings = Vec::new(); match bindings { @@ -571,7 +576,7 @@ async fn parse_let( _ => return Err(ParseAstError::BadForm(span.clone())), } - let new_env = env.new_lexical_contour(Gc::new(new_contour)); + let new_env = env.push_lexical_contour(Gc::new(new_contour)); let body = Body::parse(body, &new_env, cont, span).await?; let mut bindings: Vec<_> = compiled_bindings @@ -734,18 +739,15 @@ impl Vector { for expr in exprs { vals.push(Value::from_syntax(expr)); } - Self { vals } + Self { vals } } } - impl SyntaxQuote { async fn parse(exprs: &[Syntax], span: &Span) -> Result { match exprs { [] => Err(ParseAstError::ExpectedArgument(span.clone())), - [expr] => Ok(SyntaxQuote { - syn: expr.clone(), - }), + [expr] => Ok(SyntaxQuote { syn: expr.clone() }), [_, arg, ..] => Err(ParseAstError::UnexpectedArgument(arg.span().clone())), } } diff --git a/src/builtin.rs b/src/builtin.rs index c9e702e..2c62bb4 100644 --- a/src/builtin.rs +++ b/src/builtin.rs @@ -1,5 +1,11 @@ use crate::{ - continuation::Continuation, env::Env, error::RuntimeError, gc::Gc, proc::{ExternalFn, ValuesOrPreparedCall}, 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; diff --git a/src/continuation.rs b/src/continuation.rs index 809acf6..392b2bd 100644 --- a/src/continuation.rs +++ b/src/continuation.rs @@ -171,13 +171,10 @@ impl Resumable for ResumableDefineVar { } fn clone_stack(&self) -> Arc { - /* Arc::new(Self { env: self.env.deep_clone(), name: self.name.clone(), }) - */ - todo!() } } @@ -217,13 +214,10 @@ impl Resumable for ResumableBody { } fn clone_stack(&self) -> Arc { - /* Arc::new(Self { env: self.env.deep_clone(), remaining: self.remaining.clone(), }) - */ - todo!() } } @@ -276,15 +270,12 @@ impl Resumable for ResumableLet { } fn clone_stack(&self) -> Arc { - /* Arc::new(Self { - scope: Gc::new(self.scope.read().deep_clone()), + scope: self.scope.deep_clone(), curr: self.curr.clone(), remaining_bindings: self.remaining_bindings.clone(), body: self.body.clone(), }) - */ - todo!() } } @@ -327,14 +318,11 @@ impl Resumable for ResumableIf { } fn clone_stack(&self) -> Arc { - /* Arc::new(Self { env: self.env.deep_clone(), success: self.success.clone(), failure: self.failure.clone(), }) - */ - todo!() } } @@ -388,12 +376,10 @@ impl Resumable for ResumableAnd { } fn clone_stack(&self) -> Arc { - /* - Arc::new(Self { - env: self.env.deep_clone(), - args: self.args.clone(), - })*/ - todo!() + Arc::new(Self { + env: self.env.deep_clone(), + args: self.args.clone(), + }) } } @@ -447,13 +433,10 @@ impl Resumable for ResumableOr { } 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!() } } @@ -481,18 +464,15 @@ impl Resumable for ResumableSet { ) -> Result>, RuntimeError> { let arg = args.require_one()?; let val = arg.read().clone(); - self.var.set(&self.env, &Gc::new(val)); + self.var.set(&self.env, &Gc::new(val)).await; Ok(Vec::new()) } fn clone_stack(&self) -> Arc { - /* - Arc::new(Self { - env: self.env.deep_clone(), - var: self.var.clone(), + Arc::new(Self { + env: self.env.deep_clone(), + var: self.var.clone(), }) - */ - todo!() } } @@ -535,13 +515,10 @@ impl Resumable for ResumableSyntaxCase { } fn clone_stack(&self) -> Arc { - /* Arc::new(Self { env: self.env.deep_clone(), transformer: self.transformer.clone(), }) - */ - todo!() } } @@ -614,7 +591,6 @@ impl Resumable for ResumableCall { } fn clone_stack(&self) -> Arc { - /* Arc::new(Self { env: self.env.deep_clone(), collected: self.collected.clone(), @@ -622,8 +598,6 @@ impl Resumable for ResumableCall { proc_name: self.proc_name.clone(), location: self.location.clone(), }) - */ - todo!() } } @@ -649,7 +623,6 @@ pub async fn call_cc( .await } - #[derive(Clone, Trace)] pub struct CallWithValues { min_args: usize, diff --git a/src/env.rs b/src/env.rs index 2fae7cf..892cd0f 100644 --- a/src/env.rs +++ b/src/env.rs @@ -1,6 +1,6 @@ use indexmap::IndexSet; use proc_macros::Trace; -use std::{borrow::Cow, collections::HashMap}; +use std::collections::HashMap; use tokio::sync::OnceCell; use crate::{ @@ -10,7 +10,7 @@ use crate::{ gc::{init_gc, Gc}, lex::{LexError, Token}, parse::ParseError, - syntax::{ExpansionCtx, Identifier, Mark, ParsedSyntax}, + syntax::{ExpansionCtx, Identifier, ParsedSyntax}, value::Value, }; @@ -39,6 +39,9 @@ impl Env { pub async fn top() -> Gc { TOP_LEVEL_ENV .get_or_init(|| async { + init_gc(); + println!("init gc"); + let mut top = Env::default(); // Install the builtins: @@ -46,9 +49,12 @@ impl Env { builtin.install(&mut top); } + println!("builtins installed"); + // Install the stdlib: let top = Gc::new(top); let _ = top.eval(include_str!("stdlib.scm")).await.unwrap(); + println!("evaling"); top }) @@ -56,10 +62,6 @@ impl Env { .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 { @@ -90,8 +92,8 @@ impl Env { /// 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 { + let (idx, new) = self.var_names.insert_full(ident.clone()); + if !new { self.vars[idx] = val; } else { self.vars.push(val); @@ -133,7 +135,18 @@ impl Env { } impl Gc { + /// Create a new lexical contour that is a child of self. + pub fn new_lexical_contour(&self) -> Env { + Env { + up: Some(self.clone()), + vars: Vec::with_capacity(1), // There will probably always be at least one var + var_names: IndexSet::default(), + macros: HashMap::new(), + } + } + /// Evaluate a string, returning all of the results in a Vec + // TODO: Add file name pub async fn eval<'e>(&self, exprs: &'e str) -> Result>>, EvalError<'e>> { let tokens = Token::tokenize_str(exprs)?; let sexprs = ParsedSyntax::parse(&tokens)?; @@ -148,6 +161,16 @@ impl Gc { } Ok(results) } + + pub fn deep_clone(&self) -> Self { + let this = self.read(); + Gc::new(Env { + up: this.up.as_ref().map(|up| up.deep_clone()), + vars: this.vars.clone(), + var_names: this.var_names.clone(), + macros: this.macros.clone(), + }) + } } #[derive(derive_more::From, Debug)] @@ -202,6 +225,10 @@ impl MacroVarRef { pub fn fetch(&self) -> Gc { self.env.read().fetch_var(self.var_ref) } + + pub fn set(&self, value: &Gc) { + self.env.write().set_var(self.var_ref, value.clone()); + } } /// References a variable in the global scope. Essentially, any variable that is @@ -218,9 +245,40 @@ impl GlobalRef { } // Throw error when variable is undefined - pub async fn fetch(&self) -> Option> { - todo!() + pub fn fetch(&self, default: &Gc) -> Option> { + let top = if let Some(top) = TOP_LEVEL_ENV.get() { + top.clone() + } else { + // Currently installing the top level environment. + get_top_env_from_curr(default.clone()) + }; + + let top = top.read(); + let Some(var) = top.fetch_var_ref(&self.name) else { + return None; + }; + Some(top.fetch_var(var)) + } + + pub fn set(&self, default: &Gc, value: &Gc) { + let top = if let Some(top) = TOP_LEVEL_ENV.get() { + top.clone() + } else { + // Currently installing the top level environment. + get_top_env_from_curr(default.clone()) + }; + top.write().def_local_var(&self.name, value.clone()); + } +} + +fn get_top_env_from_curr(mut curr: Gc) -> Gc { + while let Some(up) = { + let curr = curr.read(); + curr.up.as_ref().cloned() + } { + curr = up.clone(); } + curr } /// A reference that can either be global, macro, or regular @@ -232,12 +290,20 @@ pub enum Ref { } impl Ref { - pub fn set(&self, env: &Gc, value: &Gc) { - todo!() + pub fn fetch(&self, env: &Gc) -> Result, Identifier> { + match self { + Self::Macro(m) => Ok(m.fetch()), + Self::Global(g) => g.fetch(env).ok_or_else(|| g.name.clone()), + Self::Regular(v) => Ok(env.read().fetch_var(*v)), + } } - pub async fn fetch(&self, env: &Gc) -> Result, Identifier> { - todo!() + pub async fn set(&self, env: &Gc, value: &Gc) { + match self { + Self::Macro(m) => m.set(value), + Self::Global(g) => g.set(env, value), + Self::Regular(v) => env.write().set_var(*v, value.clone()), + } } } @@ -277,12 +343,20 @@ impl ExpansionEnv<'_> { !matches!(self.fetch_var_ref(ident), Ref::Global(_)) } - pub fn new_expansion_env<'a>(&'a self, ctxs: Vec) -> ExpansionEnv<'a> { - todo!() + pub fn push_expansion_env<'a>(&'a self, ctxs: Vec) -> ExpansionEnv<'a> { + ExpansionEnv { + lexical_contour: self.lexical_contour.clone(), + up: Some(self), + expansion_ctxs: ctxs, + } } - pub fn new_lexical_contour<'a>(&'a self, gc: Gc) -> ExpansionEnv<'a> { - todo!() + pub fn push_lexical_contour<'a>(&'a self, gc: Gc) -> ExpansionEnv<'a> { + ExpansionEnv { + up: Some(self), + expansion_ctxs: Vec::new(), + lexical_contour: gc, + } } pub fn fetch_var_ref(&self, ident: &Identifier) -> Ref { @@ -358,252 +432,3 @@ impl ExpansionEnv<'_> { } } } - -/* -#[derive(derive_more::Debug, Trace)] -pub struct LexicalContour { - #[debug(skip)] - pub up: Env, - #[debug("{:?}", vars.keys().cloned().collect::>())] - vars: HashMap>, - #[debug("{:?}", macros.keys().cloned().collect::>())] - macros: HashMap>, -} - -impl LexicalContour { - pub fn is_bound(&self, ident: &Identifier) -> bool { - self.vars.contains_key(ident) || self.macros.contains_key(ident) || self.up.is_bound(ident) - } - - fn fetch_var(&self, ident: &Identifier) -> Option> { - if let Some(var) = self.vars.get(ident) { - return Some(var.clone()); - } - // Macros are also variables - if let Some(var) = self.macros.get(ident) { - return Some(var.clone()); - } - // Check the next lexical scope up - self.up.fetch_var(ident) - } - - fn fetch_macro(&self, ident: &Identifier) -> Option { - // Only check the macro definitions - if let Some(var) = self.macros.get(ident) { - return Some(MacroLookup::WithoutEnv(var.clone())); - } - self.up.fetch_macro(ident).map(MacroLookup::WithEnv) - } - - pub fn def_var(&mut self, ident: &Identifier, value: Gc) { - // If the identifier is defined as a macro, remove it. - if self.macros.contains_key(ident) { - self.macros.remove(ident); - } - self.vars.insert(ident.clone(), value); - } - - pub fn def_macro(&mut self, ident: &Identifier, value: Gc) { - // If the identifier is defined as a variable, remove it - if self.vars.contains_key(ident) { - self.vars.remove(ident); - } - self.macros.insert(ident.clone(), value); - } - - pub fn deep_clone(&self) -> Self { - Self { - up: self.up.deep_clone(), - vars: self.vars.clone(), - macros: self.macros.clone(), - } - } -} - -#[derive(derive_more::Debug, Trace)] -pub struct ExpansionContext { - up: Env, - mark: Mark, - #[debug(skip)] - macro_env: Env, -} - -impl ExpansionContext { - pub fn is_bound(&self, ident: &Identifier) -> bool { - if ident.marks.contains(&self.mark) { - let mut stripped = ident.clone(); - stripped.mark(self.mark); - self.macro_env.is_bound(&stripped) - } else { - self.up.is_bound(ident) - } - } - - pub fn fetch_var(&self, ident: &Identifier) -> Option> { - // If the ident contains this mark, it comes from the macro and - // we must fetch from the macro's environment. - if ident.marks.contains(&self.mark) { - let mut stripped = ident.clone(); - stripped.mark(self.mark); - self.macro_env.fetch_var(&stripped) - } else { - self.up.fetch_var(ident) - } - } - - pub fn fetch_macro(&self, ident: &Identifier) -> Option<(Env, Gc)> { - if ident.marks.contains(&self.mark) { - let mut stripped = ident.clone(); - stripped.mark(self.mark); - self.macro_env.fetch_macro(&stripped) - } else { - self.up.fetch_macro(ident) - } - } - - pub fn deep_clone(&self) -> Self { - Self { - up: self.up.deep_clone(), - mark: self.mark, - macro_env: self.macro_env.deep_clone(), - } - } -} - -#[derive(Clone, Trace, Debug)] -pub enum Env { - /// This is the top level environment - Top, - /// This is an expansion context - Expansion(Gc), - /// This is a lexical contour - LexicalContour(Gc), -} - -impl Env { - pub fn is_bound(&self, ident: &Identifier) -> bool { - match self { - Self::Top => false, - Self::Expansion(expansion) => expansion.read().is_bound(ident), - Self::LexicalContour(env) => env.read().is_bound(ident), - } - } - - pub fn fetch_var(&self, ident: &Identifier) -> Option> { - match self { - Self::Top => None, - Self::Expansion(expansion) => expansion.read().fetch_var(ident), - Self::LexicalContour(env) => env.read().fetch_var(ident), - } - } - - pub fn fetch_macro(&self, ident: &Identifier) -> Option<(Env, Gc)> { - match self { - Self::Top => None, - Self::Expansion(expansion) => expansion.read().fetch_macro(ident), - Self::LexicalContour(env) => match env.read().fetch_macro(ident) { - Some(MacroLookup::WithEnv((env, value))) => Some((env, value)), - Some(MacroLookup::WithoutEnv(value)) => Some((self.clone(), value)), - _ => None, - }, - } - } - - pub async fn top() -> Self { - // We should probably find another place to init_gc, but this is honestly fine - init_gc(); - - let mut top = Self::Top.new_lexical_contour(); - // Install the builtins: - for builtin in inventory::iter:: { - builtin.install(&mut top); - } - let top = Self::LexicalContour(Gc::new(top)); - // Install the stdlib: - let _ = top.eval(include_str!("stdlib.scm")).await.unwrap(); - top - } - - pub fn new_lexical_contour(&self) -> LexicalContour { - LexicalContour { - up: self.clone(), - // mark, - vars: HashMap::default(), - macros: HashMap::default(), - } - } - - pub fn new_expansion_context(&self, mark: Mark, macro_env: Env) -> ExpansionContext { - ExpansionContext { - up: self.clone(), - mark, - macro_env, - } - } - - pub fn def_var(&self, ident: &Identifier, value: Gc) { - match self { - Self::Top => unreachable!(), - Self::Expansion(expansion) => expansion.read().up.def_var(ident, value), - Self::LexicalContour(contour) => contour.write().def_var(ident, value), - } - } - - pub fn def_macro(&self, ident: &Identifier, value: Gc) { - match self { - Self::Top => unreachable!(), - Self::Expansion(expansion) => expansion.read().up.def_macro(ident, value), - Self::LexicalContour(contour) => contour.write().def_macro(ident, value), - } - } - - /// 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 result = sexpr.compile(self, &None).await?.eval(self, &None).await?; - results.push(result); - } - Ok(results) - */ - todo!() - } - - - pub fn deep_clone(&self) -> Self { - match self { - Self::Top => Self::Top, - Self::Expansion(expansion) => Self::Expansion(Gc::new(expansion.read().deep_clone())), - Self::LexicalContour(env) => Self::LexicalContour(Gc::new(env.read().deep_clone())), - } - } -} - -impl From> for Env { - fn from(env: Gc) -> Self { - Self::Expansion(env) - } -} - -impl From> for Env { - fn from(env: Gc) -> Self { - Self::LexicalContour(env) - } -} - -enum MacroLookup { - WithEnv((Env, Gc)), - WithoutEnv(Gc), -} - -#[derive(derive_more::From, Debug)] -pub enum EvalError<'e> { - LexError(LexError<'e>), - ParseError(ParseError<'e>), - // CompileError(CompileError), - RuntimeError(RuntimeError), -} -*/ diff --git a/src/main.rs b/src/main.rs index f5973b6..0958dfa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,6 @@ use reedline::{Reedline, Signal, ValidationResult, Validator}; use scheme_rs::{env::Env, lex::Token, parse::ParseError, syntax::ParsedSyntax}; -use std::{ - borrow::Cow, -}; +use std::borrow::Cow; struct InputParser; @@ -51,6 +49,7 @@ async fn main() { let mut rl = Reedline::create().with_validator(Box::new(InputParser)); let mut n_results = 1; let top = Env::top().await; + println!("installed"); loop { let Ok(Signal::Success(input)) = rl.read_line(&Prompt) else { println!("exiting..."); diff --git a/src/proc.rs b/src/proc.rs index 5d08ac7..f70bc78 100644 --- a/src/proc.rs +++ b/src/proc.rs @@ -82,7 +82,7 @@ impl Callable for Procedure { args: Vec>, cont: &Option>, ) -> Result { - let env = Gc::new(self.up.read().new_lexical_contour()); + let env = Gc::new(self.up.new_lexical_contour()); let provided = args.len(); let mut args_iter = args.iter().peekable(); diff --git a/src/records.rs b/src/records.rs index 3a514a7..4a4439b 100644 --- a/src/records.rs +++ b/src/records.rs @@ -1,6 +1,4 @@ -use std::{collections::HashMap, sync::Arc}; - -use async_trait::async_trait; +use std::collections::HashMap; use crate::{ ast, diff --git a/src/syntax.rs b/src/syntax.rs index e18cf15..2caa8be 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -1,21 +1,18 @@ use crate::{ - ast::{self, Literal}, - // compile::{Compile, CompileError}, + ast::Literal, continuation::Continuation, env::{Env, ExpansionEnv}, error::RuntimeError, - // eval::Eval, gc::{Gc, Trace}, lex::{InputSpan, Lexeme, Token}, lists::list_to_vec_with_null, parse::ParseError, - records, util::RequireOne, value::Value, }; use futures::future::BoxFuture; use proc_macros::builtin; -use std::{borrow::Cow, collections::BTreeSet, fmt, sync::Arc}; +use std::{collections::BTreeSet, fmt, sync::Arc}; #[derive(Debug, Clone, PartialEq, Trace)] pub struct Span { @@ -287,28 +284,6 @@ 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(); - let mut expansion = Cow::Borrowed(self); - loop { - match expansion.expand_once(env, cont).await? { - Expansion::Unexpanded => { - return Ok(FullyExpanded { - expansion_envs, - expanded: expansion, - }) - }, - Expansion::Expanded { mark, macro_env, syntax } => { - expansion_envs.push(ExpansionCtx::new(mark, macro_env)); - expansion = Cow::Owned(syntax); - } - } - } - } - */ - /// Fully expand the outermost syntax object. pub async fn expand( mut self, @@ -335,121 +310,6 @@ impl Syntax { } } } - - pub async fn test(self: Arc) -> i32 { - todo!() - } - - pub fn as_list(&self) -> Option<&[Syntax]> { - todo!() - } - - pub fn as_ident(&self) -> Option<&Identifier> { - todo!() - } - - /* - 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 - } - [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; - } - } - 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?), - } - } - 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 enum Expansion { @@ -463,18 +323,6 @@ pub enum Expansion { }, } -/* -impl Expansion<'_> { - pub fn is_expanded(&self) -> bool { - matches!(self, Self::Expanded { .. }) - } - - pub fn is_unexpanded(&self) -> bool { - matches!(self, Self::Unexpanded(_)) - } -} - */ - pub struct ExpansionCtx { pub mark: Mark, pub env: Gc, @@ -497,38 +345,6 @@ impl AsRef for FullyExpanded { } } -/* -impl<'a> Expansion<'a> { - pub fn compile( - self, - env: &'a Env, - cont: &'a Option>, - ) -> BoxFuture<'a, Result, CompileError>> { - Box::pin(async move { - match self { - Self::Unexpanded(syntax) => syntax.compile_expanded(env, cont).await, - Self::Expanded { - mark, - syntax, - macro_env, - } => { - // If the expression has been expanded, we may need to expand it again, but - // it must be done in a new expansion context. - let env = - Env::Expansion(Gc::new(env.new_expansion_context(mark, macro_env.clone()))); - Ok(Arc::new(MacroExpansionPoint::new( - mark, - macro_env, - syntax.expand(&env, cont).await?.compile(&env, cont).await?, - )) as Arc) - } - } - }) - } -} - -*/ - #[derive(Debug)] pub struct ParsedSyntax { pub doc_comment: Option, @@ -657,6 +473,14 @@ impl Syntax { matches!(self, Self::Null { .. }) } + pub fn as_ident(&self) -> Option<&Identifier> { + if let Syntax::Identifier { ident, .. } = self { + Some(ident) + } else { + None + } + } + pub fn new_list(list: Vec, span: impl Into) -> Self { Self::List { list, @@ -664,6 +488,14 @@ impl Syntax { } } + pub fn as_list(&self) -> Option<&[Syntax]> { + if let Syntax::List { list, .. } = self { + Some(list) + } else { + None + } + } + pub fn is_list(&self) -> bool { matches!(self, Self::List { .. }) } @@ -703,8 +535,6 @@ impl Syntax { } } -/* - #[builtin("syntax->datum")] pub async fn syntax_to_datum( _cont: &Option>, @@ -738,4 +568,3 @@ pub async fn datum_to_syntax( datum, )))]) } -*/ diff --git a/src/value.rs b/src/value.rs index 4cc6789..082fe64 100644 --- a/src/value.rs +++ b/src/value.rs @@ -38,10 +38,7 @@ pub enum Value { impl Value { pub fn is_callable(&self) -> bool { - matches!( - self, - Self::Procedure(_) | Self::ExternalFn(_) - ) + matches!(self, Self::Procedure(_) | Self::ExternalFn(_)) } /// #f is false, everything else is true diff --git a/tests/r6rs.rs b/tests/r6rs.rs index d458212..a433543 100644 --- a/tests/r6rs.rs +++ b/tests/r6rs.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use scheme_rs::{ + ast::AstNode, builtin, continuation::Continuation, env::Env, @@ -33,12 +34,12 @@ async fn r6rs() { let r6rs_tok = Token::tokenize_file(include_str!("r6rs.scm"), "r6rs.scm").unwrap(); let r6rs_sexprs = ParsedSyntax::parse(&r6rs_tok).unwrap(); for sexpr in r6rs_sexprs { - sexpr - .compile(&top, &None) + let result = AstNode::from_syntax(sexpr.syntax, &top, &None) .await .unwrap() - .eval(&top, &None) - .await .unwrap(); + + // TODO: Catch continuation calls + let _ = result.eval(&top, &None).await.unwrap(); } } From e6dfe233b6dd9f9914404866e7dbbd1f0e299c4c Mon Sep 17 00:00:00 2001 From: Matthew Plant Date: Thu, 26 Dec 2024 19:56:14 -0500 Subject: [PATCH 5/7] WIP --- benches/fib.rs | 14 +------ src/ast/eval.rs | 4 +- src/ast/mod.rs | 7 +++- src/ast/parse.rs | 41 ++++++++++--------- src/continuation.rs | 43 +------------------- src/env.rs | 97 ++++++++++++++++++++++++++++++++++----------- src/lex.rs | 6 +-- src/lib.rs | 2 +- src/main.rs | 3 +- src/records.rs | 2 + src/syntax.rs | 15 ++++--- src/value.rs | 22 +++++----- tests/r6rs.rs | 15 ++----- tests/r6rs.scm | 15 ------- 14 files changed, 141 insertions(+), 145 deletions(-) diff --git a/benches/fib.rs b/benches/fib.rs index 7076c5f..f62ab62 100644 --- a/benches/fib.rs +++ b/benches/fib.rs @@ -1,21 +1,11 @@ -use scheme_rs::{env::Env, lex::Token, syntax::ParsedSyntax}; +use scheme_rs::env::Env; use criterion::*; async fn fib() { let top = Env::top().await; - let r6rs_tok = Token::tokenize_file(include_str!("fib.scm"), "fib.scm").unwrap(); - let r6rs_sexprs = ParsedSyntax::parse(&r6rs_tok).unwrap(); - for sexpr in r6rs_sexprs { - sexpr - .compile(&top, &None) - .await - .unwrap() - .eval(&top, &None) - .await - .unwrap(); - } + let _ = top.eval("fib.scm", include_str!("fib.scm")).await.unwrap(); } fn fib_benchmark(c: &mut Criterion) { diff --git a/src/ast/eval.rs b/src/ast/eval.rs index c737e70..3547919 100644 --- a/src/ast/eval.rs +++ b/src/ast/eval.rs @@ -90,6 +90,7 @@ impl Expression { env: &'a Gc, cont: &'a Option>, ) -> BoxFuture<'a, Result> { + //println!("expr: {self:#?}"); Box::pin(async move { match self { Self::Undefined => val(Value::Undefined), @@ -158,6 +159,7 @@ impl Call { let arg = arg.eval(env, &Some(cont)).await?.require_one()?; collected.push(arg); } + // println!("prepared: {:#?}", env); Ok(ValuesOrPreparedCall::PreparedCall(PreparedCall::prepare( collected, Some(ProcCallDebugInfo::new(&self.proc_name, &self.location)), @@ -190,7 +192,7 @@ impl Let { Arc::new(ResumableLet::new(&scope, ident, remaining, &self.body)), cont, )); - let val = expr.eval(&scope, &Some(cont)).await?.require_one()?; + let val = expr.eval(env, &Some(cont)).await?.require_one()?; scope.write().def_local_var(ident, val); } self.body.tail_eval(&scope, cont).await diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 0e429a1..47edb69 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -60,7 +60,7 @@ impl AstNode { let expansion_env = ExpansionEnv::from_env(env); let FullyExpanded { expanded, - expansion_envs, + expansion_ctxs: expansion_envs, } = syn.expand(&expansion_env, cont).await?; let expansion_env = expansion_env.push_expansion_env(expansion_envs); Self::from_syntax_with_expansion_env(expanded, &expansion_env, cont).await @@ -75,10 +75,15 @@ impl AstNode { Some( [Syntax::Identifier { ident, .. }, Syntax::Identifier { ident: name, .. }, expr, Syntax::Null { .. }], ) if ident.name == "define-syntax" => { + // println!("defining here {}", ident.name); // TODO: Error if define syntax isn't proper, error. + // println!("mod.rs:80"); define_syntax(name, expr.clone(), &env.lexical_contour, cont).await?; Ok(None) } + Some([Syntax::Identifier { ident, span, .. }, ..]) if ident.name == "define-syntax" => { + return Err(parse::ParseAstError::BadForm(span.clone())); + } Some(syn @ [Syntax::Identifier { ident, span, .. }, ..]) if ident.name == "define" => { Ok(Some(Self::Definition( Definition::parse(syn, env, cont, span).await?, diff --git a/src/ast/parse.rs b/src/ast/parse.rs index 9b6d1f0..e88e374 100644 --- a/src/ast/parse.rs +++ b/src/ast/parse.rs @@ -163,7 +163,7 @@ impl Body { let mut exprs_parsed = Vec::new(); for def in defs.into_iter() { - let new_expansion_env = env.push_expansion_env(def.expansion_envs); + let new_expansion_env = env.push_expansion_env(def.expansion_ctxs); defs_parsed.push( Definition::parse( def.expanded.as_list().unwrap(), @@ -176,7 +176,7 @@ impl Body { } for expr in exprs.into_iter() { - let new_expansion_env = env.push_expansion_env(expr.expansion_envs); + let new_expansion_env = env.push_expansion_env(expr.expansion_ctxs); exprs_parsed.push( Expression::parse_expanded(expr.expanded, &new_expansion_env, cont).await?, ); @@ -218,12 +218,8 @@ where return Err(ParseAstError::EmptyBody(span.clone())); } - let mut expanded = Vec::new(); for unexpanded in body { - expanded.push(unexpanded.clone().expand(env, cont).await?); - } - - for expanded in expanded.into_iter() { + let expanded = unexpanded.clone().expand(env, cont).await?; let is_def = { match expanded.as_ref().as_list() { Some([Syntax::Identifier { ident, .. }, body @ .., Syntax::Null { .. }]) @@ -232,10 +228,10 @@ where splice_in(defs, exprs, body, env, cont, span).await?; continue; } - Some([Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }]) - if ident == "define-syntax" => - { - define_syntax(ident, expr.clone(), &env.lexical_contour, cont).await?; + Some( + [Syntax::Identifier { ident, .. }, Syntax::Identifier { ident: name, .. }, expr, Syntax::Null { .. }], + ) if ident == "define-syntax" => { + define_syntax(name, expr.clone(), &env.lexical_contour, cont).await?; continue; } Some( @@ -256,6 +252,11 @@ where .def_local_var(ident, Gc::new(Value::Undefined)); true } + Some([Syntax::Identifier { ident, span, .. }, ..]) + if ident == "define-syntax" => + { + return Err(ParseAstError::BadForm(span.clone())); + } _ => false, } }; @@ -280,7 +281,7 @@ pub(super) async fn define_syntax( let expansion_env = ExpansionEnv::from_env(env); let FullyExpanded { expanded, - expansion_envs, + expansion_ctxs: expansion_envs, } = expr.expand(&expansion_env, cont).await?; let expansion_env = expansion_env.push_expansion_env(expansion_envs); let value = Expression::parse(expanded, &expansion_env, cont) @@ -300,7 +301,7 @@ impl Expression { ) -> Result { let FullyExpanded { expanded, - expansion_envs, + expansion_ctxs: expansion_envs, } = syn.expand(&env, cont).await?; let expansion_env = env.push_expansion_env(expansion_envs); Self::parse_expanded(expanded, &expansion_env, cont).await @@ -371,7 +372,7 @@ impl Expression { { Or::parse(tail, env, cont).await.map(Expression::Or) } - [Syntax::Identifier { ident, span, .. }, tail @ .., Syntax::Null { .. }] + [Syntax::Identifier { ident, span, .. }, tail @ ..] if ident.name == "quote" => { Quote::parse(tail, span).await.map(Expression::Quote) @@ -564,7 +565,7 @@ async fn parse_let( let mut compiled_bindings = Vec::new(); match bindings { - [Syntax::Null { .. }] => (), + [] | [Syntax::Null { .. }] => (), [bindings @ .., Syntax::Null { .. }] => { for binding in bindings { let binding = LetBinding::parse(binding, env, cont, &previously_bound).await?; @@ -573,7 +574,9 @@ async fn parse_let( compiled_bindings.push(binding); } } - _ => return Err(ParseAstError::BadForm(span.clone())), + _ => { + return Err(ParseAstError::BadForm(span.clone())); + } } let new_env = env.push_lexical_contour(Gc::new(new_contour)); @@ -724,11 +727,13 @@ impl Set { impl Quote { async fn parse(exprs: &[Syntax], span: &Span) -> Result { match exprs { - [] => Err(ParseAstError::ExpectedArgument(span.clone())), - [expr] => Ok(Quote { + [] => Err(dbg!(ParseAstError::ExpectedArgument(span.clone()))), + [Syntax::Null { .. }] => Ok(Quote { val: Value::Null }), + [expr, Syntax::Null { .. }] => Ok(Quote { val: Value::from_syntax(expr), }), [_, arg, ..] => Err(ParseAstError::UnexpectedArgument(arg.span().clone())), + _ => Err(ParseAstError::BadForm(span.clone())), } } } diff --git a/src/continuation.rs b/src/continuation.rs index 392b2bd..87d1565 100644 --- a/src/continuation.rs +++ b/src/continuation.rs @@ -2,9 +2,9 @@ use async_trait::async_trait; use proc_macros::builtin; use crate::{ - ast::{self, AstNode, Body, Expression}, + ast::{AstNode, Body, Expression}, env::{Env, ExpansionEnv, Ref}, - error::{RuntimeError, RuntimeErrorKind}, + error::RuntimeError, expand::Transformer, gc::{Gc, Trace}, proc::{Callable, PreparedCall, ProcCallDebugInfo, ValuesOrPreparedCall}, @@ -104,45 +104,6 @@ impl Callable for Option> { } } -/* -#[derive(Trace)] -pub struct CatchContinuationCall { - inner: Arc, -} - -impl CatchContinuationCall { - pub fn new(inner: Arc) -> Self { - Self { inner } - } -} - -#[async_trait] -impl Eval for CatchContinuationCall { - async fn eval( - &self, - env: &Env, - cont: &Option>, - ) -> Result>, RuntimeError> { - let mut inner = self.inner.eval(env, cont).await; - while let Err(RuntimeError { - kind: RuntimeErrorKind::AbandonCurrentContinuation { args, new_cont }, - .. - }) = inner - { - // Abandon the current continuation and evaluate the newly returned one - // TODO: Retain the backtrace for errors - // let arg = args.pop().unwrap(); - if let Some(new_cont) = new_cont { - inner = new_cont.resume(args, cont).await; - } else { - return Ok(args); - } - } - inner - } -} - */ - #[derive(Trace)] pub struct ResumableDefineVar { env: Gc, diff --git a/src/env.rs b/src/env.rs index 892cd0f..e2e90b1 100644 --- a/src/env.rs +++ b/src/env.rs @@ -6,7 +6,8 @@ use tokio::sync::OnceCell; use crate::{ ast::{parse::ParseAstError, AstNode}, builtin::Builtin, - error::RuntimeError, + continuation::Resumable, + error::{RuntimeError, RuntimeErrorKind}, gc::{init_gc, Gc}, lex::{LexError, Token}, parse::ParseError, @@ -16,10 +17,11 @@ use crate::{ /// An Environment, or store of variables and macros with a reference to its containing /// lexical scope. -#[derive(Debug, Default, Trace)] +#[derive(derive_more::Debug, Default, Trace)] pub struct Env { /// The containing environment of this environment, or None if this is a top level /// environment. + #[debug(skip)] 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 @@ -40,7 +42,6 @@ impl Env { TOP_LEVEL_ENV .get_or_init(|| async { init_gc(); - println!("init gc"); let mut top = Env::default(); @@ -49,12 +50,12 @@ impl Env { builtin.install(&mut top); } - println!("builtins installed"); - // Install the stdlib: let top = Gc::new(top); - let _ = top.eval(include_str!("stdlib.scm")).await.unwrap(); - println!("evaling"); + let _ = top + .eval("stdlib.scm", include_str!("stdlib.scm")) + .await + .unwrap(); top }) @@ -147,21 +148,52 @@ impl Gc { /// Evaluate a string, returning all of the results in a Vec // TODO: Add file name - pub async fn eval<'e>(&self, exprs: &'e str) -> Result>>, EvalError<'e>> { - let tokens = Token::tokenize_str(exprs)?; + pub async fn eval<'e>( + &self, + file_name: &str, + exprs: &'e str, + ) -> Result>>, EvalError<'e>> { + let tokens = Token::tokenize_file(file_name, 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 { + let Some(expr) = AstNode::from_syntax(sexpr.syntax, self, &None).await? else { continue; }; // TODO: Catch continuation calls - let vals = result.eval(self, &None).await?; + let vals = self.abandon_cc_trampoline(expr).await?; results.push(vals); } Ok(results) } + async fn abandon_cc_trampoline(&self, expr: AstNode) -> Result>, RuntimeError> { + let mut inner = expr.eval(self, &None).await; + while let Err(RuntimeError { + kind: RuntimeErrorKind::AbandonCurrentContinuation { args, new_cont }, + .. + }) = inner + { + // Abandon the current continuation and evaluate the newly returned one + // TODO: Retain the backtrace for errors + // let arg = args.pop().unwrap(); + if let Some(new_cont) = new_cont { + inner = new_cont.resume(args, &None).await; + } else { + return Ok(args); + } + } + inner + } + + pub fn distance(&self, rhs: &Gc) -> usize { + if self == rhs { + 0 + } else { + 1 + self.read().up.as_ref().unwrap().distance(rhs) + } + } + pub fn deep_clone(&self) -> Self { let this = self.read(); Gc::new(Env { @@ -314,9 +346,11 @@ enum MacroLookup { WithoutEnv(Gc), } +#[derive(derive_more::Debug)] pub struct ExpansionEnv<'a> { up: Option<&'a ExpansionEnv<'a>>, - expansion_ctxs: Vec, + pub expansion_ctxs: Vec, + #[debug(skip)] pub lexical_contour: Gc, } @@ -370,30 +404,42 @@ impl ExpansionEnv<'_> { self.lexical_contour .read() .fetch_var_ref(ident) - .map_or_else(|| self.fetch_macro_var_ref(ident), Ref::Regular) + .map_or_else( + || match self.fetch_macro_var_ref(ident) { + Ref::Macro(m) => Ref::Regular({ + let mut local = m.var_ref; + local.depth += self.lexical_contour.distance(&m.env); + local + }), + x => x, + }, + 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 { + let mut ident = ident.clone(); + for expansion_ctx in self.expansion_ctxs.iter().rev() { 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)); + let Some(expansion_ctx_ref) = expansion_ctx.env.read().fetch_var_ref(&ident) else { + continue; }; + return Ref::Macro(MacroVarRef { env: expansion_ctx.env.clone(), - var_ref, + var_ref: expansion_ctx_ref, }); } } if let Some(up) = self.up { - up.fetch_macro_var_ref(ident) + up.fetch_macro_var_ref(&ident) } else { Ref::Global(GlobalRef::new(ident.clone())) } @@ -412,21 +458,24 @@ impl ExpansionEnv<'_> { // 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)> { + let mut ident = ident.clone(); 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)), + match expansion_ctx.env.read().fetch_macro(&ident) { + Some(MacroLookup::WithEnv { env, value }) => return Some((env, value)), + Some(MacroLookup::WithoutEnv(value)) => { + return Some((expansion_ctx.env.clone(), value)) + } + None => (), }; } } if let Some(up) = self.up { - up.fetch_macro_macro(ident) + up.fetch_macro_macro(&ident) } else { None } diff --git a/src/lex.rs b/src/lex.rs index 00dcde2..a6170bd 100644 --- a/src/lex.rs +++ b/src/lex.rs @@ -323,8 +323,8 @@ pub struct Token<'a> { pub type LexError<'a> = nom::Err>>; impl<'a> Token<'a> { - pub fn tokenize_file(s: &'a str, filename: &str) -> Result, LexError<'a>> { - let mut span = InputSpan::new_extra(s, Arc::new(filename.to_string())); + pub fn tokenize_file(file_name: &str, s: &'a str) -> Result, LexError<'a>> { + let mut span = InputSpan::new_extra(s, Arc::new(file_name.to_string())); let mut output = Vec::new(); while !span.is_empty() { let (remaining, ()) = interlexeme_space(span)?; @@ -343,6 +343,6 @@ impl<'a> Token<'a> { } pub fn tokenize_str(s: &'a str) -> Result, LexError<'a>> { - Self::tokenize_file(s, "") + Self::tokenize_file("", s) } } diff --git a/src/lib.rs b/src/lib.rs index b12d22c..86fb196 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,7 @@ pub mod lists; pub mod num; pub mod parse; pub mod proc; -pub mod records; +// pub mod records; pub mod syntax; pub mod util; pub mod value; diff --git a/src/main.rs b/src/main.rs index 0958dfa..8fc943b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,13 +49,12 @@ async fn main() { let mut rl = Reedline::create().with_validator(Box::new(InputParser)); let mut n_results = 1; let top = Env::top().await; - println!("installed"); loop { let Ok(Signal::Success(input)) = rl.read_line(&Prompt) else { println!("exiting..."); return; }; - match top.eval(&input).await { + match top.eval("", &input).await { Ok(results) => { for result in results.into_iter().flatten() { println!("${n_results} = {}", result.read().fmt()); diff --git a/src/records.rs b/src/records.rs index 4a4439b..8271820 100644 --- a/src/records.rs +++ b/src/records.rs @@ -1,3 +1,4 @@ +/* use std::collections::HashMap; use crate::{ @@ -604,3 +605,4 @@ impl Eval for RecordPredicate { } } */ +*/ diff --git a/src/syntax.rs b/src/syntax.rs index 2caa8be..394ee48 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -290,12 +290,12 @@ impl Syntax { env: &ExpansionEnv<'_>, cont: &Option>, ) -> Result { - let mut expansion_envs = Vec::new(); + let mut env = env.push_expansion_env(Vec::new()); loop { - match self.expand_once(env, cont).await? { + match self.expand_once(&env, cont).await? { Expansion::Unexpanded => { return Ok(FullyExpanded { - expansion_envs, + expansion_ctxs: env.expansion_ctxs, expanded: self, }) } @@ -304,7 +304,7 @@ impl Syntax { macro_env, syntax, } => { - expansion_envs.push(ExpansionCtx::new(mark, macro_env)); + env.expansion_ctxs.push(ExpansionCtx::new(mark, macro_env)); self = syntax; } } @@ -312,19 +312,23 @@ impl Syntax { } } +#[derive(derive_more::Debug)] pub enum Expansion { /// Syntax remained unchanged after expansion Unexpanded, /// Syntax was expanded, producing a new expansion context Expanded { mark: Mark, + #[debug(skip)] macro_env: Gc, syntax: Syntax, }, } +#[derive(derive_more::Debug, Clone)] pub struct ExpansionCtx { pub mark: Mark, + #[debug(skip)] pub env: Gc, } @@ -334,8 +338,9 @@ impl ExpansionCtx { } } +#[derive(Debug)] pub struct FullyExpanded { - pub expansion_envs: Vec, + pub expansion_ctxs: Vec, pub expanded: Syntax, } diff --git a/src/value.rs b/src/value.rs index 082fe64..4603698 100644 --- a/src/value.rs +++ b/src/value.rs @@ -2,11 +2,10 @@ use crate::{ ast, continuation::Continuation, error::RuntimeError, - expand::Transformer, gc::Gc, num::Number, proc::{Callable, ExternalFn, Procedure}, - records::{Record, RecordType}, + // records::{Record, RecordType}, syntax::Syntax, Trace, }; @@ -29,9 +28,8 @@ pub enum Value { Syntax(Syntax), Procedure(Procedure), ExternalFn(ExternalFn), - // Transformer(Transformer), - Record(Record), - RecordType(Gc), + // Record(Record), + // RecordType(Gc), Future(#[debug(skip)] Shared>, RuntimeError>>>), Continuation(#[debug(skip)] Option>), } @@ -94,8 +92,8 @@ impl Value { Self::Future(_) => "".to_string(), // Self::Transformer(_) => "".to_string(), Self::Continuation(_) => "".to_string(), - Self::Record(_) => "".to_string(), - Self::RecordType(_) => "".to_string(), + // Self::Record(_) => "".to_string(), + // Self::RecordType(_) => "".to_string(), Self::Undefined => "".to_string(), } } @@ -141,8 +139,8 @@ impl Value { Self::Procedure(_) | Self::ExternalFn(_) => "procedure", Self::Future(_) => "future", Self::Continuation(_) => "continuation", - Self::Record(_) => "record", - Self::RecordType(_) => "record-type", + // Self::Record(_) => "record", + // Self::RecordType(_) => "record-type", Self::Undefined => "undefined", } } @@ -189,8 +187,8 @@ impl Clone for Value { Self::ExternalFn(ext_fn) => Self::ExternalFn(*ext_fn), Self::Future(fut) => Self::Future(fut.clone()), Self::Continuation(cont) => Self::Continuation(cont.clone()), - Self::Record(record) => Self::Record(record.clone()), - Self::RecordType(rt) => Self::RecordType(rt.clone()), + // Self::Record(record) => Self::Record(record.clone()), + // Self::RecordType(rt) => Self::RecordType(rt.clone()), Self::Undefined => Self::Undefined, } } @@ -237,6 +235,7 @@ impl<'a> TryFrom<&'a Value> for &'a Number { } } +/* impl<'a> TryFrom<&'a Value> for &'a Record { type Error = RuntimeError; @@ -269,6 +268,7 @@ impl<'a> TryFrom<&'a Value> for &'a Gc { } } } +*/ pub fn eqv(a: &Gc, b: &Gc) -> bool { let a = a.read(); diff --git a/tests/r6rs.rs b/tests/r6rs.rs index a433543..3e78e3f 100644 --- a/tests/r6rs.rs +++ b/tests/r6rs.rs @@ -31,15 +31,8 @@ pub async fn test_assert( async fn r6rs() { let top = Env::top().await; - let r6rs_tok = Token::tokenize_file(include_str!("r6rs.scm"), "r6rs.scm").unwrap(); - let r6rs_sexprs = ParsedSyntax::parse(&r6rs_tok).unwrap(); - for sexpr in r6rs_sexprs { - let result = AstNode::from_syntax(sexpr.syntax, &top, &None) - .await - .unwrap() - .unwrap(); - - // TODO: Catch continuation calls - let _ = result.eval(&top, &None).await.unwrap(); - } + let _ = top + .eval("r6rs.scm", include_str!("r6rs.scm")) + .await + .unwrap(); } diff --git a/tests/r6rs.scm b/tests/r6rs.scm index bc3b3e1..a6d7933 100644 --- a/tests/r6rs.scm +++ b/tests/r6rs.scm @@ -201,18 +201,3 @@ ;; ((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)))))) From 78f97612e8986ab33d326df15cc5be8b10bff180 Mon Sep 17 00:00:00 2001 From: Matthew Plant Date: Thu, 26 Dec 2024 19:57:48 -0500 Subject: [PATCH 6/7] Clean up --- src/ast/eval.rs | 4 ++-- src/ast/mod.rs | 2 +- src/ast/parse.rs | 18 +++++++++--------- src/env.rs | 11 ++++------- tests/r6rs.rs | 3 --- 5 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/ast/eval.rs b/src/ast/eval.rs index 3547919..f4c19e7 100644 --- a/src/ast/eval.rs +++ b/src/ast/eval.rs @@ -112,7 +112,7 @@ impl Expression { Self::Begin(body) => body.tail_eval(env, cont).await, Self::Var(var) => Ok(ValuesOrPreparedCall::Values(vec![var .fetch(env) - .map_err(|ident| RuntimeError::undefined_variable(ident))?])), + .map_err(RuntimeError::undefined_variable)?])), } }) } @@ -336,7 +336,7 @@ impl SyntaxCase { Expression::parse(transformed, &expansion_env, cont) .await .expect("fixme") - .eval(&env, cont) + .eval(env, cont) .await } } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 47edb69..9742507 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -82,7 +82,7 @@ impl AstNode { Ok(None) } Some([Syntax::Identifier { ident, span, .. }, ..]) if ident.name == "define-syntax" => { - return Err(parse::ParseAstError::BadForm(span.clone())); + Err(parse::ParseAstError::BadForm(span.clone())) } Some(syn @ [Syntax::Identifier { ident, span, .. }, ..]) if ident.name == "define" => { Ok(Some(Self::Definition( diff --git a/src/ast/parse.rs b/src/ast/parse.rs index e88e374..21a5667 100644 --- a/src/ast/parse.rs +++ b/src/ast/parse.rs @@ -82,7 +82,7 @@ impl Definition { second: span.clone(), }); } - new_env.def_local_var(&ident, Gc::new(Value::Undefined)); + new_env.def_local_var(ident, Gc::new(Value::Undefined)); bound.insert(ident.clone(), span.clone()); fixed.push(ident.clone()); } @@ -106,7 +106,7 @@ impl Definition { }); } let remaining = ident.clone(); - new_env.def_local_var(&ident, Gc::new(Value::Undefined)); + new_env.def_local_var(ident, Gc::new(Value::Undefined)); bound.insert(remaining.clone(), span.clone()); Formals::VarArgs { fixed: fixed.into_iter().collect(), @@ -214,7 +214,7 @@ where 'a: 'b, { Box::pin(async move { - if body.len() == 0 { + if body.is_empty() { return Err(ParseAstError::EmptyBody(span.clone())); } @@ -302,7 +302,7 @@ impl Expression { let FullyExpanded { expanded, expansion_ctxs: expansion_envs, - } = syn.expand(&env, cont).await?; + } = syn.expand(env, cont).await?; let expansion_env = env.push_expansion_env(expansion_envs); Self::parse_expanded(expanded, &expansion_env, cont).await } @@ -403,7 +403,7 @@ impl Expression { [Syntax::Identifier { ident, span, .. }, .., Syntax::Null { .. }] if ident.name == "define" => { - return Err(ParseAstError::DefInExprContext(span.clone())); + Err(ParseAstError::DefInExprContext(span.clone())) } // Regular old function call: @@ -413,7 +413,7 @@ impl Expression { .map(Expression::Call) } - _ => return Err(ParseAstError::BadForm(span.clone())), + _ => Err(ParseAstError::BadForm(span.clone())), }, } }) @@ -488,7 +488,7 @@ async fn parse_lambda( second: span.clone(), }); } - new_contour.def_local_var(&ident, Gc::new(Value::Undefined)); + new_contour.def_local_var(ident, Gc::new(Value::Undefined)); bound.insert(ident.clone(), span.clone()); fixed.push(ident.clone()); } @@ -508,7 +508,7 @@ async fn parse_lambda( second: span.clone(), }); } - new_contour.def_local_var(&ident, Gc::new(Value::Undefined)); + new_contour.def_local_var(ident, Gc::new(Value::Undefined)); let remaining = ident.clone(); Formals::VarArgs { fixed: fixed.into_iter().collect(), @@ -727,7 +727,7 @@ impl Set { impl Quote { async fn parse(exprs: &[Syntax], span: &Span) -> Result { match exprs { - [] => Err(dbg!(ParseAstError::ExpectedArgument(span.clone()))), + [] => Err(ParseAstError::ExpectedArgument(span.clone())), [Syntax::Null { .. }] => Ok(Quote { val: Value::Null }), [expr, Syntax::Null { .. }] => Ok(Quote { val: Value::from_syntax(expr), diff --git a/src/env.rs b/src/env.rs index e2e90b1..304a8e2 100644 --- a/src/env.rs +++ b/src/env.rs @@ -70,8 +70,7 @@ impl Env { || { self.up .as_ref() - .map(|up| up.read().fetch_var_ref(ident).map(VarRef::inc_depth)) - .flatten() + .and_then(|up| up.read().fetch_var_ref(ident).map(VarRef::inc_depth)) }, |offset| Some(VarRef { depth: 0, offset }), ) @@ -286,9 +285,7 @@ impl GlobalRef { }; let top = top.read(); - let Some(var) = top.fetch_var_ref(&self.name) else { - return None; - }; + let var = top.fetch_var_ref(&self.name)?; Some(top.fetch_var(var)) } @@ -377,7 +374,7 @@ impl ExpansionEnv<'_> { !matches!(self.fetch_var_ref(ident), Ref::Global(_)) } - pub fn push_expansion_env<'a>(&'a self, ctxs: Vec) -> ExpansionEnv<'a> { + pub fn push_expansion_env(&self, ctxs: Vec) -> ExpansionEnv<'_> { ExpansionEnv { lexical_contour: self.lexical_contour.clone(), up: Some(self), @@ -385,7 +382,7 @@ impl ExpansionEnv<'_> { } } - pub fn push_lexical_contour<'a>(&'a self, gc: Gc) -> ExpansionEnv<'a> { + pub fn push_lexical_contour(&self, gc: Gc) -> ExpansionEnv<'_> { ExpansionEnv { up: Some(self), expansion_ctxs: Vec::new(), diff --git a/tests/r6rs.rs b/tests/r6rs.rs index 3e78e3f..9020e34 100644 --- a/tests/r6rs.rs +++ b/tests/r6rs.rs @@ -1,14 +1,11 @@ use std::sync::Arc; use scheme_rs::{ - ast::AstNode, builtin, continuation::Continuation, env::Env, error::RuntimeError, gc::Gc, - lex::Token, - syntax::ParsedSyntax, value::{eqv, Value}, }; From 19fb320dfd907f36b451040fb8f1f060d7cf8837 Mon Sep 17 00:00:00 2001 From: Matthew Plant Date: Thu, 26 Dec 2024 20:04:13 -0500 Subject: [PATCH 7/7] Remove debug stuff --- src/ast/eval.rs | 2 -- src/ast/mod.rs | 3 --- 2 files changed, 5 deletions(-) diff --git a/src/ast/eval.rs b/src/ast/eval.rs index f4c19e7..c4dca60 100644 --- a/src/ast/eval.rs +++ b/src/ast/eval.rs @@ -90,7 +90,6 @@ impl Expression { env: &'a Gc, cont: &'a Option>, ) -> BoxFuture<'a, Result> { - //println!("expr: {self:#?}"); Box::pin(async move { match self { Self::Undefined => val(Value::Undefined), @@ -159,7 +158,6 @@ impl Call { let arg = arg.eval(env, &Some(cont)).await?.require_one()?; collected.push(arg); } - // println!("prepared: {:#?}", env); Ok(ValuesOrPreparedCall::PreparedCall(PreparedCall::prepare( collected, Some(ProcCallDebugInfo::new(&self.proc_name, &self.location)), diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 9742507..289b58e 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -75,9 +75,6 @@ impl AstNode { Some( [Syntax::Identifier { ident, .. }, Syntax::Identifier { ident: name, .. }, expr, Syntax::Null { .. }], ) if ident.name == "define-syntax" => { - // println!("defining here {}", ident.name); - // TODO: Error if define syntax isn't proper, error. - // println!("mod.rs:80"); define_syntax(name, expr.clone(), &env.lexical_contour, cont).await?; Ok(None) }