airlang 0.24.0

Air is a minimalist and universal programming language.
Documentation
use std::mem::take;

use crate::semantics::cfg::Cfg;
use crate::semantics::core::key::KeyEval;
use crate::semantics::func::DynFunc;
use crate::semantics::val::CallVal;
use crate::semantics::val::CellVal;
use crate::semantics::val::ListVal;
use crate::semantics::val::MapVal;
use crate::semantics::val::PairVal;
use crate::semantics::val::Val;
use crate::type_::Key;

pub(crate) struct CellForm<'a, Value> {
    pub(crate) value: &'a Value,
}

impl<'a, Value, Ctx> DynFunc<Cfg, Ctx, CellVal, CellVal> for CellForm<'a, Value>
where Value: DynFunc<Cfg, Ctx, Val, Val>
{
    fn call(&self, cfg: &mut Cfg, ctx: &mut Ctx, mut cell: CellVal) -> CellVal {
        cell.value = self.value.call(cfg, ctx, take(&mut cell.value));
        cell
    }
}

pub(crate) struct PairForm<'a, Left, Right> {
    pub(crate) left: &'a Left,
    pub(crate) right: &'a Right,
}

impl<'a, Left, Right, Ctx> DynFunc<Cfg, Ctx, PairVal, PairVal> for PairForm<'a, Left, Right>
where
    Left: DynFunc<Cfg, Ctx, Val, Val>,
    Right: DynFunc<Cfg, Ctx, Val, Val>,
{
    fn call(&self, cfg: &mut Cfg, ctx: &mut Ctx, mut pair: PairVal) -> PairVal {
        pair.left = self.left.call(cfg, ctx, take(&mut pair.left));
        pair.right = self.right.call(cfg, ctx, take(&mut pair.right));
        pair
    }
}

pub(crate) struct CallForm<'a, Func, Input> {
    pub(crate) func: &'a Func,
    pub(crate) input: &'a Input,
}

impl<'a, Func, Input, Ctx> DynFunc<Cfg, Ctx, CallVal, CallVal> for CallForm<'a, Func, Input>
where
    Func: DynFunc<Cfg, Ctx, Val, Val>,
    Input: DynFunc<Cfg, Ctx, Val, Val>,
{
    fn call(&self, cfg: &mut Cfg, ctx: &mut Ctx, mut call: CallVal) -> CallVal {
        call.func = self.func.call(cfg, ctx, take(&mut call.func));
        call.input = self.input.call(cfg, ctx, take(&mut call.input));
        call
    }
}

pub(crate) struct ListForm<'a, Item> {
    pub(crate) item: &'a Item,
}

impl<'a, Item, Ctx> DynFunc<Cfg, Ctx, ListVal, ListVal> for ListForm<'a, Item>
where Item: DynFunc<Cfg, Ctx, Val, Val>
{
    fn call(&self, cfg: &mut Cfg, ctx: &mut Ctx, mut list: ListVal) -> ListVal {
        for v in list.iter_mut() {
            *v = self.item.call(cfg, ctx, take(v));
        }
        list
    }
}

pub(crate) struct MapForm<'a, Value> {
    pub(crate) value: &'a Value,
}

impl<'a, Value, Ctx> DynFunc<Cfg, Ctx, MapVal, MapVal> for MapForm<'a, Value>
where Value: DynFunc<Cfg, Ctx, Val, Val>
{
    fn call(&self, cfg: &mut Cfg, ctx: &mut Ctx, mut map: MapVal) -> MapVal {
        for v in map.values_mut() {
            *v = self.value.call(cfg, ctx, take(v));
        }
        map
    }
}

#[derive(Default, Copy, Clone)]
pub struct Form;

impl DynFunc<Cfg, Val, Val, Val> for Form {
    fn call(&self, cfg: &mut Cfg, ctx: &mut Val, val: Val) -> Val {
        if !cfg.step() {
            return Val::default();
        }
        match val {
            Val::Key(key) => self.call(cfg, ctx, key),
            Val::Cell(cell) => Val::Cell(self.call(cfg, ctx, cell)),
            Val::Pair(pair) => Val::Pair(self.call(cfg, ctx, pair)),
            Val::Call(call) => Val::Call(self.call(cfg, ctx, call)),
            Val::List(list) => Val::List(self.call(cfg, ctx, list)),
            Val::Map(map) => Val::Map(self.call(cfg, ctx, map)),
            v => v,
        }
    }
}

impl DynFunc<Cfg, Val, Key, Val> for Form {
    fn call(&self, cfg: &mut Cfg, ctx: &mut Val, key: Key) -> Val {
        KeyEval.call(cfg, ctx, key)
    }
}

impl DynFunc<Cfg, Val, CellVal, CellVal> for Form {
    fn call(&self, cfg: &mut Cfg, ctx: &mut Val, cell: CellVal) -> CellVal {
        CellForm { value: self }.call(cfg, ctx, cell)
    }
}

impl DynFunc<Cfg, Val, PairVal, PairVal> for Form {
    fn call(&self, cfg: &mut Cfg, ctx: &mut Val, pair: PairVal) -> PairVal {
        PairForm { left: self, right: self }.call(cfg, ctx, pair)
    }
}

impl DynFunc<Cfg, Val, CallVal, CallVal> for Form {
    fn call(&self, cfg: &mut Cfg, ctx: &mut Val, call: CallVal) -> CallVal {
        CallForm { func: self, input: self }.call(cfg, ctx, call)
    }
}

impl DynFunc<Cfg, Val, ListVal, ListVal> for Form {
    fn call(&self, cfg: &mut Cfg, ctx: &mut Val, list: ListVal) -> ListVal {
        ListForm { item: self }.call(cfg, ctx, list)
    }
}

impl DynFunc<Cfg, Val, MapVal, MapVal> for Form {
    fn call(&self, cfg: &mut Cfg, ctx: &mut Val, map: MapVal) -> MapVal {
        MapForm { value: self }.call(cfg, ctx, map)
    }
}