rain_lang/parser/
builder.rs

1/*!
2AST-to-`rain`-IR conversion and related utilities
3*/
4use std::convert::Infallible;
5use std::borrow::Borrow;
6use smallvec::{smallvec, SmallVec};
7use std::hash::Hash;
8use super::symbol_table::SymbolTable;
9use super::ast::{Expr, Sexpr, Path, Let, Pattern, SimpleAssignment, Scope};
10use crate::value::{
11    ValueDesc, ValId,
12    error::ValueError,
13    expr::SexprArgs
14};
15
16/// A rain IR builder which consumes an AST and outputs IR, along with handling errors
17#[derive(Debug, Clone)]
18pub struct Builder<S: Eq + Hash> {
19    symbols: SymbolTable<S, ValId>
20}
21
22/// Errors building `rain` IR
23#[derive(Debug, Clone)]
24pub enum BuilderError<'a> {
25    /// A value construction error
26    ValueError(ValueError),
27    /// Symbol not defined
28    SymbolUndefined(&'a str),
29    /// Build not implemented
30    BuildNotImplemented
31}
32
33impl<'a> From<ValueError> for BuilderError<'a> {
34    fn from(err: ValueError) -> BuilderError<'a> { BuilderError::ValueError(err) }
35}
36
37impl<'a> From<Infallible> for BuilderError<'a> {
38    fn from(err: Infallible) -> BuilderError<'a> { match err {} }
39}
40
41impl<'a> BuilderError<'a> {
42    /// Get the builder error corresponding to a given value error
43    pub fn val<E: Into<ValueError>>(err: E) -> BuilderError<'a>
44    { BuilderError::ValueError(err.into()) }
45}
46
47/// The size of a small vector of definitions
48pub const SMALL_DEFINITIONS: usize = 1;
49
50/// A symbol definition, along with the previous definition, if any
51#[derive(Debug, Clone)]
52pub struct Definition<'a> {
53    /// The name of the symbol defined
54    pub name: &'a str,
55    /// The value it is defined to have
56    pub value: ValId,
57    /// The old value it had before, if any
58    pub previous: Option<ValId>
59}
60
61impl<'a, S: Eq + Hash + From<&'a str> + Borrow<str>> Builder<S> {
62    /// Create a new IR builder
63    pub fn new() -> Builder<S> {
64        Builder {
65            symbols: SymbolTable::new()
66        }
67    }
68    /// Build a let expression, registering the symbols defined in the current scope
69    /// Returns a list of symbols defined
70    pub fn build_let(&mut self, let_statement: &Let<'a>) ->
71    Result<SmallVec<[Definition<'a>; SMALL_DEFINITIONS]>, BuilderError<'a>> {
72        self.assign_pattern(&let_statement.pattern, &let_statement.expr)
73    }
74    /// Assign an expression to a pattern
75    /// Returns a list of symbols defined, along with previous definitions (if any)
76    pub fn assign_pattern(&mut self, pattern: &Pattern<'a>, expr: &Expr<'a>) ->
77    Result<SmallVec<[Definition<'a>; SMALL_DEFINITIONS]>, BuilderError<'a>> {
78        match pattern {
79            Pattern::Simple(simple_assignment) =>
80                self.build_simple_assign(simple_assignment, expr)
81                    .map(|assigned| smallvec![assigned])
82        }
83    }
84    /// Build a simple assignment.
85    pub fn build_simple_assign(&mut self, simple: &SimpleAssignment<'a>, expr: &Expr<'a>)
86    -> Result<Definition<'a>, BuilderError<'a>> {
87        //TODO: typing
88        let name = simple.name;
89        let value = self.build_expr(expr)?;
90        let previous = self.symbols.def(S::from(name), value.clone());
91        Ok(Definition{ name, value, previous })
92    }
93    /// Build the value for an expression
94    pub fn build_expr(&mut self, expr: &Expr<'a>) -> Result<ValId, BuilderError<'a>> {
95        use Expr::*;
96        match expr {
97            Bool(b) => b.to_node(),
98            BoolTy(b) => b.to_node(),
99            LogicalOp(l) => l.to_node(),
100            Path(p) => self.lookup_path(p),
101            Sexpr(s) => self.build_sexpr(s),
102            Scope(s) => self.build_scope(s),
103            _ => Err(BuilderError::BuildNotImplemented)
104        }
105    }
106    /// Build the value for a scope
107    pub fn build_scope(&mut self, scope: &Scope<'a>) -> Result<ValId, BuilderError<'a>> {
108        self.symbols.push(); // Push a new scope
109        // Build definitions
110        for def in scope.definitions.iter() { self.build_let(def)?; }
111        // Build value, if any
112        let res = if let Some(value) = &scope.value {
113            self.build_expr(value)
114        } else {
115            //TODO: module return
116            Err(BuilderError::BuildNotImplemented)
117        };
118        self.symbols.pop(); // Pop the scope
119        res
120    }
121    /// Look up a path
122    pub fn lookup_path(&self, path: &Path<'a>) -> Result<ValId, BuilderError<'a>> {
123        if path.names.len() == 1 {
124            let name = path.names[0];
125            self.symbols.get(name).cloned().ok_or(BuilderError::SymbolUndefined(name))
126        } else {
127            Err(BuilderError::BuildNotImplemented)
128        }
129    }
130    /// Build the value for an S-expression
131    pub fn build_sexpr(&mut self, sexpr: &Sexpr<'a>) -> Result<ValId, BuilderError<'a>> {
132        let args = self.build_sexpr_args(sexpr)?;
133        let sexpr = args.normalize().map_err(BuilderError::ValueError)?;
134        sexpr.to_node()
135    }
136    /// Build the arguments for an S-expression
137    pub fn build_sexpr_args(&mut self, sexpr: &Sexpr<'a>) -> Result<SexprArgs, BuilderError<'a>> {
138        let mut ops = SmallVec::new();
139        for op in sexpr.ops.iter().map(|op| self.build_expr(op)) {
140            match op {
141                Ok(op) => ops.push(op),
142                Err(err) => return Err(err)
143            }
144        }
145        Ok(SexprArgs(ops))
146    }
147}
148
149#[cfg(test)]
150mod tests {
151    use super::*;
152    use crate::parser::{parse_expr, parse_statement};
153
154    #[test]
155    fn simple_logical_expressions_build_properly() {
156        let mut builder = Builder::<&str>::new();
157        let t = &ValId::from(true);
158        let f = &ValId::from(false);
159        let logical_expressions = [
160            ("(#and #true #false)", f),
161            ("(#or #true #false)", t),
162            ("(#not #true)", f),
163            ("(#not #false)", t),
164            ("(#xor #true #true)", f),
165            ("(#or (#or #false #true) (#xor #false #false))", t)
166        ];
167        for (expr, result) in logical_expressions.iter() {
168            let expr = match parse_expr(expr) {
169                Ok((rest, expr)) => {
170                    assert_eq!(
171                        rest, "",
172                        "Did not parse all of valid expression \"{}\": remainder = {:?}",
173                        expr, rest
174                    );
175                    expr
176                },
177                Err(err) => panic!("Got parse error {:?} for valid expression \"{}\"", err, expr)
178            };
179            let built = match builder.build_expr(&expr) {
180                Ok(built) => built,
181                Err(err) => panic!("Valid expression \"{}\" gives build error: {:#?}", expr, err)
182            };
183            assert_eq!(&built, *result);
184        }
185    }
186
187    #[test]
188    fn simple_assignments_build_properly() {
189        let mut builder = Builder::<&str>::new();
190        let program = [
191            "let false = (#or #false #false);",
192            "let true = (#and #true (#and #true #true));",
193            "let x = (#xor true false);",
194            "let y = (#xor true true);"
195        ];
196        for line in program.iter() {
197            let l = match parse_statement(line) {
198                Ok((rest, l)) => {
199                    assert_eq!(
200                        rest, "",
201                        "Unparsed portion {:?} of valid let \"{}\"",
202                        rest, line
203                    );
204                    l
205                },
206                Err(err) =>
207                    panic!("Valid let \"{}\" gives parse error: {:#?}", line, err)
208            };
209            match builder.build_let(&l) {
210                Ok(_) => {},
211                Err(err) => panic!("Valid let \"{}\" gives build error: {:#?}", line, err)
212            };
213        }
214        let t = &ValId::from(true);
215        let f = &ValId::from(false);
216        let variables = [
217            ("true", t), ("false", f), ("x", t), ("y", f)
218        ];
219        for (variable, value) in variables.iter() {
220            match builder.build_expr(&parse_expr(variable).expect("Valid identifier").1) {
221                Ok(built) => assert_eq!(
222                    &built, *value,
223                    "Invalid variable assignment {} = {} != {}", variable, built, value),
224                Err(err) => panic!("Error looking up variable {}: {:#?}", variable, err)
225            }
226        }
227    }
228}