Initial commit
[minnow.git] / src / minnow / codegen_cppoutput.cpp
blob6fe44463e79365b2cd70af2e183c1e710ba81d3d
1 #include "codegen_cppoutput.hpp"
3 #include <boost/shared_ptr.hpp>
4 #include <iostream>
5 #include <string>
7 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::handleCall(CallExprAST *ast, const std::string &container, const std::string &container_name) {
8 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode), gc_temp;
9 std::vector<boost::shared_ptr<GeneratedCode> > gc_args;
10 bool isExtern = checkIfExtern(ast->name);
12 for (int i = 0, j = ast->children.size(); i != j; ++i) {
13 gc_args.push_back(visit (ast->children[i]));
16 for (int i = 0, j = ast->children.size(); i != j; ++i) {
17 //if (i != 0)
18 // gc.get()->inits << ", ";
19 if (gc_args[i].get()->decls.str() != "") {
20 gc.get()->decls << gc_args[i].get()->decls.str();
22 if (gc_args[i].get()->inits.str() != "") {
23 gc.get()->inits << gc_args[i].get()->inits.str();
27 if (ast->name == "return") {
28 //if this is a return call, we need to clear our scope stack up to where we came from
30 if (gc_args.size() > 1) {
31 throw CompilerException("Too many arguments in return", ast->filepos);
34 int unwindAmount = currentScopeCount.back();
35 for (int i = 0; i < unwindAmount; ++i) {
36 VariableInfo *vi = scopeStack[scopeStack.size()-1-i];
37 if ((vi->type.requiresCopyDelete())&&(!checkIfActor(vi->type.declType))) {
38 //since it's a return, we don't want to delete what we're returning, so be careful. This isn't the best way to do this, so I'm open to suggestions.
39 if ((gc_args.size() == 1) && (vi->name != gc_args[0].get()->output.str())) {
40 gc.get()->inits << "if (" << vi->name << " != NULL) {" << std::endl;
41 gc.get()->inits << " delete(" << vi->name << ");" << std::endl;
42 gc.get()->inits << "}" << std::endl;
47 gc.get()->output << "return (";
48 for (int i = 0, j = ast->children.size(); i != j; ++i) {
49 if (i != 0)
50 gc.get()->output << ", ";
52 if (gc_args[i].get()->output.str() != "") {
53 gc.get()->output << gc_args[i].get()->output.str();
56 gc.get()->output << ")";
58 //"return" is a special case, so get out of here
59 return gc;
62 std::string tmpName = nextTemp();
63 std::string retType = lookupReturnType(ast, container);
64 if (retType != "void") {
65 gc.get()->decls << retType << " " << tmpName << ";" << std::endl;
68 gc.get()->inits << "case(" << currentContId << "):" << std::endl;
69 ++currentContId;
71 gc.get()->inits << outputResumeBlock();
73 if (!isExtern) {
74 gc.get()->inits << "actor__->parentThread->timeSliceEndTime = timeLeft__;" << std::endl;
77 if (retType != "void") {
78 gc.get()->inits << tmpName << " = ";
79 if (container_name != "") {
80 gc.get()->inits << container_name << "->";
82 gc.get()->inits << ast->name << "(";
84 else {
85 if (container_name != "") {
86 gc.get()->inits << container_name << "->";
88 gc.get()->inits << ast->name << "(";
91 for (int i = 0, j = ast->children.size(); i != j; ++i) {
92 if (i != 0)
93 gc.get()->inits << ", ";
95 if (gc_args[i].get()->output.str() != "") {
96 gc.get()->inits << gc_args[i].get()->output.str();
100 if (!isExtern) {
101 if (ast->children.size() > 0) {
102 gc.get()->inits << ", ";
104 gc.get()->inits << "actor__";
107 gc.get()->inits << ");" << std::endl;
108 if (isExtern) {
109 //since the external call will no decrement the timeslice, we need to do it manually
110 gc.get()->inits << "--timeLeft__;" << std::endl;
112 if (!isExtern) {
113 gc.get()->inits << "timeLeft__ = actor__->parentThread->timeSliceEndTime;" << std::endl;
115 gc.get()->inits << outputPauseBlock(false);
117 if (retType != "void") {
118 gc.get()->output << tmpName;
121 return gc;
124 //catch all that will dispatch out to others
125 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(ASTNode *ast) {
126 boost::shared_ptr<GeneratedCode> gc;
128 NumberExprAST *neast;
129 BooleanExprAST *boeast;
130 QuoteExprAST *qeast;
131 VariableExprAST *veast;
132 VarDeclExprAST *vdeast;
133 ArrayIndexedExprAST *aieast;
134 //ArrayDeclExprAST *adeast;
135 EndExprAST *eeast;
136 IfExprAST *ieast;
137 WhileExprAST *weast;
138 BinaryExprAST *beast;
139 CallExprAST *ceast;
140 ActionAST *actast;
141 FunctionAST *funast;
142 ActorAST *actorast;
143 ClassAST *classast;
144 AppAST *appast;
146 if (ast == NULL) {
147 //NOP
148 gc = boost::shared_ptr<GeneratedCode>(new GeneratedCode);
149 return gc;
151 //Number, Variable, ArrayIndexed, Binary, Quote, Call, DefFun, End, VarDecl, If, While
152 switch (ast->type()) {
153 case (NodeType::Number) :
154 neast = dynamic_cast<NumberExprAST*>(ast);
155 if (neast == NULL) {
156 printf("FIXME: Number compiler exception\n");
158 gc = visit(neast);
159 break;
160 case (NodeType::Boolean) :
161 boeast = dynamic_cast<BooleanExprAST*>(ast);
162 if (boeast == NULL) {
163 printf("FIXME: Number compiler exception\n");
165 gc = visit(boeast);
166 break;
167 case (NodeType::Variable) :
168 veast = dynamic_cast<VariableExprAST*>(ast);
169 if (veast == NULL) {
170 printf("FIXME: Variable compiler exception\n");
172 gc = visit(veast);
173 break;
174 case (NodeType::ArrayIndexed) :
175 aieast = dynamic_cast<ArrayIndexedExprAST*>(ast);
176 if (aieast == NULL) {
177 printf("FIXME: Array indexed compiler exception\n");
179 gc = visit(aieast);
180 break;
181 case (NodeType::Binary) :
182 beast = dynamic_cast<BinaryExprAST*>(ast);
183 if (beast == NULL) {
184 printf("FIXME: Variable compiler exception\n");
186 gc = visit(beast);
187 break;
188 case (NodeType::Quote) :
189 qeast = dynamic_cast<QuoteExprAST*>(ast);
190 if (qeast == NULL) {
191 printf("FIXME: Variable compiler exception\n");
193 gc = visit(qeast);
194 break;
195 case (NodeType::Call) :
196 ceast = dynamic_cast<CallExprAST*>(ast);
197 if (ceast == NULL) {
198 printf("FIXME: Call compiler exception\n");
200 gc = visit(ceast);
201 break;
202 case (NodeType::End) :
203 eeast = dynamic_cast<EndExprAST*>(ast);
204 if (eeast == NULL) {
205 printf("FIXME: End compiler exception\n");
207 gc = visit(eeast);
208 break;
209 case (NodeType::VarDecl) :
210 vdeast = dynamic_cast<VarDeclExprAST*>(ast);
211 if (vdeast == NULL) {
212 printf("FIXME: VarDecl compiler exception\n");
214 gc = visit(vdeast);
215 break;
216 case (NodeType::If) :
217 ieast = dynamic_cast<IfExprAST*>(ast);
218 if (ieast == NULL) {
219 printf("FIXME: If compiler exception\n");
222 gc = visit(ieast);
223 break;
224 case (NodeType::While) :
225 weast = dynamic_cast<WhileExprAST*>(ast);
226 if (weast == NULL) {
227 printf("FIXME: While compiler exception\n");
229 gc = visit(weast);
230 break;
231 case (NodeType::Action) :
232 actast = dynamic_cast<ActionAST*>(ast);
233 if (actast == NULL) {
234 printf("FIXME: action compiler exception\n");
236 gc = visit(actast);
237 break;
238 case (NodeType::Function) :
239 funast = dynamic_cast<FunctionAST*>(ast);
240 if (funast == NULL) {
241 printf("FIXME: function compiler exception\n");
243 gc = visit(funast);
244 break;
245 case (NodeType::Actor) :
246 actorast = dynamic_cast<ActorAST*>(ast);
247 if (actorast == NULL) {
248 printf("FIXME: actor compiler exception\n");
250 gc = visit(actorast);
251 break;
252 case (NodeType::Class) :
253 classast = dynamic_cast<ClassAST*>(ast);
254 if (classast == NULL) {
255 printf("FIXME: class compiler exception\n");
257 gc = visit(classast);
258 break;
259 case (NodeType::App) :
260 appast = dynamic_cast<AppAST*>(ast);
261 if (appast == NULL) {
262 printf("FIXME: app compiler exception\n");
264 gc = visit(appast);
265 break;
266 default :
267 throw CompilerException("Unknown element", ast->filepos);
270 return gc;
273 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(NumberExprAST *ast) {
274 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
276 gc.get()->output << ast->val;
278 return gc;
280 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(QuoteExprAST *ast) {
281 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
283 gc.get()->output << "\"" << ast->val << "\"";
285 return gc;
287 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(BooleanExprAST *ast) {
288 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
290 if (ast->val == true) {
291 gc.get()->output << "true";
293 else {
294 gc.get()->output << "false";
296 return gc;
299 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(VariableExprAST *ast) {
300 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
302 //TODO: Putting these here for now, but we should handle keywords in a more special place in the future
303 if ((ast->name == "return") || (ast->name == "done")) {
304 if (inAction) {
305 //if this is a return call, we need to clear our scope stack up to where we came from
306 int unwindAmount = currentScopeCount.back();
307 for (int i = 0; i < unwindAmount; ++i) {
308 VariableInfo *vi = scopeStack[scopeStack.size()-1-i];
309 if ((vi->type.requiresCopyDelete())&&(!checkIfActor(vi->type.declType))) {
310 gc.get()->output << "if (" << vi->name << " != NULL) {" << std::endl;
311 gc.get()->output << " delete(" << vi->name << ");" << std::endl;
312 gc.get()->output << "}" << std::endl;
316 if (ast->name == "return") {
317 gc.get()->output << "--timeLeft__;" << std::endl;
318 gc.get()->output << "actor__->parentThread->timeSliceEndTime = timeLeft__;" << std::endl;
319 gc.get()->output << "actor__->actorState = ActorState::WAITING_FOR_ACTION;" << std::endl;
320 gc.get()->output << "return; " << std::endl;
322 else if (ast->name == "done") {
323 gc.get()->output << "--timeLeft__;" << std::endl;
324 gc.get()->output << "actor__->parentThread->timeSliceEndTime = timeLeft__;" << std::endl;
325 gc.get()->output << "actor__->actorState = ActorState::DELETED;" << std::endl;
326 gc.get()->output << "return; " << std::endl;
328 return gc;
332 VariableInfo *vi = findVarInScope(ast->name);
333 if (vi == NULL) {
334 std::ostringstream oss;
335 oss << "Unknown variable '" << ast->name << "'";
336 throw CompilerException(oss.str(), ast->filepos);
339 if (vi->scopeType == ScopeType::Actor) {
340 if (vi->name == "this") {
341 gc.get()->output << "actor__->actorId";
343 else {
344 gc.get()->output << "actor__->" << ast->name;
347 else {
348 gc.get()->output << ast->name;
351 return gc;
353 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(VarDeclExprAST *ast) {
354 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
356 VariableInfo *vi = ast->vi; //new VariableInfo(ast->name, ast->declType, ContainerType::Scalar, ScopeType::CodeBlock);
358 if (vi->type.containerType == ContainerType::Scalar) {
359 std::map<std::string, ActorAST*>::iterator finder = actors.find(vi->type.declType);
361 if (finder != actors.end()) {
362 if (ast->isSpawn) {
363 std::string actorTemp = nextTemp();
364 gc.get()->decls << "actorId_t " << vi->name << ";" << std::endl;
365 gc.get()->inits << vi->type.declType << " *" << actorTemp << ";" << std::endl;
366 gc.get()->output << "{ " << actorTemp << " = new " << vi->type.declType << "();" << std::endl;
367 if (finder->second->isIsolated) {
368 gc.get()->output << " actor__->parentThread->ScheduleNewIsolatedActor(" << actorTemp << ");" << std::endl;
370 else {
371 gc.get()->output << " actor__->parentThread->ScheduleNewActor(" << actorTemp << ");" << std::endl;
373 gc.get()->output << " " << vi->name << " = " << actorTemp << "->actorId; }" << std::endl;
375 else {
376 gc.get()->decls << "actorId_t " << vi->name << ";" << std::endl;
379 else {
380 gc.get()->decls << lookupAssocType(vi->type) << " " << vi->name << ";" << std::endl;
381 if (ast->isAlloc) {
382 //TRIM
383 std::string allocType = lookupAssocType(vi->type);
384 allocType = allocType.erase(allocType.size()-1);
386 gc.get()->output << vi->name << " = new " << allocType << "();" << std::endl;
388 gc.get()->output << vi->name;
391 else if (vi->type.containerType == ContainerType::Array) {
392 std::map<std::string, ActorAST*>::iterator finder = actors.find(vi->type.declType);
394 if (finder != actors.end()) {
395 if (ast->isSpawn) {
396 std::string tmpName = nextTemp();
397 gc.get()->decls << "int " << tmpName << ";" << std::endl;
399 std::string actorTemp = nextTemp();
400 std::string loopTemp = nextTemp();
401 gc.get()->decls << vi->type.declType << " *" << actorTemp << ";" << std::endl;
403 gc.get()->decls << "std::vector<actorId_t> *" << vi->name << ";" << std::endl;
405 gc.get()->output << tmpName << " = ";
407 if (vi->size != NULL) {
408 boost::shared_ptr<GeneratedCode> gc_temp = visit (vi->size);
409 if (gc_temp.get()->decls.str() != "") {
410 gc.get()->decls << gc_temp.get()->decls.str();
412 if (gc_temp.get()->inits.str() != "") {
413 gc.get()->output << gc_temp.get()->inits.str();
415 if (gc_temp.get()->output.str() != "") {
416 gc.get()->output << gc_temp.get()->output.str();
419 else {
420 gc.get()->output << "0";
422 gc.get()->output << ";" << std::endl;
423 gc.get()->output << vi->name << " = new std::vector<actorId_t>(" << tmpName << ");" << std::endl;
425 gc.get()->output << "for (int " << loopTemp << "=0; " << loopTemp << " < " << tmpName << "; ++" << loopTemp << ") {" << std::endl;
426 gc.get()->output << " " << actorTemp << " = new " << vi->type.declType << "();" << std::endl;
427 if (finder->second->isIsolated) {
428 gc.get()->output << " actor__->parentThread->ScheduleNewIsolatedActor(" << actorTemp << ");" << std::endl;
430 else {
431 gc.get()->output << " actor__->parentThread->ScheduleNewActor(" << actorTemp << ");" << std::endl;
433 gc.get()->output << " (*" << vi->name << ")[" << loopTemp << "] = " << actorTemp << "->actorId;" << std::endl;
434 gc.get()->output << "}" << std::endl;
436 else {
437 gc.get()->decls << "std::vector<actorId_t> *" << vi->name << ";" << std::endl;
438 gc.get()->output << vi->name << " = new std::vector<actorId_t>(";
439 if (vi->size != NULL) {
440 boost::shared_ptr<GeneratedCode> gc_temp = visit (vi->size);
441 if (gc_temp.get()->decls.str() != "") {
442 gc.get()->decls << gc_temp.get()->decls.str();
444 if (gc_temp.get()->inits.str() != "") {
445 gc.get()->output << gc_temp.get()->inits.str();
447 if (gc_temp.get()->output.str() != "") {
448 gc.get()->output << gc_temp.get()->output.str();
451 else {
452 gc.get()->output << "0";
454 gc.get()->output << ");" << std::endl;
457 else {
458 gc.get()->decls << lookupAssocType(vi->type) << " " << vi->name << ";" << std::endl;
459 std::string allocType = lookupAssocType(vi->type);
460 allocType = allocType.erase(allocType.size()-1); //TRIM off the trailing '*'
461 gc.get()->output << vi->name << " = new " << allocType << "(";
462 if (vi->size != NULL) {
463 boost::shared_ptr<GeneratedCode> gc_temp = visit (vi->size);
464 if (gc_temp.get()->decls.str() != "") {
465 gc.get()->decls << gc_temp.get()->decls.str();
467 if (gc_temp.get()->inits.str() != "") {
468 gc.get()->output << gc_temp.get()->inits.str();
470 if (gc_temp.get()->output.str() != "") {
471 gc.get()->output << gc_temp.get()->output.str();
474 else {
475 gc.get()->output << "0";
477 gc.get()->output << ")";
479 //FIXME? Would you ever follow an array decl with an assignment? If so, we should probably check for that
482 ++(currentScopeCount.back());
483 scopeStack.push_back(vi);
485 return gc;
487 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(ArrayIndexedExprAST *ast) {
488 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
490 VariableInfo *vi = findVarInScope(ast->name);
491 if (vi == NULL) {
492 std::ostringstream oss;
493 oss << "Unknown array variable '" << ast->name << "'";
494 throw CompilerException(oss.str(), ast->filepos);
496 else if (vi->type.containerType != ContainerType::Array) {
497 std::ostringstream oss;
498 oss << "Variable '" << ast->name << "' is not of an array type";
499 throw CompilerException(oss.str(), ast->filepos);
501 if (vi->scopeType == ScopeType::Actor) {
502 gc.get()->output << "(*(actor__->" << ast->name << "))";
504 else {
505 gc.get()->output << "(*" << ast->name << ")";
507 gc.get()->output << "[";
508 boost::shared_ptr<GeneratedCode> gc_temp = visit (ast->children[0]);
509 if (gc_temp.get()->decls.str() != "") {
510 gc.get()->decls << gc_temp.get()->decls.str();
512 if (gc_temp.get()->inits.str() != "") {
513 gc.get()->output << gc_temp.get()->inits.str();
515 if (gc_temp.get()->output.str() != "") {
516 gc.get()->output << gc_temp.get()->output.str();
518 gc.get()->output << "]";
520 return gc;
523 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(EndExprAST *ast) {
524 //do nothing
525 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
527 return gc;
530 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(IfExprAST *ast) {
531 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
532 boost::shared_ptr<GeneratedCode> gc_cond;
534 std::string condTemp = nextTemp();
536 gc.get()->decls << "bool " << condTemp << ";" << std::endl;
538 gc_cond = visit (ast->children[0]);
539 if (gc_cond.get()->decls.str() != "") {
540 gc.get()->decls << gc_cond.get()->decls.str();
542 if (gc_cond.get()->inits.str() != "") {
543 gc.get()->output << gc_cond.get()->inits.str();
546 if (gc_cond.get()->output.str() != "") {
547 gc.get()->output << condTemp << " = " << gc_cond.get()->output.str() << ";" << std::endl;
550 gc.get()->output << "if (" << condTemp << ") {" << std::endl;
552 for (std::vector<ASTNode*>::iterator iter = ast->children[1]->children.begin(),
553 end = ast->children[1]->children.end(); iter != end; ++iter) {
555 boost::shared_ptr<GeneratedCode> gc_temp = visit (*iter);
556 if (gc_temp.get()->decls.str() != "") {
557 gc.get()->decls << gc_temp.get()->decls.str();
559 if (gc_temp.get()->inits.str() != "") {
560 gc.get()->output << gc_temp.get()->inits.str();
562 if (gc_temp.get()->output.str() != "") {
563 gc.get()->output << gc_temp.get()->output.str();
565 gc.get()->output << ";" << std::endl;
567 gc.get()->output << "}";
568 if (ast->children[2]->children.size() > 0) {
569 gc.get()->output << "else {" << std::endl;
570 for (std::vector<ASTNode*>::iterator iter = ast->children[2]->children.begin(),
571 end = ast->children[2]->children.end(); iter != end; ++iter) {
573 boost::shared_ptr<GeneratedCode> gc_temp = visit (*iter);
574 if (gc_temp.get()->decls.str() != "") {
575 gc.get()->decls << gc_temp.get()->decls.str();
577 if (gc_temp.get()->inits.str() != "") {
578 gc.get()->output << gc_temp.get()->inits.str();
580 if (gc_temp.get()->output.str() != "") {
581 gc.get()->output << gc_temp.get()->output.str();
583 gc.get()->output << ";" << std::endl;
585 gc.get()->output << "}" << std::endl;
588 return gc;
591 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(WhileExprAST *ast) {
592 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
593 boost::shared_ptr<GeneratedCode> gc_cond, gc_temp;
595 std::string condTemp = nextTemp();
597 gc.get()->decls << "bool " << condTemp << ";" << std::endl;
598 gc.get()->output << "case(" << currentContId << "):" << std::endl;
599 ++currentContId;
600 gc.get()->output << (outputResumeBlock());
602 gc_cond = visit (ast->children[0]);
603 if (gc_cond.get()->decls.str() != "") {
604 gc.get()->decls << gc_cond.get()->decls.str();
606 if (gc_cond.get()->inits.str() != "") {
607 gc.get()->output << gc_cond.get()->inits.str();
609 if (gc_cond.get()->output.str() != "") {
610 gc.get()->output << condTemp << " = " << gc_cond.get()->output.str() << ";" << std::endl;
612 gc.get()->output << "while (" << condTemp << ") {" << std::endl;
613 gc.get()->output << (outputPauseBlock(true));
614 for (std::vector<ASTNode*>::iterator iter = ast->children[1]->children.begin(),
615 end = ast->children[1]->children.end(); iter != end; ++iter) {
616 gc_temp = visit (*iter);
617 if (gc_temp.get()->decls.str() != "") {
618 gc.get()->decls << gc_temp.get()->decls.str();
620 if (gc_temp.get()->inits.str() != "") {
621 gc.get()->output << gc_temp.get()->inits.str();
623 if (gc_temp.get()->output.str() != "") {
624 gc.get()->output << gc_temp.get()->output.str();
627 gc.get()->output << ";" << std::endl;
629 gc_cond = visit (ast->children[0]);
630 if (gc_cond.get()->decls.str() != "") {
631 gc.get()->decls << gc_cond.get()->decls.str();
633 if (gc_cond.get()->inits.str() != "") {
634 gc.get()->output << gc_cond.get()->inits.str();
636 if (gc_cond.get()->output.str() != "") {
637 gc.get()->output << condTemp << " = " << gc_cond.get()->output.str() << ";" << std::endl;
640 gc.get()->output << "}";
642 return gc;
644 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(BinaryExprAST *ast) {
645 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
646 boost::shared_ptr<GeneratedCode> gc_temp;
648 if (ast->op == "::") {
649 CallExprAST *ceast = dynamic_cast<CallExprAST*>(ast->children[1]);
650 VariableExprAST *veast = dynamic_cast<VariableExprAST*>(ast->children[0]);
651 ArrayIndexedExprAST *aieast = dynamic_cast<ArrayIndexedExprAST*>(ast->children[0]);
653 VariableInfo *vi;
655 if (ceast == NULL) {
656 std::ostringstream msg;
657 msg << "Can't build message, right hand side is type: " << ast->children[1]->type();
658 throw CompilerException(msg.str(), ast->filepos);
661 if ((veast == NULL) && (aieast == NULL)) {
662 std::ostringstream msg;
663 msg << "Can't build message, left hand side is type: " << ast->children[0]->type();
664 throw CompilerException(msg.str(), ast->filepos);
666 else if (veast != NULL) {
667 vi = findVarInScope(veast->name);
668 if (vi == NULL) {
669 std::ostringstream oss;
670 oss << "Unknown variable for message '" << veast->name << "'";
671 throw CompilerException(oss.str(), veast->filepos);
674 else { //if (aieast != NULL) {
675 vi = findVarInScope(aieast->name);
676 if (vi == NULL) {
677 std::ostringstream oss;
678 oss << "Unknown variable for message '" << aieast->name << "'";
679 throw CompilerException(oss.str(), aieast->filepos);
683 //int argSize = ceast->args.size();
684 std::string msgName = nextTemp();
685 std::string actorIfLocal = nextTemp();
686 std::string msgArray;
688 gc.get()->decls << "Actor *" << actorIfLocal << ";" << std::endl;
690 gc.get()->output << actorIfLocal << " = actor__->parentThread->ActorIfLocal(";
691 gc_temp = visit (ast->children[0]);
693 if (gc_temp.get()->decls.str() != "") {
694 gc.get()->decls << gc_temp.get()->decls.str();
696 if (gc_temp.get()->inits.str() != "") {
697 gc.get()->output << gc_temp.get()->inits.str();
699 if (gc_temp.get()->output.str() != "") {
700 gc.get()->output << gc_temp.get()->output.str();
702 gc.get()->output << ", actor__);" << std::endl;
704 gc.get()->output << "if ((" << actorIfLocal << " == NULL) || (" << actorIfLocal << "->actorState != ActorState::WAITING_FOR_ACTION)) {" << std::endl;
705 gc.get()->decls << "Message " << msgName << ";" << std::endl;
706 gc.get()->output << " " << msgName << ".recipient = ";
708 gc_temp = visit (ast->children[0]);
709 if (gc_temp.get()->decls.str() != "") {
710 gc.get()->decls << gc_temp.get()->decls.str();
712 if (gc_temp.get()->inits.str() != "") {
713 gc.get()->output << gc_temp.get()->inits.str();
715 if (gc_temp.get()->output.str() != "") {
716 gc.get()->output << gc_temp.get()->output.str();
719 gc.get()->output << ";" << std::endl;
720 gc.get()->output << " " << msgName << ".numArgs = " << ceast->children.size() << ";" << std::endl;
721 gc.get()->output << " " << msgName << ".messageType = MessageType::ACTION_MESSAGE;" << std::endl;
722 gc.get()->output << " " << msgName << ".task = &" << vi->type.declType << "__" << ceast->name << "_action;" << std::endl;
724 //std::cout << "arg size: " << ceast->args.size() << std::endl;
725 if (ceast->children.size() > 4 ) {
726 msgArray = nextTemp();
727 gc.get()->decls << "std::vector<TypeUnion> *" << msgArray << " = new std::vector<TypeUnion>();" << std::endl;
729 for (unsigned int i = 0; i < ceast->children.size(); ++i) {
730 //boost::shared_ptr<TypeInfo> ti = resolveType(ceast->children[i]);
732 boost::shared_ptr<GeneratedCode> gc_temp = visit (ceast->children[i]);
733 if (gc_temp.get()->decls.str() != "") {
734 gc.get()->decls << gc_temp.get()->decls.str();
736 if (gc_temp.get()->inits.str() != "") {
737 gc.get()->output << gc_temp.get()->inits.str();
739 if (gc_temp.get()->output.str() != "") {
740 //gc.get()->output << gc_temp.get()->output.str();
741 gc.get()->output << " " << lookupPushForTypeAndBlock
742 (ceast->children[i]->programmaticType, gc_temp.get()->output.str());
744 if (ceast->children.size() > 4 ) {
745 gc.get()->output << " " << msgArray << "->push_back(tmpTU__);" << std::endl;
747 else {
748 gc.get()->output << " " << msgName << ".arg[" << i << "] = tmpTU__;" << std::endl;
752 if (ceast->children.size() > 4 ) {
753 gc.get()->output << " " << msgName << ".arg[0].VoidPtr = " << msgArray << ";" << std::endl;
756 gc.get()->output << "actor__->parentThread->SendMessage(" << msgName << ");" << std::endl;
757 gc.get()->output << "}" << std::endl;
758 gc.get()->output << "else {" << std::endl;
760 for (unsigned int i = 0; i < ceast->children.size(); ++i) {
761 //boost::shared_ptr<TypeInfo> ti = resolveType(ceast->children[i]);
762 //gc.get()->output << "tmpTU__.UInt32 = ";
764 boost::shared_ptr<GeneratedCode> gc_temp = visit (ceast->children[i]);
765 if (gc_temp.get()->decls.str() != "") {
766 gc.get()->decls << gc_temp.get()->decls.str();
768 if (gc_temp.get()->inits.str() != "") {
769 gc.get()->output << gc_temp.get()->inits.str();
771 if (gc_temp.get()->output.str() != "") {
772 //gc.get()->output << gc_temp.get()->output.str();
773 gc.get()->output << " " << lookupPushForTypeAndBlock
774 (ceast->children[i]->programmaticType, gc_temp.get()->output.str());
775 //gc.get()->output << " " << msgName << ".arg[" << i << "] = tmpTU__;" << std::endl;
778 gc.get()->output << ";" << std::endl;
779 gc.get()->output << actorIfLocal << "->heapStack.push_back(tmpTU__);" << std::endl;
782 gc.get()->output << actorIfLocal << "->task = &" << vi->type.declType << "__" << ceast->name << "_action;" << std::endl;
783 gc.get()->output << actorIfLocal << "->actorState = ActorState::ACTIVE;" << std::endl;
785 gc.get()->output << "actor__->parentThread->hotActor = " << actorIfLocal << ";" << std::endl;
786 gc.get()->output << "if (" << actorIfLocal << "->runQueueRevId != actor__->parentThread->runQueueRevId) {" << std::endl;
787 gc.get()->output << " actor__->parentThread->runningActors.push_back(" << actorIfLocal << ");" << std::endl;
788 gc.get()->output << " " << actorIfLocal << "->runQueueRevId = actor__->parentThread->runQueueRevId;" << std::endl;
789 gc.get()->output << " }" << std::endl;
790 gc.get()->output << "}" << std::endl;
792 else if (ast->op == ".") {
793 VariableExprAST *veast = dynamic_cast<VariableExprAST*>(ast->children[1]);
794 CallExprAST *ceast = dynamic_cast<CallExprAST*>(ast->children[1]);
795 if ((veast == NULL) && (ceast == NULL)) {
796 std::cout << "Can't use '.' in this context, is type: " << ast->children[1]->type() << std::endl;
797 exit(1);
799 else {
800 VariableExprAST *lhs_ast = dynamic_cast<VariableExprAST*>(ast->children[0]);
801 //ArrayIndexedExprAST *lhs_aieast = dynamic_cast<ArrayIndexedExprAST*>(ast->LHS);
802 if (lhs_ast == NULL) {
803 throw CompilerException("Left hand side is not a variable (this is a limitation of the current system)", ast->filepos);
805 //boost::shared_ptr<TypeInfo> lhs_type = resolveType(ast->children[0]);
806 //std::cout << "Accessing type: " << lhs_type.get()->declType << std::endl;
808 if (veast != NULL) {
809 ClassAST* s = this->classes[ast->children[0]->programmaticType.declType];
810 //check to see if the struct has an attribute member named this
812 bool foundVar = false;
813 for (std::vector<ASTNode*>::iterator iter = s->children.begin(),
814 end = s->children.end(); iter != end; ++iter) {
816 VarDeclExprAST *vdeast = dynamic_cast<VarDeclExprAST*>(*iter);
817 if (vdeast != NULL) {
818 if (vdeast->vi->name == veast->name) {
819 gc.get()->output << lhs_ast->name << "->" << veast->name;
820 foundVar = true;
821 break;
825 if (foundVar == false) {
826 std::ostringstream msg;
827 msg << "Can't find '" << veast->name << "' inside of '" << lhs_ast->name << "'";
828 throw CompilerException(msg.str(), ast->filepos);
831 if (ceast != NULL) {
832 gc_temp = handleCall(ceast, ast->children[0]->programmaticType.declType, lhs_ast->name);
833 if (gc_temp.get()->decls.str() != "") {
834 gc.get()->decls << gc_temp.get()->decls.str();
836 if (gc_temp.get()->inits.str() != "") {
837 gc.get()->output << gc_temp.get()->inits.str();
839 if (gc_temp.get()->output.str() != "") {
840 gc.get()->output << gc_temp.get()->output.str();
845 else {
846 gc_temp = visit (ast->children[0]);
847 if (gc_temp.get()->decls.str() != "") {
848 gc.get()->decls << gc_temp.get()->decls.str();
850 if (gc_temp.get()->inits.str() != "") {
851 gc.get()->inits << gc_temp.get()->inits.str();
853 if (gc_temp.get()->output.str() != "") {
854 gc.get()->output << gc_temp.get()->output.str();
856 gc.get()->output << ast->op;
857 gc_temp = visit (ast->children[1]);
858 if (gc_temp.get()->decls.str() != "") {
859 gc.get()->decls << gc_temp.get()->decls.str();
861 if (gc_temp.get()->inits.str() != "") {
862 gc.get()->inits << gc_temp.get()->inits.str();
864 if (gc_temp.get()->output.str() != "") {
865 gc.get()->output << gc_temp.get()->output.str();
868 return gc;
871 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(CallExprAST *ast) {
872 return handleCall(ast, "", "");
876 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(ClassAST *ast, DeclStage::Stage stage) {
877 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode), gc_temp(new GeneratedCode);
879 FunctionAST *funast;
880 VarDeclExprAST *varDecl;
882 //DeclStage::Stage stage;
883 if (stage == DeclStage::FORWARD) {
884 this->classes[ast->name] = ast;
885 gc.get()->output << "class " << ast->name << ";" << std::endl;
887 if (stage == DeclStage::IMPL) {
888 std::map<std::string, ActorAST*>::iterator finder;
890 currentScopeCount.push_back(0);
891 scopeContainerId = currentScopeCount.size(); //remember where we started
892 gc.get()->output << "class " << ast->name << " {" << std::endl << "public: " << std::endl;
893 currentFunGroup = funStack.size();
895 //then push a variable that will be how we message ourselves
896 std::string name("this");
897 VariableInfo *vi = new VariableInfo(name, ast->name, ContainerType::Scalar, ScopeType::Struct);
898 ++(currentScopeCount.back());
899 scopeStack.push_back(vi);
901 for (std::vector<ASTNode*>::iterator iter = ast->children.begin(), end = ast->children.end(); iter != end; ++iter) {
902 switch ((*iter)->type()) {
903 case (NodeType::Function) :
904 funStack.push_back(dynamic_cast<PrototypeAST*>((*iter)->children[0]));
905 break;
906 case (NodeType::VarDecl) :
907 varDecl = dynamic_cast<VarDeclExprAST*>(*iter);
909 varDecl->vi->scopeType = ScopeType::Struct;
911 ++(currentScopeCount.back());
912 scopeStack.push_back(varDecl->vi);
913 break;
914 default:
915 throw CompilerException("Unknown feature insde of class", (*iter)->filepos);
916 break;
920 for (std::vector<ASTNode*>::iterator iter = ast->children.begin(), end = ast->children.end(); iter != end; ++iter) {
921 switch ((*iter)->type()) {
922 case (NodeType::Function) :
923 funast = dynamic_cast<FunctionAST*>(*iter);
924 gc_temp = visit(funast, stage);
925 break;
926 case (NodeType::VarDecl) :
927 varDecl = dynamic_cast<VarDeclExprAST*>(*iter);
929 finder = actors.find(varDecl->vi->type.declType);
931 if (finder != actors.end()) {
932 if (varDecl->vi->type.containerType == ContainerType::Scalar) {
933 gc.get()->output << "actorId_t " << varDecl->vi->name << ";" << std::endl;
935 else if (varDecl->vi->type.containerType == ContainerType::Array) {
936 gc.get()->output << "actorId_t " << varDecl->vi->name << "[";
938 boost::shared_ptr<GeneratedCode> gc_temp = visit (varDecl->vi->size);
939 if (gc_temp.get()->decls.str() != "") {
940 gc.get()->output << gc_temp.get()->decls.str();
942 if (gc_temp.get()->inits.str() != "") {
943 gc.get()->output << gc_temp.get()->inits.str();
945 if (gc_temp.get()->output.str() != "") {
946 gc.get()->output << gc_temp.get()->output.str();
949 gc.get()->output << "];" << std::endl;
953 else {
954 if (varDecl->vi->type.containerType == ContainerType::Scalar) {
955 gc.get()->output << lookupAssocType(varDecl->vi->type) << " " << varDecl->vi->name << ";" << std::endl;
957 else if (varDecl->vi->type.containerType == ContainerType::Array) {
958 gc.get()->output << lookupAssocType(varDecl->vi->type) << " " << varDecl->vi->name << "[";
959 boost::shared_ptr<GeneratedCode> gc_temp = visit (varDecl->vi->size);
961 if (gc_temp.get()->decls.str() != "") {
962 gc.get()->output << gc_temp.get()->decls.str();
964 if (gc_temp.get()->inits.str() != "") {
965 gc.get()->output << gc_temp.get()->inits.str();
967 if (gc_temp.get()->output.str() != "") {
968 gc.get()->output << gc_temp.get()->output.str();
971 gc.get()->output << "];" << std::endl;
975 break;
976 default:
977 throw CompilerException("Unknown feature insde of class", (*iter)->filepos);
978 break;
980 if (gc_temp.get()->decls.str() != "") {
981 gc.get()->output << gc_temp.get()->decls.str();
983 if (gc_temp.get()->inits.str() != "") {
984 gc.get()->output << gc_temp.get()->inits.str();
986 if (gc_temp.get()->output.str() != "") {
987 gc.get()->output << gc_temp.get()->output.str();
991 gc.get()->output << ast->name << "() { }" << std::endl;
993 //TODO: I'm not sure if I need a traditional copy constructor, or this pointer style
994 //gc.get()->output << ast->name << "(const " << ast->name << "& p) {" << std::endl;
995 gc.get()->output << ast->name << "(" << ast->name << "* p__) {" << std::endl;
997 for (std::vector<ASTNode*>::iterator iter = ast->children.begin(), end = ast->children.end(); iter != end; ++iter) {
998 VarDeclExprAST *vdeast = dynamic_cast<VarDeclExprAST*>(*iter);
999 if (vdeast != NULL) {
1000 if (vdeast->vi->type.requiresCopyDelete()) {
1001 gc.get()->output << "if (" << vdeast->vi->name
1002 << " != NULL) { delete " << vdeast->vi->name << "; };" << std::endl;
1003 gc.get()->output << vdeast->vi->name << " = new "
1004 << lookupAssocType(vdeast->vi->type) << "(p__->" << vdeast->vi->name << ");" << std::endl;
1006 else {
1007 gc.get()->output << vdeast->vi->name << " = " << "p__->" << vdeast->vi->name << ";" << std::endl;
1011 gc.get()->output << "}" << std::endl;
1012 gc.get()->output << "};" << std::endl;
1014 int unwindAmount = currentScopeCount.back();
1015 for (int i = 0; i < unwindAmount; ++i) {
1016 scopeStack.pop_back();
1018 currentScopeCount.pop_back();
1020 //Get us back to seeing only the functions we could see before we entered the actor
1021 while (funStack.size() != currentFunGroup) {
1022 funStack.pop_back();
1025 return gc;
1028 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(ActorAST *ast, DeclStage::Stage stage) {
1029 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode), gc_temp(new GeneratedCode);
1031 ActionAST *actast;
1032 FunctionAST *funast;
1033 VarDeclExprAST *varDecl;
1035 //DeclStage::Stage stage;
1036 if (stage == DeclStage::DECL) {
1037 currentScopeCount.push_back(0);
1038 scopeContainerId = currentScopeCount.size(); //remember where we started
1039 gc.get()->output << "class " << ast->name << " : public Actor {" << std::endl << "public: " << std::endl;
1040 currentFunGroup = funStack.size();
1042 //then push a variable that will be how we message ourselves
1043 std::string name("this");
1044 VariableInfo *vi = new VariableInfo(name, ast->name, ContainerType::Scalar, ScopeType::Actor);
1045 ++(currentScopeCount.back());
1046 scopeStack.push_back(vi);
1048 actors[ast->name] = ast;
1050 for (std::vector<ASTNode*>::iterator iter = ast->children.begin(), end = ast->children.end(); iter != end; ++iter) {
1051 switch ((*iter)->type()) {
1052 case (NodeType::Function) :
1053 if (stage == DeclStage::DECL) {
1054 funStack.push_back(dynamic_cast<PrototypeAST*>((*iter)->children[0]));
1056 funast = dynamic_cast<FunctionAST*>(*iter);
1057 gc_temp = visit(funast, stage);
1058 break;
1059 case (NodeType::VarDecl) :
1060 varDecl = dynamic_cast<VarDeclExprAST*>(*iter);
1061 if (stage == DeclStage::DECL) {
1062 varDecl->vi->scopeType = ScopeType::Actor;
1064 ++(currentScopeCount.back());
1065 scopeStack.push_back(varDecl->vi);
1066 std::map<std::string, ActorAST*>::iterator finder = actors.find(varDecl->vi->type.declType);
1068 if (finder != actors.end()) {
1069 if (varDecl->vi->type.containerType == ContainerType::Scalar) {
1070 gc.get()->output << "actorId_t " << varDecl->vi->name << ";" << std::endl;
1072 else if (varDecl->vi->type.containerType == ContainerType::Array) {
1073 gc.get()->output << "actorId_t " << varDecl->vi->name << "[";
1075 boost::shared_ptr<GeneratedCode> gc_temp = visit (varDecl->vi->size);
1076 if (gc_temp.get()->decls.str() != "") {
1077 gc.get()->output << gc_temp.get()->decls.str();
1079 if (gc_temp.get()->inits.str() != "") {
1080 gc.get()->output << gc_temp.get()->inits.str();
1082 if (gc_temp.get()->output.str() != "") {
1083 gc.get()->output << gc_temp.get()->output.str();
1086 gc.get()->output << "];" << std::endl;
1090 else {
1091 if (varDecl->vi->type.containerType == ContainerType::Scalar) {
1092 gc.get()->output << lookupAssocType(varDecl->vi->type) << " " << varDecl->vi->name << ";" << std::endl;
1094 else if (varDecl->vi->type.containerType == ContainerType::Array) {
1095 gc.get()->output << lookupAssocType(varDecl->vi->type) << " " << varDecl->vi->name << "[";
1096 boost::shared_ptr<GeneratedCode> gc_temp = visit (varDecl->vi->size);
1098 if (gc_temp.get()->decls.str() != "") {
1099 gc.get()->output << gc_temp.get()->decls.str();
1101 if (gc_temp.get()->inits.str() != "") {
1102 gc.get()->output << gc_temp.get()->inits.str();
1104 if (gc_temp.get()->output.str() != "") {
1105 gc.get()->output << gc_temp.get()->output.str();
1108 gc.get()->output << "];" << std::endl;
1114 break;
1115 case (NodeType::Action) :
1116 //handled later
1117 break;
1118 default:
1119 throw CompilerException("Unhandled element in actor definition", (*iter)->filepos);
1120 break;
1122 if (gc_temp.get()->decls.str() != "") {
1123 gc.get()->output << gc_temp.get()->decls.str();
1125 if (gc_temp.get()->inits.str() != "") {
1126 gc.get()->output << gc_temp.get()->inits.str();
1128 if (gc_temp.get()->output.str() != "") {
1129 gc.get()->output << gc_temp.get()->output.str();
1133 if (stage == DeclStage::DECL) {
1134 gc.get()->output << "};" << std::endl;
1137 for (std::vector<ASTNode*>::iterator iter = ast->children.begin(), end = ast->children.end(); iter != end; ++iter) {
1138 switch ((*iter)->type()) {
1139 case (NodeType::Action) :
1140 actast = dynamic_cast<ActionAST*>(*iter);
1141 gc_temp = visit(actast, ast->name, stage);
1143 if (gc_temp.get()->decls.str() != "") {
1144 gc.get()->output << gc_temp.get()->decls.str();
1146 if (gc_temp.get()->inits.str() != "") {
1147 gc.get()->output << gc_temp.get()->inits.str();
1149 if (gc_temp.get()->output.str() != "") {
1150 gc.get()->output << gc_temp.get()->output.str();
1152 break;
1153 case (NodeType::Function) :
1154 //handled earlier
1155 break;
1156 case (NodeType::VarDecl) :
1157 //handled earlier
1158 break;
1159 default:
1160 throw CompilerException("Unhandled element in actor definition", (*iter)->filepos);
1161 break;
1165 if (stage == DeclStage::IMPL) {
1166 int unwindAmount = currentScopeCount.back();
1167 for (int i = 0; i < unwindAmount; ++i) {
1168 scopeStack.pop_back();
1170 currentScopeCount.pop_back();
1172 //Get us back to seeing only the functions we could see before we entered the actor
1173 while (funStack.size() != currentFunGroup) {
1174 funStack.pop_back();
1178 return gc;
1180 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(PrototypeAST *ast, DeclStage::Stage stage) {
1181 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
1183 bool isExtern = checkIfExtern(ast->name);
1185 gc.get()->output << lookupAssocType(ast->returnType) << " " << ast->name << "(";
1186 for (int i = 0, j = ast->children.size(); i != j; ++i) {
1187 VarDeclExprAST *varDecl = dynamic_cast<VarDeclExprAST*>(ast->children[i]);
1188 if (stage == DeclStage::IMPL) {
1189 ++(currentScopeCount.back());
1190 scopeStack.push_back(varDecl->vi);
1192 if (i != 0) {
1193 gc.get()->output << ", ";
1196 gc.get()->output << lookupAssocType(varDecl->vi->type) << " " << varDecl->vi->name;
1198 if (!isExtern) {
1199 if (ast->children.size() > 0) {
1200 gc.get()->output << ", ";
1202 gc.get()->output << "Actor *actor__";
1204 gc.get()->output << ")";
1206 return gc;
1208 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(FunctionAST *ast, DeclStage::Stage stage) {
1209 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
1211 PrototypeAST *proto = dynamic_cast<PrototypeAST*>(ast->children[0]);
1213 if (stage == DeclStage::FORWARD) {
1214 if (ast->children[1]->children.size() == 0) {
1215 gc.get()->output << "extern ";
1216 //this->externFns.push_back(ast->proto->name);
1218 boost::shared_ptr<GeneratedCode> gc_temp = visit (proto, stage);
1219 if (gc_temp.get()->decls.str() != "") {
1220 gc.get()->decls << gc_temp.get()->decls.str();
1222 if (gc_temp.get()->inits.str() != "") {
1223 gc.get()->output << gc_temp.get()->inits.str();
1225 if (gc_temp.get()->output.str() != "") {
1226 gc.get()->output << gc_temp.get()->output.str();
1229 gc.get()->output << ";" << std::endl;
1231 else if (stage == DeclStage::IMPL) {
1232 if (ast->children[1]->children.size() == 0) {
1233 boost::shared_ptr<GeneratedCode> gc_temp(new GeneratedCode);
1234 return gc_temp;
1236 else {
1237 scopeContainerId = currentScopeCount.size(); //remember where we started
1238 currentScopeCount.push_back(0);
1240 boost::shared_ptr<GeneratedCode> gc_temp = visit (proto, stage);
1241 if (gc_temp.get()->decls.str() != "") {
1242 gc.get()->decls << gc_temp.get()->decls.str();
1244 if (gc_temp.get()->inits.str() != "") {
1245 gc.get()->decls << gc_temp.get()->inits.str();
1247 if (gc_temp.get()->output.str() != "") {
1248 gc.get()->decls << gc_temp.get()->output.str();
1251 setupDontCare(proto->returnType);
1253 currentContId = 0;
1255 gc.get()->decls << "{" << std::endl;
1257 gc.get()->output << "TypeUnion tmpTU__;" << std::endl;
1258 gc.get()->output << "unsigned int timeLeft__ = actor__->parentThread->timeSliceEndTime;" << std::endl;
1260 gc.get()->output << "actor__->parentThread->timeSliceEndTime = timeLeft__;" << std::endl;
1261 gc.get()->output << "int contId__ = 0;" << std::endl;
1262 gc.get()->output << "if (actor__->isResuming) {" << std::endl;
1263 gc.get()->output << " contId__ = actor__->heapStack.back().Int32; actor__->heapStack.pop_back();" << std::endl;
1264 gc.get()->output << " if (actor__->heapStack.size() == 0) {" << std::endl;
1265 gc.get()->output << " actor__->isResuming = false;" << std::endl;
1266 gc.get()->output << " }" << std::endl;
1267 gc.get()->output << "}" << std::endl;
1268 gc.get()->output << "actor__->parentThread->timeSliceEndTime = timeLeft__;" << std::endl;
1270 gc.get()->output << "switch(contId__) {" <<std::endl;
1271 gc.get()->output << "case(" << currentContId << "):" << std::endl;
1273 ++currentContId;
1275 for (std::vector<ASTNode*>::iterator iter = ast->children[1]->children.begin(),
1276 end = ast->children[1]->children.end(); iter != end; ++iter) {
1277 boost::shared_ptr<GeneratedCode> gc_temp = visit (*iter);
1278 if (gc_temp.get()->decls.str() != "") {
1279 gc.get()->decls << gc_temp.get()->decls.str();
1281 if (gc_temp.get()->inits.str() != "") {
1282 gc.get()->output << gc_temp.get()->inits.str();
1284 if (gc_temp.get()->output.str() != "") {
1285 gc.get()->output << gc_temp.get()->output.str();
1287 gc.get()->output << ";" << std::endl;
1291 gc.get()->output << " }" << std::endl;
1293 int unwindAmount = currentScopeCount.back();
1294 for (int i = 0; i < unwindAmount; ++i) {
1295 VariableInfo *vi = scopeStack.back();
1296 if (vi->type.containerType == ContainerType::Array) {
1297 gc.get()->output << "if (" << vi->name << " != NULL) {" << std::endl;
1298 if (isCopyDelete(vi->type)) {
1299 gc.get()->output << " for (int i__=0; i__ < " << vi->name << "->size(); ++i__) { if (" << vi->name << "[i__] != NULL) { delete " << vi->name << "[i__];} }" << std::endl;
1301 gc.get()->output << " " << vi->name << "->clear();" << std::endl;
1302 gc.get()->output << " delete(" << vi->name << ");" << std::endl;
1303 gc.get()->output << "}" << std::endl;
1305 else if ((vi->type.requiresCopyDelete())&&(!checkIfActor(vi->type.declType))) {
1306 gc.get()->output << "if (" << vi->name << " != NULL) {" << std::endl;
1307 gc.get()->output << " delete(" << vi->name << ");" << std::endl;
1308 gc.get()->output << "}" << std::endl;
1310 scopeStack.pop_back();
1312 currentScopeCount.pop_back();
1314 gc.get()->output << "}" << std::endl;
1318 return gc;
1321 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(ActionAST *ast, std::string actorName, DeclStage::Stage stage) {
1322 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
1323 inAction = true;
1325 PrototypeAST *proto = dynamic_cast<PrototypeAST*>(ast->children[0]);
1327 if (stage == DeclStage::DECL) {
1328 gc.get()->output << "void " << actorName << "__" << proto->name << "_action(Actor *a__);" << std::endl;
1330 else if (stage == DeclStage::IMPL) {
1331 gc.get()->decls << "void " << actorName << "__" << proto->name << "_action(Actor *a__) ";
1333 scopeContainerId = currentScopeCount.size(); //remember where we started
1334 currentScopeCount.push_back(0);
1336 currentContId = 0;
1337 //std::string retVal = "void";
1338 //setupDontCare(retVal);
1339 this->dontCareReturnVal = "";
1341 gc.get()->decls << "{" << std::endl;
1343 gc.get()->decls << actorName << " *actor__ = static_cast<" << actorName << "*>(a__);" << std::endl;
1344 gc.get()->decls << "TypeUnion tmpTU__;" << std::endl;
1345 gc.get()->decls << "unsigned int timeLeft__ = actor__->parentThread->timeSliceEndTime;" << std::endl;
1347 gc.get()->output << "int contId__ = 0;" << std::endl;
1348 gc.get()->output << "if (actor__->isResuming) {" << std::endl;
1349 gc.get()->output << " contId__ = actor__->heapStack.back().Int32; actor__->heapStack.pop_back();" << std::endl;
1350 gc.get()->output << " if (actor__->heapStack.size() == 0) {" << std::endl;
1351 gc.get()->output << " actor__->isResuming = false;" << std::endl;
1352 gc.get()->output << " }" << std::endl;
1353 gc.get()->output << "}" << std::endl;
1354 gc.get()->output << "else {" << std::endl;
1356 for (std::vector<ASTNode*>::reverse_iterator iter = ast->children[0]->children.rbegin(), end = ast->children[0]->children.rend(); iter != end; ++iter) {
1357 VarDeclExprAST *varDecl = dynamic_cast<VarDeclExprAST*>(*iter);
1358 gc.get()->decls << lookupAssocType(varDecl->vi->type) << " " << varDecl->vi->name << ";" << std::endl;
1359 gc.get()->output << lookupPopForVar(varDecl->vi) << ";" << std::endl;
1361 ++(currentScopeCount.back());
1362 scopeStack.push_back(varDecl->vi);
1364 gc.get()->output << "}" << std::endl;
1366 gc.get()->output << "switch(contId__) {" <<std::endl;
1367 gc.get()->output << "case(" << currentContId << "):" << std::endl;
1368 ++currentContId;
1370 for (std::vector<ASTNode*>::iterator iter = ast->children[1]->children.begin(),
1371 end = ast->children[1]->children.end(); iter != end; ++iter) {
1372 boost::shared_ptr<GeneratedCode> gc_temp = visit (*iter);
1373 if (gc_temp.get()->decls.str() != "") {
1374 gc.get()->decls << gc_temp.get()->decls.str();
1376 if (gc_temp.get()->inits.str() != "") {
1377 gc.get()->output << gc_temp.get()->inits.str();
1379 if (gc_temp.get()->output.str() != "") {
1380 gc.get()->output << gc_temp.get()->output.str();
1383 gc.get()->output << ";" << std::endl;
1386 gc.get()->output << "}" << std::endl;
1387 gc.get()->output << "--timeLeft__;" << std::endl;
1388 gc.get()->output << "actor__->parentThread->timeSliceEndTime = timeLeft__;" << std::endl;
1389 gc.get()->output << "actor__->actorState = ActorState::WAITING_FOR_ACTION;" << std::endl;
1391 int unwindAmount = currentScopeCount.back();
1392 for (int i = 0; i < unwindAmount; ++i) {
1393 VariableInfo *vi = scopeStack.back();
1394 if ((vi->type.requiresCopyDelete())&&(!checkIfActor(vi->type.declType))) {
1395 gc.get()->output << "if (" << vi->name << " != NULL) {" << std::endl;
1396 gc.get()->output << " delete(" << vi->name << ");" << std::endl;
1397 gc.get()->output << "}" << std::endl;
1399 scopeStack.pop_back();
1401 currentScopeCount.pop_back();
1403 gc.get()->output << "}" << std::endl;
1406 inAction = false;
1407 return gc;
1409 boost::shared_ptr<GeneratedCode> CodegenCPPOutput::visit(AppAST *ast) {
1410 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode), gc_temp(new GeneratedCode);
1412 ActionAST *actast;
1413 FunctionAST *funast;
1414 ActorAST *actorast;
1415 ClassAST *classast;
1417 ActionAST *mainAction = NULL;
1419 gc.get()->decls << "//automatically generated by Minnow->C++ codegen (0.1)" << std::endl;
1420 gc.get()->decls << "#include \"aquarium.hpp\"" << std::endl;
1422 gc.get()->decls << "inline int convertToInt(std::string s){std::istringstream i(s);int x;i >> x;return x;}" << std::endl;
1423 gc.get()->decls << "inline void puti(int i){std::cout << i << std::endl; }" << std::endl;
1424 gc.get()->decls << "inline void putstring(std::string s){std::cout << s << std::endl; }" << std::endl;
1426 DeclStage::Stage stage;
1427 for (int i = 0; i < 3; ++i) {
1428 switch(i) {
1429 case (0) : stage = DeclStage::FORWARD; break;
1430 case (1) : stage = DeclStage::DECL; break;
1431 case (2) : stage = DeclStage::IMPL; break;
1433 for (std::vector<ASTNode*>::iterator iter = ast->children.begin(), end = ast->children.end(); iter != end; ++iter) {
1434 //std::cout << "CHILD: " << (*iter)->nodeType << " at " << (*iter)->filepos.lineNumber << " " << (*iter)->filepos.colStart << std::endl;
1435 switch ((*iter)->type()) {
1436 case (NodeType::Action) :
1437 actast = dynamic_cast<ActionAST*>(*iter);
1438 if (stage == DeclStage::FORWARD) {
1439 if (dynamic_cast<PrototypeAST*>(actast->children[0])->name != "main") {
1440 throw CompilerException("Only the 'main' action is allowed at the top level");
1442 else {
1443 mainAction = actast;
1446 gc_temp = visit(actast, "Actor", stage);
1447 break;
1448 case (NodeType::Function) :
1449 if (stage == DeclStage::FORWARD) {
1450 funStack.push_back(dynamic_cast<PrototypeAST*>((*iter)->children[0]));
1452 funast = dynamic_cast<FunctionAST*>(*iter);
1453 gc_temp = visit(funast, stage);
1454 break;
1455 case (NodeType::Actor) :
1456 actorast = dynamic_cast<ActorAST*>(*iter);
1457 gc_temp = visit(actorast, stage);
1458 break;
1459 case (NodeType::Class) :
1460 classast = dynamic_cast<ClassAST*>(*iter);
1461 gc_temp = visit(classast, stage);
1462 break;
1463 default:
1464 throw CompilerException("Unhandled element in application", (*iter)->filepos);
1465 break;
1467 if (gc_temp.get()->decls.str() != "") {
1468 gc.get()->output << gc_temp.get()->decls.str();
1470 if (gc_temp.get()->inits.str() != "") {
1471 gc.get()->output << gc_temp.get()->inits.str();
1473 if (gc_temp.get()->output.str() != "") {
1474 gc.get()->output << gc_temp.get()->output.str();
1480 gc.get()->output << "int main(int argc, char *argv[]){" << std::endl;
1482 if (mainAction == NULL) {
1483 throw CompilerException("Can not find 'main' action");
1485 else {
1486 PrototypeAST* mainProto = dynamic_cast<PrototypeAST*>(mainAction->children[0]);
1488 if (mainProto->children.size() > 0) {
1489 gc.get()->output << "VM_Main(argc, argv, Actor__main_action, true);" << std::endl;
1491 else {
1492 gc.get()->output << "VM_Main(argc, argv, Actor__main_action, false);" << std::endl;
1497 gc.get()->output << "return(0);" << std::endl;
1498 gc.get()->output << "};" << std::endl;
1499 return gc;
1502 std::string CodegenCPPOutput::translate(ASTNode *ast) {
1503 boost::shared_ptr<GeneratedCode> gc(new GeneratedCode);
1505 gc = visit(ast);
1507 std::ostringstream output;
1508 if (gc.get()->decls.str() != "") {
1509 output << gc.get()->decls.str();
1511 if (gc.get()->inits.str() != "") {
1512 output << gc.get()->inits.str();
1514 if (gc.get()->output.str() != "") {
1515 output << gc.get()->output.str();
1518 return output.str();