wp-lang 0.3.0

WPL language crate with AST, parser, evaluator, builtins, and generators.
Documentation
use crate::parser::error::{WPLCodeErrorTrait, WplCodeError};
use derive_getters::Getters;
use smol_str::SmolStr;
use std::collections::VecDeque;
use std::fmt::{Display, Formatter};
use std::io::Write;
use wp_primitives::Parser;

use crate::ast::debug::{DebugFormat, DepIndent};
use crate::ast::{WplRule, WplRuleMeta, WplTag};
use crate::parser::MergeTags;
use crate::parser::wpl_pkg::wpl_package;

use super::AnnFun;

#[derive(Default, Clone, Getters, Debug)]
pub struct WplPackage {
    pub name: SmolStr,
    pub rules: VecDeque<WplRule>,
    pub tags: Option<AnnFun>,
}

impl WplPackage {
    pub(crate) fn append(&mut self, p0: Vec<WplRule>) {
        for i in p0 {
            self.rules.push_back(i);
        }
    }
}

impl WplPackage {
    pub fn export_tags(&self) -> Option<Vec<WplTag>> {
        self.tags.as_ref().map(|x| x.export_tags())
    }
}

#[derive(Serialize, Deserialize)]
pub struct WplPkgMeta {
    pub name: SmolStr,
    pub rules: Vec<WplRuleMeta>,
}

impl From<&WplPackage> for WplPkgMeta {
    fn from(value: &WplPackage) -> Self {
        let mut rules = Vec::new();
        let pkg_tags = value.export_tags();
        for i in &value.rules {
            let mut r_stat = WplRuleMeta::from(i);
            if let Some(mut x) = pkg_tags.clone() {
                r_stat.tags.append(&mut x);
            }
            rules.push(r_stat);
        }
        Self {
            name: value.name.clone(),
            rules,
        }
    }
}

impl DebugFormat for WplPackage {
    fn write<W>(&self, w: &mut W) -> std::io::Result<()>
    where
        W: ?Sized + Write + DepIndent,
    {
        if let Some(tag) = &self.tags {
            tag.write(w)?;
        }

        write!(w, "package {} ", self.name)?;
        self.write_open_brace(w)?;
        self.write_new_line(w)?;

        for rule in &self.rules {
            rule.write(w)?;
            self.write_new_line(w)?;
        }
        self.write_close_brace(w)?;
        self.write_new_line(w)?;

        Ok(())
    }
}

impl Display for WplPackage {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.fmt_string().unwrap_or_default())
    }
}

impl MergeTags for WplPackage {
    fn merge_tags(&mut self, _: &Option<AnnFun>) {
        self.rules.merge_tags(&self.tags);
    }
}

impl WplPackage {
    pub fn new<S: Into<SmolStr>>(name: S, rules: Vec<WplRule>) -> Self {
        let name = name.into();
        debug_assert!(!name.is_empty());

        Self {
            name,
            rules: VecDeque::from(rules),
            tags: None,
        }
    }

    pub fn parse(data: &mut &str, path: &str) -> Result<Self, WplCodeError> {
        let package = wpl_package
            .parse_next(data)
            .map_err(|e| WplCodeError::from_syntax(e, data, path))?;
        Ok(package)
    }

    pub fn is_empty(&self) -> bool {
        self.rules.is_empty()
    }
}