Initial commit
[minnow.git] / src / minnow / codegen_cppoutput.hpp
blobbae09fd61d66aa6511701703622d626a8a45887f
1 #ifndef CODEGEN_CPPOUTPUT_HPP
2 #define CODEGEN_CPPOUTPUT_HPP
4 #include <vector>
5 #include <string>
6 #include <sstream>
7 #include <map>
9 #include <boost/shared_ptr.hpp>
11 #include "parser.hpp"
13 class DeclStage { public: enum Stage {FORWARD, DECL, IMPL}; };
15 struct GeneratedCode {
16 std::ostringstream decls;
17 std::ostringstream inits;
18 std::ostringstream output;
21 class CodegenCPPOutput {
22 std::map<std::string, ActorAST*> actors;
23 std::map<std::string, ClassAST*> classes;
24 //std::vector<std::string> builtins;
25 std::vector<VariableInfo*> scopeStack;
26 std::vector<PrototypeAST*> funStack;
27 //std::vector<std::string> externFns;
28 //std::vector<PrototypeAST*> externFns;
29 std::string dontCareReturnVal;
30 long startOfLinePos;
31 int scopeContainerId;
32 std::vector<int> currentScopeCount; //counts the number of elems local to the current scope
33 unsigned int currentFunGroup;
34 int currentContId;
35 int tempNumber;
37 bool inAction;
39 std::string nextTemp() {
40 char buffer[30];
41 sprintf(buffer, "tmp%i__", tempNumber);
42 ++tempNumber;
43 return std::string(buffer);
46 VariableInfo* findVarInScope(const std::string &name) {
47 for (std::vector<VariableInfo*>::reverse_iterator iter = scopeStack.rbegin(), end = scopeStack.rend(); iter != end; ++iter) {
48 if ((*iter)->name == name) {
49 return *iter;
53 return NULL;
56 //FIXME: This won't work with function overloading
58 bool checkIfExtern(const std::string &fn) {
59 for (std::vector<PrototypeAST*>::reverse_iterator iter = funStack.rbegin(), end = funStack.rend(); iter != end; ++iter) {
60 if ((*iter)->name == fn) {
61 return (*iter)->isExtern;
65 return false;
67 // if (find(externFns.begin(), externFns.end(), fn) != externFns.end()) {
68 // return true;
69 // }
70 // else {
71 // return false;
72 // }
75 bool checkIfActor(const std::string &s) {
76 std::map<std::string, ActorAST*>::iterator finder = actors.find(s);
78 return (finder != actors.end());
81 //void setupDontCare(const std::string &typeName) {
82 void setupDontCare(const TypeInfo &ti) {
83 //FIXME: Add in the position this happened
85 if (ti.containerType == ContainerType::Array) {
86 dontCareReturnVal = "NULL";
88 else if (ti.declType == "void") {
89 dontCareReturnVal = "";
91 else if (ti.declType == "bool") {
92 dontCareReturnVal = "false";
94 else if (ti.declType == "int") {
95 dontCareReturnVal = "0";
97 else if (ti.declType == "double") {
98 dontCareReturnVal = "0.0";
100 else if (ti.declType == "string") {
101 dontCareReturnVal = "\"\"";
103 else {
104 std::ostringstream msg;
105 msg << "Unknown typename '" << ti.declType << "'";
107 throw CompilerException(msg.str());
111 bool isCopyDelete(const TypeInfo &ti) {
112 bool answer = true;
113 if (ti.declType == "void") {
114 answer = false;
116 else if (ti.declType == "bool") {
117 answer = false;
119 else if (ti.declType == "int") {
120 answer = false;
122 else if (ti.declType == "double") {
123 answer = false;
125 else if (ti.declType == "string") {
126 answer = false;
129 return answer;
132 std::string lookupAssocType(const TypeInfo &ti) {
133 //std::map<std::string, ActorAST*>::iterator finder = actors.find(ti.declType);
135 //if (finder != actors.end()) {
136 if (checkIfActor(ti.declType)) {
137 if (ti.containerType == ContainerType::Array) {
138 return "std::vector<actorId_t>*";
140 else {
141 return "actorId_t";
144 else {
145 std::ostringstream arrayType;
146 if (ti.containerType == ContainerType::Array) {
147 if ((ti.declType == "int") || (ti.declType == "float") || (ti.declType == "bool") || (ti.declType == "double") || (ti.declType == "void")) {
148 arrayType << "std::vector<" << ti.declType << ">*";
150 else if (ti.declType == "string") {
151 arrayType << "std::vector<std::string>*";
153 else {
154 arrayType << "std::vector<" << ti.declType << "*>*";
156 return arrayType.str();
158 else {
159 if ((ti.declType == "int") || (ti.declType == "float") || (ti.declType == "bool") || (ti.declType == "double") || (ti.declType == "void")) {
160 arrayType << ti.declType;
162 else if (ti.declType == "string") {
163 arrayType << "std::string";
165 else {
166 arrayType << ti.declType << "*";
168 return arrayType.str();
173 //std::string lookupPushForTypeAndBlock(const boost::shared_ptr<TypeInfo> ti, const std::string &block) {
174 std::string lookupPushForTypeAndBlock(TypeInfo &ti, const std::string &block) {
175 std::ostringstream o;
176 //std::map<std::string, ActorAST*>::iterator finder = actors.find(ti.get()->declType);
177 //if (finder != actors.end()) {
178 if (checkIfActor(ti.declType)) {
179 o << " tmpTU__.UInt32 = " << block << ";" << std::endl;
181 else if (ti.containerType == ContainerType::Array) {
182 //o << " tmpTU__.VoidPtr = " << block << ";" << std::endl;
183 std::string allocType = lookupAssocType(ti);
184 allocType = allocType.erase(allocType.size()-1);
187 o << " tmpTU__.VoidPtr = new " << allocType << "();" << std::endl;
188 if (ti.containedTypes[0].requiresCopyDelete()) {
189 o << " for (int i__=0; i__ < " << block << "->size(); ++i__) { (("
190 << lookupAssocType(ti) << ")(tmpTU__.VoidPtr))->push_back(new "
191 << ti.declType << "((*" << block << ")[i__])); }" << std::endl;
193 else {
194 o << " for (int i__=0; i__ < " << block << "->size(); ++i__) { (("
195 << lookupAssocType(ti) << ")(tmpTU__.VoidPtr))->push_back((*"
196 << block << ")[i__]); }" << std::endl;
199 else if (ti.declType == "int") {
200 o << " tmpTU__.UInt32 = " << block << ";" << std::endl;
202 else if (ti.declType == "string") {
203 o << " tmpTU__.VoidPtr = strcpy(new char[" << block << ".size() + 1], " << block << ".c_str());" << std::endl;
205 else if (ti.declType == "double") {
206 o << " tmpTU__.Double = " << block << ";" << std::endl;
208 else if (ti.declType == "float") {
209 o << " tmpTU__.Float = " << block << ";" << std::endl;
211 else if (ti.declType == "bool") {
212 o << " tmpTU__.Bool = " << block << ";" << std::endl;
214 else {
215 //TRIM
216 std::string allocType = lookupAssocType(ti);
217 allocType = allocType.erase(allocType.size()-1);
218 o << " tmpTU__.VoidPtr = new " << allocType << "(" << block << ");" << std::endl;
220 return o.str();
223 std::string lookupPushForVar(const VariableInfo *vi) {
224 std::ostringstream o;
225 if (vi->type.containerType == ContainerType::Array) {
226 o << " tmpTU__.VoidPtr = " << vi->name << ";" << std::endl;
228 else if (vi->type.declType == "int") {
229 o << " tmpTU__.UInt32 = " << vi->name << ";" << std::endl;
231 else if (vi->type.declType == "string") {
232 o << " tmpTU__.VoidPtr = strcpy(new char[" << vi->name << ".size() + 1], " << vi->name << ".c_str());" << std::endl;
234 else if (vi->type.declType == "double") {
235 o << " tmpTU__.Double = " << vi->name << ";" << std::endl;
237 else if (vi->type.declType == "float") {
238 o << " tmpTU__.Float = " << vi->name << ";" << std::endl;
240 else if (vi->type.declType == "bool") {
241 o << " tmpTU__.Bool = " << vi->name << ";" << std::endl;
243 else {
244 //std::map<std::string, ActorAST*>::iterator finder = actors.find(vi->type.declType);
246 //if (finder != actors.end()) {
247 if (checkIfActor(vi->type.declType)) {
248 o << " tmpTU__.UInt32 = " << vi->name << ";" << std::endl;
250 else {
251 o << " tmpTU__.VoidPtr = " << vi->name << ";" << std::endl;
255 o << " actor__->heapStack.push_back(tmpTU__);" << std::endl;
256 return o.str();
259 std::string lookupPopForVar(const VariableInfo *vi) {
260 std::ostringstream o;
261 if (vi->type.containerType == ContainerType::Array) {
262 o << " " << vi->name << " = (" << lookupAssocType(vi->type) << ")(actor__->heapStack.back().VoidPtr); actor__->heapStack.pop_back();" << std::endl;
264 else if (vi->type.declType == "int") {
265 o << " " << vi->name << " = actor__->heapStack.back().UInt32; actor__->heapStack.pop_back();" << std::endl;
267 else if (vi->type.declType == "string") {
268 o << " " << vi->name << ".assign((char *)(actor__->heapStack.back().VoidPtr)); actor__->heapStack.pop_back(); delete((char *)(tmpTU__.VoidPtr));" << std::endl;
270 else if (vi->type.declType == "double") {
271 o << " " << vi->name << " = actor__->heapStack.back().Double; actor__->heapStack.pop_back();" << std::endl;
273 else if (vi->type.declType == "float") {
274 o << " " << vi->name << " = actor__->heapStack.back().Float; actor__->heapStack.pop_back();" << std::endl;
276 else if (vi->type.declType == "bool") {
277 o << " " << vi->name << " = actor__->heapStack.back().Bool; actor__->heapStack.pop_back();" << std::endl;
279 else {
280 //std::map<std::string, ActorAST*>::iterator finder = actors.find(vi->type.declType);
282 //if (finder != actors.end()) {
283 if (checkIfActor(vi->type.declType)) {
284 o << " " << vi->name << " = (" << lookupAssocType(vi->type) << ")(actor__->heapStack.back().UInt32); actor__->heapStack.pop_back();" << std::endl;
286 else {
287 o << " " << vi->name << " = (" << lookupAssocType(vi->type) << ")(actor__->heapStack.back().VoidPtr); actor__->heapStack.pop_back();" << std::endl;
291 return o.str();
295 std::string lookupInternalType(const VariableInfo *vi) {
296 std::map<std::string, ActorAST*>::iterator finder = actors.find(vi->type.declType);
298 if (finder != actors.end()) {
299 if (vi->type.typeType == TypeType::Array) {
300 return "std::vector<actorId_t>*";
302 else {
303 return "actorId_t";
306 else {
307 if (vi->type.typeType == TypeType::Array) {
308 std::ostringstream arrayType;
309 arrayType << "std::vector<" << lookupAssocType(vi->type.declType) << ">*";
310 return arrayType.str();
312 else {
313 return lookupAssocType(vi->type.declType);
319 TypeInfo lookupReturnTypeInfo(const CallExprAST *ast) {
320 //std::string returnVal("int");
322 for (std::vector<PrototypeAST*>::reverse_iterator iter = funStack.rbegin(),
323 end = funStack.rend(); iter != end; ++iter) {
324 //FIXME: This is insufficient for overloaded functions
325 if ((*iter)->name == ast->name) {
326 //TypeInfo ti((*iter)->type, TypeType::Scalar);
327 return (*iter)->returnType;
332 if (find(externFns.begin(), externFns.end(), ast->name) == externFns.end()) {
333 std::ostringstream msg;
334 msg << "Can not find function '" << ast->name << "'";
335 std::string outmsg = msg.str();
336 throw CompilerException(outmsg, ast->pos);
338 else {
339 TypeInfo ti;
340 return ti;
343 //return "";
344 //return returnVal;
346 std::ostringstream msg;
347 msg << "Can not find function '" << ast->name << "'";
348 std::string outmsg = msg.str();
349 throw CompilerException(outmsg, ast->filepos);
352 std::string lookupReturnType(const CallExprAST *ast, const std::string &container) {
353 //std::string returnVal("int");
355 if (container == "") {
356 for (std::vector<PrototypeAST*>::reverse_iterator iter = funStack.rbegin(), end = funStack.rend(); iter != end; ++iter) {
357 //FIXME: This is insufficient for overloaded functions
358 if ((*iter)->name == ast->name) {
359 //TypeInfo ti((*iter)->type, TypeType::Scalar);
360 return lookupAssocType((*iter)->returnType);
364 //TODO: Re-enable this
366 else {
367 for (std::vector<ASTNode*>::iterator iter = classes[container]->children.begin(),
368 end = classes[container]->children.end(); iter != end; ++iter) {
370 FunctionAST *fast = dynamic_cast<FunctionAST*>(*iter);
371 if (fast != NULL) {
372 //FIXME: This is insufficient for overloaded functions
373 PrototypeAST *proto = dynamic_cast<PrototypeAST*>(fast->children[0]);
374 if (proto->name == ast->name) {
375 //TypeInfo ti((*iter)->type, TypeType::Scalar);
376 return lookupAssocType(proto->returnType);
382 std::ostringstream msg;
383 msg << "Can not find function '" << ast->name << "'";
384 std::string outmsg = msg.str();
385 throw CompilerException(outmsg, ast->filepos);
388 if (find(externFns.begin(), externFns.end(), ast->name) == externFns.end()) {
389 std::ostringstream msg;
390 msg << "Can not find function '" << ast->name << "'";
391 std::string outmsg = msg.str();
392 throw CompilerException(outmsg, ast->pos);
393 return "";
395 else {
396 return "";
399 //return returnVal;
402 std::string outputResumeBlock() {
403 std::ostringstream output;
405 int resumeCount = 0;
406 int scopeStackSize = scopeStack.size() - 1;
407 for (unsigned int i = scopeContainerId; i < currentScopeCount.size(); ++i) {
408 resumeCount += currentScopeCount[i];
411 output << "if (actor__->isResuming) {" << std::endl;
412 for (int i = 0; i < resumeCount; ++i) {
413 VariableInfo *vi = scopeStack[scopeStackSize-i];
414 output << lookupPopForVar(vi);
416 output << " if (actor__->heapStack.size() == 0) {" << std::endl;
417 output << " actor__->isResuming = false;" << std::endl;
418 output << " }" << std::endl;
419 output << "}" << std::endl;
421 return output.str();
424 std::string outputPauseBlock(bool decrement) {
425 std::ostringstream output;
427 int resumeCount = 0;
428 int scopeStackSize = scopeStack.size() - 1;
429 for (unsigned int i = scopeContainerId; i < currentScopeCount.size(); ++i) {
430 resumeCount += currentScopeCount[i];
433 if (decrement) {
434 output << "if (timeLeft__ > 0) {" << std::endl;
435 output << " --timeLeft__;" << std::endl;
436 output << "}" << std::endl;
437 output << "else {" << std::endl;
439 else {
440 output << "if (timeLeft__ == 0) {" << std::endl;
443 output << " actor__->parentThread->timeSliceEndTime = timeLeft__;" << std::endl;
445 for (int i = scopeStackSize-resumeCount + 1; i <= scopeStackSize; ++i) {
446 VariableInfo *vi = scopeStack[i];
447 output << lookupPushForVar(vi);
449 output << " tmpTU__.UInt32 = " << (currentContId-1) << ";" << std::endl;
450 output << " actor__->heapStack.push_back(tmpTU__);" << std::endl;
451 output << " return " << dontCareReturnVal << ";" << std::endl;
452 output << "}" << std::endl;
454 return output.str();
457 boost::shared_ptr<TypeInfo> resolveType(ASTNode *ast);
458 boost::shared_ptr<GeneratedCode> handleCall(CallExprAST *ast, const std::string &container, const std::string &container_name);
460 boost::shared_ptr<GeneratedCode> visit(ASTNode *ast); //catch all that will dispatch out to others
461 boost::shared_ptr<GeneratedCode> visit(NumberExprAST *ast);
462 boost::shared_ptr<GeneratedCode> visit(BooleanExprAST *ast);
463 boost::shared_ptr<GeneratedCode> visit(QuoteExprAST *ast);
464 boost::shared_ptr<GeneratedCode> visit(VariableExprAST *ast);
465 boost::shared_ptr<GeneratedCode> visit(VarDeclExprAST *ast);
466 boost::shared_ptr<GeneratedCode> visit(ArrayIndexedExprAST *ast);
467 //boost::shared_ptr<GeneratedCode> visit(ArrayDeclExprAST *ast);
468 boost::shared_ptr<GeneratedCode> visit(EndExprAST *ast);
469 boost::shared_ptr<GeneratedCode> visit(IfExprAST *ast);
470 boost::shared_ptr<GeneratedCode> visit(WhileExprAST *ast);
471 boost::shared_ptr<GeneratedCode> visit(BinaryExprAST *ast);
472 boost::shared_ptr<GeneratedCode> visit(CallExprAST *ast);
473 boost::shared_ptr<GeneratedCode> visit(ClassAST *ast, DeclStage::Stage stage);
474 boost::shared_ptr<GeneratedCode> visit(ActorAST *ast, DeclStage::Stage stage);
475 boost::shared_ptr<GeneratedCode> visit(PrototypeAST *ast, DeclStage::Stage stage);
476 boost::shared_ptr<GeneratedCode> visit(ActionAST *ast, std::string actorName, DeclStage::Stage stage);
477 boost::shared_ptr<GeneratedCode> visit(FunctionAST *ast, DeclStage::Stage stage);
478 boost::shared_ptr<GeneratedCode> visit(AppAST *ast);
479 public:
480 std::string translate(ASTNode *ast);
482 CodegenCPPOutput() {
483 //builtins.push_back("int");
484 tempNumber = 0;
485 inAction = false;
489 #endif