airlang_bin 0.3.0

The Air Programming Language
use std::rc::Rc;

use airlang::{
    Ask,
    AskMode,
    Call,
    CallMode,
    CtxConstFn,
    CtxFreeFn,
    CtxMutableFn,
    Func,
    FuncVal,
    Invariant,
    List,
    ListItemMode,
    ListMode,
    Map,
    MapMode,
    Mode,
    MutableCtx,
    Pair,
    Symbol,
    SymbolMode,
    Val,
    ValMode,
};

use crate::prelude::{
    eval::EvalPrelude,
    process::ProcessPrelude,
    repl::ReplPrelude,
};

thread_local!(pub(crate) static PRELUDE: AllPrelude = AllPrelude::default());

#[derive(Default)]
pub(crate) struct AllPrelude {
    pub(crate) repl: ReplPrelude,
    pub(crate) eval: EvalPrelude,
    pub(crate) process: ProcessPrelude,
}

pub(crate) trait Prelude {
    fn put(&self, ctx: MutableCtx);
}

impl Prelude for AllPrelude {
    fn put(&self, mut ctx: MutableCtx) {
        self.repl.put(ctx.reborrow());
        self.eval.put(ctx.reborrow());
        self.process.put(ctx.reborrow());
    }
}

#[derive(Clone)]
pub(crate) struct Named<T> {
    pub(crate) name: &'static str,
    pub(crate) value: T,
}

impl<T> Named<T> {
    pub(crate) fn new(name: &'static str, value: T) -> Self {
        Self { name, value }
    }
}

impl<T: Into<Val> + Clone> Named<T> {
    pub(crate) fn put(&self, ctx: MutableCtx) {
        let name = unsafe { Symbol::from_str_unchecked(self.name) };
        let val = self.value.clone().into();
        let _ = ctx.put(name, Invariant::Const, val);
    }
}

fn named_free_fn(
    name: &'static str,
    input_mode: Mode,
    output_mode: Mode,
    func: impl CtxFreeFn + 'static,
) -> Named<FuncVal> {
    let name_symbol = unsafe { Symbol::from_str_unchecked(name) };
    let func = Func::new_free(input_mode, output_mode, name_symbol, Rc::new(func));
    let func_val = FuncVal::from(func);
    Named::new(name, func_val)
}

#[allow(unused)]
fn named_const_fn(
    name: &'static str,
    input_mode: Mode,
    output_mode: Mode,
    func: impl CtxConstFn + 'static,
) -> Named<FuncVal> {
    let name_symbol = unsafe { Symbol::from_str_unchecked(name) };
    let func = Func::new_const(input_mode, output_mode, name_symbol, Rc::new(func));
    let func_val = FuncVal::from(func);
    Named::new(name, func_val)
}

fn named_mutable_fn(
    name: &'static str,
    input_mode: Mode,
    output_mode: Mode,
    func: impl CtxMutableFn + 'static,
) -> Named<FuncVal> {
    let name_symbol = unsafe { Symbol::from_str_unchecked(name) };
    let func = Func::new_mutable(input_mode, output_mode, name_symbol, Rc::new(func));
    let func_val = FuncVal::from(func);
    Named::new(name, func_val)
}

fn default_mode() -> Mode {
    Mode::default()
}

#[allow(unused)]
fn symbol_id_mode() -> Mode {
    let mode = ValMode {
        symbol: SymbolMode::Id,
        ..Default::default()
    };
    Mode::Custom(Box::new(mode))
}

#[allow(unused)]
fn pair_mode(first: Mode, second: Mode) -> Mode {
    let mode = ValMode {
        pair: Box::new(Pair::new(first, second)),
        ..Default::default()
    };
    Mode::Custom(Box::new(mode))
}

#[allow(unused)]
fn call_mode(func: Mode, input: Mode) -> Mode {
    let mode = ValMode {
        call: Box::new(CallMode::Struct(Call::new(func, input))),
        ..Default::default()
    };
    Mode::Custom(Box::new(mode))
}

#[allow(unused)]
fn ask_mode(func: Mode, output: Mode) -> Mode {
    let mode = ValMode {
        ask: Box::new(AskMode::Struct(Ask::new(func, output))),
        ..Default::default()
    };
    Mode::Custom(Box::new(mode))
}

#[allow(unused)]
fn list_all_mode(mode: Mode) -> Mode {
    let mode = ValMode {
        list: Box::new(ListMode::All(mode)),
        ..Default::default()
    };
    Mode::Custom(Box::new(mode))
}

#[allow(unused)]
fn list_some_mode(list_item: List<ListItemMode>) -> Mode {
    let mode = ValMode {
        list: Box::new(ListMode::Some(list_item)),
        ..Default::default()
    };
    Mode::Custom(Box::new(mode))
}

#[allow(unused)]
fn map_all_mode(key: Mode, value: Mode) -> Mode {
    let mode = ValMode {
        map: Box::new(MapMode::All(Pair::new(key, value))),
        ..Default::default()
    };
    Mode::Custom(Box::new(mode))
}

fn map_some_mode(map_mode: Map<Val, Mode>) -> Mode {
    let mode = ValMode {
        map: Box::new(MapMode::Some(map_mode)),
        ..Default::default()
    };
    Mode::Custom(Box::new(mode))
}

mod repl;

mod eval;

mod process;