1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use std::{collections::HashMap, fmt, iter::FromIterator};

use crate::R;

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Ident(String);

impl Ident {
    pub fn as_str(&self) -> &str {
        &self.0
    }
}

pub type TypeExpr = crate::TypeExpr<Ident, crate::Expr<R<Ident>>>;
pub type Expr = crate::Expr<R<Ident>>;
pub type Field = crate::Field<TypeExpr>;
pub type NodeApp = crate::NodeApp<Ident, crate::Expr<R<Ident>>>;

// FIXME: Limit allowed identifiers
impl std::str::FromStr for Ident {
    type Err = std::convert::Infallible;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Ident(s.into()))
    }
}

impl fmt::Display for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

#[derive(Debug, Clone)]
pub struct Path(Vec<Ident>);

impl Path {
    pub fn len(&self) -> usize {
        self.0.len()
    }

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

    pub fn split_branch(self) -> Result<(Ident, Path, Ident), Self> {
        if self.len() >= 2 {
            let mut components = self.0;
            let name = components.pop().unwrap();
            let root = components.remove(0);
            Ok((root, Path(components), name))
        } else {
            Err(self)
        }
    }
}

impl<'a> FromIterator<&'a Ident> for Path {
    fn from_iter<T>(iter: T) -> Path
    where
        T: IntoIterator<Item = &'a Ident>,
    {
        Path(iter.into_iter().cloned().collect())
    }
}

impl fmt::Display for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for (i, ident) in self.0.iter().enumerate() {
            write!(f, "{}", ident)?;
            if i + 1 < self.0.len() {
                f.write_str(".")?;
            }
        }
        Ok(())
    }
}

impl std::str::FromStr for Path {
    type Err = std::convert::Infallible;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // FIXME: limit identifiers
        Ok(Path(s.split('.').map(|s| s.parse().unwrap()).collect()))
    }
}

impl<'a> IntoIterator for &'a Path {
    type IntoIter = std::slice::Iter<'a, Ident>;
    type Item = &'a Ident;

    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}

impl IntoIterator for Path {
    type IntoIter = std::vec::IntoIter<Ident>;
    type Item = Ident;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

#[derive(Debug, Clone)]
pub struct Root {
    pub name: Ident,
    pub description: Option<String>,
    pub fields: Vec<Field>,
}

#[derive(Debug, Clone)]
pub struct Branch {
    pub root: Ident,
    pub path: Path,
    pub name: Ident,
    pub description: Option<String>,
    pub condition: Expr,
    pub implies: Vec<NodeApp>,
    pub fields: Vec<Field>,
    pub properties: HashMap<String, lexpr::Value>,
}

#[derive(Debug, Clone)]
pub struct Enum {
    pub name: Ident,
    pub description: Option<String>,
    pub discriminants: Vec<Field>,
    pub variants: Vec<Variant>,
}

#[derive(Debug, Clone)]
pub struct Variant {
    pub name: Ident,
    pub condition: Expr,
    pub fields: Vec<Field>,
    pub properties: HashMap<String, lexpr::Value>,
}