airlang 0.23.0

Air is a minimalist and universal programming language.
Documentation
use std::ops::Deref;

use self::lib::CoreLib;
use crate::bug;
use crate::cfg::prelude::CorePrelude;
use crate::cfg::prelude::prelude_repr;
use crate::semantics::cfg::Cfg;
use crate::semantics::val::FuncVal;
use crate::semantics::val::LinkVal;
use crate::semantics::val::Val;
use crate::type_::Key;
use crate::type_::Map;

pub trait CfgMod {
    fn extend(self, cfg: &Cfg);
}

#[derive(Clone)]
pub struct CoreCfg {
    pub lib: CoreLib,
    pub prelude: CorePrelude,
}

impl Default for CoreCfg {
    fn default() -> Self {
        let lib = CoreLib::default();
        let prelude = CorePrelude::new(&lib);
        Self { lib, prelude }
    }
}

impl CfgMod for CoreCfg {
    fn extend(self, cfg: &Cfg) {
        self.lib.extend(cfg);
        let prelude = prelude_repr(self.prelude);
        let prelude = Val::Link(LinkVal::new(Val::Map(prelude.into()), false));
        cfg.extend_scope(Key::from_str_unchecked(Self::PRELUDE), prelude);
    }
}

impl CoreCfg {
    pub const PRELUDE: &str = "_prelude";

    pub fn prelude(cfg: &mut Cfg, tag: &str) -> Option<Map<Key, Val>> {
        let prelude = cfg.import(Key::from_str_unchecked(Self::PRELUDE));
        let Some(prelude) = prelude else {
            bug!(cfg, "{tag}: value not found for key {} in config", Self::PRELUDE);
            return None;
        };
        let Val::Link(prelude) = prelude else {
            bug!(cfg, "{tag}: expected {} to be a link, but got {prelude}", Self::PRELUDE);
            return None;
        };
        let Ok(prelude) = prelude.try_borrow() else {
            bug!(cfg, "{tag}: link is in use");
            return None;
        };
        let Val::Map(prelude) = prelude.deref().clone() else {
            bug!(cfg, "{tag}: expected {} to be a link of a map", Self::PRELUDE);
            return None;
        };
        Some(Map::from(prelude))
    }
}

pub fn extend(cfg: &Cfg, key: &str, val: impl Into<Val>) {
    cfg.extend_scope(Key::from_str_unchecked(key), val.into());
}

pub fn extend_func(cfg: &Cfg, key: &str, val: impl Into<FuncVal>) {
    cfg.extend_scope(Key::from_str_unchecked(key), Val::Func(val.into()));
}

pub mod lib;

pub mod prelude;

pub mod error;

mod repr;

mod utils;