Skip to content
This repository has been archived by the owner on Dec 10, 2024. It is now read-only.

Commit

Permalink
refactor: improve eval code
Browse files Browse the repository at this point in the history
  • Loading branch information
aripiprazole committed Nov 23, 2023
1 parent 6e4b7a7 commit 1f5d544
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 9 deletions.
60 changes: 52 additions & 8 deletions src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ use std::{
sync::{Arc, RwLock},
};

use thiserror::Error;
use Trampoline::{Continue, Done, Raise};

use crate::{
semantic::{defmacro::keyword, Expr, Literal},
semantic::{
defmacro::{keyword, soft_vec},
Expr, Literal,
},
SrcPos, Term,
};

Expand Down Expand Up @@ -76,7 +80,7 @@ pub enum Value {
Nil,
}

#[derive(Hash, Clone, PartialEq, Eq)]
#[derive(Debug, Hash, Clone, PartialEq, Eq)]
pub struct Keyword {
pub name: String,
pub is_atom: bool,
Expand Down Expand Up @@ -137,12 +141,12 @@ impl Trampoline<Value> {
}

impl TryFrom<Value> for Keyword {
type Error = Expr;
type Error = ExpansionError;

fn try_from(value: Value) -> Result<Self, Self::Error> {
match value {
Value::Keyword(keyword) => Ok(keyword),
_ => Err(keyword!("eval.error/keyword-expected")),
_ => Err(ExpansionError::ExpectedKeyword),
}
}
}
Expand Down Expand Up @@ -202,6 +206,21 @@ fn fun_expand(fun: crate::semantic::Fun, environment: &Environment) -> Result<Va
}))
}

/// Errors that can occur during expansion.
#[derive(Error, Debug, Clone)]
pub enum ExpansionError {
#[error("expected keyword")]
ExpectedKeyword,
}

impl From<ExpansionError> for Expr {
fn from(error: ExpansionError) -> Self {
match error {
ExpansionError::ExpectedKeyword => keyword!("eval.error/expected-keyword"),
}
}
}

impl Expr {
/// Expand the expression into a value.
pub fn expand(self, environment: &Environment) -> Result<Value, Expr> {
Expand Down Expand Up @@ -268,21 +287,46 @@ impl Expr {
}
}

/// Errors that can occur during evaluation.
#[derive(Error, Debug, Clone)]
pub enum EvalError {
#[error("undefined keyword")]
UndefinedKeyword(Keyword),

#[error("expected fun")]
ExpectedFun,

#[error("expected atomic")]
ExpectedAtomic,
}

impl From<EvalError> for Expr {
fn from(value: EvalError) -> Self {
match value {
EvalError::UndefinedKeyword(Keyword { name, .. }) => {
soft_vec!(keyword!("eval.error/expected-keyword"), name)
}
EvalError::ExpectedFun => keyword!("eval.error/expected-fun"),
EvalError::ExpectedAtomic => keyword!("eval.error/expected-atomic"),
}
}
}

impl Value {
/// Evaluate the expression into a value.
pub fn eval(self, environment: &Environment) -> Trampoline<Value> {
match self {
Value::Deref { box value, .. } => {
let Value::Atomic(atomic) = value else {
bail!(keyword!("eval.error/atomic-expected"))
bail!(EvalError::ExpectedAtomic)
};
let guard = atomic.read().expect("poisoned atomic");

Done(guard.clone())
}
Value::Set { box target, value } => {
let Value::Atomic(atomic) = target else {
bail!(keyword!("eval.error/atomic-expected"))
bail!(EvalError::ExpectedAtomic)
};
let mut guard = atomic.write().expect("poisoned atomic");
*guard = value.eval(environment)?.clone();
Expand All @@ -291,7 +335,7 @@ impl Value {
Value::Keyword(keyword) if !keyword.is_atom => {
match environment.find_definition(keyword.clone()) {
Some(Definition { value, .. }) => Done(value),
None => Done(Value::Keyword(keyword)),
None => bail!(EvalError::UndefinedKeyword(keyword)),
}
}
Value::Apply { callee, arguments } => match callee.eval(environment)? {
Expand All @@ -302,7 +346,7 @@ impl Value {
}
fun.call(environment, new_arguments)
}
_ => bail!(keyword!("eval.error/fun-expected")),
_ => bail!(EvalError::ExpectedFun),
},
Value::List(old_elements) => {
let mut new_elements = Vec::new();
Expand Down
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ impl Display for Term {
}
}

impl From<String> for Term {
fn from(s: String) -> Self {
Term::String(s)
}
}

impl From<usize> for Term {
fn from(n: usize) -> Self {
Term::Int(n as u64)
Expand Down
2 changes: 1 addition & 1 deletion src/semantic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,5 +460,5 @@ macro_rules! keyword {

use define_ast;
use define_builtin;
use soft_vec;
pub(crate) use keyword;
pub(crate) use soft_vec;

0 comments on commit 1f5d544

Please sign in to comment.