1 #include <cassert>
2 #include <cstddef>
3 #include "location.hh"
4 #include <iostream>
5 #include <memory>
6 #include <rumur/Decl.h>
7 #include <rumur/Expr.h>
8 #include <rumur/Property.h>
9 #include <rumur/Ptr.h>
10 #include <rumur/Rule.h>
11 #include <rumur/Stmt.h>
12 #include <rumur/except.h>
13 #include <rumur/traverse.h>
14 #include <string>
15 #include <vector>
16 
17 namespace rumur {
18 
19 namespace {
20 /* A traversal pass that checks any return statements within a rule do not
21  * have a trailing expression.
22  */
23 class ReturnChecker : public ConstTraversal {
24 
25 public:
26   /* Avoid recursing into functions, that may have return statements with an
27    * expression.
28    */
visit_function(const Function &)29   void visit_function(const Function &) final {}
visit_functioncall(const FunctionCall &)30   void visit_functioncall(const FunctionCall &) final {}
visit_procedurecall(const ProcedureCall &)31   void visit_procedurecall(const ProcedureCall &) final {}
32 
visit_return(const Return & n)33   void visit_return(const Return &n) final {
34     if (n.expr != nullptr)
35       throw Error("return statement in rule or startstate returns a value",
36                   n.loc);
37 
38     // No need to recurse into the return statement's child.
39   }
40 
check(const Node & n)41   static void check(const Node &n) {
42     ReturnChecker c;
43     c.dispatch(n);
44   }
45 
46   virtual ~ReturnChecker() = default;
47 };
48 } // namespace
49 
Rule(const std::string & name_,const location & loc_)50 Rule::Rule(const std::string &name_, const location &loc_)
51     : Node(loc_), name(name_) {}
52 
flatten() const53 std::vector<Ptr<Rule>> Rule::flatten() const { return {Ptr<Rule>(clone())}; }
54 
AliasRule(const std::vector<Ptr<AliasDecl>> & aliases_,const std::vector<Ptr<Rule>> & rules_,const location & loc_)55 AliasRule::AliasRule(const std::vector<Ptr<AliasDecl>> &aliases_,
56                      const std::vector<Ptr<Rule>> &rules_, const location &loc_)
57     : Rule("", loc_), rules(rules_) {
58 
59   aliases = aliases_;
60 }
61 
clone() const62 AliasRule *AliasRule::clone() const { return new AliasRule(*this); }
63 
visit(BaseTraversal & visitor)64 void AliasRule::visit(BaseTraversal &visitor) {
65   visitor.visit_aliasrule(*this);
66 }
67 
visit(ConstBaseTraversal & visitor) const68 void AliasRule::visit(ConstBaseTraversal &visitor) const {
69   visitor.visit_aliasrule(*this);
70 }
71 
flatten() const72 std::vector<Ptr<Rule>> AliasRule::flatten() const {
73   std::vector<Ptr<Rule>> rs;
74   for (const Ptr<Rule> &r : rules) {
75     for (Ptr<Rule> &f : r->flatten()) {
76       f->aliases.insert(f->aliases.begin(), aliases.begin(), aliases.end());
77       rs.push_back(f);
78     }
79   }
80   return rs;
81 }
82 
SimpleRule(const std::string & name_,const Ptr<Expr> & guard_,const std::vector<Ptr<Decl>> & decls_,const std::vector<Ptr<Stmt>> & body_,const location & loc_)83 SimpleRule::SimpleRule(const std::string &name_, const Ptr<Expr> &guard_,
84                        const std::vector<Ptr<Decl>> &decls_,
85                        const std::vector<Ptr<Stmt>> &body_,
86                        const location &loc_)
87     : Rule(name_, loc_), guard(guard_), decls(decls_), body(body_) {}
88 
clone() const89 SimpleRule *SimpleRule::clone() const { return new SimpleRule(*this); }
90 
validate() const91 void SimpleRule::validate() const { ReturnChecker::check(*this); }
92 
visit(BaseTraversal & visitor)93 void SimpleRule::visit(BaseTraversal &visitor) {
94   visitor.visit_simplerule(*this);
95 }
96 
visit(ConstBaseTraversal & visitor) const97 void SimpleRule::visit(ConstBaseTraversal &visitor) const {
98   visitor.visit_simplerule(*this);
99 }
100 
StartState(const std::string & name_,const std::vector<Ptr<Decl>> & decls_,const std::vector<Ptr<Stmt>> & body_,const location & loc_)101 StartState::StartState(const std::string &name_,
102                        const std::vector<Ptr<Decl>> &decls_,
103                        const std::vector<Ptr<Stmt>> &body_,
104                        const location &loc_)
105     : Rule(name_, loc_), decls(decls_), body(body_) {}
106 
clone() const107 StartState *StartState::clone() const { return new StartState(*this); }
108 
validate() const109 void StartState::validate() const { ReturnChecker::check(*this); }
110 
visit(BaseTraversal & visitor)111 void StartState::visit(BaseTraversal &visitor) {
112   visitor.visit_startstate(*this);
113 }
114 
visit(ConstBaseTraversal & visitor) const115 void StartState::visit(ConstBaseTraversal &visitor) const {
116   visitor.visit_startstate(*this);
117 }
118 
PropertyRule(const std::string & name_,const Property & property_,const location & loc_)119 PropertyRule::PropertyRule(const std::string &name_, const Property &property_,
120                            const location &loc_)
121     : Rule(name_, loc_), property(property_) {}
122 
clone() const123 PropertyRule *PropertyRule::clone() const { return new PropertyRule(*this); }
124 
visit(BaseTraversal & visitor)125 void PropertyRule::visit(BaseTraversal &visitor) {
126   visitor.visit_propertyrule(*this);
127 }
128 
visit(ConstBaseTraversal & visitor) const129 void PropertyRule::visit(ConstBaseTraversal &visitor) const {
130   visitor.visit_propertyrule(*this);
131 }
132 
Ruleset(const std::vector<Quantifier> & quantifiers_,const std::vector<Ptr<Rule>> & rules_,const location & loc_)133 Ruleset::Ruleset(const std::vector<Quantifier> &quantifiers_,
134                  const std::vector<Ptr<Rule>> &rules_, const location &loc_)
135     : Rule("", loc_), rules(rules_) {
136   quantifiers = quantifiers_;
137 }
138 
clone() const139 Ruleset *Ruleset::clone() const { return new Ruleset(*this); }
140 
validate() const141 void Ruleset::validate() const {
142   for (const Quantifier &q : quantifiers) {
143     if (!q.constant())
144       throw Error("non-constant quantifier expression as ruleset parameter",
145                   q.loc);
146   }
147 }
148 
visit(BaseTraversal & visitor)149 void Ruleset::visit(BaseTraversal &visitor) { visitor.visit_ruleset(*this); }
150 
visit(ConstBaseTraversal & visitor) const151 void Ruleset::visit(ConstBaseTraversal &visitor) const {
152   visitor.visit_ruleset(*this);
153 }
154 
flatten() const155 std::vector<Ptr<Rule>> Ruleset::flatten() const {
156   std::vector<Ptr<Rule>> rs;
157   for (const Ptr<Rule> &r : rules) {
158     for (Ptr<Rule> &f : r->flatten()) {
159       for (const Quantifier &q : quantifiers)
160         f->quantifiers.push_back(q);
161       rs.push_back(f);
162     }
163   }
164   return rs;
165 }
166 
167 } // namespace rumur
168