1 #pragma once
2 
3 #include "CodeGenerator.h"
4 #include <cstddef>
5 #include <iostream>
6 #include <rumur/rumur.h>
7 #include <string>
8 #include <unordered_map>
9 #include <unordered_set>
10 #include <vector>
11 
12 // generator for C-like code
13 class __attribute__((visibility("hidden"))) CLikeGenerator
14     : public CodeGenerator,
15       public rumur::ConstBaseTraversal {
16 
17 protected:
18   std::ostream &out;
19   bool pack;
20 
21   // mapping of Enum unique_ids to the name of a TypeDecl to them
22   std::unordered_map<size_t, std::string> enum_typedefs;
23 
24   // collection of unique_ids that were emitted as pointers instead of standard
25   // variables
26   std::unordered_set<size_t> is_pointer;
27 
28   // list of comments from the original source
29   std::vector<rumur::Comment> comments;
30 
31   // whether each comment has been written to the output yet
32   std::vector<bool> emitted;
33 
34 public:
CLikeGenerator(const std::vector<rumur::Comment> & comments_,std::ostream & out_,bool pack_)35   CLikeGenerator(const std::vector<rumur::Comment> &comments_,
36                  std::ostream &out_, bool pack_)
37       : out(out_), pack(pack_), comments(comments_),
38         emitted(comments_.size(), false) {}
39 
40   void visit_add(const rumur::Add &n) final;
41   void visit_aliasdecl(const rumur::AliasDecl &n) final;
42   void visit_aliasrule(const rumur::AliasRule &) final;
43   void visit_aliasstmt(const rumur::AliasStmt &n) final;
44   void visit_and(const rumur::And &n) final;
45   void visit_array(const rumur::Array &n) final;
46   void visit_assignment(const rumur::Assignment &n) final;
47   void visit_band(const rumur::Band &n) final;
48   void visit_bnot(const rumur::Bnot &n) final;
49   void visit_bor(const rumur::Bor &n) final;
50   void visit_clear(const rumur::Clear &n) final;
51   void visit_div(const rumur::Div &n) final;
52   void visit_element(const rumur::Element &n) final;
53   void visit_enum(const rumur::Enum &n) final;
54   void visit_eq(const rumur::Eq &n) final;
55   void visit_errorstmt(const rumur::ErrorStmt &n) final;
56   void visit_exists(const rumur::Exists &n) final;
57   void visit_exprid(const rumur::ExprID &n) final;
58   void visit_field(const rumur::Field &n) final;
59   void visit_implication(const rumur::Implication &n) final;
60   void visit_isundefined(const rumur::IsUndefined &) final;
61   void visit_for(const rumur::For &n) final;
62   void visit_forall(const rumur::Forall &n) final;
63   void visit_functioncall(const rumur::FunctionCall &n) final;
64   void visit_geq(const rumur::Geq &n) final;
65   void visit_gt(const rumur::Gt &n) final;
66   void visit_if(const rumur::If &n) final;
67   void visit_ifclause(const rumur::IfClause &n) final;
68   void visit_leq(const rumur::Leq &n) final;
69   void visit_lsh(const rumur::Lsh &n) final;
70   void visit_lt(const rumur::Lt &n) final;
71   void visit_mod(const rumur::Mod &n) final;
72   void visit_model(const rumur::Model &n) final;
73   void visit_mul(const rumur::Mul &n) final;
74   void visit_negative(const rumur::Negative &n) final;
75   void visit_neq(const rumur::Neq &n) final;
76   void visit_not(const rumur::Not &n) final;
77   void visit_number(const rumur::Number &n) final;
78   void visit_or(const rumur::Or &n) final;
79   void visit_procedurecall(const rumur::ProcedureCall &n) final;
80   void visit_property(const rumur::Property &) final;
81   void visit_propertystmt(const rumur::PropertyStmt &n) final;
82   void visit_put(const rumur::Put &n) final;
83   void visit_quantifier(const rumur::Quantifier &n) final;
84   void visit_range(const rumur::Range &) final;
85   void visit_record(const rumur::Record &n) final;
86   void visit_return(const rumur::Return &n) final;
87   void visit_rsh(const rumur::Rsh &n) final;
88   void visit_ruleset(const rumur::Ruleset &) final;
89   void visit_scalarset(const rumur::Scalarset &) final;
90   void visit_sub(const rumur::Sub &n) final;
91   void visit_switch(const rumur::Switch &n) final;
92   void visit_switchcase(const rumur::SwitchCase &n) final;
93   void visit_ternary(const rumur::Ternary &n) final;
94   void visit_typedecl(const rumur::TypeDecl &n) final;
95   void visit_typeexprid(const rumur::TypeExprID &n) final;
96   void visit_undefine(const rumur::Undefine &n) final;
97   void visit_while(const rumur::While &n) final;
98   void visit_xor(const rumur::Xor &n) final;
99 
100   // helpers to make output more natural
101   CLikeGenerator &operator<<(const std::string &s);
102   CLikeGenerator &operator<<(const rumur::Node &n);
103 
104   // make this class abstract
105   virtual ~CLikeGenerator() = 0;
106 
107 private:
108   // generate a print statement of the given expression and (possibly
109   // not-terminal) type
110   void print(const std::string &suffix, const rumur::TypeExpr &t,
111              const rumur::Expr &e, size_t counter);
112 
113 protected:
114   // output comments preceding the given node
115   size_t emit_leading_comments(const rumur::Node &n);
116 
117   // discard any un-emitted comments preceding the given position
118   size_t drop_comments(const rumur::position &pos);
119 
120   // output single line comments following the given node
121   size_t emit_trailing_comments(const rumur::Node &n);
122 };
123