#![allow(clippy::inline_always)]
use core::marker::PhantomData;
pub trait Expr {
type Return;
type Scope;
const COMPLEXITY: usize;
fn eval(&self, scope: &mut Self::Scope) -> Self::Return;
}
pub struct Block<T: StatementNode<Scope = Scope>, Scope>(pub T, pub PhantomData<Scope>);
impl<T: StatementNode<Scope = Scope>, Scope> Expr for Block<T, Scope> {
type Return = T::Return;
type Scope = Scope;
const COMPLEXITY: usize = 1 + T::COMPLEXITY;
#[inline(always)]
fn eval(&self, scope: &mut Self::Scope) -> Self::Return {
self.0.eval(scope)
}
}
pub trait StatementNode: Expr {}
pub struct EndList<Scope>(PhantomData<Scope>);
impl<Scope> Expr for EndList<Scope> {
type Return = ();
type Scope = Scope;
const COMPLEXITY: usize = 0;
#[inline(always)]
fn eval(&self, _: &mut Self::Scope) -> Self::Return {}
}
impl<Scope> StatementNode for EndList<Scope> {}
pub struct StatementList<
S: Expr<Return = (), Scope = Scope>,
NextStatement: StatementNode<Scope = Scope>,
Scope,
>(pub S, pub NextStatement, pub PhantomData<Scope>);
impl<S: Expr<Return = (), Scope = Scope>, NextStatement: StatementNode<Scope = Scope>, Scope> Expr
for StatementList<S, NextStatement, Scope>
{
type Return = NextStatement::Return;
type Scope = Scope;
const COMPLEXITY: usize = S::COMPLEXITY + NextStatement::COMPLEXITY;
#[inline(always)]
fn eval(&self, scope: &mut Self::Scope) -> Self::Return {
self.0.eval(scope);
self.1.eval(scope)
}
}
impl<S: Expr<Return = (), Scope = Scope>, NextStatement: StatementNode<Scope = Scope>, Scope>
StatementNode for StatementList<S, NextStatement, Scope>
{
}
pub struct ImplicitReturn<S: Expr<Scope = Scope>, Scope>(pub S, pub PhantomData<Scope>);
impl<S: Expr<Scope = Scope>, Scope> Expr for ImplicitReturn<S, Scope> {
type Return = S::Return;
type Scope = Scope;
const COMPLEXITY: usize = S::COMPLEXITY;
#[inline]
fn eval(&self, scope: &mut Self::Scope) -> Self::Return {
self.0.eval(scope)
}
}
impl<S: Expr<Scope = Scope>, Scope> StatementNode for ImplicitReturn<S, Scope> {}
pub struct Literal<T: Copy , Scope>(pub T, pub PhantomData<Scope>);
impl<T: Copy, Scope> Expr for Literal<T, Scope> {
type Return = T;
type Scope = Scope;
const COMPLEXITY: usize = 0; #[inline(always)]
fn eval(&self, _: &mut Self::Scope) -> Self::Return {
self.0
}
}
pub struct If<
Cond: Expr<Return = bool, Scope = Scope>,
Left: Expr<Return = (), Scope = Scope>,
Scope,
>(pub Cond, pub Left, pub PhantomData<Scope>);
impl<Cond: Expr<Return = bool, Scope = Scope>, Left: Expr<Return = (), Scope = Scope>, Scope> Expr
for If<Cond, Left, Scope>
{
type Return = Left::Return;
type Scope = Scope;
const COMPLEXITY: usize = 1 + Cond::COMPLEXITY + Left::COMPLEXITY;
#[inline(always)]
fn eval(&self, scope: &mut Self::Scope) -> Self::Return {
if self.0.eval(scope) {
self.1.eval(scope);
}
}
}
pub struct IfElse<
Cond: Expr<Return = bool, Scope = Scope>,
Left: Expr<Scope = Scope>,
Right: Expr<Return = Left::Return, Scope = Scope>,
Scope,
>(pub Cond, pub Left, pub Right, pub PhantomData<Scope>);
impl<
Cond: Expr<Return = bool, Scope = Scope>,
Left: Expr<Scope = Scope>,
Right: Expr<Return = Left::Return, Scope = Scope>,
Scope,
> Expr for IfElse<Cond, Left, Right, Scope>
{
type Return = Left::Return;
type Scope = Scope;
const COMPLEXITY: usize = 1 + Cond::COMPLEXITY + Left::COMPLEXITY + Right::COMPLEXITY;
#[inline(always)]
fn eval(&self, scope: &mut Self::Scope) -> Self::Return {
if self.0.eval(scope) {
self.1.eval(scope)
} else {
self.2.eval(scope)
}
}
}
pub struct Add<Left: Expr<Scope = Scope>, Right: Expr<Scope = Scope>, Scope>(
pub Left,
pub Right,
pub PhantomData<Scope>,
)
where
Left::Return: core::ops::Add<Right::Return>;
impl<Left: Expr<Scope = Scope>, Right: Expr<Scope = Scope>, Scope> Expr for Add<Left, Right, Scope>
where
Left::Return: core::ops::Add<Right::Return>,
{
type Return = <Left::Return as core::ops::Add<Right::Return>>::Output;
type Scope = Scope;
const COMPLEXITY: usize = 1 + Left::COMPLEXITY + Right::COMPLEXITY;
#[inline(always)]
fn eval(&self, scope: &mut Self::Scope) -> Self::Return {
#![allow(clippy::arithmetic_side_effects)]
self.0.eval(scope) + self.1.eval(scope)
}
}
pub struct Sub<Left: Expr<Scope = Scope>, Right: Expr<Scope = Scope>, Scope>(
pub Left,
pub Right,
pub PhantomData<Scope>,
)
where
Left::Return: core::ops::Sub<Right::Return>;
impl<Left: Expr<Scope = Scope>, Right: Expr<Scope = Scope>, Scope> Expr for Sub<Left, Right, Scope>
where
Left::Return: core::ops::Sub<Right::Return>,
{
type Return = <Left::Return as core::ops::Sub<Right::Return>>::Output;
type Scope = Scope;
const COMPLEXITY: usize = 1 + Left::COMPLEXITY + Right::COMPLEXITY;
#[inline(always)]
fn eval(&self, scope: &mut Self::Scope) -> Self::Return {
#![allow(clippy::arithmetic_side_effects)]
self.0.eval(scope) - self.1.eval(scope)
}
}