use crate::diagnostics::{Error as DiagnosticError, Result};
use crate::eval::value::{Value};
use std::collections::HashMap;
use std::fmt;
use std::sync::Arc;
pub mod monad;
pub mod handler;
pub mod generational;
pub mod lifting;
pub mod advanced_monads;
pub mod continuation_monad;
pub mod builtin_monads;
pub mod list_monad;
pub mod parser_monad;
pub mod effect_context;
pub mod effect_handler_ref;
pub mod effect_system;
pub mod lifting_config;
pub use monad::*;
pub use handler::*;
pub use generational::*;
pub use lifting::*;
pub use advanced_monads::*;
pub use continuation_monad::{
ContinuationMonad, ContinuationFunction, ContinuationComputation,
EvaluationFrame, EffectfulComputation, run_continuation, escape_continuation
};
pub use builtin_monads::{
Maybe, Either, IO, State, Reader, IOContext, FileMode, FileHandle,
ListMonad, ParserMonad
};
pub use list_monad::{List, ValueList, ListFunc};
pub use parser_monad::{Parser, ParseResult, ParseError, Input, Position, ParserCache};
pub use continuation_monad::ContIOAction;
pub use continuation_monad::ContStateAction;
pub use effect_context::*;
pub use effect_handler_ref::*;
pub use effect_system::*;
pub use lifting_config::*;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Effect {
Pure,
IO,
State,
Error,
Custom(String),
}
pub trait EffectHandler: std::fmt::Debug {
fn handle(&self, effect: &Effect, args: &[Value]) -> Result<EffectResult>;
fn effect_name(&self) -> &str;
fn can_handle(&self, effect: &Effect) -> bool;
}
#[derive(Debug, Clone)]
pub enum EffectResult {
Value(Value),
Continue(Value),
Unhandled,
Error(DiagnosticError),
}
#[derive(Debug, Clone)]
pub enum LiftingCondition {
Always,
OperationName(String),
HasEffect(Vec<Effect>),
Custom(fn(&str, &[Effect]) -> bool),
}
impl Effect {
pub fn is_pure(&self) -> bool {
matches!(self, Effect::Pure)
}
pub fn is_io(&self) -> bool {
matches!(self, Effect::IO)
}
pub fn is_state(&self) -> bool {
matches!(self, Effect::State)
}
pub fn is_error(&self) -> bool {
matches!(self, Effect::Error)
}
pub fn combine(&self, other: &Effect) -> Effect {
match (self, other) {
(Effect::Pure, other) => other.clone(),
(this, Effect::Pure) => this.clone(),
(Effect::Error, _) | (_, Effect::Error) => Effect::Error,
(Effect::IO, _) | (_, Effect::IO) => Effect::IO,
(Effect::State, _) | (_, Effect::State) => Effect::State,
(Effect::Custom(a), Effect::Custom(b)) if a == b => Effect::Custom(a.clone()),
(Effect::Custom(a), _) => Effect::Custom(a.clone()),
}
}
pub fn strength(&self) -> u8 {
match self {
Effect::Pure => 0,
Effect::State => 1,
Effect::IO => 2,
Effect::Error => 3,
Effect::Custom(_) => 4,
}
}
}
impl PartialOrd for Effect {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Effect {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.strength().cmp(&other.strength())
}
}
impl fmt::Display for Effect {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Effect::Pure => write!(f, "Pure"),
Effect::IO => write!(f, "IO"),
Effect::State => write!(f, "State"),
Effect::Error => write!(f, "Error"),
Effect::Custom(name) => write!(f, "Custom({name})"),
}
}
}