Break, continue, and DEFER statements! Woooo

This commit is contained in:
Nathan Braswell
2015-05-15 15:19:55 -04:00
parent 5dcb5ba02a
commit 795f8715ff
8 changed files with 106 additions and 43 deletions

View File

@@ -58,6 +58,12 @@ std::string ASTData::ASTTypeToString(ASTType type) {
return "for_loop";
case return_statement:
return "return_statement";
case break_statement:
return "break_statement";
case continue_statement:
return "continue_statement";
case defer_statement:
return "defer_statement";
case assignment_statement:
return "assignment_statement";
case declaration_statement:

View File

@@ -586,6 +586,12 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
newNode = new NodeTree<ASTData>(name, ASTData(for_loop));
} else if (name == "return_statement") {
newNode = new NodeTree<ASTData>(name, ASTData(return_statement));
} else if (name == "break_statement") {
newNode = new NodeTree<ASTData>(name, ASTData(break_statement));
} else if (name == "continue_statement") {
newNode = new NodeTree<ASTData>(name, ASTData(continue_statement));
} else if (name == "defer_statement") {
newNode = new NodeTree<ASTData>(name, ASTData(defer_statement));
} else if (name == "assignment_statement") {
newNode = new NodeTree<ASTData>(name, ASTData(assignment_statement));
std::string assignFuncName = concatSymbolTree(children[1]);
@@ -609,16 +615,9 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
return newNode;
} else if (name == "declaration_statement") {
newNode = new NodeTree<ASTData>(name, ASTData(declaration_statement));
// NodeTree<ASTData>* newIdentifier = transform(children[1], scope); //Transform the identifier
// newIdentifier->getDataRef()->valueType = Type(concatSymbolTree(children[0]));//set the type of the identifier
std::string newIdentifierStr = concatSymbolTree(children[0]);
NodeTree<Symbol>* typeSyntaxNode = getNode("type", children);
Type* identifierType = typeSyntaxNode ? typeFromTypeNode(typeSyntaxNode, scope, templateTypeReplacements) : nullptr;
//if (children.size() > 1 && concatSymbolTree(children[1]) == ".")
//identifierType = typeFromTypeNode(children.back(), scope, templateTypeReplacements);
//else
//identifierType = typeFromTypeNode(children[2], scope, templateTypeReplacements);
if (identifierType)
std::cout << "Declaring an identifier " << newIdentifierStr << " to be of type " << identifierType->toString() << std::endl;
@@ -652,9 +651,6 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
return newNode;
}
//skipChildren.insert(0); //These, the type and the identifier, have been taken care of.
//skipChildren.insert(2);
//auto transChildren = transformChildren(children, skipChildren, scope, types, templateTypeReplacements);
auto boolExp = getNode("boolean_expression", children);
NodeTree<ASTData>* toAssign = boolExp ? transform(boolExp, scope, types, templateTypeReplacements) : nullptr;
// for type inferencing
@@ -673,7 +669,6 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
newNode->addChild(newIdentifier);
if (toAssign)
newNode->addChild(toAssign);
//newNode->addChildren(transChildren);
return newNode;
} else if (name == "if_comp") {
newNode = new NodeTree<ASTData>(name, ASTData(if_comp));

View File

@@ -304,31 +304,15 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
case code_block:
{
output += "{\n";
std::string destructorString = "";
tabLevel++;
for (int i = 0; i < children.size(); i++) {
//std::cout << "Line " << i << std::endl;
std::string line = generate(children[i], enclosingObject);
//std::cout << line << std::endl;
output += line;
if (children[i]->getChildren().size() && children[i]->getChildren()[0]->getDataRef()->type == declaration_statement) {
NodeTree<ASTData> *identifier = children[i]->getChildren()[0]->getChildren()[0];
Type* declarationType = identifier->getDataRef()->valueType;
if (declarationType->getIndirection())
continue;
NodeTree<ASTData> *typeDefinition = declarationType->typeDefinition;
if (!typeDefinition)
continue;
if (typeDefinition->getDataRef()->scope.find("destruct") == typeDefinition->getDataRef()->scope.end())
continue;
// ***************************************************************************************
// I've decided not to do the destructor thing. This will come back soon for defer though!
// ***************************************************************************************
//destructorString += tabs() + scopePrefix(from) + CifyName(typeDefinition->getDataRef()->symbol.getName())
//+ "__" + "destruct" + "(&" + generate(identifier, enclosingObject) + ");\n";//Call the destructor
}
}
output += destructorString;
// we push on a new vector to hold deferred statements
deferDoubleStack.push_back(std::vector<NodeTree<ASTData>*>());
for (int i = 0; i < children.size(); i++)
output += generate(children[i], enclosingObject);
// we pop off the vector and go through them in reverse emitting them
for (auto iter = deferDoubleStack.back().rbegin(); iter != deferDoubleStack.back().rend(); iter++)
output += generate(*iter, enclosingObject);
deferDoubleStack.pop_back();
tabLevel--;
output += tabs() + "}";
return output;
@@ -348,24 +332,59 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
std::cout << "Then statement is a block, emitting the block not the statement so no trailing semicolon" << std::endl;
output += generate(children[1]->getChildren()[0], enclosingObject);
} else {
// ALSO we always emit blocks now, to handle cases like defer when several statements need to be
// run in C even though it is a single Kraken statement
std::cout << "Then statement is a simple statement, regular emitting the statement so trailing semicolon" << std::endl;
output += generate(children[1], enclosingObject);
output += "{ " + generate(children[1], enclosingObject) + " }";
}
// Always emit blocks here too
if (children.size() > 2)
output += " else " + generate(children[2], enclosingObject);
output += " else { " + generate(children[2], enclosingObject) + " }";
return output;
case while_loop:
// keep track of the current size of the deferDoubleStack so that statements that
// break or continue inside this loop can correctly emit all of the defers through
// all of the inbetween scopes
loopDeferStackDepth.push(deferDoubleStack.size());
output += "while (" + generate(children[0], enclosingObject) + ")\n\t" + generate(children[1], enclosingObject);
// and pop it off again
loopDeferStackDepth.pop();
return output;
case for_loop:
// keep track of the current size of the deferDoubleStack so that statements that
// break or continue inside this loop can correctly emit all of the defers through
// all of the inbetween scopes
loopDeferStackDepth.push(deferDoubleStack.size());
//The strSlice's are there to get ride of an unwanted return and an unwanted semicolon(s)
output += "for (" + strSlice(generate(children[0], enclosingObject),0,-3) + generate(children[1], enclosingObject) + ";" + strSlice(generate(children[2], enclosingObject),0,-3) + ")\n\t" + generate(children[3], enclosingObject);
// and pop it off again
loopDeferStackDepth.pop();
return output;
case return_statement:
// we pop off the vector and go through them in reverse emitting them, going
// through all of both arrays, as return will go through all scopes
for (auto topItr = deferDoubleStack.rbegin(); topItr != deferDoubleStack.rend(); topItr++)
for (auto iter = (*topItr).rbegin(); iter != (*topItr).rend(); iter++)
output += generate(*iter, enclosingObject);
if (children.size())
return "return " + generate(children[0], enclosingObject);
else
return "return";
case break_statement:
// handle everything that's been deferred all the way back to the loop's scope
for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--)
for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
output += generate(*iter, enclosingObject);
return output + "break";
case continue_statement:
// handle everything that's been deferred all the way back to the loop's scope
for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--)
for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
output += generate(*iter, enclosingObject);
return output + "continue";
case defer_statement:
deferDoubleStack.back().push_back(children[0]);
return "/*defer " + generate(children[0], enclosingObject) + "*/";
case assignment_statement:
return generate(children[0], enclosingObject) + " = " + generate(children[1], enclosingObject);
case declaration_statement: