tin_lang/ir/system/
infer_constexpr.rs1use 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}