]> gitweb.ps.run Git - toc/blob - src/toc.h
type modifiers, parenthesized expressions, chained access expressions
[toc] / src / toc.h
1 #pragma once\r
2 \r
3 #include <iostream>\r
4 #include <sstream>\r
5 \r
6 #include "repr.h"\r
7 \r
8 template<typename T>\r
9 std::ostream & operator<< (std::ostream & out, const std::vector<T> & v) {\r
10   bool comma = false;\r
11   for (auto t : v) {\r
12     if (comma) out << ", ";\r
13     else comma = true;\r
14     out << t;\r
15   }\r
16   return out;\r
17 }\r
18 \r
19 std::ostream & operator<< (std::ostream & out, const Type & t);\r
20 std::ostream & operator<< (std::ostream & out, const Variable & v);\r
21 std::ostream & operator<< (std::ostream & out, const Body & b);\r
22 std::ostream & operator<< (std::ostream & out, const UnaryOperatorExpr & o);\r
23 std::ostream & operator<< (std::ostream & out, const BinaryOperatorExpr & o);\r
24 std::ostream & operator<< (std::ostream & out, const TernaryOperatorExpr & o);\r
25 std::ostream & operator<< (std::ostream & out, const Expr & e);\r
26 std::ostream & operator<< (std::ostream & out, const Stmt & s);\r
27 \r
28 void tocFunction (std::ostream & out, const Function & f, bool stub);\r
29 void tocStruct   (std::ostream & out, const Struct & s, bool stub);\r
30 void tocProgram  (std::ostream & out, const Program & p);\r
31 \r
32 static const int TAB_WIDTH = 2;\r
33 static int indentation = 0;\r
34 static void indent(std::ostream & out, int change = 0) {\r
35   indentation += change;\r
36   out << std::string(indentation, ' ');\r
37 }\r
38 \r
39 std::ostream & operator<< (std::ostream & out, const Type & t) {\r
40   out << t.name;\r
41 \r
42   return out;\r
43 }\r
44 std::ostream & operator<< (std::ostream & out, const Variable & v) {\r
45   out << v.type << " ";\r
46 \r
47   std::stringstream sstr;\r
48   std::string s = v.name;\r
49 \r
50   for (auto m = v.type.modifiers.rbegin(); m != v.type.modifiers.rend(); m++) {\r
51     if (m->type == TypeModifierType::Pointer) {\r
52       sstr.str(std::string());\r
53       sstr << "*(" << s << ")";\r
54       s = sstr.str();\r
55     }\r
56     else {\r
57       sstr.str(std::string());\r
58       sstr << "(" << s << ")[";\r
59       if (m->_staticArray)\r
60         sstr << m->_arraySize;\r
61       sstr << "]";\r
62       s = sstr.str();\r
63     }\r
64   }\r
65   out << s;\r
66 \r
67   return out;\r
68 }\r
69 std::ostream & operator<< (std::ostream & out, const Body & b) {\r
70   indent(out);\r
71   out << "{\n";\r
72   indentation += 2;\r
73 \r
74   for (auto v : b.variables) {\r
75     indent(out);\r
76     out << v << ";\n";\r
77   }\r
78 \r
79   out << "\n";\r
80   \r
81   for (auto s : b.statements) {\r
82     indent(out);\r
83     out << s << "\n";\r
84   }\r
85 \r
86   indent(out, -2);\r
87   out << "}\n";\r
88 \r
89   return out;\r
90 }\r
91 std::ostream & operator<< (std::ostream & out, const UnaryOperatorExpr & o) {\r
92   if (o.type == UnaryOperatorType::IncrementPost || o.type == UnaryOperatorType::DecrementPost) {\r
93     out << UnaryOperatorTypeStrings[(int)o.type] << *o.expr;\r
94   }\r
95   else {\r
96     out << *o.expr << UnaryOperatorTypeStrings[(int)o.type];\r
97   }\r
98 \r
99   return out;\r
100 }\r
101 std::ostream & operator<< (std::ostream & out, const BinaryOperatorExpr & o) {\r
102   out << *o.lexpr << " " << BinaryOperatorTypeStrings[(int)o.type] << " " << *o.rexpr;\r
103 \r
104   return out;\r
105 }\r
106 std::ostream & operator<< (std::ostream & out, const TernaryOperatorExpr & o) {\r
107   out << *o.lexpr << " ? " << *o.rexprTrue << " : " << *o.rexprFalse;\r
108 \r
109   return out;\r
110 }\r
111 std::ostream & operator<< (std::ostream & out, const Expr & e) {\r
112   if (e.parenthesized)\r
113     out << "(";\r
114 \r
115   switch (e.type) {\r
116   case ExprType::Func:\r
117     out << e._func.functionName << "(" << e._func.arguments << ")"; break;\r
118   case ExprType::Lit:\r
119     /**/ if (e._lit.type == LitType::Int) out << e._lit._int;\r
120     else if (e._lit.type == LitType::Decimal) out << e._lit._decimal;\r
121     else if (e._lit.type == LitType::String) out << e._lit._string;\r
122     else if (e._lit.type == LitType::Bool) out << e._lit._bool;\r
123     break;\r
124   case ExprType::Identifier:\r
125     out << e._identifier.name; break;\r
126   case ExprType::Brackets:\r
127     out << *e._brackets.lexpr << "[" << *e._brackets.rexpr << "]"; break;\r
128   case ExprType::Dot:\r
129     out << *e._dot.expr << "." << e._dot.ident.name; break;\r
130   case ExprType::UnaryOperator:\r
131     out << e._unaryOperator; break;\r
132   case ExprType::BinaryOperator:\r
133     out << e._binaryOperator; break;\r
134   case ExprType::TernaryOperator:\r
135     out << e._ternaryOperator; break;\r
136   }\r
137   \r
138   if (e.parenthesized)\r
139     out << ")";\r
140 \r
141   return out;\r
142 }\r
143 std::ostream & operator<< (std::ostream & out, const Stmt & s) {\r
144   switch (s.type) {\r
145   case StmtType::If:\r
146     out << "if (" << s._if.condition << ")\n" << s._if.body; break;\r
147   case StmtType::Switch:\r
148     out << "switch (" << s._switch.ident.name << ")\n{\n";\r
149     for (auto c : s._switch.cases) {\r
150       indent(out, 2);\r
151       out << "case " << *c.expr << ": " << c.body << "break;";\r
152     }\r
153     indent(out, -2);\r
154     out << "}\n";\r
155     break;\r
156   case StmtType::For:\r
157     out << "for (" <<\r
158       s._for.varName << " = " << *s._for.initValue << "; " <<\r
159       *s._for.condition << "; " <<\r
160       *s._for.action <<\r
161       ")\n" << s._for.body; break;\r
162   case StmtType::While:\r
163     out << "while (" << s._while.condition << ")\n" << s._while.body; break;\r
164   case StmtType::Assign:\r
165     out << s._assign.name << " = " << s._assign.expr << ";"; break;\r
166   case StmtType::Return:\r
167     out << "return " << s._return.expr << ";"; break;\r
168   case StmtType::Expr:\r
169     out << s._expr << ";"; break;\r
170   }\r
171 \r
172   return out;\r
173 }\r
174 \r
175 \r
176 void tocFunction (std::ostream & out, const Function & f, bool stub) {\r
177   out << f.returnType << " " << f.name << " (" << f.parameters << ")";\r
178 \r
179   if (stub) {\r
180     out << ";\n";\r
181   }\r
182   else {\r
183     out << "\n" << f.body;\r
184   }\r
185 }\r
186 void tocStruct (std::ostream & out, const Struct & s, bool stub) {\r
187   out << "struct " << s.name;\r
188   if (stub) {\r
189     out << ";\n";\r
190     for (auto m : s.methods) {\r
191       m.parameters.insert(m.parameters.begin(), {"this", {s.name, {{TypeModifierType::Pointer, false, -1}}}});\r
192       out << m.returnType << " " <<\r
193         s.name << "_" << m.name <<\r
194         " (" << m.parameters << ");\n";\r
195     }\r
196     return;\r
197   }\r
198   out << "\n{\n";\r
199   indentation += 2;\r
200 \r
201   for (auto m : s.members) {\r
202     indent(out);\r
203     out << m << ";\n";\r
204   }\r
205 \r
206   indent(out, -2);\r
207   out << "};\n";\r
208   \r
209   for (auto m : s.methods) {\r
210     m.parameters.insert(m.parameters.begin(), {"this", {s.name, {{TypeModifierType::Pointer, false, -1}}}});  \r
211     out << m.returnType << " " << s.name << "_" << m.name << " (" << m.parameters << ")\n" << m.body;\r
212   }\r
213 }\r
214 void tocProgram (std::ostream & out, const Program & p) {\r
215   for (auto s : p.structs) {\r
216     tocStruct(out, s, true);\r
217   }\r
218   for (auto f : p.functions) {\r
219     tocFunction(out, f, true);\r
220   }\r
221 \r
222   for (auto v : p.variables) {\r
223     out << v << ";\n";\r
224   }\r
225   for (auto s : p.structs) {\r
226     tocStruct(out, s, false);\r
227   }\r
228   for (auto f : p.functions) {\r
229     tocFunction(out, f, false);\r
230   }\r
231 }\r