forked from Orchid/orchid
executor, mostly
This commit is contained in:
@@ -1,15 +1,22 @@
|
||||
use mappable_rc::Mrc;
|
||||
use itertools::Itertools;
|
||||
use ordered_float::NotNan;
|
||||
use std::hash::Hash;
|
||||
use std::{hash::Hash, intrinsics::likely};
|
||||
use std::fmt::Debug;
|
||||
use crate::executor::{ExternFn, Atom};
|
||||
use crate::utils::mrc_empty_slice;
|
||||
use crate::{executor::{ExternFn, Atom}, utils::one_mrc_slice};
|
||||
|
||||
use super::Literal;
|
||||
|
||||
/// An S-expression with a type
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
pub struct Expr(pub Clause, pub Mrc<[Clause]>);
|
||||
impl Expr {
|
||||
pub fn into_clause(self) -> Clause {
|
||||
if likely(self.1.len() == 0) { self.0 }
|
||||
else { Clause::S('(', one_mrc_slice(self)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Expr {
|
||||
fn clone(&self) -> Self {
|
||||
@@ -37,6 +44,7 @@ pub enum Clause {
|
||||
qualified: Mrc<[String]>
|
||||
},
|
||||
S(char, Mrc<[Expr]>),
|
||||
Explicit(Mrc<Expr>),
|
||||
Lambda(String, Mrc<[Expr]>, Mrc<[Expr]>),
|
||||
Auto(Option<String>, Mrc<[Expr]>, Mrc<[Expr]>),
|
||||
ExternFn(ExternFn),
|
||||
@@ -53,37 +61,49 @@ pub enum Clause {
|
||||
impl Clause {
|
||||
pub fn body(&self) -> Option<Mrc<[Expr]>> {
|
||||
match self {
|
||||
Clause::Auto(_, _, body) |
|
||||
Clause::Lambda(_, _, body) |
|
||||
Clause::S(_, body) => Some(Mrc::clone(body)),
|
||||
Self::Auto(_, _, body) |
|
||||
Self::Lambda(_, _, body) |
|
||||
Self::S(_, body) => Some(Mrc::clone(body)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
pub fn typ(&self) -> Option<Mrc<[Expr]>> {
|
||||
match self {
|
||||
Clause::Auto(_, typ, _) | Clause::Lambda(_, typ, _) => Some(Mrc::clone(typ)),
|
||||
Self::Auto(_, typ, _) | Self::Lambda(_, typ, _) => Some(Mrc::clone(typ)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
pub fn into_expr(self) -> Expr {
|
||||
if let Self::S('(', body) = &self {
|
||||
if body.len() == 1 { body[0].clone() }
|
||||
else { Expr(self, mrc_empty_slice()) }
|
||||
} else { Expr(self, mrc_empty_slice()) }
|
||||
}
|
||||
pub fn from_exprv(exprv: Mrc<[Expr]>) -> Option<Clause> {
|
||||
if exprv.len() == 0 { None }
|
||||
else if exprv.len() == 1 { Some(exprv[0].clone().into_clause()) }
|
||||
else { Some(Self::S('(', exprv)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Clause {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Clause::S(c, b) => Clause::S(*c, Mrc::clone(b)),
|
||||
Clause::Auto(n, t, b) => Clause::Auto(
|
||||
Self::S(c, b) => Self::S(*c, Mrc::clone(b)),
|
||||
Self::Auto(n, t, b) => Self::Auto(
|
||||
n.clone(), Mrc::clone(t), Mrc::clone(b)
|
||||
),
|
||||
Clause::Name { local: l, qualified: q } => Clause::Name {
|
||||
Self::Name { local: l, qualified: q } => Self::Name {
|
||||
local: l.clone(), qualified: Mrc::clone(q)
|
||||
},
|
||||
Clause::Lambda(n, t, b) => Clause::Lambda(
|
||||
Self::Lambda(n, t, b) => Self::Lambda(
|
||||
n.clone(), Mrc::clone(t), Mrc::clone(b)
|
||||
),
|
||||
Clause::Placeh{key, vec} => Clause::Placeh{key: key.clone(), vec: *vec},
|
||||
Clause::Literal(l) => Clause::Literal(l.clone()),
|
||||
Clause::ExternFn(nc) => Clause::ExternFn(nc.clone()),
|
||||
Clause::Atom(a) => Clause::Atom(a.clone())
|
||||
Self::Placeh{key, vec} => Self::Placeh{key: key.clone(), vec: *vec},
|
||||
Self::Literal(l) => Self::Literal(l.clone()),
|
||||
Self::ExternFn(nc) => Self::ExternFn(nc.clone()),
|
||||
Self::Atom(a) => Self::Atom(a.clone()),
|
||||
Self::Explicit(expr) => Self::Explicit(Mrc::clone(expr))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,7 +147,8 @@ impl Debug for Clause {
|
||||
Self::Placeh{key, vec: Some((prio, true))} => write!(f, "...${key}:{prio}"),
|
||||
Self::Placeh{key, vec: Some((prio, false))} => write!(f, "..${key}:{prio}"),
|
||||
Self::ExternFn(nc) => write!(f, "{nc:?}"),
|
||||
Self::Atom(a) => write!(f, "{a:?}")
|
||||
Self::Atom(a) => write!(f, "{a:?}"),
|
||||
Self::Explicit(expr) => write!(f, "@{:?}", expr.as_ref())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use mappable_rc::Mrc;
|
||||
|
||||
use crate::utils::{Stackframe, to_mrc_slice};
|
||||
use crate::utils::{Stackframe, to_mrc_slice, mrc_empty_slice};
|
||||
|
||||
use super::{ast, typed};
|
||||
|
||||
@@ -26,7 +26,9 @@ pub enum Error {
|
||||
///
|
||||
/// [expr] handles this case, so it's only really possible to get this
|
||||
/// error if you're calling [clause] directly
|
||||
ExprToClause(typed::Expr)
|
||||
ExprToClause(typed::Expr),
|
||||
/// @ tokens only ever occur between a function and a parameter
|
||||
NonInfixAt
|
||||
}
|
||||
|
||||
/// Try to convert an expression from AST format to typed lambda
|
||||
@@ -44,21 +46,37 @@ pub fn exprv(exprv: &[ast::Expr]) -> Result<typed::Expr, Error> {
|
||||
exprv_rec(exprv, Stackframe::new(None))
|
||||
}
|
||||
|
||||
fn apply_rec(f: typed::Expr, x: &ast::Expr, names: Stackframe<Option<&str>>)
|
||||
-> Result<typed::Clause, Error> {
|
||||
if let ast::Expr(ast::Clause::Explicit(inner), empty_slice) = x {
|
||||
assert!(empty_slice.len() == 0,
|
||||
"It is assumed that Explicit nodes can never have type annotations as the \
|
||||
wrapped expression node matches all trailing colons."
|
||||
);
|
||||
let x = expr_rec(inner.as_ref(), names)?;
|
||||
Ok(typed::Clause::Explicit(Mrc::new(f), Mrc::new(x)))
|
||||
} else {
|
||||
let x = expr_rec(x, names)?;
|
||||
Ok(typed::Clause::Apply(Mrc::new(f), Mrc::new(x)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Recursive state of [exprv]
|
||||
fn exprv_rec(v: &[ast::Expr], names: Stackframe<Option<&str>>) -> Result<typed::Expr, Error> {
|
||||
if v.len() == 0 {return Err(Error::EmptyS)}
|
||||
if v.len() == 1 {return expr_rec(&v[0], names)}
|
||||
let (head, tail) = v.split_at(2);
|
||||
let f = expr_rec(&head[0], names)?;
|
||||
let x = expr_rec(&head[1], names)?;
|
||||
let x = &head[1];
|
||||
// TODO this could probably be normalized, it's a third copy.
|
||||
tail.iter().map(|e| expr_rec(e, names)).fold(
|
||||
Ok(typed::Clause::Apply(Mrc::new(f), Mrc::new(x))),
|
||||
|acc, e| Ok(typed::Clause::Apply(
|
||||
Mrc::new(typed::Expr(acc?, to_mrc_slice(vec![]))),
|
||||
Mrc::new(e?)
|
||||
))
|
||||
).map(|cls| typed::Expr(cls, to_mrc_slice(vec![])))
|
||||
tail.iter().fold(
|
||||
apply_rec(f, x, names),
|
||||
|acc, e| apply_rec(
|
||||
typed::Expr(acc?, mrc_empty_slice()),
|
||||
e,
|
||||
names
|
||||
)
|
||||
).map(|cls| typed::Expr(cls, mrc_empty_slice()))
|
||||
}
|
||||
|
||||
/// Recursive state of [expr]
|
||||
@@ -115,6 +133,7 @@ fn clause_rec(cls: &ast::Clause, names: Stackframe<Option<&str>>)
|
||||
else {Err(Error::ExprToClause(typed::Expr(val, typ)))}
|
||||
},
|
||||
ast::Clause::Name { local: None, .. } => Err(Error::Symbol),
|
||||
ast::Clause::Placeh { .. } => Err(Error::Placeholder)
|
||||
ast::Clause::Placeh { .. } => Err(Error::Placeholder),
|
||||
ast::Clause::Explicit(..) => Err(Error::NonInfixAt)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user