From dc3cb43682a14ff9c005caff198ec825d292c96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Wed, 22 Nov 2023 22:11:48 -0300 Subject: [PATCH] feat: add macro expansion --- src/eval.rs | 127 ++++++++++++++++++++++++++++++++++++------------ src/semantic.rs | 2 +- 2 files changed, 98 insertions(+), 31 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index a6665f6..8877dad 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -1,5 +1,4 @@ use std::{ - collections::VecDeque, convert::Infallible, ops::{ControlFlow, FromResidual, Try}, sync::{Arc, RwLock}, @@ -8,26 +7,59 @@ use std::{ use Trampoline::{Continue, Done, Raise}; use crate::{ - semantic::{self, defmacro::keyword, Expr}, - SrcPos, + semantic::{self, defmacro::keyword, Expr, Literal}, + SrcPos, Term, }; +pub struct Definition { + pub is_macro_definition: bool, + pub name: String, + pub value: Value, +} + pub struct Frame { pub name: Option, pub src_pos: SrcPos, - pub variables: im::HashMap, + pub definitions: im::HashMap, pub is_catching_scope: bool, } +#[derive(Clone)] +pub struct Keyword { + pub name: String, +} + #[derive(Clone)] pub enum Value { Fun(semantic::Fun), List(Arc>), - Literal(semantic::Literal), - Apply(semantic::Apply), - Def(semantic::Def), - DefMacro(semantic::DefMacro), - Quote(semantic::Quote), + Int(u64), + Keyword(Keyword), + String(String), + Float(u64), + Apply { + callee: Box, + arguments: Vec, + }, + Def { + name: Keyword, + value: Box, + }, + DefMacro { + name: Keyword, + value: Box, + }, + Set { + target: Box, + value: Box, + }, + Deref { + value: Box, + }, + Recur { + arguments: Vec, + }, + Quote(Expr), Atomic(Arc>), Ptr(*mut ()), Nil, @@ -36,7 +68,7 @@ pub enum Value { pub struct Environment { pub global: Value, pub expanded: bool, - pub frames: Arc>, + pub frames: Arc>>, } pub enum Trampoline { @@ -45,28 +77,63 @@ pub enum Trampoline { Continue(Box Trampoline>), } -pub fn eval(expr: Expr, environment: Environment) -> Trampoline { - match expr { - Expr::List(_) => todo!(), - Expr::Apply(_) => todo!(), - Expr::Def(_) => todo!(), - Expr::DefMacro(_) => todo!(), - Expr::Quote(_) => todo!(), - Expr::Recur(_) => todo!(), - Expr::Deref(deref) => { - let Value::Atomic(atomic) = eval(deref.value()?, environment)? else { - bail!(keyword!("eval.error/atomic-expected")) - }; - let guard = atomic.read().expect("poisoned atomic"); - - Done(guard.clone()) +impl Trampoline { + pub fn eval_into_result(self) -> Result { + match self.branch() { + ControlFlow::Continue(value) => Ok(value), + ControlFlow::Break(Err(err)) => Err(err), + _ => unreachable!(), } - Expr::Atomic(_) => todo!(), - Expr::Set(_) => todo!(), + } +} - // Bridges one-to-one from Value, to Expr, and back to Value. - Expr::Fun(fun) => Trampoline::Done(Value::Fun(fun)), - Expr::Literal(literal) => Trampoline::Done(Value::Literal(literal)), +impl Expr { + pub fn expand(self, environment: &Environment) -> Result { + match self { + Expr::Fun(_) => todo!(), + Expr::List(_) => todo!(), + Expr::Apply(_) => todo!(), + Expr::Def(_) => todo!(), + Expr::Recur(recur) => Ok(Value::Recur { + arguments: recur + .spine()? + .into_iter() + .map(|expr| expr.expand(environment)) + .collect::, _>>()?, + }), + Expr::Deref(deref) => Ok(Value::Deref { + value: deref.value()?.expand(environment)?.into(), + }), + Expr::Atomic(_) => todo!(), + Expr::Set(_) => todo!(), + Expr::DefMacro(_) => todo!(), + Expr::Quote(expr) => Ok(Value::Quote(expr.expression()?)), + Expr::Literal(Literal(Term::Atom(keyword))) => Ok(Value::Keyword(Keyword { + name: keyword, + })), + Expr::Literal(Literal(Term::Identifier(identifier))) => Ok(Value::Keyword(Keyword { + name: identifier, + })), + Expr::Literal(Literal(Term::Int(value))) => Ok(Value::Int(value)), + Expr::Literal(Literal(Term::String(value))) => Ok(Value::String(value)), + Expr::Literal(Literal(Term::Float(_, _))) => todo!(), + Expr::Literal(_) => Err(keyword!("eval.error/invalid-literal")), + } + } + + pub fn eval(self, environment: &Environment) -> Trampoline { + match self.expand(environment)? { + Value::Deref { box value, .. } => { + let Value::Atomic(atomic) = value else { + bail!(keyword!("eval.error/atomic-expected")) + }; + let guard = atomic.read().expect("poisoned atomic"); + + Done(guard.clone()) + } + + value => Done(value), + } } } diff --git a/src/semantic.rs b/src/semantic.rs index 138bd50..17278ca 100644 --- a/src/semantic.rs +++ b/src/semantic.rs @@ -427,7 +427,7 @@ macro_rules! define_ast { $(#[$field_outer])* #[derive(Debug, Clone)] - pub struct $variant($crate::Term); + pub struct $variant(pub $crate::Term); impl From<$variant> for $crate::Term { fn from(value: $variant) -> Self {