From f85ed8139a07a8f0b7c427380996eae11171fe48 Mon Sep 17 00:00:00 2001 From: Matthew Plant Date: Tue, 24 Dec 2024 20:55:38 -0500 Subject: [PATCH] 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, )))]) } +*/