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
use opslang_ast::*;
use std::collections::HashSet;

pub struct Variables {
    pub variables: HashSet<String>,
    pub telemetry_variables: HashSet<String>,
}

impl Variables {
    pub fn empty() -> Self {
        Variables {
            variables: HashSet::new(),
            telemetry_variables: HashSet::new(),
        }
    }

    pub fn from_statement(stmt: &SingleStatement) -> Self {
        let mut vs = Variables::empty();
        vs.stmt(stmt);
        vs
    }

    fn stmt(&mut self, stmt: &SingleStatement) {
        use SingleStatement::*;
        match stmt {
            Call(_) => (),
            Wait(w) => self.expr(&w.condition),
            Assert(c) => self.expr(&c.condition),
            AssertEq(c) => {
                self.expr(&c.left);
                self.expr(&c.right);
                if let Some(t) = &c.tolerance {
                    self.expr(t)
                }
            }

            Command(cmd) => {
                for arg in &cmd.args {
                    self.expr(arg);
                }
            }
            Let(l) => self.expr(&l.rhs),
            Print(p) => self.expr(&p.arg),
            Set(p) => self.expr(&p.expr),
        }
    }

    fn expr(&mut self, expr: &Expr) {
        match expr {
            Expr::Variable(VariablePath { raw }) => {
                self.variables.insert(raw.to_owned());
            }
            Expr::TlmRef(VariablePath { raw }) => {
                self.telemetry_variables.insert(raw.to_owned());
            }
            Expr::Literal(_) => {}
            Expr::UnOp(_, expr) => self.expr(expr),
            Expr::BinOp(_, lhs, rhs) => {
                self.expr(lhs);
                self.expr(rhs);
            }
            Expr::FunCall(fun, args) => {
                self.expr(fun);
                for arg in args {
                    self.expr(arg);
                }
            }
        }
    }
}