tin_lang/ir/system/
infer_constexpr.rs

1use specs;
2
3use ir::component::constexpr;
4use ir::component::element;
5use std::ops;
6
7pub struct System;
8
9impl<'a> specs::System<'a> for System {
10    type SystemData = (
11        specs::Entities<'a>,
12        specs::ReadStorage<'a, element::Element>,
13        specs::WriteStorage<'a, constexpr::Constexpr>,
14    );
15
16    fn run(&mut self, (entities, elements, mut constexprs): Self::SystemData) {
17        use specs::prelude::ParallelIterator;
18        use specs::ParJoin;
19
20        loop {
21            let new_constexprs = (&entities, &elements, !&constexprs)
22                .par_join()
23                .filter(|(_, element, _)| infer_constexpr(element, &constexprs))
24                .map(|(entity, _, _)| entity)
25                .collect::<Vec<_>>();
26            debug!("inferred new constexprs: {:?}", new_constexprs);
27            if new_constexprs.is_empty() {
28                break;
29            }
30
31            for entity in new_constexprs {
32                constexprs.insert(entity, constexpr::Constexpr).unwrap();
33            }
34        }
35    }
36}
37
38fn infer_constexpr<D>(
39    element: &element::Element,
40    constexprs: &specs::Storage<constexpr::Constexpr, D>,
41) -> bool
42where
43    D: ops::Deref<Target = specs::storage::MaskedStorage<constexpr::Constexpr>>,
44{
45    match *element {
46        element::Element::NumberValue(_) => true,
47        element::Element::StringValue(_) => true,
48        element::Element::Tuple(element::Tuple { ref fields }) => {
49            fields.iter().all(|f| constexprs.contains(*f))
50        }
51        element::Element::Record(element::Record { ref fields }) => {
52            fields.values().all(|v| constexprs.contains(*v))
53        }
54        element::Element::UnOp(element::UnOp { operand, .. }) => constexprs.contains(operand),
55        element::Element::BiOp(element::BiOp { lhs, rhs, .. }) => {
56            constexprs.contains(lhs) && constexprs.contains(rhs)
57        }
58        element::Element::Variable(element::Variable { initializer, .. }) => {
59            constexprs.contains(initializer)
60        }
61        element::Element::Select(element::Select { record, .. }) => constexprs.contains(record),
62        element::Element::Apply(element::Apply {
63            function,
64            ref parameters,
65        }) => constexprs.contains(function) && parameters.iter().all(|p| constexprs.contains(*p)),
66        element::Element::Parameter(element::Parameter { .. }) => false,
67        element::Element::Capture(element::Capture { captured, .. }) => {
68            constexprs.contains(captured)
69        }
70        element::Element::Closure(element::Closure {
71            ref captures,
72            ref statements,
73            result,
74            ..
75        }) => {
76            captures.iter().all(|c| constexprs.contains(*c))
77                && statements.iter().all(|s| constexprs.contains(*s))
78                && constexprs.contains(result)
79        }
80        element::Element::Module(element::Module { ref variables }) => {
81            variables.values().all(|v| constexprs.contains(*v))
82        }
83    }
84}