#![allow(unused)]
use std::collections::HashMap;
use std::mem;
use std::sync::{Arc, Condvar, Mutex};
use cljrs_gc::GcPtr;
use cljrs_reader::Form;
use crate::Value;
pub type MethodMap = HashMap<Arc<str>, Value>;
#[derive(Debug)]
pub struct Protocol {
pub name: Arc<str>,
pub ns: Arc<str>,
pub methods: Vec<ProtocolMethod>,
pub impls: Mutex<HashMap<Arc<str>, MethodMap>>,
}
impl Protocol {
pub fn new(name: Arc<str>, ns: Arc<str>, methods: Vec<ProtocolMethod>) -> Self {
Self {
name,
ns,
methods,
impls: Mutex::new(HashMap::new()),
}
}
}
impl cljrs_gc::Trace for Protocol {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
{
let impls = self.impls.lock().unwrap();
for method_map in impls.values() {
for v in method_map.values() {
v.trace(visitor);
}
}
}
}
}
#[derive(Debug, Clone)]
pub struct ProtocolMethod {
pub name: Arc<str>,
pub min_arity: usize,
pub variadic: bool,
}
impl cljrs_gc::Trace for ProtocolMethod {
fn trace(&self, _: &mut cljrs_gc::MarkVisitor) {}
}
#[derive(Debug)]
pub struct ProtocolFn {
pub protocol: GcPtr<Protocol>,
pub method_name: Arc<str>,
pub min_arity: usize,
pub variadic: bool,
}
impl cljrs_gc::Trace for ProtocolFn {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
use cljrs_gc::GcVisitor as _;
visitor.visit(&self.protocol);
}
}
#[derive(Debug)]
pub struct MultiFn {
pub name: Arc<str>,
pub dispatch_fn: Value,
pub methods: Mutex<HashMap<String, Value>>,
pub prefers: Mutex<HashMap<String, Vec<String>>>,
pub default_dispatch: String,
}
impl MultiFn {
pub fn new(name: Arc<str>, dispatch_fn: Value, default_dispatch: String) -> Self {
Self {
name,
dispatch_fn,
methods: Mutex::new(HashMap::new()),
prefers: Mutex::new(HashMap::new()),
default_dispatch,
}
}
}
impl cljrs_gc::Trace for MultiFn {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
self.dispatch_fn.trace(visitor);
{
let methods = self.methods.lock().unwrap();
for v in methods.values() {
v.trace(visitor);
}
}
}
}
#[derive(Debug)]
pub struct Var {
pub namespace: Arc<str>,
pub name: Arc<str>,
pub value: Mutex<Option<Value>>,
pub is_macro: bool,
pub meta: Mutex<Option<Value>>,
pub watches: Mutex<Vec<(Value, Value)>>,
}
impl Var {
pub fn new(namespace: impl Into<Arc<str>>, name: impl Into<Arc<str>>) -> Self {
Self {
namespace: namespace.into(),
name: name.into(),
value: Mutex::new(None),
is_macro: false,
meta: Mutex::new(None),
watches: Mutex::new(Vec::new()),
}
}
pub fn is_bound(&self) -> bool {
self.value.lock().unwrap().is_some()
}
pub fn deref(&self) -> Option<Value> {
self.value.lock().unwrap().clone()
}
pub fn bind(&self, v: Value) {
*self.value.lock().unwrap() = Some(v);
}
pub fn get_meta(&self) -> Option<Value> {
self.meta.lock().unwrap().clone()
}
pub fn set_meta(&self, m: Value) {
*self.meta.lock().unwrap() = Some(m);
}
pub fn full_name(&self) -> String {
format!("{}/{}", self.namespace, self.name)
}
}
impl cljrs_gc::Trace for Var {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
{
let value = self.value.lock().unwrap();
if let Some(v) = value.as_ref() {
v.trace(visitor);
}
}
{
let meta = self.meta.lock().unwrap();
if let Some(m) = meta.as_ref() {
m.trace(visitor);
}
}
{
let watches = self.watches.lock().unwrap();
for (key, f) in watches.iter() {
key.trace(visitor);
f.trace(visitor);
}
}
}
}
#[derive(Debug)]
pub struct Atom {
pub value: Mutex<Value>,
pub meta: Mutex<Option<Value>>,
pub validator: Mutex<Option<Value>>,
pub watches: Mutex<Vec<(Value, Value)>>,
}
impl Atom {
pub fn new(v: Value) -> Self {
Self {
value: Mutex::new(v),
meta: Mutex::new(None),
validator: Mutex::new(None),
watches: Mutex::new(Vec::new()),
}
}
pub fn deref(&self) -> Value {
self.value.lock().unwrap().clone()
}
pub fn reset(&self, v: Value) -> Value {
let mut guard = self.value.lock().unwrap();
*guard = v.clone();
v
}
pub fn get_meta(&self) -> Option<Value> {
self.meta.lock().unwrap().clone()
}
pub fn set_meta(&self, m: Option<Value>) {
*self.meta.lock().unwrap() = m;
}
pub fn get_validator(&self) -> Option<Value> {
self.validator.lock().unwrap().clone()
}
pub fn set_validator(&self, vf: Option<Value>) {
*self.validator.lock().unwrap() = vf;
}
}
impl cljrs_gc::Trace for Atom {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
{
let value = self.value.lock().unwrap();
value.trace(visitor);
}
{
let meta = self.meta.lock().unwrap();
if let Some(m) = meta.as_ref() {
m.trace(visitor);
}
}
{
let validator = self.validator.lock().unwrap();
if let Some(vf) = validator.as_ref() {
vf.trace(visitor);
}
}
{
let watches = self.watches.lock().unwrap();
for (key, f) in watches.iter() {
key.trace(visitor);
f.trace(visitor);
}
}
}
}
#[derive(Debug)]
pub struct Namespace {
pub name: Arc<str>,
pub interns: Mutex<HashMap<Arc<str>, GcPtr<Var>>>,
pub refers: Mutex<HashMap<Arc<str>, GcPtr<Var>>>,
pub aliases: Mutex<HashMap<Arc<str>, Arc<str>>>,
}
impl Namespace {
pub fn new(name: impl Into<Arc<str>>) -> Self {
Self {
name: name.into(),
interns: Mutex::new(HashMap::new()),
refers: Mutex::new(HashMap::new()),
aliases: Mutex::new(HashMap::new()),
}
}
}
impl cljrs_gc::Trace for Namespace {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
use cljrs_gc::GcVisitor as _;
{
let interns = self.interns.lock().unwrap();
for var in interns.values() {
visitor.visit(var);
}
}
{
let refers = self.refers.lock().unwrap();
for var in refers.values() {
visitor.visit(var);
}
}
}
}
pub type NativeFnPtr = fn(&[Value]) -> crate::error::ValueResult<Value>;
pub type NativeFnFunc = Arc<dyn Fn(&[Value]) -> crate::error::ValueResult<Value> + Send + Sync>;
#[derive(Clone, Debug)]
pub enum Arity {
Fixed(usize),
Variadic { min: usize },
}
pub struct NativeFn {
pub name: Arc<str>,
pub arity: Arity,
pub func: NativeFnFunc,
}
impl NativeFn {
pub fn new(name: impl Into<Arc<str>>, arity: Arity, func: NativeFnPtr) -> Self {
Self {
name: name.into(),
arity,
func: Arc::new(func),
}
}
pub fn with_closure(
name: impl Into<Arc<str>>,
arity: Arity,
func: impl Fn(&[Value]) -> crate::error::ValueResult<Value> + Send + Sync + 'static,
) -> Self {
Self {
name: name.into(),
arity,
func: Arc::new(func),
}
}
}
impl std::fmt::Debug for NativeFn {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NativeFn")
.field("name", &self.name)
.field("arity", &self.arity)
.field("func", &"<fn>")
.finish()
}
}
impl cljrs_gc::Trace for NativeFn {
fn trace(&self, _: &mut cljrs_gc::MarkVisitor) {}
}
#[derive(Debug, Clone)]
pub struct CljxFnArity {
pub params: Vec<Arc<str>>,
pub rest_param: Option<Arc<str>>,
pub body: Vec<Form>,
pub destructure_params: Vec<(usize, Form)>,
pub destructure_rest: Option<Form>,
pub ir_arity_id: u64,
}
#[derive(Debug, Clone)]
pub struct CljxFn {
pub name: Option<Arc<str>>,
pub arities: Vec<CljxFnArity>,
pub closed_over_names: Vec<Arc<str>>,
pub closed_over_vals: Vec<Value>,
pub is_macro: bool,
pub defining_ns: Arc<str>,
}
impl CljxFn {
pub fn new(
name: Option<Arc<str>>,
arities: Vec<CljxFnArity>,
closed_over_names: Vec<Arc<str>>,
closed_over_vals: Vec<Value>,
is_macro: bool,
defining_ns: Arc<str>,
) -> Self {
Self {
name,
arities,
closed_over_names,
closed_over_vals,
is_macro,
defining_ns,
}
}
}
impl cljrs_gc::Trace for CljxFn {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
for v in &self.closed_over_vals {
v.trace(visitor);
}
}
}
#[derive(Debug)]
pub struct BoundFn {
pub wrapped: Value,
pub captured_bindings: HashMap<usize, Value>,
}
impl cljrs_gc::Trace for BoundFn {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
self.wrapped.trace(visitor);
for val in self.captured_bindings.values() {
val.trace(visitor);
}
}
}
pub trait Thunk: Send + Sync + std::fmt::Debug + cljrs_gc::Trace {
fn force(&self) -> Result<Value, String>;
}
pub enum LazySeqState {
Pending(Box<dyn Thunk>),
Forced(Value),
Error(String),
}
pub struct LazySeq {
pub state: Mutex<LazySeqState>,
}
impl LazySeq {
pub fn new(thunk: Box<dyn Thunk>) -> Self {
Self {
state: Mutex::new(LazySeqState::Pending(thunk)),
}
}
pub fn realize(&self) -> Value {
let thunk = {
let mut guard = self.state.lock().unwrap();
match &*guard {
LazySeqState::Forced(v) => return v.clone(),
LazySeqState::Error(_) => return Value::Nil,
LazySeqState::Pending(_) => {}
}
let prev = mem::replace(&mut *guard, LazySeqState::Forced(Value::Nil));
let LazySeqState::Pending(thunk) = prev else {
unreachable!("state was not Pending")
};
thunk
};
match thunk.force() {
Ok(result) => {
*self.state.lock().unwrap() = LazySeqState::Forced(result.clone());
result
}
Err(msg) => {
*self.state.lock().unwrap() = LazySeqState::Error(msg);
Value::Nil
}
}
}
pub fn error(&self) -> Option<String> {
let guard = self.state.lock().unwrap();
if let LazySeqState::Error(e) = &*guard {
Some(e.clone())
} else {
None
}
}
}
impl std::fmt::Debug for LazySeq {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "LazySeq(...)")
}
}
impl cljrs_gc::Trace for LazySeq {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
{
let state = self.state.lock().unwrap();
match &*state {
LazySeqState::Pending(thunk) => thunk.trace(visitor),
LazySeqState::Forced(v) => v.trace(visitor),
LazySeqState::Error(_) => {}
}
}
}
}
#[derive(Debug, Clone)]
pub struct CljxCons {
pub head: Value,
pub tail: Value,
}
impl cljrs_gc::Trace for CljxCons {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
self.head.trace(visitor);
self.tail.trace(visitor);
}
}
pub struct Volatile {
pub value: Mutex<Value>,
}
impl Volatile {
pub fn new(v: Value) -> Self {
Self {
value: Mutex::new(v),
}
}
pub fn deref(&self) -> Value {
self.value.lock().unwrap().clone()
}
pub fn reset(&self, v: Value) -> Value {
*self.value.lock().unwrap() = v.clone();
v
}
}
impl std::fmt::Debug for Volatile {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Volatile")
}
}
impl cljrs_gc::Trace for Volatile {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
{
let value = self.value.lock().unwrap();
value.trace(visitor);
}
}
}
pub enum DelayState {
Pending(Box<dyn Thunk>),
Forced(Value),
}
pub struct Delay {
pub state: Mutex<DelayState>,
}
impl Delay {
pub fn new(thunk: Box<dyn Thunk>) -> Self {
Self {
state: Mutex::new(DelayState::Pending(thunk)),
}
}
pub fn force(&self) -> Result<Value, String> {
let thunk = {
let mut guard = self.state.lock().unwrap();
if let DelayState::Forced(v) = &*guard {
return Ok(v.clone());
}
let prev = mem::replace(&mut *guard, DelayState::Forced(Value::Nil));
let DelayState::Pending(thunk) = prev else {
unreachable!("state was not Pending")
};
thunk
};
let result = thunk.force()?;
*self.state.lock().unwrap() = DelayState::Forced(result.clone());
Ok(result)
}
pub fn is_realized(&self) -> bool {
matches!(&*self.state.lock().unwrap(), DelayState::Forced(_))
}
}
impl std::fmt::Debug for Delay {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Delay")
}
}
impl cljrs_gc::Trace for Delay {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
{
let state = self.state.lock().unwrap();
match &*state {
DelayState::Pending(thunk) => thunk.trace(visitor),
DelayState::Forced(v) => v.trace(visitor),
}
}
}
}
pub struct CljxPromise {
pub value: Mutex<Option<Value>>,
pub cond: Condvar,
}
impl CljxPromise {
pub fn new() -> Self {
Self {
value: Mutex::new(None),
cond: Condvar::new(),
}
}
pub fn deliver(&self, v: Value) {
let mut guard = self.value.lock().unwrap();
if guard.is_none() {
*guard = Some(v);
self.cond.notify_all();
}
}
pub fn deref_blocking(&self) -> Value {
let mut guard = self.value.lock().unwrap();
while guard.is_none() {
guard = self.cond.wait(guard).unwrap();
}
guard.as_ref().unwrap().clone()
}
pub fn is_realized(&self) -> bool {
self.value.lock().unwrap().is_some()
}
}
impl Default for CljxPromise {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for CljxPromise {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Promise")
}
}
impl cljrs_gc::Trace for CljxPromise {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
{
let value = self.value.lock().unwrap();
if let Some(v) = value.as_ref() {
v.trace(visitor);
}
}
}
}
pub enum FutureState {
Running,
Done(Value),
Failed(String),
Cancelled,
}
pub struct CljxFuture {
pub state: Mutex<FutureState>,
pub cond: Condvar,
}
impl CljxFuture {
pub fn new() -> Self {
Self {
state: Mutex::new(FutureState::Running),
cond: Condvar::new(),
}
}
pub fn is_done(&self) -> bool {
!matches!(&*self.state.lock().unwrap(), FutureState::Running)
}
pub fn is_cancelled(&self) -> bool {
matches!(&*self.state.lock().unwrap(), FutureState::Cancelled)
}
}
impl Default for CljxFuture {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for CljxFuture {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Future")
}
}
impl cljrs_gc::Trace for CljxFuture {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
{
let state = self.state.lock().unwrap();
if let FutureState::Done(v) = &*state {
v.trace(visitor);
}
}
}
}
pub type AgentFn = Box<dyn FnOnce(Value) -> Result<Value, Value> + Send>;
pub enum AgentMsg {
Update(AgentFn),
Shutdown,
}
pub struct Agent {
pub state: Arc<Mutex<Value>>,
pub error: Arc<Mutex<Option<Value>>>,
pub sender: Mutex<std::sync::mpsc::SyncSender<AgentMsg>>,
pub watches: Mutex<Vec<(Value, Value)>>,
}
impl Agent {
pub fn get_state(&self) -> Value {
self.state.lock().unwrap().clone()
}
pub fn get_error(&self) -> Option<Value> {
self.error.lock().unwrap().clone()
}
pub fn clear_error(&self) {
*self.error.lock().unwrap() = None;
}
}
impl std::fmt::Debug for Agent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Agent")
}
}
impl cljrs_gc::Trace for Agent {
fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
{
let state = self.state.lock().unwrap();
state.trace(visitor);
}
{
let error = self.error.lock().unwrap();
if let Some(e) = error.as_ref() {
e.trace(visitor);
}
}
{
let watches = self.watches.lock().unwrap();
for (key, f) in watches.iter() {
key.trace(visitor);
f.trace(visitor);
}
}
}
}