subscript_compiler/frontend/pass/
pp_normalize.rs

1//! AST post-parser canonicalization.
2use std::rc::Rc;
3use std::borrow::Cow;
4use std::collections::{HashSet, VecDeque, LinkedList};
5use std::iter::FromIterator;
6use std::vec;
7use itertools::Itertools;
8
9use crate::frontend::data::*;
10use crate::frontend::ast::*;
11
12
13///////////////////////////////////////////////////////////////////////////////
14// PARSER AST TO BACKEND AST & NORMALIZATION
15///////////////////////////////////////////////////////////////////////////////
16
17
18pub fn to_unnormalized_backend_ir<'a>(children: Vec<Node<'a>>) -> Vec<Node<'a>> {
19    let mut results: Vec<Node> = Default::default();
20    for child in children {
21        let last = {
22            let mut valid_left_pos = None;
23            for ix in (0..results.len()).rev() {
24                let leftward = results
25                    .get(ix)
26                    .filter(|x| !x.is_whitespace());
27                if valid_left_pos.is_none() && leftward.is_some() {
28                    valid_left_pos = Some(ix);
29                    break;
30                }
31            }
32            // results.back_mut()
33            // unimplemented!()
34            if let Some(ix) = valid_left_pos {
35                results.get_mut(ix)
36            } else {
37                None
38            }
39        };
40        let last_is_ident = last.as_ref().map(|x| x.is_ident()).unwrap_or(false);
41        let last_is_tag = last.as_ref().map(|x| x.is_tag()).unwrap_or(false);
42        // RETURN NONE IF CHILD IS ADDED TO SOME EXISTING NODE
43        let new_child = match child {
44            Node::Tag(..) => unimplemented!(),
45            Node::Enclosure(node) if last_is_ident && node.data.is_square_parens() => {
46                let last = last.unwrap();
47                let mut name = last
48                    .unwrap_ident()
49                    .unwrap()
50                    .clone();
51                let parameters = to_unnormalized_backend_ir(node.data.children);
52                let new_node = Node::Tag(Tag {
53                    name: name.clone(),
54                    parameters: Some(parameters),
55                    children: Vec::new(),
56                    rewrite_rules: Vec::new(),
57                });
58                *last = new_node;
59                None
60            }
61            Node::Enclosure(node) if last_is_ident && node.data.is_curly_brace() => {
62                let last = last.unwrap();
63                let mut name = last
64                    .unwrap_ident()
65                    .unwrap()
66                    .clone();
67                let children = to_unnormalized_backend_ir(node.data.children);
68                let new_node = Node::Tag(Tag {
69                    name,
70                    parameters: None,
71                    children: vec![
72                        Node::unannotated_enclosure(
73                            EnclosureKind::CurlyBrace,
74                            children,
75                        )
76                    ],
77                    rewrite_rules: Vec::new(),
78                });
79                *last = new_node;
80                None
81            }
82            Node::Enclosure(node) if last_is_tag && node.data.is_curly_brace() => {
83                let tag = last.unwrap();
84                let children = to_unnormalized_backend_ir(node.data.children);
85                tag.unwrap_tag_mut()
86                    .unwrap()
87                    .children
88                    .push(Node::unannotated_enclosure(
89                        EnclosureKind::CurlyBrace,
90                        children,
91                    ));
92                None
93            }
94            Node::Enclosure(node) => {
95                let children = to_unnormalized_backend_ir(node.data.children);
96                let new_node = Node::unannotated_enclosure(
97                    node.data.kind,
98                    children,
99                );
100                Some(new_node)
101            }
102            Node::Ident(node) => {
103                let new_node = Node::Ident(node);
104                Some(new_node)
105            }
106            Node::InvalidToken(node) => {
107                let new_node = Node::String(node);
108                Some(new_node)
109            }
110            Node::String(node) => {
111                let mut is_token = false;
112                for sym in TOKEN_SET {
113                    if *sym == &node.data {
114                        is_token = true;
115                        break;
116                    }
117                }
118                if is_token {
119                    Some(Node::String(node))
120                } else {
121                    Some(Node::String(node))
122                }
123            }
124        };
125        if let Some(new_child) = new_child {
126            results.push(new_child);
127        }
128    }
129    results
130}
131
132
133fn into_rewrite_rules<'a>(
134    children: Vec<Node<'a>>
135) -> Vec<RewriteRule<Node<'a>>> {
136    let mut results = Vec::new();
137    for ix in 0..children.len() {
138        if ix == 0 {
139            continue;
140        }
141        let left = children.get(ix - 1);
142        let current = children
143            .get(ix)
144            .and_then(|x| x.unwrap_string())
145            .filter(|x| &x.data == "=>");
146        let right = children.get(ix + 1);
147        match (left, current, right) {
148            (Some(left), Some(_), Some(right)) => {
149                results.push(RewriteRule {
150                    from: left.clone(),
151                    to: right.clone(),
152                })
153            }
154            _ => ()
155        }
156    }
157    results
158}
159
160pub fn block_level_normalize<'a>(children: Vec<Node<'a>>) -> Vec<Node<'a>> {
161    let mut results = Vec::new();
162    for child in children {
163        if child.is_named_block("!where") {
164            let child = child.into_tag().unwrap();
165            let last = results
166                .last_mut()
167                .and_then(Node::unwrap_tag_mut);
168            if let Some(last) = last {
169                let rewrite_rule = into_rewrite_rules(
170                    child.children,
171                );
172                last.rewrite_rules.extend(rewrite_rule);
173                continue;
174            }
175        } else {
176            results.push(child);
177        }
178    }
179    results
180}
181
182pub fn parameter_level_normalize_pass(node: Node) -> Node {
183    fn go(parameters: Vec<Node>) -> Vec<Node> {
184        parameters
185            .iter()
186            .filter_map(Node::get_string)
187            .map(|x| x.data)
188            .collect::<Vec<_>>()
189            .join("")
190            .split_whitespace()
191            .map(ToOwned::to_owned)
192            .map(|x| Node::String(Ann::unannotated(Cow::Owned(x))))
193            .collect::<Vec<_>>()
194    }
195    match node {
196        Node::Tag(mut tag) => {
197            tag.parameters = tag.parameters.map(go);
198            Node::Tag(tag)
199        }
200        x => x
201    }
202}
203
204
205/// Parses the given source code and returns a normalized backend AST vector.
206pub fn run_compiler_frontend<'a>(source: &'a str) -> Vec<Node<'a>> {
207    // PARSE SOURCE CODE
208    let children = crate::frontend::parser::parse_source(source);
209    // NORMALIZE IR
210    let children = to_unnormalized_backend_ir(children);
211    // NORMALIZE IR
212    let node = Node::new_fragment(children)
213        .transform_children(Rc::new(block_level_normalize))
214        .transform(
215            NodeEnvironment::default(),
216            Rc::new(|_, x| parameter_level_normalize_pass(x))
217        );
218    // DONE
219    node.into_fragment()
220}