terrified to start testing
This commit is contained in:
@@ -7,16 +7,15 @@ use orchid_base::{
|
||||
FmtCtx, FmtUnit, Format, OrcErr, OrcErrv, Pos, Sym, Variants, match_mapping, tl_cache,
|
||||
};
|
||||
|
||||
use crate::api;
|
||||
use crate::atom::{AtomFactory, AtomicFeatures};
|
||||
use crate::conv::{ToExpr, ToExprFuture};
|
||||
use crate::entrypoint::request;
|
||||
use crate::expr::Expr;
|
||||
use crate::system::sys_id;
|
||||
use crate::{AtomFactory, AtomicFeatures, Expr, ToExpr, ToExprFuture, api, request, sys_id};
|
||||
|
||||
/// Newly generated AST. Values of this type should not typically be constructed
|
||||
/// manually but through the helpers in this module
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GExpr {
|
||||
/// AST node type
|
||||
pub kind: GExprKind,
|
||||
/// Code location associated with the expression for debugging purposes
|
||||
pub pos: Pos,
|
||||
}
|
||||
impl GExpr {
|
||||
@@ -38,7 +37,10 @@ impl GExpr {
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Reassign location information. The typical default is [Pos::Inherit]
|
||||
pub fn at(self, pos: Pos) -> Self { GExpr { pos, kind: self.kind } }
|
||||
/// Send the expression to the interpreter to be compiled and to become
|
||||
/// shareable across extensions
|
||||
pub async fn create(self) -> Expr {
|
||||
Expr::deserialize(request(api::Create(sys_id(), self.serialize().await)).await).await
|
||||
}
|
||||
@@ -49,20 +51,36 @@ impl Format for GExpr {
|
||||
}
|
||||
}
|
||||
|
||||
/// AST nodes recognized by the interpreter
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum GExprKind {
|
||||
/// Function call
|
||||
Call(Box<GExpr>, Box<GExpr>),
|
||||
/// Lambda expression. Argument numbers are matched when equal
|
||||
Lambda(u64, Box<GExpr>),
|
||||
/// Slot for a lambda argument
|
||||
Arg(u64),
|
||||
/// The second expression is only valid after the first one had already been
|
||||
/// fully normalized. The main use case is the pattern `Lambda(0, Seq(0,
|
||||
/// Call(foo, 0)))` where foo is an atom that attempts to downcast its
|
||||
/// argument.
|
||||
Seq(Box<GExpr>, Box<GExpr>),
|
||||
/// A reference to a constant from the shared constant tree. It is best to
|
||||
/// mark the system that provides named constants as a dependency, but this is
|
||||
/// not required
|
||||
Const(Sym),
|
||||
/// A newly created atom. Since at this point the atom needs to be registered
|
||||
/// inside the extension but doesn't yet have an [api::ExprTicket], atoms need
|
||||
/// their own [api::Atom::drop] if they have an identity
|
||||
#[allow(private_interfaces)]
|
||||
NewAtom(AtomFactory),
|
||||
/// An expression previously registered or coming from outside the extension
|
||||
Slot(Expr),
|
||||
/// A runtime error
|
||||
Bottom(OrcErrv),
|
||||
}
|
||||
impl GExprKind {
|
||||
pub async fn serialize(self) -> api::ExpressionKind {
|
||||
async fn serialize(self) -> api::ExpressionKind {
|
||||
match_mapping!(self, Self => api::ExpressionKind {
|
||||
Call(
|
||||
f => Box::new(f.serialize().await),
|
||||
@@ -117,6 +135,8 @@ impl ToExpr for Sym {
|
||||
/// Creates an expression from a new atom that we own.
|
||||
pub fn new_atom<A: AtomicFeatures>(atom: A) -> GExpr { inherit(GExprKind::NewAtom(atom.factory())) }
|
||||
|
||||
/// An expression which is only valid if a number of dependencies had already
|
||||
/// been normalized
|
||||
pub fn seq(
|
||||
deps: impl IntoGExprStream,
|
||||
val: impl ToExpr,
|
||||
@@ -135,17 +155,24 @@ pub fn seq(
|
||||
})
|
||||
}
|
||||
|
||||
/// Argument bound by an enclosing [lam] or [dyn_lambda]
|
||||
pub fn arg(n: u64) -> GExpr { inherit(GExprKind::Arg(n)) }
|
||||
|
||||
/// A lambda expression. The difference from [dyn_lambda] is purely aesthetic
|
||||
pub fn lam<const N: u64>(b: impl ToExpr) -> ToExprFuture<impl Future<Output = GExpr>> {
|
||||
dyn_lambda(N, b)
|
||||
}
|
||||
|
||||
/// A lambda expression. The difference from [lam] is purely aesthetic
|
||||
pub fn dyn_lambda(n: u64, b: impl ToExpr) -> ToExprFuture<impl Future<Output = GExpr>> {
|
||||
ToExprFuture(async move { inherit(GExprKind::Lambda(n, Box::new(b.to_gen().await))) })
|
||||
}
|
||||
|
||||
/// one or more items that are convertible to expressions. In practice, a
|
||||
/// [ToExpr], [Vec<GExpr>], or a tuple of types that all implement [ToExpr]. For
|
||||
/// compilation performance, the tuple's arity may not be more than 6
|
||||
pub trait IntoGExprStream {
|
||||
/// Convert each item to an expression and return them
|
||||
fn into_gexpr_stream(self) -> impl Stream<Item = GExpr>;
|
||||
}
|
||||
impl<T: ToExpr> IntoGExprStream for T {
|
||||
@@ -184,6 +211,7 @@ mod tuple_impls {
|
||||
tuple_impl!(A B C D E F);
|
||||
}
|
||||
|
||||
/// Call a (curried) function
|
||||
pub fn call(
|
||||
f: impl ToExpr,
|
||||
argv: impl IntoGExprStream,
|
||||
@@ -195,6 +223,7 @@ pub fn call(
|
||||
})
|
||||
}
|
||||
|
||||
/// Call a function on a dynamic number of arguments
|
||||
pub fn call_v(
|
||||
f: impl ToExpr,
|
||||
argv: impl IntoIterator<Item: ToExpr>,
|
||||
@@ -208,6 +237,7 @@ pub fn call_v(
|
||||
})
|
||||
}
|
||||
|
||||
/// A runtime error
|
||||
pub fn bot(ev: impl IntoIterator<Item = OrcErr>) -> GExpr {
|
||||
inherit(GExprKind::Bottom(OrcErrv::new(ev).unwrap()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user