From fcc0e770a5607b107520e385d3e584fe2d010a91 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Fri, 6 Nov 2015 03:23:55 -0500 Subject: [PATCH 1/5] Fixed a limitToFunction bug or two, work on ADTs --- .gitignore | 2 + include/CGenerator.h | 5 + krakenGrammer.kgm | 6 +- src/ASTTransformation.cpp | 59 ++++-- src/CGenerator.cpp | 392 ++++++++++++++++++++++---------------- src/Importer.cpp | 1 + stdlib/io.krak | 2 +- tests/test_adt.krak | 34 +++- 8 files changed, 313 insertions(+), 188 deletions(-) diff --git a/.gitignore b/.gitignore index 619c07f..2b5c1df 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ build-ninja stats *.swp *.swm +*.swn *.swo *.png *krakout* @@ -16,3 +17,4 @@ callgrind* *.comp_bac bintest.bin *.dot +.stfolder diff --git a/include/CGenerator.h b/include/CGenerator.h index d342b12..c0749fe 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -28,6 +28,7 @@ class CGenerator { ~CGenerator(); void generateCompSet(std::map*> ASTs, std::string outputName); std::string generateTypeStruct(NodeTree* from); + bool isUnderNodeWithType(NodeTree* from, ASTType type); bool isUnderTranslationUnit(NodeTree* from, NodeTree* typeDefinition); NodeTree* highestScope(NodeTree* node); std::pair generateTranslationUnit(std::string name, std::map*> ASTs); @@ -40,6 +41,8 @@ class CGenerator { std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr, ClosureTypeSpecialType closureSpecial); static std::string CifyName(std::string name); static std::string scopePrefix(NodeTree* from); + std::string simpleComplexName(std::string simpleName, std::string complexName); + std::string prefixIfNeeded(std::string prefix, std::string name); std::string generateObjectMethod(NodeTree* enclosingObject, NodeTree* from, std::string *functionPrototype); NodeTree* getMethodsObjectType(NodeTree* scope, std::string functionName); NodeTree* getMethod(Type* type, std::string method, std::vector types); @@ -56,6 +59,8 @@ class CGenerator { std::string linkerString; std::string functionTypedefString; std::string functionTypedefStringPre; + std::set usedNameSet; + std::map simpleComplexNameMap; std::map> functionTypedefMap; std::map*>, std::string> closureStructMap; std::vector*>> distructDoubleStack; diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index d6bcc94..122ae4c 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -16,6 +16,7 @@ template_param_list = template_param_list WS "," WS template_param | template_pa template_param = identifier WS traits | identifier ; import = "import" WS identifier line_end | "import" WS identifier WS ":" WS "\*" line_end | "import" WS identifier WS ":" WS identifier_list line_end ; +identifier_list = identifier | identifier WS "," WS identifier_list ; # all for optional semicolons line_break = " @@ -57,7 +58,6 @@ triple_quoted_string = "\"\"\"((\"\"(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i #identifier = alpha_alphanumeric ; identifier = augmented_alpha_alphanumeric ; -identifier_list = identifier | identifier WS "," WS identifier_list ; scope_op = ":" ":" ; scoped_identifier = scoped_identifier WS scope_op WS identifier | identifier ; @@ -89,7 +89,9 @@ traits = "\(" WS trait_list WS "\)" ; trait_list = trait_list WS "," WS scoped_identifier | scoped_identifier ; adt_nonterm = "adt" ; -adt_def = adt_nonterm WS identifier WS "{" WS identifier_list WS "}" ; +adt_def = adt_nonterm WS identifier WS "{" WS adt_option_list WS "}" ; +adt_option_list = adt_option | adt_option WS "," WS adt_option_list ; +adt_option = identifier | identifier WS dec_type ; if_statement = "if" WS "\(" WS boolean_expression WS "\)" WS statement | "if" WS "\(" WS boolean_expression WS "\)" WS statement WS "else" WS statement ; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index a1707d9..20c43b6 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -98,7 +98,7 @@ NodeTree* ASTTransformation::firstPass(std::string fileName, NodeTreegetDataRef()->getName() == "adt_def") { - std::string name = concatSymbolTree(i->getChildren()[0]); + std::string name = concatSymbolTree(getNode("identifier", i)); NodeTree* adt_dec = addToScope("~enclosing_scope", translationUnit, new NodeTree("adt_def", ASTData(adt_def, Symbol(name, true, name)))); addToScope(name, adt_dec, translationUnit); translationUnit->addChild(adt_dec); @@ -193,16 +193,37 @@ void ASTTransformation::secondPass(NodeTree* ast, NodeTree* par //Do the inside of classes here secondPassDoClassInsides(typeDef, typedefChildren, std::map()); } else if (i->getDataRef()->getName() == "adt_def") { - std::string name = concatSymbolTree(i->getChildren()[0]); + std::cout << "ADT DEF" << std::endl; + std::cout << "there are " << getNodes("adt_option", i).size() << " adt_options" << std::endl; + std::string name = concatSymbolTree(getNode("identifier", i)); NodeTree* adtDef = ast->getDataRef()->scope[name][0]; //No overloaded types (besides uninstantiated templates, which can have multiple versions based on types or specilizations) - for (NodeTree* j : i->getChildren()) { - if (j->getDataRef()->getName() == "identifier") { - std::string ident_name = concatSymbolTree(j); - std::cout << "add ing " << ident_name << " to " << name << " for ADT" << std::endl; - NodeTree* enum_variant_identifier = new NodeTree("identifier", ASTData(identifier, Symbol(ident_name, true), adtDef->getDataRef()->valueType)); - adtDef->addChild(enum_variant_identifier); - addToScope(ident_name, enum_variant_identifier, adtDef); - addToScope("~enclosing_scope", adtDef, enum_variant_identifier); + for (NodeTree* j : getNodes("adt_option", i)) { + std::string ident_name = concatSymbolTree(getNode("identifier", j)); + std::cout << "add ing " << ident_name << " to " << name << " for ADT" << std::endl; + NodeTree* enum_variant_identifier; + NodeTree* possibleType = getNode("type", j); + NodeTree* enum_variant_function = nullptr; + if (possibleType) { + Type* actual_type = typeFromTypeNode(possibleType, adtDef, std::map()); + enum_variant_identifier = new NodeTree("identifier", ASTData(identifier, Symbol(ident_name, true), actual_type)); + + // also make a function prototype for a function that returns an instance of this type. If we don't contain a type, it's just the literal + //enum_variant_function = new NodeTree("function", ASTData(function, Symbol("fun_"+ident_name, true), new Type(std::vector{actual_type}, adtDef->getDataRef()->valueType))); + enum_variant_function = new NodeTree("function", ASTData(function, Symbol(ident_name, true), new Type(std::vector{actual_type}, adtDef->getDataRef()->valueType))); + } else { + enum_variant_identifier = new NodeTree("identifier", ASTData(identifier, Symbol(ident_name, true), adtDef->getDataRef()->valueType)); + // now a function in both cases... + enum_variant_function = new NodeTree("function", ASTData(function, Symbol(ident_name, true), new Type(std::vector(), adtDef->getDataRef()->valueType))); + } + adtDef->addChild(enum_variant_identifier); + addToScope(ident_name, enum_variant_identifier, adtDef); + addToScope("~enclosing_scope", adtDef, enum_variant_identifier); + // this comes second so it is added to the enclosing scope second so that the function is found last on identifer lookup so we can still access members that are not functions + // as their names alias each other + if (enum_variant_function) { + adtDef->addChild(enum_variant_function); + addToScope(ident_name, enum_variant_function, adtDef); + addToScope("~enclosing_scope", adtDef, enum_variant_function); } } } else if (i->getDataRef()->getName() == "function") { @@ -518,7 +539,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode->addChildren(parameters); // update type with actual type newNode->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), newNode->getDataRef()->valueType); - auto statement = transform(getNode("statement", children), scope, types, limitToFunction, templateTypeReplacements); + auto statement = transform(getNode("statement", children), scope, types, false, templateTypeReplacements); // definitly do not limit this statement to functions if (name == "lambda") newNode->getDataRef()->closedVariables = findVariablesToClose(newNode, statement, scope); for (auto i : newNode->getDataRef()->closedVariables) @@ -564,7 +585,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree } else if (name == "expression" || name == "shiftand" || name == "term" || name == "unarad" || name == "access_operation") { //If this is an actual part of an expression, not just a premoted child if (children.size() > 2) { - NodeTree* lhs = transform(children[0], scope, std::vector(),limitToFunction, templateTypeReplacements); //LHS does not inherit types + NodeTree* lhs = transform(children[0], scope, std::vector(),false, templateTypeReplacements); //LHS does not inherit types, or limittofunction NodeTree* rhs; if (name == "access_operation") { std::cout << "lhs is: " << lhs->getDataRef()->toString() << std::endl; @@ -1033,7 +1054,9 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* scope, s if (possibleMatches.size()) { for (auto i : possibleMatches) { //We're not looking for types - if (i->getDataRef()->type == type_def || i->getDataRef()->type == adt_def) + //if (i->getDataRef()->type == type_def || i->getDataRef()->type == adt_def) + // actually, lets make it we're only looking for things with type function + if (i->getDataRef()->valueType->baseType != function_type) continue; Type* functionType = i->getDataRef()->valueType; @@ -1389,11 +1412,6 @@ std::map ASTTransformation::makeTemplateFunctionTypeMap(Node return typeMap; } -// We need recursion protection -std::vector*> ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup, bool includeModules) { - return scopeLookup(scope, lookup, includeModules, std::set*>()); -} - NodeTree* ASTTransformation::generateThis(NodeTree* scope) { // if we're looking for this, traverse up until we find the declaration of this object and assign it's type to this NodeTree* trans; @@ -1410,6 +1428,11 @@ NodeTree* ASTTransformation::generateThis(NodeTree* scope) { return identifier; } +// We need recursion protection +std::vector*> ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup, bool includeModules) { + return scopeLookup(scope, lookup, includeModules, std::set*>()); +} + std::vector*> ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup, bool includeModules, std::set*> visited) { std::cout << "Scp]|[e looking up " << lookup << std::endl; std::cout << "current: " << scope->getDataRef()->toString() << std::endl; diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index a8eb38c..ffa1c0f 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -17,19 +17,22 @@ void CGenerator::generateCompSet(std::map*> ASTs, std::cout << "\n\n =====GENERATE PASS===== \n\n" << std::endl; std::cout << "\n\nGenerate pass for: " << outputName << std::endl; buildString += outputName + ".c "; - std::ofstream outputCFile, outputHFile; + //std::ofstream outputCFile, outputHFile; + std::ofstream outputCFile; outputCFile.open(outputName + "/" + outputName + ".c"); - outputHFile.open(outputName + "/" + outputName + ".h"); - if (outputCFile.is_open() || outputHFile.is_open()) { + //outputHFile.open(outputName + "/" + outputName + ".h"); + //if (outputCFile.is_open() || outputHFile.is_open()) { + if (outputCFile.is_open()) { // Prequel common to all files auto chPair = generateTranslationUnit(outputName, ASTs); - outputHFile << "#include \n#include \n#include \n" << chPair.first; - outputCFile << "#include \"" + outputName + ".h\"\n\n" << chPair.second; + //outputHFile << "#include \n#include \n#include \n" << chPair.first; + //outputCFile << "#include \"" + outputName + ".h\"\n\n" << chPair.second; + outputCFile << "#include \n#include \n#include \n" << chPair.first << "\n\n// C FILE BEGIN\n\n" << chPair.second; } else { std::cerr << "Cannot open file " << outputName << ".c/h" << std::endl; } outputCFile.close(); - outputHFile.close(); + //outputHFile.close(); buildString += linkerString; buildString += "-o " + outputName; @@ -54,150 +57,186 @@ std::string CGenerator::getID() { std::string CGenerator::generateTypeStruct(NodeTree* from) { auto data = from->getData(); auto children = from->getChildren(); - std::string objectString; - if (data.type == type_def) - objectString = "struct __struct_dummy_"; - else if (data.type == adt_def) - objectString = "enum __adt_dummy_"; - objectString += scopePrefix(from) + CifyName(data.symbol.getName()) + "__ {\n"; + std::string structString, enumString, functionString; + std::string enumName = "__enum_dummy_" + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())+"__"); + enumString = "enum " + enumName + " {\n"; + structString = "struct __struct_dummy_"; + structString += prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())+"__") + " {\n"; + if (data.type == adt_def) { + structString = "typedef " + structString + "enum " + enumName + " flag;\n union { \n"; + } tabLevel++; - for (int i = (data.type == adt_def ? 1 : 0); i < children.size(); i++) { + + for (auto child : children) { //std::cout << children[i]->getName() << std::endl; - if (children[i]->getName() != "function") - objectString += tabs() + generate(children[i], nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n"); + if (child->getName() != "function") { + if (data.type == adt_def) { + // if this is not a plain no-data adt member (so if it is a primitive or doesn't have a reference back to) + // wait a sec, this is easier + if ( child->getDataRef()->valueType->typeDefinition != from) + structString += tabs() + ValueTypeToCType(child->getDataRef()->valueType, child->getDataRef()->symbol.getName()) + "; /* adt data member */\n"; + } else { + structString += tabs() + generate(child, nullptr).oneString() + "\n"; + } + enumString += tabs() + generate(child, nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n"); + } else { + if (data.type == adt_def) { + functionString += "\n" + ValueTypeToCType(child->getDataRef()->valueType->returnType, "fun_" + child->getDataRef()->symbol.getName()) + "(" + + (child->getDataRef()->valueType->parameterTypes.size() ? ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0], "in") : "") + "); /*adt func*/\n"; + } + } } tabLevel--; - objectString += "};"; - return objectString; + if (data.type == adt_def) { + //structString += "} data; /*end union*/ \n"; + structString += "}; /*end union*/\n } " + CifyName(data.symbol.getName()) + "; /* end struct */"; + } else { + structString += "};"; + } + enumString += "};\n"; + if (data.type == adt_def) + return enumString + structString + functionString; + return structString; } // This method recurseivly generates all aliases of some definition std::string CGenerator::generateAliasChains(std::map*> ASTs, NodeTree* definition) { - std::string output; - for (auto trans : ASTs) { - for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) { - for (auto declaration : i->second) { - auto declarationData = declaration->getDataRef(); - if (declarationData->type == type_def - && declarationData->valueType->typeDefinition != declaration - && declarationData->valueType->typeDefinition == definition) { - output += "typedef " + - scopePrefix(definition) + CifyName(definition->getDataRef()->symbol.getName()) + " " + - scopePrefix(declaration) + CifyName(declarationData->symbol.getName()) + ";\n"; - // Recursively add the ones that depend on this one - output += generateAliasChains(ASTs, declaration); - } +std::string output; +for (auto trans : ASTs) { + for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) { + for (auto declaration : i->second) { + auto declarationData = declaration->getDataRef(); + if (declarationData->type == type_def + && declarationData->valueType->typeDefinition != declaration + && declarationData->valueType->typeDefinition == definition) { + output += "typedef " + + prefixIfNeeded(scopePrefix(definition), CifyName(definition->getDataRef()->symbol.getName())) + " " + + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData->symbol.getName())) + ";\n"; + // Recursively add the ones that depend on this one + output += generateAliasChains(ASTs, declaration); } } } - return output; +} +return output; +} + +bool CGenerator::isUnderNodeWithType(NodeTree* from, ASTType type) { +auto scope = from->getDataRef()->scope; +auto upper = scope.find("~enclosing_scope"); +if (upper != scope.end()) { + if (upper->second[0]->getDataRef()->type == type) + return true; + return isUnderNodeWithType(upper->second[0], type); +} +return false; } bool CGenerator::isUnderTranslationUnit(NodeTree* from, NodeTree* node) { - auto scope = from->getDataRef()->scope; - for (auto i : scope) - for (auto j : i.second) - if (j == node) - return true; +auto scope = from->getDataRef()->scope; +for (auto i : scope) + for (auto j : i.second) + if (j == node) + return true; - auto upper = scope.find("~enclosing_scope"); - if (upper != scope.end()) - return isUnderTranslationUnit(upper->second[0], node); - return false; +auto upper = scope.find("~enclosing_scope"); +if (upper != scope.end()) + return isUnderTranslationUnit(upper->second[0], node); +return false; } NodeTree* CGenerator::highestScope(NodeTree* node) { - auto it = node->getDataRef()->scope.find("~enclosing_scope"); - while (it != node->getDataRef()->scope.end()) { - node = it->second[0]; - it = node->getDataRef()->scope.find("~enclosing_scope"); - } - return node; +auto it = node->getDataRef()->scope.find("~enclosing_scope"); +while (it != node->getDataRef()->scope.end()) { + node = it->second[0]; + it = node->getDataRef()->scope.find("~enclosing_scope"); +} +return node; } // We do translation units in their own function so they can do the pariwise h/c stuff and regualr in function body generation does not std::pair CGenerator::generateTranslationUnit(std::string name, std::map*> ASTs) { - // We now pass in the entire map of ASTs and loop through them so that we generate out into a single file - std::string cOutput, hOutput; - // Ok, so we've got to do this in passes to preserve mututally recursive definitions. - // - // First Pass: All classes get "struct dummy_thing; typedef struct dummy_thing thing;". - // Also, other typedefs follow after their naming. - // Second Pass: All top level variable declarations - // Third Pass: Define all actual structs of a class, in correct order (done with posets) - // Fourth Pass: Declare all function prototypes (as functions may be mutually recursive too). - // (this includes object methods) - // Fifth Pass: Define all functions (including object methods). +// We now pass in the entire map of ASTs and loop through them so that we generate out into a single file +std::string cOutput, hOutput; +// Ok, so we've got to do this in passes to preserve mututally recursive definitions. +// +// First Pass: All classes get "struct dummy_thing; typedef struct dummy_thing thing;". +// Also, other typedefs follow after their naming. +// Second Pass: All top level variable declarations +// Third Pass: Define all actual structs of a class, in correct order (done with posets) +// Fourth Pass: Declare all function prototypes (as functions may be mutually recursive too). +// (this includes object methods) +// Fifth Pass: Define all functions (including object methods). - // However, most of these do not actually have to be done as separate passes. First, second, fourth, and fifth - // are done simultanously, but append to different strings that are then concatinated properly, in order. +// However, most of these do not actually have to be done as separate passes. First, second, fourth, and fifth +// are done simultanously, but append to different strings that are then concatinated properly, in order. - std::string importIncludes = "/**\n * Import Includes\n */\n\n"; - std::string topLevelCPassthrough = "/**\n * Top Level C Passthrough\n */\n\n"; - std::string variableExternDeclarations = "/**\n * Extern Variable Declarations \n */\n\n"; - std::string plainTypedefs = "/**\n * Plain Typedefs\n */\n\n"; - std::string variableDeclarations = "/**\n * Variable Declarations \n */\n\n"; - std::string classStructs = "/**\n * Class Structs\n */\n\n"; - std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n"; - std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n"; - // There also exists functionTypedefString which is a member variable that keeps - // track of utility typedefs that allow our C type generation to be more sane - // it is emitted in the h file right before functionPrototypes +std::string importIncludes = "/**\n * Import Includes\n */\n\n"; +std::string topLevelCPassthrough = "/**\n * Top Level C Passthrough\n */\n\n"; +std::string variableExternDeclarations = "/**\n * Extern Variable Declarations \n */\n\n"; +std::string plainTypedefs = "/**\n * Plain Typedefs\n */\n\n"; +std::string variableDeclarations = "/**\n * Variable Declarations \n */\n\n"; +std::string classStructs = "/**\n * Class Structs\n */\n\n"; +std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n"; +std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n"; +// There also exists functionTypedefString which is a member variable that keeps +// track of utility typedefs that allow our C type generation to be more sane +// it is emitted in the h file right before functionPrototypes - Poset*> typedefPoset; - for (auto trans : ASTs) { - auto children = trans.second->getChildren(); - for (int i = 0; i < children.size(); i++) { - if (children[i]->getDataRef()->type == type_def) { - // If we're an alias type, continue. We handle those differently - if (children[i]->getDataRef()->valueType->typeDefinition != children[i]) - continue; +Poset*> typedefPoset; +for (auto trans : ASTs) { + auto children = trans.second->getChildren(); + for (int i = 0; i < children.size(); i++) { + if (children[i]->getDataRef()->type == type_def) { + // If we're an alias type, continue. We handle those differently + if (children[i]->getDataRef()->valueType->typeDefinition != children[i]) + continue; - typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies. - // If it has dependencies, there's no harm in adding it here - // Go through every child in the class looking for declaration statements. For each of these that is not a primitive type - // we will add a dependency from this definition to that definition in the poset. - std::vector*> classChildren = children[i]->getChildren(); - for (auto j : classChildren) { - if (j->getDataRef()->type == declaration_statement) { - Type* decType = j->getChildren()[0]->getDataRef()->valueType; // Type of the declaration - if (decType->typeDefinition && decType->getIndirection() == 0) // If this is a custom type and not a pointer - typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency - } + typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies. + // If it has dependencies, there's no harm in adding it here + // Go through every child in the class looking for declaration statements. For each of these that is not a primitive type + // we will add a dependency from this definition to that definition in the poset. + std::vector*> classChildren = children[i]->getChildren(); + for (auto j : classChildren) { + if (j->getDataRef()->type == declaration_statement) { + Type* decType = j->getChildren()[0]->getDataRef()->valueType; // Type of the declaration + if (decType->typeDefinition && decType->getIndirection() == 0) // If this is a custom type and not a pointer + typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency } - } else if (children[i]->getDataRef()->type == adt_def) { - // - typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies. } + } else if (children[i]->getDataRef()->type == adt_def) { + // + typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies. } } - //Now generate the typedef's in the correct, topological order - for (NodeTree* i : typedefPoset.getTopoSort()) - classStructs += generateTypeStruct(i) + "\n"; +} +//Now generate the typedef's in the correct, topological order +for (NodeTree* i : typedefPoset.getTopoSort()) + classStructs += generateTypeStruct(i) + "\n"; - // Declare everything in translation unit scope here (now for ALL translation units). (allows stuff from other files, automatic forward declarations) - // Also, everything in all of the import's scopes - // Also c passthrough - for (auto trans : ASTs) { - // First go through and emit all the passthroughs, etc - for (auto i : trans.second->getChildren()) { - if (i->getDataRef()->type == if_comp) - topLevelCPassthrough += generate(i, nullptr).oneString(); - } +// Declare everything in translation unit scope here (now for ALL translation units). (allows stuff from other files, automatic forward declarations) +// Also, everything in all of the import's scopes +// Also c passthrough +for (auto trans : ASTs) { + // First go through and emit all the passthroughs, etc + for (auto i : trans.second->getChildren()) { + if (i->getDataRef()->type == if_comp) + topLevelCPassthrough += generate(i, nullptr).oneString(); + } - for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) { - for (auto declaration : i->second) { - std::vector*> decChildren = declaration->getChildren(); - ASTData declarationData = declaration->getData(); - switch(declarationData.type) { - case identifier: - { - auto parent = declaration->getDataRef()->scope["~enclosing_scope"][0]; - if (parent->getChildren().size() == 1) - variableDeclarations += ValueTypeToCType(declarationData.valueType, scopePrefix(declaration) + declarationData.symbol.getName()) + "; /*identifier*/\n"; - else - variableDeclarations += ValueTypeToCType(declarationData.valueType, generate(parent->getChildren()[0], nullptr, true, nullptr).oneString()) + " = " + generate(parent->getChildren()[1], nullptr, true, nullptr).oneString() + ";"; + for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) { + for (auto declaration : i->second) { + std::vector*> decChildren = declaration->getChildren(); + ASTData declarationData = declaration->getData(); + switch(declarationData.type) { + case identifier: + { + auto parent = declaration->getDataRef()->scope["~enclosing_scope"][0]; + if (parent->getChildren().size() == 1) + variableDeclarations += ValueTypeToCType(declarationData.valueType, prefixIfNeeded(scopePrefix(declaration), declarationData.symbol.getName())) + "; /*identifier*/\n"; + else + variableDeclarations += ValueTypeToCType(declarationData.valueType, generate(parent->getChildren()[0], nullptr, true, nullptr).oneString()) + " = " + generate(parent->getChildren()[1], nullptr, true, nullptr).oneString() + ";"; variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType, declarationData.symbol.getName()) + "; /*extern identifier*/\n"; break; } @@ -217,12 +256,11 @@ std::pair CGenerator::generateTranslationUnit(std::str parameters += ValueTypeToCType(decChildren[j]->getData().valueType, generate(decChildren[j], nullptr).oneString()); nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType); } - functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType->returnType, ((declarationData.symbol.getName() == "main") ? "" : function_header + scopePrefix(declaration)) + - CifyName(declarationData.symbol.getName() + nameDecoration)) + - "(" + parameters + "); /*func*/\n"; + std::string funName = (declarationData.symbol.getName() == "main") ? "main" : + function_header + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName() + nameDecoration)); + functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType->returnType, funName) + "(" + parameters + "); /*func*/\n"; // generate function - std::cout << "Generating " << scopePrefix(declaration) + - CifyName(declarationData.symbol.getName()) << std::endl; + std::cout << "Generating " << prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) << std::endl; functionDefinitions += generate(declaration, nullptr).oneString(); } } @@ -238,13 +276,12 @@ std::pair CGenerator::generateTranslationUnit(std::str continue; // Aliases of objects are done with the thing it alises // Otherwise, we're actually a renaming of a primitive, can generate here plainTypedefs += "typedef " + ValueTypeToCType(declarationData.valueType, - scopePrefix(declaration) + - CifyName(declarationData.symbol.getName())) + ";\n"; + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName()))) + ";\n"; plainTypedefs += generateAliasChains(ASTs, declaration); } else { plainTypedefs += "typedef struct __struct_dummy_" + - scopePrefix(declaration) + CifyName(declarationData.symbol.getName()) + "__ " + - scopePrefix(declaration) + CifyName(declarationData.symbol.getName()) + ";\n"; + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName()) + "__") + " " + + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) + ";\n"; functionPrototypes += "/* Method Prototypes for " + declarationData.symbol.getName() + " */\n"; // We use a seperate string for this because we only include it if this is the file we're defined in std::string objectFunctionDefinitions = "/* Method Definitions for " + declarationData.symbol.getName() + " */\n"; @@ -264,19 +301,15 @@ std::pair CGenerator::generateTranslationUnit(std::str case adt_def: { //type - plainTypedefs += "/* adt " + declarationData.symbol.getName() + " */\n"; - //plainTypedefs += "typedef struct __adt_dummy_" + - plainTypedefs += "typedef enum __adt_dummy_" + - scopePrefix(declaration) + CifyName(declarationData.symbol.getName()) + "__ " + - scopePrefix(declaration) + CifyName(declarationData.symbol.getName()) + ";\n"; - // We use a seperate string for this because we only include it if this is the file we're defined in - std::string enumString = "/* Enum Definition for " + declarationData.symbol.getName() + " */\n"; - // skip the name of the thing - for (int j = 1; j < decChildren.size(); j++) { - std::cout << decChildren[j]->getName() << std::endl; - if (decChildren[j]->getName() == "identifier") //If object method and not template - enumString += "an_option \n"; - } + //don't even need to do this anymore, it's all earlier + //plainTypedefs += "/* adt " + declarationData.symbol.getName() + " */\n"; + //plainTypedefs += "typedef struct __struct_dummy_" + + //prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())+ "__") + " " + + //prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) + ";\n"; + //// skip the name of the thing + //for (int j = 1; j < decChildren.size(); j++) { + //std::cout << decChildren[j]->getName() << std::endl; + //} break; } default: @@ -344,8 +377,8 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc preName += "(*"; postName += ")"; } - // we're scope prefixing EVERYTHING - return preName + scopePrefix(from) + CifyName(data.symbol.getName()) + postName; //Cifying does nothing if not an operator overload + // we're scope prefixing EVERYTHING, but only if needed + return preName + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())) + postName; //Cifying does nothing if not an operator overload } case function: { @@ -370,8 +403,9 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc if (justFuncName) { std::string funcName; if (data.symbol.getName() != "main") - funcName += function_header + scopePrefix(from); - funcName += CifyName(data.symbol.getName() + nameDecoration); + funcName += function_header + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName() + nameDecoration)); + else + funcName += CifyName(data.symbol.getName() + nameDecoration); if (from->getDataRef()->closedVariables.size()) { std::string tmpStruct = "closureStruct" + getID(); output.preValue += closureStructType(data.closedVariables) + " " + tmpStruct + " = {"; @@ -384,7 +418,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc std::string preName; if (enclosingObject && enclosingObject->getDataRef()->scope.find(varName) != enclosingObject->getDataRef()->scope.end()) preName += "this->"; - varName = (varName == "this") ? varName : scopePrefix(var) + varName; + varName = (varName == "this") ? varName : prefixIfNeeded(scopePrefix(var), varName); // so that we can close over things that have been closed over by an enclosing closure output.preValue += "." + varName + " = &/*woo*/" + generate(var, enclosingObject, justFuncName, enclosingFunction).oneString() + "/*woo*/"; //output.preValue += "." + varName + " = &" + preName + varName; @@ -396,8 +430,9 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc } } else { // Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock - output = "\n" + ValueTypeToCType(data.valueType->returnType, ((data.symbol.getName() == "main") ? "" : function_header + scopePrefix(from)) + - CifyName(data.symbol.getName() + nameDecoration)) + "(" + parameters + ") {\n" + generate(children[children.size()-1], enclosingObject, justFuncName, from).oneString(); + std::string funName = (data.symbol.getName() == "main") ? "main" : function_header + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName() + nameDecoration)); + output = "\n" + ValueTypeToCType(data.valueType->returnType, funName) + "(" + parameters + ") {\n" + + generate(children[children.size()-1], enclosingObject, justFuncName, from).oneString(); output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject); output += "}\n"; } @@ -615,6 +650,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc return CCodeTriple(""); case simple_passthrough: { + std::string pre_end_dec, end_assign; // Stuff is bit more interesting now! XXX std::string pre_passthrough, post_passthrough; // Handle input/output parameters @@ -623,17 +659,27 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc for (auto in_or_out : optParamAssignLists) { for (auto assign : in_or_out->getChildren()) { auto assignChildren = assign->getChildren(); - if (in_or_out->getDataRef()->type == in_passthrough_params) + if (in_or_out->getDataRef()->type == in_passthrough_params) { + std::string currentName = generate(assignChildren[0], enclosingObject, enclosingFunction).oneString(); + std::string toName; if (assignChildren.size() == 2) - pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, assignChildren[1]->getDataRef()->symbol.getName()) + " = " + generate(assignChildren[0], enclosingObject, enclosingFunction).oneString() + ";\n"; + toName = assignChildren[1]->getDataRef()->symbol.getName(); else - pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, assignChildren[0]->getDataRef()->symbol.getName()) + " = " + generate(assignChildren[0], enclosingObject, enclosingFunction).oneString() + ";\n"; - else if (in_or_out->getDataRef()->type == out_passthrough_params) + toName = assignChildren[0]->getDataRef()->symbol.getName(); + if (currentName != toName) + pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, toName) + " = " + currentName + ";\n"; + } else if (in_or_out->getDataRef()->type == out_passthrough_params) { + std::string currentName = generate(assignChildren[0], enclosingObject, justFuncName, enclosingFunction).oneString(); + std::string toName; if (assignChildren.size() == 2) - post_passthrough += generate(assignChildren[0], enclosingObject, justFuncName, enclosingFunction).oneString() + " = " + assignChildren[1]->getDataRef()->symbol.getName() + ";\n"; + toName = assignChildren[1]->getDataRef()->symbol.getName(); else - post_passthrough += generate(assignChildren[0], enclosingObject, justFuncName, enclosingFunction).oneString() + " = " + assignChildren[0]->getDataRef()->symbol.getName() + ";\n"; - else + toName += assignChildren[0]->getDataRef()->symbol.getName(); + std::string trans_dec_name = currentName + "_end_assign"; + pre_end_dec += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, trans_dec_name) + ";\n"; + post_passthrough += trans_dec_name + " = " + toName + ";\n"; + end_assign += currentName + " = " + trans_dec_name + ";\n"; + } else linkerString += " " + strSlice(generate(in_or_out, enclosingObject, justFuncName, enclosingFunction).oneString(), 1, -2) + " "; } } @@ -641,8 +687,11 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc // The actual passthrough string is the last child now, as we might // have passthrough_params be the first child // we don't generate, as that will escape the returns and we don't want that. We'll just grab the string - //return pre_passthrough + strSlice(generate(children.back(, enclosingFunction), enclosingObject, justFuncName).oneString(), 3, -4) + post_passthrough; - return pre_passthrough + strSlice(children.back()->getDataRef()->symbol.getName(), 3, -4) + post_passthrough; + // we don't want the scope stuff if we're at top level for an include, etc.... + if (isUnderNodeWithType(from,function)) + return pre_end_dec + "{" + pre_passthrough + strSlice(children.back()->getDataRef()->symbol.getName(), 3, -4) + post_passthrough + "}\n" + end_assign; + else + return strSlice(children.back()->getDataRef()->symbol.getName(), 3, -4); } case function_call: { @@ -704,7 +753,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); // Note that we only add scoping to the object, as this specifies our member function too -/*HERE*/ return function_header + scopePrefix(unaliasedTypeDef) + CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" + +/*HERE*/ return function_header + prefixIfNeeded(scopePrefix(unaliasedTypeDef), CifyName(unaliasedTypeDef->getDataRef()->symbol.getName())) +"__" + CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject, true, enclosingFunction) + ","; //The comma lets the upper function call know we already started the param list //Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses @@ -746,11 +795,11 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc //Check to see if we're inside of an object and this is a method call bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]); if (isSelfObjectMethod) { - output += function_header + scopePrefix(children[0]) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"; + output += function_header + prefixIfNeeded(scopePrefix(children[0]), CifyName(enclosingObject->getDataRef()->symbol.getName())) +"__"; output += CifyName(name + nameDecoration) + "("; output += std::string(addClosedOver ? "(*closed_variables->this)" : "this") + (children.size() > 1 ? "," : ""); } else { - output += function_header + scopePrefix(children[0]) + CifyName(name + nameDecoration) + "("; + output += function_header + prefixIfNeeded(scopePrefix(children[0]), CifyName(name + nameDecoration)) + "("; } } } @@ -877,8 +926,9 @@ std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, distructDoubleStack.back().push_back(children[i]); } - std::string functionSignature = "\n" + ValueTypeToCType(data.valueType->returnType, function_header + scopePrefix(from) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__" - + CifyName(data.symbol.getName()) + nameDecoration) + "(" + ValueTypeToCType(&enclosingObjectType, "this") + parameters + ")"; + std::string functionSignature = "\n" + ValueTypeToCType(data.valueType->returnType, function_header + + prefixIfNeeded(scopePrefix(from), CifyName(enclosingObject->getDataRef()->symbol.getName())) + "__" + + CifyName(data.symbol.getName()) + nameDecoration) + "(" + ValueTypeToCType(&enclosingObjectType, "this") + parameters + ")"; *functionPrototype += functionSignature + ";\n"; // Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock // @@ -928,7 +978,7 @@ std::string CGenerator::generateMethodIfExists(Type* type, std::string method, s std::string nameDecoration; for (Type *paramType : methodDef->getDataRef()->valueType->parameterTypes) nameDecoration += "_" + ValueTypeToCTypeDecoration(paramType); - return function_header + scopePrefix(typeDefinition) + CifyName(typeDefinition->getDataRef()->symbol.getName()) + "__" + method + nameDecoration + "(" + parameter + ");\n"; + return function_header + prefixIfNeeded(scopePrefix(typeDefinition), CifyName(typeDefinition->getDataRef()->symbol.getName())) + "__" + method + nameDecoration + "(" + parameter + ");\n"; } return ""; } @@ -952,7 +1002,7 @@ std::string CGenerator::closureStructType(std::set*> closedVar // will actually change the underlying function's type. We cheat and just add a * //auto tmp = var->getDataRef()->valueType->withIncreasedIndirection(); std::string varName = var->getDataRef()->symbol.getName(); - varName = (varName == "this") ? varName : scopePrefix(var) + varName; + varName = (varName == "this") ? varName : prefixIfNeeded(scopePrefix(var), varName); typedefString += ValueTypeToCType(var->getDataRef()->valueType->withoutReference(), "*"+varName) + ";"; } std::string structName = "closureStructType" + getID(); @@ -970,7 +1020,7 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl switch (type->baseType) { case none: if (type->typeDefinition) - return_type = scopePrefix(type->typeDefinition) + CifyName(type->typeDefinition->getDataRef()->symbol.getName()); + return_type = prefixIfNeeded(scopePrefix(type->typeDefinition), CifyName(type->typeDefinition->getDataRef()->symbol.getName())); else return_type = "none"; break; @@ -1128,4 +1178,20 @@ std::string CGenerator::scopePrefix(NodeTree* from) { // that parent object will get scoped. When we add a package system, we'll have to then add their scoping here return scopePrefix(from->getDataRef()->scope["~enclosing_scope"][0]); } +std::string CGenerator::prefixIfNeeded(std::string prefix, std::string name) { + return simpleComplexName(name, prefix + name); +} +std::string CGenerator::simpleComplexName(std::string simpleName, std::string complexName) { + auto already = simpleComplexNameMap.find(complexName); + if (already != simpleComplexNameMap.end()) + return already->second; + if (usedNameSet.find(simpleName) == usedNameSet.end()) { + usedNameSet.insert(simpleName); + simpleComplexNameMap[complexName] = simpleName; + return simpleName; + } + usedNameSet.insert(complexName); + simpleComplexNameMap[complexName] = complexName; + return complexName; +} diff --git a/src/Importer.cpp b/src/Importer.cpp index a721f85..9c3ab8c 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -47,6 +47,7 @@ Importer::Importer(Parser* parserIn, std::vector includePaths, std: collapseSymbols.push_back(Symbol("opt_typed_parameter_list", false)); collapseSymbols.push_back(Symbol("opt_parameter_list", false)); collapseSymbols.push_back(Symbol("identifier_list", false)); + collapseSymbols.push_back(Symbol("adt_option_list", false)); collapseSymbols.push_back(Symbol("statement_list", false)); collapseSymbols.push_back(Symbol("parameter_list", false)); collapseSymbols.push_back(Symbol("typed_parameter_list", false)); diff --git a/stdlib/io.krak b/stdlib/io.krak index 79d4e7c..6d38329 100644 --- a/stdlib/io.krak +++ b/stdlib/io.krak @@ -131,7 +131,7 @@ fun read_file_binary(path: string::string): vector::vector { __if_comp__ __C__ { simple_passthrough(data = data::) """ - free(data) + free(data); """ } return toRet diff --git a/tests/test_adt.krak b/tests/test_adt.krak index 161d30e..9846883 100644 --- a/tests/test_adt.krak +++ b/tests/test_adt.krak @@ -5,16 +5,42 @@ adt options { option1 } +adt maybe_int { + no_int, + an_int: int +} + +fun handle_possibility(it: maybe_int) { + if (it == maybe_int::no_int()) + println("no int") + /*if (it == maybe_int::an_int) {*/ + else { + print("an int: ") + println(it.an_int) + } +} + +fun give_maybe(give_it: bool): maybe_int { + if (give_it) + return maybe_int::an_int(7) + return maybe_int::no_int() +} + fun can_pass(it: options): options { - return options::option1 + return it } fun main():int { - var it: options = can_pass(options::option0) - if (it == options::option0) + var it: options = can_pass(options::option0()) + if (it == options::option0()) println("nope") - if (it == options::option1) + if (it == options::option1()) println("option1") + + var possibility = give_maybe(false) + handle_possibility(possibility) + possibility = give_maybe(true) + handle_possibility(possibility) return 0 } From 2ea504ffc17593844ca9d5ee9fd903128cd71985 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Mon, 9 Nov 2015 13:26:02 -0500 Subject: [PATCH 2/5] More work on ADTs --- include/Type.h | 1 + src/ASTTransformation.cpp | 13 +- src/CGenerator.cpp | 1368 +++++++++++++++++++------------------ src/Type.cpp | 7 +- tests/test_adt.krak | 21 +- 5 files changed, 718 insertions(+), 692 deletions(-) diff --git a/include/Type.h b/include/Type.h index f783fdb..5ed2198 100644 --- a/include/Type.h +++ b/include/Type.h @@ -41,6 +41,7 @@ class Type { void decreaseIndirection(); void modifyIndirection(int mod); Type withIncreasedIndirection(); + Type *withIncreasedIndirectionPtr(); Type withDecreasedIndirection(); Type* withoutReference(); diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 20c43b6..e666be6 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -197,6 +197,15 @@ void ASTTransformation::secondPass(NodeTree* ast, NodeTree* par std::cout << "there are " << getNodes("adt_option", i).size() << " adt_options" << std::endl; std::string name = concatSymbolTree(getNode("identifier", i)); NodeTree* adtDef = ast->getDataRef()->scope[name][0]; //No overloaded types (besides uninstantiated templates, which can have multiple versions based on types or specilizations) + + // Let's make an equality function prototype + Type *thisADTType = adtDef->getDataRef()->valueType; + NodeTree* equalityFunc = new NodeTree("function", ASTData(function, Symbol("operator==", true), new Type(std::vector{thisADTType}, new Type(boolean)))); + //NodeTree* equalityFunc = new NodeTree("function", ASTData(function, Symbol("operator==", true), new Type(std::vector{thisADTType, thisADTType}, new Type(boolean)))); + adtDef->addChild(equalityFunc); + addToScope("operator==", equalityFunc, adtDef); + addToScope("~enclosing_scope", adtDef, equalityFunc); + for (NodeTree* j : getNodes("adt_option", i)) { std::string ident_name = concatSymbolTree(getNode("identifier", j)); std::cout << "add ing " << ident_name << " to " << name << " for ADT" << std::endl; @@ -209,11 +218,11 @@ void ASTTransformation::secondPass(NodeTree* ast, NodeTree* par // also make a function prototype for a function that returns an instance of this type. If we don't contain a type, it's just the literal //enum_variant_function = new NodeTree("function", ASTData(function, Symbol("fun_"+ident_name, true), new Type(std::vector{actual_type}, adtDef->getDataRef()->valueType))); - enum_variant_function = new NodeTree("function", ASTData(function, Symbol(ident_name, true), new Type(std::vector{actual_type}, adtDef->getDataRef()->valueType))); + enum_variant_function = new NodeTree("function", ASTData(function, Symbol(ident_name, true), new Type(std::vector{actual_type}, thisADTType))); } else { enum_variant_identifier = new NodeTree("identifier", ASTData(identifier, Symbol(ident_name, true), adtDef->getDataRef()->valueType)); // now a function in both cases... - enum_variant_function = new NodeTree("function", ASTData(function, Symbol(ident_name, true), new Type(std::vector(), adtDef->getDataRef()->valueType))); + enum_variant_function = new NodeTree("function", ASTData(function, Symbol(ident_name, true), new Type(std::vector(), thisADTType))); } adtDef->addChild(enum_variant_identifier); addToScope(ident_name, enum_variant_identifier, adtDef); diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index ffa1c0f..a86af5c 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -1,7 +1,7 @@ #include "CGenerator.h" CGenerator::CGenerator() : generatorString("__C__") { - tabLevel = 0; + tabLevel = 0; id = 0; function_header = "fun_"; functionTypedefString = ""; @@ -12,9 +12,9 @@ CGenerator::~CGenerator() { // Note the use of std::pair to hold two strings - the running string for the header file and the running string for the c file. void CGenerator::generateCompSet(std::map*> ASTs, std::string outputName) { - //Generate an entire set of files - std::string buildString = "#!/bin/sh\ncc -g -O3 -std=c99 "; - std::cout << "\n\n =====GENERATE PASS===== \n\n" << std::endl; + //Generate an entire set of files + std::string buildString = "#!/bin/sh\ncc -g -O3 -std=c99 "; + std::cout << "\n\n =====GENERATE PASS===== \n\n" << std::endl; std::cout << "\n\nGenerate pass for: " << outputName << std::endl; buildString += outputName + ".c "; //std::ofstream outputCFile, outputHFile; @@ -34,20 +34,20 @@ void CGenerator::generateCompSet(std::map*> ASTs, outputCFile.close(); //outputHFile.close(); - buildString += linkerString; - buildString += "-o " + outputName; - std::ofstream outputBuild; - outputBuild.open(outputName + "/" + split(outputName, '/').back() + ".sh"); - outputBuild << buildString; - outputBuild.close(); + buildString += linkerString; + buildString += "-o " + outputName; + std::ofstream outputBuild; + outputBuild.open(outputName + "/" + split(outputName, '/').back() + ".sh"); + outputBuild << buildString; + outputBuild.close(); std::cout << "DEFER DOUBLE STACK " << deferDoubleStack.size() << std::endl; } std::string CGenerator::tabs() { - std::string returnTabs; - for (int i = 0; i < tabLevel; i++) - returnTabs += "\t"; - return returnTabs; + std::string returnTabs; + for (int i = 0; i < tabLevel; i++) + returnTabs += "\t"; + return returnTabs; } std::string CGenerator::getID() { @@ -81,7 +81,15 @@ std::string CGenerator::generateTypeStruct(NodeTree* from) { enumString += tabs() + generate(child, nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n"); } else { if (data.type == adt_def) { - functionString += "\n" + ValueTypeToCType(child->getDataRef()->valueType->returnType, "fun_" + child->getDataRef()->symbol.getName()) + "(" + + std::string fun_name = child->getDataRef()->symbol.getName(); + std::string first_param; + if (fun_name == "operator==") { + fun_name = "fun_" + data.symbol.getName() + "__" + CifyName(fun_name); + first_param = ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0]->withIncreasedIndirectionPtr(), "this") + ", "; + } else { + fun_name = "fun_" + fun_name; + } + functionString += "\n" + ValueTypeToCType(child->getDataRef()->valueType->returnType, fun_name) + "(" + first_param + (child->getDataRef()->valueType->parameterTypes.size() ? ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0], "in") : "") + "); /*adt func*/\n"; } } @@ -101,144 +109,144 @@ std::string CGenerator::generateTypeStruct(NodeTree* from) { // This method recurseivly generates all aliases of some definition std::string CGenerator::generateAliasChains(std::map*> ASTs, NodeTree* definition) { -std::string output; -for (auto trans : ASTs) { - for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) { - for (auto declaration : i->second) { - auto declarationData = declaration->getDataRef(); - if (declarationData->type == type_def - && declarationData->valueType->typeDefinition != declaration - && declarationData->valueType->typeDefinition == definition) { - output += "typedef " + - prefixIfNeeded(scopePrefix(definition), CifyName(definition->getDataRef()->symbol.getName())) + " " + - prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData->symbol.getName())) + ";\n"; - // Recursively add the ones that depend on this one - output += generateAliasChains(ASTs, declaration); + std::string output; + for (auto trans : ASTs) { + for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) { + for (auto declaration : i->second) { + auto declarationData = declaration->getDataRef(); + if (declarationData->type == type_def + && declarationData->valueType->typeDefinition != declaration + && declarationData->valueType->typeDefinition == definition) { + output += "typedef " + + prefixIfNeeded(scopePrefix(definition), CifyName(definition->getDataRef()->symbol.getName())) + " " + + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData->symbol.getName())) + ";\n"; + // Recursively add the ones that depend on this one + output += generateAliasChains(ASTs, declaration); + } } } } -} -return output; + return output; } bool CGenerator::isUnderNodeWithType(NodeTree* from, ASTType type) { -auto scope = from->getDataRef()->scope; -auto upper = scope.find("~enclosing_scope"); -if (upper != scope.end()) { - if (upper->second[0]->getDataRef()->type == type) - return true; - return isUnderNodeWithType(upper->second[0], type); -} -return false; + auto scope = from->getDataRef()->scope; + auto upper = scope.find("~enclosing_scope"); + if (upper != scope.end()) { + if (upper->second[0]->getDataRef()->type == type) + return true; + return isUnderNodeWithType(upper->second[0], type); + } + return false; } bool CGenerator::isUnderTranslationUnit(NodeTree* from, NodeTree* node) { -auto scope = from->getDataRef()->scope; -for (auto i : scope) - for (auto j : i.second) - if (j == node) - return true; + auto scope = from->getDataRef()->scope; + for (auto i : scope) + for (auto j : i.second) + if (j == node) + return true; -auto upper = scope.find("~enclosing_scope"); -if (upper != scope.end()) - return isUnderTranslationUnit(upper->second[0], node); -return false; + auto upper = scope.find("~enclosing_scope"); + if (upper != scope.end()) + return isUnderTranslationUnit(upper->second[0], node); + return false; } NodeTree* CGenerator::highestScope(NodeTree* node) { -auto it = node->getDataRef()->scope.find("~enclosing_scope"); -while (it != node->getDataRef()->scope.end()) { - node = it->second[0]; - it = node->getDataRef()->scope.find("~enclosing_scope"); -} -return node; + auto it = node->getDataRef()->scope.find("~enclosing_scope"); + while (it != node->getDataRef()->scope.end()) { + node = it->second[0]; + it = node->getDataRef()->scope.find("~enclosing_scope"); + } + return node; } // We do translation units in their own function so they can do the pariwise h/c stuff and regualr in function body generation does not std::pair CGenerator::generateTranslationUnit(std::string name, std::map*> ASTs) { -// We now pass in the entire map of ASTs and loop through them so that we generate out into a single file -std::string cOutput, hOutput; -// Ok, so we've got to do this in passes to preserve mututally recursive definitions. -// -// First Pass: All classes get "struct dummy_thing; typedef struct dummy_thing thing;". -// Also, other typedefs follow after their naming. -// Second Pass: All top level variable declarations -// Third Pass: Define all actual structs of a class, in correct order (done with posets) -// Fourth Pass: Declare all function prototypes (as functions may be mutually recursive too). -// (this includes object methods) -// Fifth Pass: Define all functions (including object methods). + // We now pass in the entire map of ASTs and loop through them so that we generate out into a single file + std::string cOutput, hOutput; + // Ok, so we've got to do this in passes to preserve mututally recursive definitions. + // + // First Pass: All classes get "struct dummy_thing; typedef struct dummy_thing thing;". + // Also, other typedefs follow after their naming. + // Second Pass: All top level variable declarations + // Third Pass: Define all actual structs of a class, in correct order (done with posets) + // Fourth Pass: Declare all function prototypes (as functions may be mutually recursive too). + // (this includes object methods) + // Fifth Pass: Define all functions (including object methods). -// However, most of these do not actually have to be done as separate passes. First, second, fourth, and fifth -// are done simultanously, but append to different strings that are then concatinated properly, in order. + // However, most of these do not actually have to be done as separate passes. First, second, fourth, and fifth + // are done simultanously, but append to different strings that are then concatinated properly, in order. -std::string importIncludes = "/**\n * Import Includes\n */\n\n"; -std::string topLevelCPassthrough = "/**\n * Top Level C Passthrough\n */\n\n"; -std::string variableExternDeclarations = "/**\n * Extern Variable Declarations \n */\n\n"; -std::string plainTypedefs = "/**\n * Plain Typedefs\n */\n\n"; -std::string variableDeclarations = "/**\n * Variable Declarations \n */\n\n"; -std::string classStructs = "/**\n * Class Structs\n */\n\n"; -std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n"; -std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n"; -// There also exists functionTypedefString which is a member variable that keeps -// track of utility typedefs that allow our C type generation to be more sane -// it is emitted in the h file right before functionPrototypes + std::string importIncludes = "/**\n * Import Includes\n */\n\n"; + std::string topLevelCPassthrough = "/**\n * Top Level C Passthrough\n */\n\n"; + std::string variableExternDeclarations = "/**\n * Extern Variable Declarations \n */\n\n"; + std::string plainTypedefs = "/**\n * Plain Typedefs\n */\n\n"; + std::string variableDeclarations = "/**\n * Variable Declarations \n */\n\n"; + std::string classStructs = "/**\n * Class Structs\n */\n\n"; + std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n"; + std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n"; + // There also exists functionTypedefString which is a member variable that keeps + // track of utility typedefs that allow our C type generation to be more sane + // it is emitted in the h file right before functionPrototypes -Poset*> typedefPoset; -for (auto trans : ASTs) { - auto children = trans.second->getChildren(); - for (int i = 0; i < children.size(); i++) { - if (children[i]->getDataRef()->type == type_def) { - // If we're an alias type, continue. We handle those differently - if (children[i]->getDataRef()->valueType->typeDefinition != children[i]) - continue; + Poset*> typedefPoset; + for (auto trans : ASTs) { + auto children = trans.second->getChildren(); + for (int i = 0; i < children.size(); i++) { + if (children[i]->getDataRef()->type == type_def) { + // If we're an alias type, continue. We handle those differently + if (children[i]->getDataRef()->valueType->typeDefinition != children[i]) + continue; - typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies. - // If it has dependencies, there's no harm in adding it here - // Go through every child in the class looking for declaration statements. For each of these that is not a primitive type - // we will add a dependency from this definition to that definition in the poset. - std::vector*> classChildren = children[i]->getChildren(); - for (auto j : classChildren) { - if (j->getDataRef()->type == declaration_statement) { - Type* decType = j->getChildren()[0]->getDataRef()->valueType; // Type of the declaration - if (decType->typeDefinition && decType->getIndirection() == 0) // If this is a custom type and not a pointer - typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency + typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies. + // If it has dependencies, there's no harm in adding it here + // Go through every child in the class looking for declaration statements. For each of these that is not a primitive type + // we will add a dependency from this definition to that definition in the poset. + std::vector*> classChildren = children[i]->getChildren(); + for (auto j : classChildren) { + if (j->getDataRef()->type == declaration_statement) { + Type* decType = j->getChildren()[0]->getDataRef()->valueType; // Type of the declaration + if (decType->typeDefinition && decType->getIndirection() == 0) // If this is a custom type and not a pointer + typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency + } } + } else if (children[i]->getDataRef()->type == adt_def) { + // + typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies. } - } else if (children[i]->getDataRef()->type == adt_def) { - // - typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies. } } -} -//Now generate the typedef's in the correct, topological order -for (NodeTree* i : typedefPoset.getTopoSort()) - classStructs += generateTypeStruct(i) + "\n"; + //Now generate the typedef's in the correct, topological order + for (NodeTree* i : typedefPoset.getTopoSort()) + classStructs += generateTypeStruct(i) + "\n"; -// Declare everything in translation unit scope here (now for ALL translation units). (allows stuff from other files, automatic forward declarations) -// Also, everything in all of the import's scopes -// Also c passthrough -for (auto trans : ASTs) { - // First go through and emit all the passthroughs, etc - for (auto i : trans.second->getChildren()) { - if (i->getDataRef()->type == if_comp) - topLevelCPassthrough += generate(i, nullptr).oneString(); - } + // Declare everything in translation unit scope here (now for ALL translation units). (allows stuff from other files, automatic forward declarations) + // Also, everything in all of the import's scopes + // Also c passthrough + for (auto trans : ASTs) { + // First go through and emit all the passthroughs, etc + for (auto i : trans.second->getChildren()) { + if (i->getDataRef()->type == if_comp) + topLevelCPassthrough += generate(i, nullptr).oneString(); + } - for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) { - for (auto declaration : i->second) { - std::vector*> decChildren = declaration->getChildren(); - ASTData declarationData = declaration->getData(); - switch(declarationData.type) { - case identifier: - { - auto parent = declaration->getDataRef()->scope["~enclosing_scope"][0]; - if (parent->getChildren().size() == 1) - variableDeclarations += ValueTypeToCType(declarationData.valueType, prefixIfNeeded(scopePrefix(declaration), declarationData.symbol.getName())) + "; /*identifier*/\n"; - else - variableDeclarations += ValueTypeToCType(declarationData.valueType, generate(parent->getChildren()[0], nullptr, true, nullptr).oneString()) + " = " + generate(parent->getChildren()[1], nullptr, true, nullptr).oneString() + ";"; - variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType, declarationData.symbol.getName()) + "; /*extern identifier*/\n"; - break; + for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) { + for (auto declaration : i->second) { + std::vector*> decChildren = declaration->getChildren(); + ASTData declarationData = declaration->getData(); + switch(declarationData.type) { + case identifier: + { + auto parent = declaration->getDataRef()->scope["~enclosing_scope"][0]; + if (parent->getChildren().size() == 1) + variableDeclarations += ValueTypeToCType(declarationData.valueType, prefixIfNeeded(scopePrefix(declaration), declarationData.symbol.getName())) + "; /*identifier*/\n"; + else + variableDeclarations += ValueTypeToCType(declarationData.valueType, generate(parent->getChildren()[0], nullptr, true, nullptr).oneString()) + " = " + generate(parent->getChildren()[1], nullptr, true, nullptr).oneString() + ";"; + variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType, declarationData.symbol.getName()) + "; /*extern identifier*/\n"; + break; } case function: { @@ -276,12 +284,12 @@ for (auto trans : ASTs) { continue; // Aliases of objects are done with the thing it alises // Otherwise, we're actually a renaming of a primitive, can generate here plainTypedefs += "typedef " + ValueTypeToCType(declarationData.valueType, - prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName()))) + ";\n"; + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName()))) + ";\n"; plainTypedefs += generateAliasChains(ASTs, declaration); } else { plainTypedefs += "typedef struct __struct_dummy_" + - prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName()) + "__") + " " + - prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) + ";\n"; + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName()) + "__") + " " + + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) + ";\n"; functionPrototypes += "/* Method Prototypes for " + declarationData.symbol.getName() + " */\n"; // We use a seperate string for this because we only include it if this is the file we're defined in std::string objectFunctionDefinitions = "/* Method Definitions for " + declarationData.symbol.getName() + " */\n"; @@ -299,19 +307,19 @@ for (auto trans : ASTs) { } break; case adt_def: - { - //type - //don't even need to do this anymore, it's all earlier - //plainTypedefs += "/* adt " + declarationData.symbol.getName() + " */\n"; - //plainTypedefs += "typedef struct __struct_dummy_" + - //prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())+ "__") + " " + - //prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) + ";\n"; - //// skip the name of the thing - //for (int j = 1; j < decChildren.size(); j++) { + { + //type + //don't even need to do this anymore, it's all earlier + //plainTypedefs += "/* adt " + declarationData.symbol.getName() + " */\n"; + //plainTypedefs += "typedef struct __struct_dummy_" + + //prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())+ "__") + " " + + //prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) + ";\n"; + //// skip the name of the thing + //for (int j = 1; j < decChildren.size(); j++) { //std::cout << decChildren[j]->getName() << std::endl; - //} - break; - } + //} + break; + } default: //std::cout << "Declaration? named " << declaration->getName() << " of unknown type " << ASTData::ASTTypeToString(declarationData.type) << " in translation unit scope" << std::endl; cOutput += "/*unknown declaration named " + declaration->getName() + "*/\n"; @@ -327,153 +335,153 @@ for (auto trans : ASTs) { //The enclosing object is for when we're generating the inside of object methods. They allow us to check scope lookups against the object we're in CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enclosingObject, bool justFuncName, NodeTree* enclosingFunction) { - ASTData data = from->getData(); - std::vector*> children = from->getChildren(); + ASTData data = from->getData(); + std::vector*> children = from->getChildren(); //std::string output; CCodeTriple output; - switch (data.type) { - case translation_unit: - { - // Should not happen! We do this in it's own function now! - std::cerr << "Trying to normal generate a translation unit! That's a nono! (" << from->getDataRef()->toString() << ")" << std::endl; - throw "That's not gonna work"; - } - break; - case interpreter_directive: - //Do nothing - break; - case import: - return CCodeTriple("/* never reached import? */\n"); - case identifier: - { - std::string preName = ""; - std::string postName = ""; - bool closed = false; - // check for this being a closed over variable - // first, get declaring function, if it exists - if (enclosingFunction) { - if (enclosingFunction->getDataRef()->closedVariables.size()) { - std::cout << "WHOH IS A CLOSER" << std::endl; - if (enclosingFunction->getDataRef()->closedVariables.find(from) != enclosingFunction->getDataRef()->closedVariables.end()) { - preName += "(*closed_variables->"; - postName += ")"; - closed = true; - } - } - } - // enclosing function comes first now, we might have a double closure that both close over the this pointer of an object - //but first, if we're this, we should just emit. (assuming enclosing object) (note that technically this would fall through, but for errors) - if (data.symbol.getName() == "this") { - if (enclosingObject || enclosingFunction) - return CCodeTriple(preName + "this" + postName); - std::cerr << "Error: this used in non-object scope" << std::endl; - throw "Error: this used in non-object scope"; - } - //If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the this reference. - if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end()) - preName = "(" + preName + "this)->"; // incase this is a closed over this that is referencing another thing (I think this happens for a.b when a is supposed to be closed over but isn't) - // dereference references, but only if inside a function and not if this is a closed over variable - if (enclosingFunction && data.valueType->is_reference && !closed) { - preName += "(*"; - postName += ")"; - } - // we're scope prefixing EVERYTHING, but only if needed - return preName + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())) + postName; //Cifying does nothing if not an operator overload - } - case function: - { - if (data.valueType->baseType == template_type) - return "/* template function: " + data.symbol.getName() + " */"; - - // we push on a new vector to hold parameters that might need a destructor call - distructDoubleStack.push_back(std::vector*>()); - - std::string nameDecoration, parameters; - if (data.closedVariables.size()) - parameters += closureStructType(data.closedVariables) + " *closed_variables"; - for (int j = 0; j < children.size()-1; j++) { - if (j > 0 || data.closedVariables.size()) - parameters += ", "; - parameters += ValueTypeToCType(children[j]->getData().valueType, generate(children[j], enclosingObject, justFuncName, enclosingFunction).oneString()); - nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType); - // add parameters to distructDoubleStack so that their destructors will be called at return (if they exist) - distructDoubleStack.back().push_back(children[j]); - } - // this is for using functions as values - if (justFuncName) { - std::string funcName; - if (data.symbol.getName() != "main") - funcName += function_header + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName() + nameDecoration)); - else - funcName += CifyName(data.symbol.getName() + nameDecoration); - if (from->getDataRef()->closedVariables.size()) { - std::string tmpStruct = "closureStruct" + getID(); - output.preValue += closureStructType(data.closedVariables) + " " + tmpStruct + " = {"; - bool notFirst = false; - for (auto var : data.closedVariables) { - if (notFirst) - output.preValue += ", "; - notFirst = true; - std::string varName = var->getDataRef()->symbol.getName(); - std::string preName; - if (enclosingObject && enclosingObject->getDataRef()->scope.find(varName) != enclosingObject->getDataRef()->scope.end()) - preName += "this->"; - varName = (varName == "this") ? varName : prefixIfNeeded(scopePrefix(var), varName); - // so that we can close over things that have been closed over by an enclosing closure - output.preValue += "." + varName + " = &/*woo*/" + generate(var, enclosingObject, justFuncName, enclosingFunction).oneString() + "/*woo*/"; - //output.preValue += "." + varName + " = &" + preName + varName; - } - output.preValue += "};\n"; - output += "("+ ValueTypeToCType(data.valueType, "") +"){(void*)" + funcName + ", &" + tmpStruct + "}"; - } else { - output += "("+ ValueTypeToCType(data.valueType, "") +"){" + funcName + ", NULL}"; - } - } else { - // Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock - std::string funName = (data.symbol.getName() == "main") ? "main" : function_header + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName() + nameDecoration)); - output = "\n" + ValueTypeToCType(data.valueType->returnType, funName) + "(" + parameters + ") {\n" + - generate(children[children.size()-1], enclosingObject, justFuncName, from).oneString(); - output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject); - output += "}\n"; - } - - distructDoubleStack.pop_back(); - return output; - } - case code_block: - { - output += "{\n"; - tabLevel++; - - // we push on a new vector to hold parameters that might need a destructor call - distructDoubleStack.push_back(std::vector*>()); - // we push on a new vector to hold deferred statements - deferDoubleStack.push_back(std::vector*>()); - for (int i = 0; i < children.size(); i++) - output += generate(children[i], enclosingObject, justFuncName, enclosingFunction).oneString(); - // 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, justFuncName, enclosingFunction).oneString(); - deferDoubleStack.pop_back(); - output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject); - distructDoubleStack.pop_back(); - - tabLevel--; - output += tabs() + "}"; - - return output; - } - case expression: - output += " " + data.symbol.getName() + ", "; - case boolean_expression: - output += " " + data.symbol.getName() + " "; - case statement: + switch (data.type) { + case translation_unit: { - CCodeTriple stat = generate(children[0], enclosingObject, justFuncName, enclosingFunction); - return tabs() + stat.preValue + stat.value + ";\n" + stat.postValue ; + // Should not happen! We do this in it's own function now! + std::cerr << "Trying to normal generate a translation unit! That's a nono! (" << from->getDataRef()->toString() << ")" << std::endl; + throw "That's not gonna work"; } - case if_statement: - output += "if (" + generate(children[0], enclosingObject, true, enclosingFunction) + ")\n\t"; + break; + case interpreter_directive: + //Do nothing + break; + case import: + return CCodeTriple("/* never reached import? */\n"); + case identifier: + { + std::string preName = ""; + std::string postName = ""; + bool closed = false; + // check for this being a closed over variable + // first, get declaring function, if it exists + if (enclosingFunction) { + if (enclosingFunction->getDataRef()->closedVariables.size()) { + std::cout << "WHOH IS A CLOSER" << std::endl; + if (enclosingFunction->getDataRef()->closedVariables.find(from) != enclosingFunction->getDataRef()->closedVariables.end()) { + preName += "(*closed_variables->"; + postName += ")"; + closed = true; + } + } + } + // enclosing function comes first now, we might have a double closure that both close over the this pointer of an object + //but first, if we're this, we should just emit. (assuming enclosing object) (note that technically this would fall through, but for errors) + if (data.symbol.getName() == "this") { + if (enclosingObject || enclosingFunction) + return CCodeTriple(preName + "this" + postName); + std::cerr << "Error: this used in non-object scope" << std::endl; + throw "Error: this used in non-object scope"; + } + //If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the this reference. + if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end()) + preName = "(" + preName + "this)->"; // incase this is a closed over this that is referencing another thing (I think this happens for a.b when a is supposed to be closed over but isn't) + // dereference references, but only if inside a function and not if this is a closed over variable + if (enclosingFunction && data.valueType->is_reference && !closed) { + preName += "(*"; + postName += ")"; + } + // we're scope prefixing EVERYTHING, but only if needed + return preName + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())) + postName; //Cifying does nothing if not an operator overload + } + case function: + { + if (data.valueType->baseType == template_type) + return "/* template function: " + data.symbol.getName() + " */"; + + // we push on a new vector to hold parameters that might need a destructor call + distructDoubleStack.push_back(std::vector*>()); + + std::string nameDecoration, parameters; + if (data.closedVariables.size()) + parameters += closureStructType(data.closedVariables) + " *closed_variables"; + for (int j = 0; j < children.size()-1; j++) { + if (j > 0 || data.closedVariables.size()) + parameters += ", "; + parameters += ValueTypeToCType(children[j]->getData().valueType, generate(children[j], enclosingObject, justFuncName, enclosingFunction).oneString()); + nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType); + // add parameters to distructDoubleStack so that their destructors will be called at return (if they exist) + distructDoubleStack.back().push_back(children[j]); + } + // this is for using functions as values + if (justFuncName) { + std::string funcName; + if (data.symbol.getName() != "main") + funcName += function_header + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName() + nameDecoration)); + else + funcName += CifyName(data.symbol.getName() + nameDecoration); + if (from->getDataRef()->closedVariables.size()) { + std::string tmpStruct = "closureStruct" + getID(); + output.preValue += closureStructType(data.closedVariables) + " " + tmpStruct + " = {"; + bool notFirst = false; + for (auto var : data.closedVariables) { + if (notFirst) + output.preValue += ", "; + notFirst = true; + std::string varName = var->getDataRef()->symbol.getName(); + std::string preName; + if (enclosingObject && enclosingObject->getDataRef()->scope.find(varName) != enclosingObject->getDataRef()->scope.end()) + preName += "this->"; + varName = (varName == "this") ? varName : prefixIfNeeded(scopePrefix(var), varName); + // so that we can close over things that have been closed over by an enclosing closure + output.preValue += "." + varName + " = &/*woo*/" + generate(var, enclosingObject, justFuncName, enclosingFunction).oneString() + "/*woo*/"; + //output.preValue += "." + varName + " = &" + preName + varName; + } + output.preValue += "};\n"; + output += "("+ ValueTypeToCType(data.valueType, "") +"){(void*)" + funcName + ", &" + tmpStruct + "}"; + } else { + output += "("+ ValueTypeToCType(data.valueType, "") +"){" + funcName + ", NULL}"; + } + } else { + // Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock + std::string funName = (data.symbol.getName() == "main") ? "main" : function_header + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName() + nameDecoration)); + output = "\n" + ValueTypeToCType(data.valueType->returnType, funName) + "(" + parameters + ") {\n" + + generate(children[children.size()-1], enclosingObject, justFuncName, from).oneString(); + output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject); + output += "}\n"; + } + + distructDoubleStack.pop_back(); + return output; + } + case code_block: + { + output += "{\n"; + tabLevel++; + + // we push on a new vector to hold parameters that might need a destructor call + distructDoubleStack.push_back(std::vector*>()); + // we push on a new vector to hold deferred statements + deferDoubleStack.push_back(std::vector*>()); + for (int i = 0; i < children.size(); i++) + output += generate(children[i], enclosingObject, justFuncName, enclosingFunction).oneString(); + // 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, justFuncName, enclosingFunction).oneString(); + deferDoubleStack.pop_back(); + output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject); + distructDoubleStack.pop_back(); + + tabLevel--; + output += tabs() + "}"; + + return output; + } + case expression: + output += " " + data.symbol.getName() + ", "; + case boolean_expression: + output += " " + data.symbol.getName() + " "; + case statement: + { + CCodeTriple stat = generate(children[0], enclosingObject, justFuncName, enclosingFunction); + return tabs() + stat.preValue + stat.value + ";\n" + stat.postValue ; + } + case if_statement: + output += "if (" + generate(children[0], enclosingObject, true, enclosingFunction) + ")\n\t"; // We have to see if the then statement is a regular single statement or a block. // If it's a block, because it's also a statement a semicolon will be emitted even though // we don't want it to be, as if (a) {b}; else {c}; is not legal C, but if (a) {b} else {c}; is. @@ -485,107 +493,107 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc output += "{ " + generate(children[1], enclosingObject, justFuncName, enclosingFunction).oneString() + " }"; } // Always emit blocks here too - if (children.size() > 2) - output += " else { " + generate(children[2], enclosingObject, justFuncName, enclosingFunction).oneString() + " }"; - return output; - case while_loop: - { - // we push on a new vector to hold while stuff that might need a destructor call - loopDistructStackDepth.push(distructDoubleStack.size()); - distructDoubleStack.push_back(std::vector*>()); - // 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()); - // gotta do like this so that the preconditions can happen every loop - output += "while (1) {\n"; - CCodeTriple condtition = generate(children[0], enclosingObject, true, enclosingFunction); - output += condtition.preValue; - output += "if (!( " + condtition.value + ")) break;\n"; - output += condtition.postValue; - output += generate(children[1], enclosingObject, justFuncName, enclosingFunction).oneString(); - output += emitDestructors(reverse(distructDoubleStack.back()),enclosingObject); - output += + "}"; - - distructDoubleStack.pop_back(); - loopDistructStackDepth.pop(); - // and pop it off again - loopDeferStackDepth.pop(); - return output; - } - case for_loop: - { - // we push on a new vector to hold for stuff that might need a destructor call - loopDistructStackDepth.push(distructDoubleStack.size()); - distructDoubleStack.push_back(std::vector*>()); - // 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) - - std::string doUpdateName = "do_update" + getID(); - // INITIALIZER - output += "{"; - output += generate(children[0], enclosingObject, true, enclosingFunction).oneString(); - output += "bool " + doUpdateName + " = false;\n"; - output += "for (;;) {"; - // UPDATE - output += "if (" + doUpdateName + ") {"; - output += generate(children[2], enclosingObject, true, enclosingFunction).oneString(); - output += "}\n"; - output += doUpdateName + " = true;\n"; - // CONDITION - // note that the postValue happens whether or not we break - CCodeTriple condition = generate(children[1], enclosingObject, true, enclosingFunction); - output += condition.preValue; - output += "if (!(" + condition.value + ")) {\n"; - output += condition.postValue; - output += "break;\n}"; - output += condition.postValue; - // BODY - output += generate(children[3], enclosingObject, justFuncName, enclosingFunction).oneString(); - output += emitDestructors(reverse(distructDoubleStack.back()),enclosingObject); - output += "}"; - output += "}"; - distructDoubleStack.pop_back(); - loopDistructStackDepth.pop(); - // 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, justFuncName, enclosingFunction).oneString(); - - std::string destructors = emitDestructors(reverse(flatten(distructDoubleStack)),enclosingObject); - if (children.size()) { - CCodeTriple expr = generate(children[0], enclosingObject, true, enclosingFunction); - output.preValue += expr.preValue; - std::string retTemp = "ret_temp" + getID(); - // use the function's return value so we do the right thing with references - output.preValue += ValueTypeToCType(enclosingFunction->getDataRef()->valueType->returnType, retTemp) + ";\n"; - if (enclosingFunction->getDataRef()->valueType->returnType->is_reference) - output.preValue += retTemp + " = &" + expr.value + ";\n"; - else if (methodExists(children[0]->getDataRef()->valueType, "copy_construct", std::vector{children[0]->getDataRef()->valueType->withIncreasedIndirection()})) - output.preValue += generateMethodIfExists(children[0]->getDataRef()->valueType, "copy_construct", "&"+retTemp + ", &" + expr.value, std::vector{children[0]->getDataRef()->valueType->withIncreasedIndirection()}); - else - output.preValue += retTemp + " = " + expr.value + ";\n"; - // move expr post to before return - output.value += expr.postValue; - output.value += destructors; - output.value += "return " + retTemp; - } else { - output.value += destructors; - output += "return"; - } + if (children.size() > 2) + output += " else { " + generate(children[2], enclosingObject, justFuncName, enclosingFunction).oneString() + " }"; return output; + case while_loop: + { + // we push on a new vector to hold while stuff that might need a destructor call + loopDistructStackDepth.push(distructDoubleStack.size()); + distructDoubleStack.push_back(std::vector*>()); + // 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()); + // gotta do like this so that the preconditions can happen every loop + output += "while (1) {\n"; + CCodeTriple condtition = generate(children[0], enclosingObject, true, enclosingFunction); + output += condtition.preValue; + output += "if (!( " + condtition.value + ")) break;\n"; + output += condtition.postValue; + output += generate(children[1], enclosingObject, justFuncName, enclosingFunction).oneString(); + output += emitDestructors(reverse(distructDoubleStack.back()),enclosingObject); + output += + "}"; + + distructDoubleStack.pop_back(); + loopDistructStackDepth.pop(); + // and pop it off again + loopDeferStackDepth.pop(); + return output; } - case break_statement: + case for_loop: + { + // we push on a new vector to hold for stuff that might need a destructor call + loopDistructStackDepth.push(distructDoubleStack.size()); + distructDoubleStack.push_back(std::vector*>()); + // 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) + + std::string doUpdateName = "do_update" + getID(); + // INITIALIZER + output += "{"; + output += generate(children[0], enclosingObject, true, enclosingFunction).oneString(); + output += "bool " + doUpdateName + " = false;\n"; + output += "for (;;) {"; + // UPDATE + output += "if (" + doUpdateName + ") {"; + output += generate(children[2], enclosingObject, true, enclosingFunction).oneString(); + output += "}\n"; + output += doUpdateName + " = true;\n"; + // CONDITION + // note that the postValue happens whether or not we break + CCodeTriple condition = generate(children[1], enclosingObject, true, enclosingFunction); + output += condition.preValue; + output += "if (!(" + condition.value + ")) {\n"; + output += condition.postValue; + output += "break;\n}"; + output += condition.postValue; + // BODY + output += generate(children[3], enclosingObject, justFuncName, enclosingFunction).oneString(); + output += emitDestructors(reverse(distructDoubleStack.back()),enclosingObject); + output += "}"; + output += "}"; + distructDoubleStack.pop_back(); + loopDistructStackDepth.pop(); + // 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, justFuncName, enclosingFunction).oneString(); + + std::string destructors = emitDestructors(reverse(flatten(distructDoubleStack)),enclosingObject); + if (children.size()) { + CCodeTriple expr = generate(children[0], enclosingObject, true, enclosingFunction); + output.preValue += expr.preValue; + std::string retTemp = "ret_temp" + getID(); + // use the function's return value so we do the right thing with references + output.preValue += ValueTypeToCType(enclosingFunction->getDataRef()->valueType->returnType, retTemp) + ";\n"; + if (enclosingFunction->getDataRef()->valueType->returnType->is_reference) + output.preValue += retTemp + " = &" + expr.value + ";\n"; + else if (methodExists(children[0]->getDataRef()->valueType, "copy_construct", std::vector{children[0]->getDataRef()->valueType->withIncreasedIndirection()})) + output.preValue += generateMethodIfExists(children[0]->getDataRef()->valueType, "copy_construct", "&"+retTemp + ", &" + expr.value, std::vector{children[0]->getDataRef()->valueType->withIncreasedIndirection()}); + else + output.preValue += retTemp + " = " + expr.value + ";\n"; + // move expr post to before return + output.value += expr.postValue; + output.value += destructors; + output.value += "return " + retTemp; + } else { + output.value += destructors; + output += "return"; + } + return output; + } + 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++) @@ -593,7 +601,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc // ok, emit destructors to where the loop ends output += emitDestructors(reverse(flatten(slice(distructDoubleStack,loopDistructStackDepth.top(),-1))),enclosingObject); return output + "break"; - case continue_statement: + 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++) @@ -601,21 +609,21 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc // ok, emit destructors to where the loop ends output += emitDestructors(reverse(flatten(slice(distructDoubleStack,loopDistructStackDepth.top(),-1))),enclosingObject); return output + "continue"; - case defer_statement: + case defer_statement: deferDoubleStack.back().push_back(children[0]); return CCodeTriple("/*defer " + generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString() + "*/"); - case assignment_statement: - return generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString() + " = " + generate(children[1], enclosingObject, true, enclosingFunction); - case declaration_statement: + case assignment_statement: + return generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString() + " = " + generate(children[1], enclosingObject, true, enclosingFunction); + case declaration_statement: // adding declaration to the distructDoubleStack so that we can call their destructors when leaving scope (}, return, break, continue) // but only if we're inside an actual doublestack if ((distructDoubleStack.size())) distructDoubleStack.back().push_back(children[0]); - if (children.size() == 1) - return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString()) + ";"; - else if (children[1]->getChildren().size() && children[1]->getChildren()[0]->getChildren().size() > 1 - && children[1]->getChildren()[0]->getChildren()[1] == children[0]) { + if (children.size() == 1) + return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString()) + ";"; + else if (children[1]->getChildren().size() && children[1]->getChildren()[0]->getChildren().size() > 1 + && children[1]->getChildren()[0]->getChildren()[1] == children[0]) { //That is, if we're a declaration with an init position call (Object a.construct()) //We can tell if our function call (children[1])'s access operation([0])'s lhs ([1]) is the thing we just declared (children[0]) // be sure to end value by passing oneString true @@ -642,13 +650,13 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc return output; } } - case if_comp: + case if_comp: // Lol, this doesn't work because the string gets prefixed now - //if (generate(children[0], enclosingObject, enclosingFunction) == generatorString) - if (children[0]->getDataRef()->symbol.getName() == generatorString) - return generate(children[1], enclosingObject, justFuncName, enclosingFunction); - return CCodeTriple(""); - case simple_passthrough: + //if (generate(children[0], enclosingObject, enclosingFunction) == generatorString) + if (children[0]->getDataRef()->symbol.getName() == generatorString) + return generate(children[1], enclosingObject, justFuncName, enclosingFunction); + return CCodeTriple(""); + case simple_passthrough: { std::string pre_end_dec, end_assign; // Stuff is bit more interesting now! XXX @@ -693,212 +701,212 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc else return strSlice(children.back()->getDataRef()->symbol.getName(), 3, -4); } - case function_call: - { - //NOTE: The first (0th) child of a function call node is the declaration of the function + case function_call: + { + //NOTE: The first (0th) child of a function call node is the declaration of the function - //Handle operators specially for now. Will later replace with - //Inlined functions in the standard library - // std::string name = data.symbol.getName(); - // std::cout << name << " == " << children[0]->getData().symbol.getName() << std::endl; - std::string name = children[0]->getDataRef()->symbol.getName(); - ASTType funcType = children[0]->getDataRef()->type; + //Handle operators specially for now. Will later replace with + //Inlined functions in the standard library + // std::string name = data.symbol.getName(); + // std::cout << name << " == " << children[0]->getData().symbol.getName() << std::endl; + std::string name = children[0]->getDataRef()->symbol.getName(); + ASTType funcType = children[0]->getDataRef()->type; - // UGLLLLYYYY - // But we have these here because some stuff has to be moved out of the giant nested blocks below and this is the way to do it - CCodeTriple functionCallSource; - bool doClosureInstead = false; + // UGLLLLYYYY + // But we have these here because some stuff has to be moved out of the giant nested blocks below and this is the way to do it + CCodeTriple functionCallSource; + bool doClosureInstead = false; - //std::cout << "Doing function: " << name << std::endl; - //Test for special functions only if what we're testing is, indeed, the definition, not a function call that returns a callable function pointer - if (funcType == function) { - if (name == "++" || name == "--") - return generate(children[1], enclosingObject, true, enclosingFunction) + name; - if ( (name == "*" || name == "&" || name == "!" || name == "-" || name == "+" ) && children.size() == 2) //Is dereference, not multiplication, address-of, or other unary operator - return name + "(" + generate(children[1], enclosingObject, true, enclosingFunction) + ")"; - if (name == "[]") - return "(" + generate(children[1], enclosingObject, true, enclosingFunction) + ")[" + generate(children[2],enclosingObject, true, enclosingFunction) + "]"; - if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" - || name == "<" || name == ">" || name == "%" || name == "=" || name == "+=" || name == "-=" || name == "*=" || name == "/=") { - return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + "(" + generate(children[2], enclosingObject, true, enclosingFunction) + "))"; - } else if (name == "&&" || name == "||") { - // b/c short circuiting, these have to be done seperately - CCodeTriple lhs = generate(children[1], enclosingObject, true, enclosingFunction); - CCodeTriple rhs = generate(children[2], enclosingObject, true, enclosingFunction); - output.preValue = lhs.preValue; - std::string shortcircuit_result = "shortcircuit_result" + getID(); - output.preValue += "bool " + shortcircuit_result + " = " + lhs.value + ";\n"; - output.preValue += lhs.postValue; - output.preValue += "if (" + std::string(name == "||" ? "!":"") + shortcircuit_result + ") { \n"; - output.preValue += rhs.preValue; - output.preValue += shortcircuit_result + " = " + rhs.value + ";\n"; - output.preValue += rhs.postValue; - output.preValue += "}\n"; - output.value = shortcircuit_result; - return output; - } else if (name == "." || name == "->") { - if (children.size() == 1) - return "/*dot operation with one child*/" + generate(children[0], enclosingObject, true, enclosingFunction).oneString() + "/*end one child*/"; - //If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method - if (children[2]->getDataRef()->type == function) { - std::string functionName = children[2]->getDataRef()->symbol.getName(); - NodeTree* possibleObjectType = children[1]->getDataRef()->valueType->typeDefinition; - //If is an object method, generate it like one. Needs extension/modification for inheritence - if (possibleObjectType) { - NodeTree* unaliasedTypeDef = getMethodsObjectType(possibleObjectType, functionName); - if (unaliasedTypeDef) { //Test to see if the function's a member of this type_def, or if this is an alias, of the original type. Get this original type if it exists. - std::string nameDecoration; - std::vector*> functionDefChildren = children[2]->getChildren(); //The function def is the rhs of the access operation - //std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl; - for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) - nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); - // Note that we only add scoping to the object, as this specifies our member function too -/*HERE*/ return function_header + prefixIfNeeded(scopePrefix(unaliasedTypeDef), CifyName(unaliasedTypeDef->getDataRef()->symbol.getName())) +"__" + + //std::cout << "Doing function: " << name << std::endl; + //Test for special functions only if what we're testing is, indeed, the definition, not a function call that returns a callable function pointer + if (funcType == function) { + if (name == "++" || name == "--") + return generate(children[1], enclosingObject, true, enclosingFunction) + name; + if ( (name == "*" || name == "&" || name == "!" || name == "-" || name == "+" ) && children.size() == 2) //Is dereference, not multiplication, address-of, or other unary operator + return name + "(" + generate(children[1], enclosingObject, true, enclosingFunction) + ")"; + if (name == "[]") + return "(" + generate(children[1], enclosingObject, true, enclosingFunction) + ")[" + generate(children[2],enclosingObject, true, enclosingFunction) + "]"; + if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" + || name == "<" || name == ">" || name == "%" || name == "=" || name == "+=" || name == "-=" || name == "*=" || name == "/=") { + return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + "(" + generate(children[2], enclosingObject, true, enclosingFunction) + "))"; + } else if (name == "&&" || name == "||") { + // b/c short circuiting, these have to be done seperately + CCodeTriple lhs = generate(children[1], enclosingObject, true, enclosingFunction); + CCodeTriple rhs = generate(children[2], enclosingObject, true, enclosingFunction); + output.preValue = lhs.preValue; + std::string shortcircuit_result = "shortcircuit_result" + getID(); + output.preValue += "bool " + shortcircuit_result + " = " + lhs.value + ";\n"; + output.preValue += lhs.postValue; + output.preValue += "if (" + std::string(name == "||" ? "!":"") + shortcircuit_result + ") { \n"; + output.preValue += rhs.preValue; + output.preValue += shortcircuit_result + " = " + rhs.value + ";\n"; + output.preValue += rhs.postValue; + output.preValue += "}\n"; + output.value = shortcircuit_result; + return output; + } else if (name == "." || name == "->") { + if (children.size() == 1) + return "/*dot operation with one child*/" + generate(children[0], enclosingObject, true, enclosingFunction).oneString() + "/*end one child*/"; + //If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method + if (children[2]->getDataRef()->type == function) { + std::string functionName = children[2]->getDataRef()->symbol.getName(); + NodeTree* possibleObjectType = children[1]->getDataRef()->valueType->typeDefinition; + //If is an object method, generate it like one. Needs extension/modification for inheritence + if (possibleObjectType) { + NodeTree* unaliasedTypeDef = getMethodsObjectType(possibleObjectType, functionName); + if (unaliasedTypeDef) { //Test to see if the function's a member of this type_def, or if this is an alias, of the original type. Get this original type if it exists. + std::string nameDecoration; + std::vector*> functionDefChildren = children[2]->getChildren(); //The function def is the rhs of the access operation + //std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl; + for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) + nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); + // Note that we only add scoping to the object, as this specifies our member function too + /*HERE*/ return function_header + prefixIfNeeded(scopePrefix(unaliasedTypeDef), CifyName(unaliasedTypeDef->getDataRef()->symbol.getName())) +"__" + CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject, true, enclosingFunction) + ","; - //The comma lets the upper function call know we already started the param list - //Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses + //The comma lets the upper function call know we already started the param list + //Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses + } else { + //std::cout << "Is not in scope or not type" << std::endl; + return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + functionName + ")"; + } } else { - //std::cout << "Is not in scope or not type" << std::endl; - return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + functionName + ")"; + //std::cout << "Is not in scope or not type" << std::endl; + return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + functionName + ")"; } } else { - //std::cout << "Is not in scope or not type" << std::endl; - return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + functionName + ")"; - } - } else { - //return "((" + generate(children[1], enclosingObject, enclosingFunction) + ")" + name + generate(children[2], enclosingObject, enclosingFunction) + ")"; - return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + generate(children[2], nullptr, true, enclosingFunction) + ")"; - } - } else { - // this could a closure literal. sigh, I know. - if (children[0]->getDataRef()->closedVariables.size()) { - functionCallSource = generate(children[0], enclosingObject, true, enclosingFunction); - doClosureInstead = true; + //return "((" + generate(children[1], enclosingObject, enclosingFunction) + ")" + name + generate(children[2], enclosingObject, enclosingFunction) + ")"; + return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + generate(children[2], nullptr, true, enclosingFunction) + ")"; + } } else { - //It's a normal function call, not a special one or a method or anything. Name decorate. - std::vector*> functionDefChildren = children[0]->getChildren(); - //std::cout << "Decorating (none-special)" << name << " " << functionDefChildren.size() << std::endl; - std::string nameDecoration; - for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) - nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); - // it is possible that this is an object method from inside a closure - // in which case, recover the enclosing object from this - bool addClosedOver = false; - if (enclosingFunction && enclosingFunction->getDataRef()->closedVariables.size()) { - for (auto closedVar : enclosingFunction->getDataRef()->closedVariables) { - if (closedVar->getDataRef()->symbol.getName() == "this") { - enclosingObject = closedVar->getDataRef()->valueType->typeDefinition; - addClosedOver = true; + // this could a closure literal. sigh, I know. + if (children[0]->getDataRef()->closedVariables.size()) { + functionCallSource = generate(children[0], enclosingObject, true, enclosingFunction); + doClosureInstead = true; + } else { + //It's a normal function call, not a special one or a method or anything. Name decorate. + std::vector*> functionDefChildren = children[0]->getChildren(); + //std::cout << "Decorating (none-special)" << name << " " << functionDefChildren.size() << std::endl; + std::string nameDecoration; + for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) + nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); + // it is possible that this is an object method from inside a closure + // in which case, recover the enclosing object from this + bool addClosedOver = false; + if (enclosingFunction && enclosingFunction->getDataRef()->closedVariables.size()) { + for (auto closedVar : enclosingFunction->getDataRef()->closedVariables) { + if (closedVar->getDataRef()->symbol.getName() == "this") { + enclosingObject = closedVar->getDataRef()->valueType->typeDefinition; + addClosedOver = true; + } } } - } - //Check to see if we're inside of an object and this is a method call - bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]); - if (isSelfObjectMethod) { - output += function_header + prefixIfNeeded(scopePrefix(children[0]), CifyName(enclosingObject->getDataRef()->symbol.getName())) +"__"; - output += CifyName(name + nameDecoration) + "("; - output += std::string(addClosedOver ? "(*closed_variables->this)" : "this") + (children.size() > 1 ? "," : ""); - } else { - output += function_header + prefixIfNeeded(scopePrefix(children[0]), CifyName(name + nameDecoration)) + "("; + //Check to see if we're inside of an object and this is a method call + bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]); + if (isSelfObjectMethod) { + output += function_header + prefixIfNeeded(scopePrefix(children[0]), CifyName(enclosingObject->getDataRef()->symbol.getName())) +"__"; + output += CifyName(name + nameDecoration) + "("; + output += std::string(addClosedOver ? "(*closed_variables->this)" : "this") + (children.size() > 1 ? "," : ""); + } else { + output += function_header + prefixIfNeeded(scopePrefix(children[0]), CifyName(name + nameDecoration)) + "("; + } } } - } - } else { - //This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function) - //It's probabally the result of an access function call (. or ->) to access an object method. - //OR a function value! - // - //THIS IS UUUUUGLLYYY too. We moved the closure part out to after the generation of the params becuase it needs to use them twice - functionCallSource = generate(children[0], enclosingObject, true, enclosingFunction); - if (functionCallSource.value[functionCallSource.value.size()-1] == ',') //If it's a member method, it's already started the parameter list. - output += children.size() > 1 ? functionCallSource : CCodeTriple(functionCallSource.preValue, functionCallSource.value.substr(0, functionCallSource.value.size()-1), functionCallSource.postValue); - else { - doClosureInstead = true; - } - } - CCodeTriple parameters; - // see if we should copy_construct / referencize all the parameters - for (int i = 1; i < children.size(); i++) { //children[0] is the declaration - Type* func_param_type = children[0]->getDataRef()->valueType->parameterTypes[i-1]; - // ok, if our param is a reference returned by another function, we don't actually want this type to be a reference if it is now. - Type *param_type = children[i]->getDataRef()->valueType->withoutReference(); - // don't copy_construct references - if (func_param_type->is_reference) { - parameters += "&" + generate(children[i], enclosingObject, true, enclosingFunction); - } else if (methodExists(children[i]->getDataRef()->valueType, "copy_construct", std::vector{param_type->withIncreasedIndirection()})) { - std::string tmpParamName = "param" + getID(); - CCodeTriple paramValue = generate(children[i], enclosingObject, true, enclosingFunction); - parameters.preValue += paramValue.preValue; - parameters.preValue += ValueTypeToCType(param_type, tmpParamName) + ";\n"; - parameters.preValue += generateMethodIfExists(param_type, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value, std::vector{children[i]->getDataRef()->valueType->withIncreasedIndirection()}); - parameters.value += tmpParamName; - parameters.postValue += paramValue.postValue; } else { - parameters += generate(children[i], enclosingObject, true, enclosingFunction); + //This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function) + //It's probabally the result of an access function call (. or ->) to access an object method. + //OR a function value! + // + //THIS IS UUUUUGLLYYY too. We moved the closure part out to after the generation of the params becuase it needs to use them twice + functionCallSource = generate(children[0], enclosingObject, true, enclosingFunction); + if (functionCallSource.value[functionCallSource.value.size()-1] == ',') //If it's a member method, it's already started the parameter list. + output += children.size() > 1 ? functionCallSource : CCodeTriple(functionCallSource.preValue, functionCallSource.value.substr(0, functionCallSource.value.size()-1), functionCallSource.postValue); + else { + doClosureInstead = true; + } } - if (i < children.size()-1) - parameters += ", "; - } - if (doClosureInstead) { - Type* funcType = children[0]->getDataRef()->valueType; - Type* retType = funcType->returnType; - bool doRet = retType->baseType != void_type || retType->getIndirection(); - std::string tmpName = "functionValueTmp" + getID(); - std::string retTmpName = "closureRetTemp" + getID(); - output += CCodeTriple(parameters.preValue + functionCallSource.preValue + ValueTypeToCType(funcType, tmpName) + " = " + functionCallSource.value + ";\n" - + (doRet ? ValueTypeToCType(retType, retTmpName) + ";\n" : "") - + "if (" + tmpName + ".data) { " + (doRet ? (retTmpName + " =") : "") + " (("+ ValueTypeToCTypeDecoration(funcType,ClosureFunctionPointerTypeWithClosedParam) +") (" + tmpName + ".func))(" + tmpName + ".data" + (children.size() > 1 ? ", " : "") + parameters.value + "); }\n" - + "else { " + (doRet ? (retTmpName + " = ") : "") + " (("+ ValueTypeToCTypeDecoration(funcType,ClosureFunctionPointerTypeWithoutClosedParam) +") (" + tmpName + ".func))(" + parameters.value + "); }\n", - (doRet ? retTmpName : ""), - parameters.postValue + functionCallSource.postValue); - } else { - output += parameters + ") "; - } - // see if we should add a destructer call to this postValue - Type* retType = children[0]->getDataRef()->valueType->returnType; - if (retType->baseType != void_type) { - // we always use return temps now :( (for psudo-pod objects that still have methods called on them, like range(1,3).for_each(...) - std::string retTempName = "return_temp" + getID(); - output.preValue += ValueTypeToCType(retType, retTempName) + " = " + output.value + ";\n"; - output.value = retTempName; - if (retType->is_reference) - output.value = "(*" + output.value + ")"; - else if (methodExists(retType, "destruct", std::vector())) { - output.postValue = generateMethodIfExists(retType, "destruct", "&"+retTempName, std::vector()) + ";\n" + output.postValue; + CCodeTriple parameters; + // see if we should copy_construct / referencize all the parameters + for (int i = 1; i < children.size(); i++) { //children[0] is the declaration + Type* func_param_type = children[0]->getDataRef()->valueType->parameterTypes[i-1]; + // ok, if our param is a reference returned by another function, we don't actually want this type to be a reference if it is now. + Type *param_type = children[i]->getDataRef()->valueType->withoutReference(); + // don't copy_construct references + if (func_param_type->is_reference) { + parameters += "&" + generate(children[i], enclosingObject, true, enclosingFunction); + } else if (methodExists(children[i]->getDataRef()->valueType, "copy_construct", std::vector{param_type->withIncreasedIndirection()})) { + std::string tmpParamName = "param" + getID(); + CCodeTriple paramValue = generate(children[i], enclosingObject, true, enclosingFunction); + parameters.preValue += paramValue.preValue; + parameters.preValue += ValueTypeToCType(param_type, tmpParamName) + ";\n"; + parameters.preValue += generateMethodIfExists(param_type, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value, std::vector{children[i]->getDataRef()->valueType->withIncreasedIndirection()}); + parameters.value += tmpParamName; + parameters.postValue += paramValue.postValue; + } else { + parameters += generate(children[i], enclosingObject, true, enclosingFunction); + } + if (i < children.size()-1) + parameters += ", "; } + if (doClosureInstead) { + Type* funcType = children[0]->getDataRef()->valueType; + Type* retType = funcType->returnType; + bool doRet = retType->baseType != void_type || retType->getIndirection(); + std::string tmpName = "functionValueTmp" + getID(); + std::string retTmpName = "closureRetTemp" + getID(); + output += CCodeTriple(parameters.preValue + functionCallSource.preValue + ValueTypeToCType(funcType, tmpName) + " = " + functionCallSource.value + ";\n" + + (doRet ? ValueTypeToCType(retType, retTmpName) + ";\n" : "") + + "if (" + tmpName + ".data) { " + (doRet ? (retTmpName + " =") : "") + " (("+ ValueTypeToCTypeDecoration(funcType,ClosureFunctionPointerTypeWithClosedParam) +") (" + tmpName + ".func))(" + tmpName + ".data" + (children.size() > 1 ? ", " : "") + parameters.value + "); }\n" + + "else { " + (doRet ? (retTmpName + " = ") : "") + " (("+ ValueTypeToCTypeDecoration(funcType,ClosureFunctionPointerTypeWithoutClosedParam) +") (" + tmpName + ".func))(" + parameters.value + "); }\n", + (doRet ? retTmpName : ""), + parameters.postValue + functionCallSource.postValue); + } else { + output += parameters + ") "; + } + // see if we should add a destructer call to this postValue + Type* retType = children[0]->getDataRef()->valueType->returnType; + if (retType->baseType != void_type) { + // we always use return temps now :( (for psudo-pod objects that still have methods called on them, like range(1,3).for_each(...) + std::string retTempName = "return_temp" + getID(); + output.preValue += ValueTypeToCType(retType, retTempName) + " = " + output.value + ";\n"; + output.value = retTempName; + if (retType->is_reference) + output.value = "(*" + output.value + ")"; + else if (methodExists(retType, "destruct", std::vector())) { + output.postValue = generateMethodIfExists(retType, "destruct", "&"+retTempName, std::vector()) + ";\n" + output.postValue; + } + } + return output; } - return output; - } - case value: - { - // ok, we now check for it being a multiline string and escape all returns if it is (so that multiline strings work) - //if (data.symbol.getName()[0] == '"') { - if (data.symbol.getName()[0] == '"' && strSlice(data.symbol.getName(), 0, 3) == "\"\"\"") { - //bool multiline_str = strSlice(data.symbol.getName(), 0, 3) == "\"\"\""; - //std::string innerString = multiline_str - //? strSlice(data.symbol.getName(), 3, -4) - //: strSlice(data.symbol.getName(), 1, -2); - std::string innerString = strSlice(data.symbol.getName(), 3, -4); - std::string newStr; - for (auto character: innerString) - if (character == '\n') - newStr += "\\n"; - else if (character == '"') - newStr += "\\\""; - else - newStr += character; - return "\"" + newStr + "\""; + case value: + { + // ok, we now check for it being a multiline string and escape all returns if it is (so that multiline strings work) + //if (data.symbol.getName()[0] == '"') { + if (data.symbol.getName()[0] == '"' && strSlice(data.symbol.getName(), 0, 3) == "\"\"\"") { + //bool multiline_str = strSlice(data.symbol.getName(), 0, 3) == "\"\"\""; + //std::string innerString = multiline_str + //? strSlice(data.symbol.getName(), 3, -4) + //: strSlice(data.symbol.getName(), 1, -2); + std::string innerString = strSlice(data.symbol.getName(), 3, -4); + std::string newStr; + for (auto character: innerString) + if (character == '\n') + newStr += "\\n"; + else if (character == '"') + newStr += "\\\""; + else + newStr += character; + return "\"" + newStr + "\""; + } + return data.symbol.getName(); } - return data.symbol.getName(); - } - default: - std::cout << "Nothing!" << std::endl; - } - for (int i = 0; i < children.size(); i++) - output += generate(children[i], enclosingObject, justFuncName, enclosingFunction).oneString(); + default: + std::cout << "Nothing!" << std::endl; + } + for (int i = 0; i < children.size(); i++) + output += generate(children[i], enclosingObject, justFuncName, enclosingFunction).oneString(); - return output; + return output; } NodeTree* CGenerator::getMethodsObjectType(NodeTree* scope, std::string functionName) { //check the thing @@ -911,24 +919,24 @@ NodeTree* CGenerator::getMethodsObjectType(NodeTree* scope, st std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, NodeTree* from, std::string *functionPrototype) { distructDoubleStack.push_back(std::vector*>()); - ASTData data = from->getData(); - Type enclosingObjectType = *(enclosingObject->getDataRef()->valueType); //Copy a new type so we can turn it into a pointer if we need to - enclosingObjectType.increaseIndirection(); - std::vector*> children = from->getChildren(); - std::string nameDecoration, parameters; + ASTData data = from->getData(); + Type enclosingObjectType = *(enclosingObject->getDataRef()->valueType); //Copy a new type so we can turn it into a pointer if we need to + enclosingObjectType.increaseIndirection(); + std::vector*> children = from->getChildren(); + std::string nameDecoration, parameters; if (!children.size()) { //problem std::cerr << " no children " << std::endl; } - for (int i = 0; i < children.size()-1; i++) { - parameters += ", " + ValueTypeToCType(children[i]->getData().valueType, generate(children[i]).oneString()); - nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType); + for (int i = 0; i < children.size()-1; i++) { + parameters += ", " + ValueTypeToCType(children[i]->getData().valueType, generate(children[i]).oneString()); + nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType); distructDoubleStack.back().push_back(children[i]); - } + } std::string functionSignature = "\n" + ValueTypeToCType(data.valueType->returnType, function_header + prefixIfNeeded(scopePrefix(from), CifyName(enclosingObject->getDataRef()->symbol.getName())) + "__" + - CifyName(data.symbol.getName()) + nameDecoration) + "(" + ValueTypeToCType(&enclosingObjectType, "this") + parameters + ")"; + CifyName(data.symbol.getName()) + nameDecoration) + "(" + ValueTypeToCType(&enclosingObjectType, "this") + parameters + ")"; *functionPrototype += functionSignature + ";\n"; // Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock // @@ -1015,16 +1023,16 @@ std::string CGenerator::closureStructType(std::set*> closedVar std::string CGenerator::ValueTypeToCType(Type *type, std::string declaration, ClosureTypeSpecialType closureSpecial) { return ValueTypeToCTypeThingHelper(type, " " + declaration, closureSpecial); } std::string CGenerator::ValueTypeToCTypeDecoration(Type *type, ClosureTypeSpecialType closureSpecial) { return CifyName(ValueTypeToCTypeThingHelper(type, "", closureSpecial)); } std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string declaration, ClosureTypeSpecialType closureSpecial) { - std::string return_type; + std::string return_type; bool do_ending = true; - switch (type->baseType) { - case none: - if (type->typeDefinition) - return_type = prefixIfNeeded(scopePrefix(type->typeDefinition), CifyName(type->typeDefinition->getDataRef()->symbol.getName())); - else - return_type = "none"; - break; - case function_type: + switch (type->baseType) { + case none: + if (type->typeDefinition) + return_type = prefixIfNeeded(scopePrefix(type->typeDefinition), CifyName(type->typeDefinition->getDataRef()->symbol.getName())); + else + return_type = "none"; + break; + case function_type: { std::string indr_str; for (int i = 0; i < type->getIndirection(); i++) @@ -1080,90 +1088,90 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl } do_ending = false; } - break; - case void_type: - return_type = "void"; - break; - case boolean: - return_type = "bool"; - break; - case integer: - return_type = "int"; - break; - case floating: - return_type = "float"; - break; - case double_percision: - return_type = "double"; - break; - case character: - return_type = "char"; - break; - default: - return_type = "unknown_ValueType"; - break; - } + break; + case void_type: + return_type = "void"; + break; + case boolean: + return_type = "bool"; + break; + case integer: + return_type = "int"; + break; + case floating: + return_type = "float"; + break; + case double_percision: + return_type = "double"; + break; + case character: + return_type = "char"; + break; + default: + return_type = "unknown_ValueType"; + break; + } if (!do_ending) return return_type; - for (int i = 0; i < type->getIndirection(); i++) - return_type += "*"; + for (int i = 0; i < type->getIndirection(); i++) + return_type += "*"; if (type->is_reference) - return_type += " /*ref*/ *"; + return_type += " /*ref*/ *"; return return_type + declaration; } std::string CGenerator::CifyName(std::string name) { - std::string operatorsToReplace[] = { "+", "plus", - "-", "minus", - "*", "star", - "/", "div", - "%", "mod", - "^", "carat", - "&", "amprsd", - "|", "pipe", - "~", "tilde", - "!", "exlmtnpt", - ",", "comma", - "=", "eq", - "++", "dbplus", - "--", "dbminus", - "<<", "dbleft", - ">>", "dbright", - "::", "scopeop", - ":", "colon", - "==", "dbq", - "!=", "notequals", - "&&", "doubleamprsnd", - "||", "doublepipe", - "+=", "plusequals", - "-=", "minusequals", - "/=", "divequals", - "%=", "modequals", - "^=", "caratequals", - "&=", "amprsdequals", - "|=", "pipeequals", - "*=", "starequals", - "<<=", "doublerightequals", - "<", "lt", - ">", "gt", - ">>=", "doubleleftequals", - "(", "openparen", - ")", "closeparen", - "[", "obk", - "]", "cbk", - " ", "space", - ".", "dot", - "->", "arrow" }; - int length = sizeof(operatorsToReplace)/sizeof(std::string); - //std::cout << "Length is " << length << std::endl; - for (int i = 0; i < length; i+= 2) { - size_t foundPos = name.find(operatorsToReplace[i]); - while(foundPos != std::string::npos) { - name = strSlice(name, 0, foundPos) + "_" + operatorsToReplace[i+1] + "_" + strSlice(name, foundPos+operatorsToReplace[i].length(), -1); - foundPos = name.find(operatorsToReplace[i]); - } - } - return name; + std::string operatorsToReplace[] = { "+", "plus", + "-", "minus", + "*", "star", + "/", "div", + "%", "mod", + "^", "carat", + "&", "amprsd", + "|", "pipe", + "~", "tilde", + "!", "exlmtnpt", + ",", "comma", + "=", "eq", + "++", "dbplus", + "--", "dbminus", + "<<", "dbleft", + ">>", "dbright", + "::", "scopeop", + ":", "colon", + "==", "dbq", + "!=", "notequals", + "&&", "doubleamprsnd", + "||", "doublepipe", + "+=", "plusequals", + "-=", "minusequals", + "/=", "divequals", + "%=", "modequals", + "^=", "caratequals", + "&=", "amprsdequals", + "|=", "pipeequals", + "*=", "starequals", + "<<=", "doublerightequals", + "<", "lt", + ">", "gt", + ">>=", "doubleleftequals", + "(", "openparen", + ")", "closeparen", + "[", "obk", + "]", "cbk", + " ", "space", + ".", "dot", + "->", "arrow" }; + int length = sizeof(operatorsToReplace)/sizeof(std::string); + //std::cout << "Length is " << length << std::endl; + for (int i = 0; i < length; i+= 2) { + size_t foundPos = name.find(operatorsToReplace[i]); + while(foundPos != std::string::npos) { + name = strSlice(name, 0, foundPos) + "_" + operatorsToReplace[i+1] + "_" + strSlice(name, foundPos+operatorsToReplace[i].length(), -1); + foundPos = name.find(operatorsToReplace[i]); + } + } + return name; } // Generate the scope prefix, that is "file_class_" for a method, etc // What do we still need to handle? Packages! But we don't have thoes yet.... diff --git a/src/Type.cpp b/src/Type.cpp index 3da76a6..a9d3029 100644 --- a/src/Type.cpp +++ b/src/Type.cpp @@ -199,7 +199,7 @@ std::string Type::toString(bool showTraits) { if (is_reference) typeString = "ref " + typeString; for (int i = 0; i < indirection; i++) - typeString = "*" + typeString; + typeString += "*"; if (indirection < 0) typeString += "negative indirection: " + intToString(indirection); if (traits.size() && showTraits) { @@ -240,6 +240,11 @@ Type Type::withIncreasedIndirection() { newOne->increaseIndirection(); return *newOne; } +Type *Type::withIncreasedIndirectionPtr() { + Type *newOne = clone(); + newOne->increaseIndirection(); + return newOne; +} Type Type::withDecreasedIndirection() { Type *newOne = clone(); newOne->decreaseIndirection(); diff --git a/tests/test_adt.krak b/tests/test_adt.krak index 9846883..b82a570 100644 --- a/tests/test_adt.krak +++ b/tests/test_adt.krak @@ -1,4 +1,4 @@ -import io:* +/*import io:**/ adt options { option0, @@ -11,12 +11,13 @@ adt maybe_int { } fun handle_possibility(it: maybe_int) { - if (it == maybe_int::no_int()) - println("no int") + if (it == maybe_int::no_int()) { + /*println("no int")*/ + } /*if (it == maybe_int::an_int) {*/ else { - print("an int: ") - println(it.an_int) + /*print("an int: ")*/ + /*println(it.an_int)*/ } } @@ -32,10 +33,12 @@ fun can_pass(it: options): options { fun main():int { var it: options = can_pass(options::option0()) - if (it == options::option0()) - println("nope") - if (it == options::option1()) - println("option1") + if (it == options::option0()) { + /*println("nope")*/ + } + if (it == options::option1()) { + /*println("option1")*/ + } var possibility = give_maybe(false) handle_possibility(possibility) From ed4ed754495832e0df909e5da0e0327eec967f74 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Fri, 13 Nov 2015 15:49:00 -0500 Subject: [PATCH 3/5] ADT equality for basic types should work --- src/ASTTransformation.cpp | 316 +++++++++++++++++++------------------- src/CGenerator.cpp | 50 ++++-- tests/test_adt.krak | 21 ++- 3 files changed, 215 insertions(+), 172 deletions(-) diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index e666be6..3718315 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -104,7 +104,7 @@ NodeTree* ASTTransformation::firstPass(std::string fileName, NodeTreeaddChild(adt_dec); adt_dec->getDataRef()->valueType = new Type(adt_dec); } else if (i->getDataRef()->getName() == "if_comp") { - std::cout << "IF COMP" << std::endl; + //std::cout << "IF COMP" << std::endl; NodeTree* newNode = addToScope("~enclosing_scope", translationUnit, new NodeTree(i->getDataRef()->getName(), ASTData(if_comp))); newNode->addChild(addToScope("~enclosing_scope", newNode, new NodeTree("identifier", ASTData(identifier, Symbol(concatSymbolTree(i->getChildren()[0]),true))))); std::set skipChildren; @@ -201,11 +201,15 @@ void ASTTransformation::secondPass(NodeTree* ast, NodeTree* par // Let's make an equality function prototype Type *thisADTType = adtDef->getDataRef()->valueType; NodeTree* equalityFunc = new NodeTree("function", ASTData(function, Symbol("operator==", true), new Type(std::vector{thisADTType}, new Type(boolean)))); - //NodeTree* equalityFunc = new NodeTree("function", ASTData(function, Symbol("operator==", true), new Type(std::vector{thisADTType, thisADTType}, new Type(boolean)))); adtDef->addChild(equalityFunc); addToScope("operator==", equalityFunc, adtDef); addToScope("~enclosing_scope", adtDef, equalityFunc); + NodeTree* inequalityFunc = new NodeTree("function", ASTData(function, Symbol("operator!=", true), new Type(std::vector{thisADTType}, new Type(boolean)))); + adtDef->addChild(inequalityFunc); + addToScope("operator!=", inequalityFunc, adtDef); + addToScope("~enclosing_scope", adtDef, inequalityFunc); + for (NodeTree* j : getNodes("adt_option", i)) { std::string ident_name = concatSymbolTree(getNode("identifier", j)); std::cout << "add ing " << ident_name << " to " << name << " for ADT" << std::endl; @@ -282,7 +286,7 @@ NodeTree* ASTTransformation::secondPassFunction(NodeTree* from, else //has traits yetToBeInstantiatedTemplateTypes[concatSymbolTree(i->getChildren()[0])] = new Type(template_type_type, parseTraits(i->getChildren()[1])); //This may have to be combined with templateTypeReplacements if we do templated member functions inside of templated classes } - std::cout << "Finished Non-Instantiated Template function " << functionName << std::endl; + //std::cout << "Finished Non-Instantiated Template function " << functionName << std::endl; return functionDef; } functionName = concatSymbolTree(children[0]); @@ -356,13 +360,13 @@ bool ASTTransformation::fourthPass(NodeTree* ast, NodeTree* par if (i.second[0]->getDataRef()->type == type_def && i.second[0]->getDataRef()->valueType->templateTypeReplacement.size() && !i.second[0]->getDataRef()->valueType->templateInstantiated) { classTemplates.push_back(i.second[0]); - std::cout << "Saving " << i.second[0]->getDataRef()->toString() << " to instantiate." << std::endl; + //std::cout << "Saving " << i.second[0]->getDataRef()->toString() << " to instantiate." << std::endl; changed = true; } } for (auto i : classTemplates) { Type* classTemplateType = i->getDataRef()->valueType; - std::cout << "Instantiating template " << i->getDataRef()->toString() << std::endl; + //std::cout << "Instantiating template " << i->getDataRef()->toString() << std::endl; for (NodeTree* j : classTemplateType->templateDefinition->getChildren()) if (j->getDataRef()->getName() == "function" && j->getChildren()[1]->getDataRef()->getName() != "template_dec") thirdPassFunction(j, searchScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method @@ -378,16 +382,16 @@ NodeTree* ASTTransformation::searchScopeForFunctionDef(NodeTree types; std::vector*> children = parseTree->getChildren(); //Skipping the initial return type and identifier as well as the final code block - std::cout << "\n Searching scope for function def, function is: " << concatSymbolTree(children[0]) << ", children size is " << children.size() << std::endl; + //std::cout << "\n Searching scope for function def, function is: " << concatSymbolTree(children[0]) << ", children size is " << children.size() << std::endl; for (auto param: getNodes("typed_parameter", children)) { //Skip over commas - std::cout << "Making type for lookup ||" << concatSymbolTree(param) << "||" << std::endl; + //std::cout << "Making type for lookup ||" << concatSymbolTree(param) << "||" << std::endl; Type type = *typeFromTypeNode(param->getChildren().back(), scope, templateTypeReplacements); - std::cout << "Type made: " << type.toString() << std::endl; + //std::cout << "Type made: " << type.toString() << std::endl; types.push_back(type); } - std::cout << "About to search scope about " << concatSymbolTree(children[0]) << std::endl; + //std::cout << "About to search scope about " << concatSymbolTree(children[0]) << std::endl; NodeTree* result = functionLookup(scope, functionName, types); - std::cout << "Done searching scope about " << concatSymbolTree(children[0]) << std::endl; + //std::cout << "Done searching scope about " << concatSymbolTree(children[0]) << std::endl; return result; } @@ -414,12 +418,12 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree if (name == "identifier" || name == "scoped_identifier") { //Make sure we get the entire name std::string lookupName = concatSymbolTree(from); - std::cout << "Looking up: " << lookupName << std::endl; + //std::cout << "Looking up: " << lookupName << std::endl; if (limitToFunction) { newNode = functionLookup(scope, lookupName, types); if (newNode == NULL) { - std::cout << "scope lookup failed! Could not find " << lookupName << " in identifier (functionLookup)" << std::endl; - std::cout << "(maybe this is supposted to happen because the function is a template and we're infrencing), or this is a operator() call" << std::endl; + std::cout << "scope lookup failed! Could not find " << lookupName << " in identifier (functionLookup)" << std::endl; + std::cout << "(maybe this is supposted to happen because the function is a template and we're infrencing), or this is a operator() call" << std::endl; // Ok, now we try the case where the lookupName is an object, and we'll try to look for operator() // in its scope for (auto possibleObj : scopeLookup(scope, lookupName)) { @@ -468,7 +472,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree } else if (name == "type_def") { //If it is an alisis of a type std::string typeAlias; - std::cout << "The scope here at type_def is " << scope->getDataRef()->toString() << std::endl; + //std::cout << "The scope here at type_def is " << scope->getDataRef()->toString() << std::endl; if (children[1]->getData().getName() == "type") { typeAlias = concatSymbolTree(children[0]); newNode = scope->getDataRef()->scope[typeAlias][0]; //The node for this type_def has already been made by translation_unit. @@ -481,7 +485,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree Type* objectType = NULL; if (children[1]->getData().getName() == "template_dec") { typeAlias = concatSymbolTree(children[0]); - std::cout << "Template Type!"<getDataRef()->scope[typeAlias][0]; //The node for this type_def has already been made by translation_unit. //This is done so that types that reference each other can be declared in any order // std::cout << "typeAlias is " << typeAlias << " and newNode is " << newNode << std::endl; @@ -521,13 +525,13 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree yetToBeInstantiatedTemplateTypes[concatSymbolTree(i)] = new Type(template_type_type); //This may have to be combined with templateTypeReplacements if we do templated member functions inside of templated classes auto transChildren = transformChildren(slice(children,3,-2), std::set(), newNode, types, limitToFunction, yetToBeInstantiatedTemplateTypes); - std::cout << "Template function " << functionName << " has these parameters: "; - for (auto i : transChildren) - std::cout << "||" << i->getDataRef()->toString() << "|| "; - std::cout << "??||" << std::endl; + //std::cout << "Template function " << functionName << " has these parameters: "; + //for (auto i : transChildren) + //std::cout << "||" << i->getDataRef()->toString() << "|| "; + //std::cout << "??||" << std::endl; newNode->addChildren(transChildren); - std::cout << "Finished Non-Instantiated Template function " << functionName << std::endl; + //std::cout << "Finished Non-Instantiated Template function " << functionName << std::endl; return newNode; } if (name == "lambda") @@ -552,9 +556,9 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree if (name == "lambda") newNode->getDataRef()->closedVariables = findVariablesToClose(newNode, statement, scope); for (auto i : newNode->getDataRef()->closedVariables) - std::cout << "OK, CLOSED: " << i->getDataRef()->toString() << std::endl; + //std::cout << "OK, CLOSED: " << i->getDataRef()->toString() << std::endl; newNode->addChild(statement); - std::cout << "finished function" << functionName << std::endl; + //std::cout << "finished function" << functionName << std::endl; return newNode; } else if (name == "code_block") { @@ -564,12 +568,12 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree } else if (name == "typed_parameter") { //newNode = transform(children[1]); //Transform to get the identifier std::string parameterName = concatSymbolTree(children[0]); - std::cout << "Doing typed parameter " << parameterName << std::endl; + //std::cout << "Doing typed parameter " << parameterName << std::endl; //std::string typeString = concatSymbolTree(children[0]);//Get the type (left child) and set our new identifer to be that type newNode = new NodeTree("identifier", ASTData(identifier, Symbol(parameterName, true), typeFromTypeNode(children[2], scope, templateTypeReplacements))); addToScope(parameterName, newNode, scope); addToScope("~enclosing_scope", scope, newNode); - std::cout << "Done doing typed_parameter " << parameterName << std::endl; + //std::cout << "Done doing typed_parameter " << parameterName << std::endl; return newNode; } else if (name == "boolean_expression" || name == "and_boolean_expression" || name == "bool_exp") { //If this is an actual part of an expression, not just a premoted term @@ -597,7 +601,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree NodeTree* lhs = transform(children[0], scope, std::vector(),false, templateTypeReplacements); //LHS does not inherit types, or limittofunction NodeTree* rhs; if (name == "access_operation") { - std::cout << "lhs is: " << lhs->getDataRef()->toString() << std::endl; + //std::cout << "lhs is: " << lhs->getDataRef()->toString() << std::endl; rhs = transform(children[2], lhs->getDataRef()->valueType->typeDefinition, types, limitToFunction, templateTypeReplacements); //If an access operation, then the right side will be in the lhs's type's scope // this might be a template member function, so do like below would do, but make it our rhs if (rhs == nullptr) @@ -640,11 +644,11 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree else funcName = concatSymbolTree(children[1]), param = transform(children[0], scope, types, limitToFunction, templateTypeReplacements); - std::cout << "\t\t\t funcName= " << funcName << " param: " << param->getDataRef()->symbol.getName() << std::endl; + //std::cout << "\t\t\t funcName= " << funcName << " param: " << param->getDataRef()->symbol.getName() << std::endl; //std::cout << "scope lookup from factor" << std::endl; std::vector*> transformedChildren; transformedChildren.push_back(param); NodeTree* function = doFunction(scope, funcName, transformedChildren, templateTypeReplacements); - std::cout << "\t\t\t AFTER dofunction= " << std::endl; + //std::cout << "\t\t\t AFTER dofunction= " << std::endl; if (function == NULL) { std::cerr << "scope lookup error! Could not find " << funcName << " in factor " << std::endl; throw "LOOKUP ERROR: " + funcName; @@ -718,10 +722,10 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree NodeTree* typeSyntaxNode = getNode("type", children); Type* identifierType = typeSyntaxNode ? typeFromTypeNode(typeSyntaxNode, scope, templateTypeReplacements) : nullptr; - if (identifierType) - std::cout << "Declaring an identifier " << newIdentifierStr << " to be of type " << identifierType->toString() << std::endl; - else - std::cout << "Declaring an identifier " << newIdentifierStr << " with type to be type-inferenced " << std::endl; + //if (identifierType) + //std::cout << "Declaring an identifier " << newIdentifierStr << " to be of type " << identifierType->toString() << std::endl; + //else + //std::cout << "Declaring an identifier " << newIdentifierStr << " with type to be type-inferenced " << std::endl; if (children.size() > 1 && concatSymbolTree(children[1]) == ".") { NodeTree* newIdentifier = new NodeTree("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), identifierType)); @@ -801,15 +805,15 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree skipChildren.insert(0); std::vector*> transformedChildren = transformChildren(children, skipChildren, scope, types, limitToFunction, templateTypeReplacements); - std::cout << "scope lookup from function_call: " << functionCallName << std::endl; - for (auto i : children) - std::cout << i << " : " << i->getName() << " : " << i->getDataRef()->getName() << std::endl; + //std::cout << "scope lookup from function_call: " << functionCallName << std::endl; + //for (auto i : children) + //std::cout << i << " : " << i->getName() << " : " << i->getDataRef()->getName() << std::endl; NodeTree* function = transform(children[0], scope, mapNodesToTypes(transformedChildren), true, templateTypeReplacements); - std::cout << "The thing: " << function << " : " << function->getName() << std::endl; - for (auto i : function->getChildren()) - std::cout << i->getName() << " "; - std::cout << std::endl; + //std::cout << "The thing: " << function << " : " << function->getName() << std::endl; + //for (auto i : function->getChildren()) + //std::cout << i->getName() << " "; + //std::cout << std::endl; newNode->addChild(function); // note that we now get the return type from the function call's type newNode->getDataRef()->valueType = function->getDataRef()->valueType->returnType; @@ -895,11 +899,11 @@ NodeTree* ASTTransformation::doFunction(NodeTree* scope, std:: auto LLElementIterator = languageLevelOperators.find(lookup); NodeTree* newNode; if (LLElementIterator != languageLevelOperators.end()) { - std::cout << "Checking for early method level operator overload" << std::endl; + //std::cout << "Checking for early method level operator overload" << std::endl; std::string lookupOp = "operator" + lookup; - for (auto i : nodes) - std::cout << i->getDataRef()->toString() << " "; - std::cout << std::endl; + //for (auto i : nodes) + //std::cout << i->getDataRef()->toString() << " "; + //std::cout << std::endl; NodeTree* operatorMethod = NULL; // make sure this isn't a pointer, also. Silly vector bug @@ -911,7 +915,7 @@ NodeTree* ASTTransformation::doFunction(NodeTree* scope, std:: } if (operatorMethod) { //Ok, so we construct - std::cout << "Early method level operator was found" << std::endl; + //std::cout << "Early method level operator was found" << std::endl; //return operatorMethod; NodeTree* newNode = new NodeTree(lookupOp, ASTData(function_call, Symbol(lookupOp, true))); NodeTree* dotFunctionCall = new NodeTree(".", ASTData(function_call, Symbol(".", true), operatorMethod->getDataRef()->valueType)); @@ -926,32 +930,32 @@ NodeTree* ASTTransformation::doFunction(NodeTree* scope, std:: newNode->getDataRef()->valueType = operatorMethod->getDataRef()->valueType->returnType; return newNode; } - std::cout << "Early method level operator was NOT found" << std::endl; + //std::cout << "Early method level operator was NOT found" << std::endl; if (lookup == "[]=") { - std::cout << "as the operator was []= we're returning nullptr now and gonna let our above handle it as seperate ones" << std::endl; + //std::cout << "as the operator was []= we're returning nullptr now and gonna let our above handle it as seperate ones" << std::endl; return nullptr; } } newNode = new NodeTree(lookup, ASTData(function_call, Symbol(lookup, true))); NodeTree* function = functionLookup(scope, lookup, mapNodesToTypes(nodes)); - std::cout << "Num of newNode children " << newNode->getChildren().size() << std::endl; + //std::cout << "Num of newNode children " << newNode->getChildren().size() << std::endl; newNode->addChild(function); - std::cout << "Num of newNode children " << newNode->getChildren().size() << std::endl; + //std::cout << "Num of newNode children " << newNode->getChildren().size() << std::endl; newNode->addChildren(nodes); - std::cout << "Num of newNode children " << newNode->getChildren().size() << std::endl; - std::cout << "nodes " << nodes.size() << std::endl; + //std::cout << "Num of newNode children " << newNode->getChildren().size() << std::endl; + //std::cout << "nodes " << nodes.size() << std::endl; //Specially handle dereference and address of to assign the correct type //We need some significant other type corrections here, maybe to the point of being their own function. (int + float, etc.) - std::cout << "the passed in nodes" << std::endl; - for (auto i : nodes) - std::cout << i->getDataRef()->toString() << " "; - std::cout<getDataRef()->toString() << " "; + //std::cout< oldTypes = mapNodesToTypes(nodes); - std::cout << "the oldtypes size" << oldTypes.size() << std::endl; + //std::cout << "the oldtypes size" << oldTypes.size() << std::endl; if ((nodes.size() != 2 && lookup == "*") || lookup == "&" || lookup == "[]") { Type* newType = oldTypes[0].clone(); if (lookup == "*" || lookup == "[]") @@ -959,9 +963,9 @@ NodeTree* ASTTransformation::doFunction(NodeTree* scope, std:: else newType->increaseIndirection(); - newNode->getDataRef()->valueType = newType, std::cout << "Operator " + lookup << " is altering indirection from " << oldTypes[0].toString() << " to " << newType->toString() << std::endl; + newNode->getDataRef()->valueType = newType; //, std::cout << "Operator " + lookup << " is altering indirection from " << oldTypes[0].toString() << " to " << newType->toString() << std::endl; } else { - std::cout << "Some other ||" << lookup << "||" << std::endl; + //std::cout << "Some other ||" << lookup << "||" << std::endl; if (function->getDataRef()->valueType) newNode->getDataRef()->valueType = function->getDataRef()->valueType->returnType; } @@ -970,7 +974,7 @@ NodeTree* ASTTransformation::doFunction(NodeTree* scope, std:: // It's important that it's the last parameter, the rhs if it has one // because of the . operator, etc if (newNode->getDataRef()->valueType == NULL) { - std::cout << "The value type from doFunction was null! (for " << lookup << ")" << std::endl; + //std::cout << "The value type from doFunction was null! (for " << lookup << ")" << std::endl; Type* newType = nullptr; if (lookup == "->") newType = oldTypes.back().clone(); @@ -984,7 +988,7 @@ NodeTree* ASTTransformation::doFunction(NodeTree* scope, std:: //newType = oldTypes.back().clone(); newNode->getDataRef()->valueType = newType; - std::cout << "function call to " << lookup << " - " << newNode->getName() << " is now " << newNode->getDataRef()->valueType << std::endl; + //std::cout << "function call to " << lookup << " - " << newNode->getName() << " is now " << newNode->getDataRef()->valueType << std::endl; } return newNode; } @@ -1049,7 +1053,7 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* scope, s //We first check to see if it's one of the special reserved identifiers (only this, for now) and return early if it is. auto LLElementIterator = languageLevelReservedWords.find(lookup); if (LLElementIterator != languageLevelReservedWords.end()) { - std::cout << "found it at language level as reserved word." << std::endl; + //std::cout << "found it at language level as reserved word." << std::endl; return LLElementIterator->second[0]; } //We search the languageLevelOperators to see if it's an operator. If so, we modifiy the lookup with a preceding "operator" @@ -1071,14 +1075,14 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* scope, s int numTypes = functionType->parameterTypes.size(); if (types.size() != numTypes) { - std::cout << "Type sizes do not match between two " << lookup << "(" << types.size() << "," << numTypes << "), types are: "; - for (auto j : types) - std::cout << j.toString() << " "; - std::cout << std::endl; - std::cout << "Versus" << std::endl; - for (int j = 0; j < numTypes; j++) - std::cout << functionType->parameterTypes[j]->toString() << " "; - std::cout << std::endl; + //std::cout << "Type sizes do not match between two " << lookup << "(" << types.size() << "," << numTypes << "), types are: "; + //for (auto j : types) + //std::cout << j.toString() << " "; + //std::cout << std::endl; + //std::cout << "Versus" << std::endl; + //for (int j = 0; j < numTypes; j++) + //std::cout << functionType->parameterTypes[j]->toString() << " "; + //std::cout << std::endl; continue; } bool typesMatch = true; @@ -1092,8 +1096,8 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* scope, s // we use test_equality so that we can pass in a false to not care about references if (!types[j].test_equality(*tmpType, false)) { typesMatch = false; - std::cout << "Types do not match between two " << lookup << " " << types[j].toString(); - std::cout << " vs " << tmpType->toString() << std::endl; + //std::cout << "Types do not match between two " << lookup << " " << types[j].toString(); + //std::cout << " vs " << tmpType->toString() << std::endl; break; } } @@ -1102,11 +1106,11 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* scope, s } } - std::cout << "could not find " << lookup << " in standard scopes, checking for operator" << std::endl; + //std::cout << "could not find " << lookup << " in standard scopes, checking for operator" << std::endl; //Note that we don't check for types. At some point we should, as we don't know how to add objects/structs without overloaded operators, etc //Also, we've already searched for the element because this is also how we keep track of operator overloading if (LLElementIterator != languageLevelOperators.end()) { - std::cout << "found it at language level as operator." << std::endl; + //std::cout << "found it at language level as operator." << std::endl; return LLElementIterator->second[0]; } std::cout << "Did not find, returning NULL" << std::endl; @@ -1118,7 +1122,7 @@ NodeTree* ASTTransformation::templateClassLookup(NodeTree* sco std::set*> mostFittingTemplates; int bestNumTraitsSatisfied = -1; auto possibleMatches = scopeLookup(scope, lookup); - std::cout << "Template Class instantiation has " << possibleMatches.size() << " possible matches." << std::endl; + //std::cout << "Template Class instantiation has " << possibleMatches.size() << " possible matches." << std::endl; for (auto i : possibleMatches) { if (i->getDataRef()->type != type_def) continue; @@ -1136,20 +1140,20 @@ NodeTree* ASTTransformation::templateClassLookup(NodeTree* sco // error out if not subset, or if we're a pointer but should have traits if (!subset(j.second, templateInstantiationTypes[typeIndex]->traits) || (templateInstantiationTypes[typeIndex]->getIndirection() && j.second.size())) { traitsEqual = false; - std::cout << "Traits not subset for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": "; + //std::cout << "Traits not subset for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": "; //std::cout << baseType << " " << indirection << " " << typeDefinition << " " << templateDefinition << " " << traits << ; - std::copy(j.second.begin(), j.second.end(), std::ostream_iterator(std::cout, " ")); - std::cout << " vs "; - std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; + //std::copy(j.second.begin(), j.second.end(), std::ostream_iterator(std::cout, " ")); + //std::cout << " vs "; + //std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator(std::cout, " ")); + //std::cout << std::endl; break; } else { - std::cout << "Traits ARE subset for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": "; + //std::cout << "Traits ARE subset for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": "; //std::cout << baseType << " " << indirection << " " << typeDefinition << " " << templateDefinition << " " << traits << ; - std::copy(j.second.begin(), j.second.end(), std::ostream_iterator(std::cout, " ")); - std::cout << " vs "; - std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; + //std::copy(j.second.begin(), j.second.end(), std::ostream_iterator(std::cout, " ")); + //std::cout << " vs "; + //std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator(std::cout, " ")); + //std::cout << std::endl; } currentTraitsSatisfied += j.second.size(); typeIndex++; @@ -1160,12 +1164,12 @@ NodeTree* ASTTransformation::templateClassLookup(NodeTree* sco //See if this is a better match than the current best if (currentTraitsSatisfied > bestNumTraitsSatisfied) { mostFittingTemplates.clear(); - std::cout << "Class satisfying " << currentTraitsSatisfied << " beats previous " << bestNumTraitsSatisfied << std::endl; + //std::cout << "Class satisfying " << currentTraitsSatisfied << " beats previous " << bestNumTraitsSatisfied << std::endl; bestNumTraitsSatisfied = currentTraitsSatisfied; } else if (currentTraitsSatisfied < bestNumTraitsSatisfied) continue; mostFittingTemplates.insert(i); - std::cout << "Current class fits, satisfying " << currentTraitsSatisfied << " traits" << std::endl; + //std::cout << "Current class fits, satisfying " << currentTraitsSatisfied << " traits" << std::endl; } if (!mostFittingTemplates.size()) { std::cout << "No template classes fit for " << lookup << "!" << std::endl; @@ -1253,8 +1257,8 @@ void ASTTransformation::unifyType(NodeTree *syntaxType, Type type, std:: std::vector*> uninTypeInstTypes = getNodes("type", getNode("template_inst", children)); std::vector*> typeInstTypes = getNodes("template_param", getNode("template_dec", typeTemplateDefinition->getChildren())); for (int i = 0; i < uninTypeInstTypes.size(); i++) { - std::cout << concatSymbolTree(uninTypeInstTypes[i]) << " : " << origionalType->toString() << " : " << concatSymbolTree(typeInstTypes[i]) << std::endl; - std::cout << "which is " << origionalType->templateTypeReplacement[concatSymbolTree(typeInstTypes[i])]->toString() << std::endl; + //std::cout << concatSymbolTree(uninTypeInstTypes[i]) << " : " << origionalType->toString() << " : " << concatSymbolTree(typeInstTypes[i]) << std::endl; + //std::cout << "which is " << origionalType->templateTypeReplacement[concatSymbolTree(typeInstTypes[i])]->toString() << std::endl; //std::cout << "which is " << *origionalType->templateTypeReplacement[concatSymbolTree(typeInstTypes[i])] << std::endl; unifyType(uninTypeInstTypes[i], *origionalType->templateTypeReplacement[concatSymbolTree(typeInstTypes[i])], templateTypeMap, typeMap); } @@ -1291,10 +1295,10 @@ NodeTree* ASTTransformation::templateFunctionLookup(NodeTree* for (auto i : possibleMatches) { if (i->getDataRef()->type != function) continue; - std::cout << "Possibility " << index++ << std::endl; + //std::cout << "Possibility " << index++ << std::endl; NodeTree* templateSyntaxTree = i->getDataRef()->valueType->templateDefinition; if (!templateSyntaxTree) { - std::cout << "Not a template, skipping" << std::endl; + //std::cout << "Not a template, skipping" << std::endl; continue; } // We have the type map here because we might want to augment it with the typeMap from @@ -1303,15 +1307,15 @@ NodeTree* ASTTransformation::templateFunctionLookup(NodeTree* // If template instantiation was explicit, use those types. Otherwise, unify to find them if (templateInstantiationTypes->size()) { templateInstantiationTypesPerFunction[i] = *templateInstantiationTypes; - std::cout << "passed in types" << std::endl; + //std::cout << "passed in types" << std::endl; }else{ unifyTemplateFunction(i, types, &templateInstantiationTypesPerFunction[i], typeMap); - std::cout << "unified types" << std::endl; + //std::cout << "unified types" << std::endl; } - std::cout << "TYPES ARE: "; - for (Type *a : templateInstantiationTypesPerFunction[i]) - std::cout << a->toString() << " : "; - std::cout << std::endl; + //std::cout << "TYPES ARE: "; + //for (Type *a : templateInstantiationTypesPerFunction[i]) + //std::cout << a->toString() << " : "; + //std::cout << std::endl; auto nameTraitsPairs = makeTemplateNameTraitPairs(templateSyntaxTree->getChildren()[1]); //Check if sizes match between the placeholder and actual template types if (nameTraitsPairs.size() != templateInstantiationTypesPerFunction[i].size()) @@ -1324,18 +1328,18 @@ NodeTree* ASTTransformation::templateFunctionLookup(NodeTree* // error out if not subset, or if we're a pointer but should have traits if (!subset(j.second, templateInstantiationTypesPerFunction[i][typeIndex]->traits) || (templateInstantiationTypesPerFunction[i][typeIndex]->getIndirection() && j.second.size())) { traitsEqual = false; - std::cout << "Traits not a subset for " << j.first << " and " << templateInstantiationTypesPerFunction[i][typeIndex]->toString() << ": |"; - std::copy(j.second.begin(), j.second.end(), std::ostream_iterator(std::cout, " ")); - std::cout << "| vs |"; - std::copy(templateInstantiationTypesPerFunction[i][typeIndex]->traits.begin(), templateInstantiationTypesPerFunction[i][typeIndex]->traits.end(), std::ostream_iterator(std::cout, " ")); - std::cout << "|" << std::endl; + //std::cout << "Traits not a subset for " << j.first << " and " << templateInstantiationTypesPerFunction[i][typeIndex]->toString() << ": |"; + //std::copy(j.second.begin(), j.second.end(), std::ostream_iterator(std::cout, " ")); + //std::cout << "| vs |"; + //std::copy(templateInstantiationTypesPerFunction[i][typeIndex]->traits.begin(), templateInstantiationTypesPerFunction[i][typeIndex]->traits.end(), std::ostream_iterator(std::cout, " ")); + //std::cout << "|" << std::endl; break; } else { - std::cout << "Traits ARE a subset for " << j.first << " and " << templateInstantiationTypesPerFunction[i][typeIndex]->toString() << ": "; - std::copy(j.second.begin(), j.second.end(), std::ostream_iterator(std::cout, " ")); - std::cout << " vs "; - std::copy(templateInstantiationTypesPerFunction[i][typeIndex]->traits.begin(), templateInstantiationTypesPerFunction[i][typeIndex]->traits.end(), std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; + //std::cout << "Traits ARE a subset for " << j.first << " and " << templateInstantiationTypesPerFunction[i][typeIndex]->toString() << ": "; + //std::copy(j.second.begin(), j.second.end(), std::ostream_iterator(std::cout, " ")); + //std::cout << " vs "; + //std::copy(templateInstantiationTypesPerFunction[i][typeIndex]->traits.begin(), templateInstantiationTypesPerFunction[i][typeIndex]->traits.end(), std::ostream_iterator(std::cout, " ")); + //std::cout << std::endl; } //As we go, build up the typeMap for when we transform the parameters for parameter checking typeMap[j.first] = templateInstantiationTypesPerFunction[i][typeIndex]; @@ -1354,11 +1358,11 @@ NodeTree* ASTTransformation::templateFunctionLookup(NodeTree* bool parameterTypesMatch = true; for (int j = 0; j < functionParameters.size(); j++) { auto paramType = typeFromTypeNode(functionParameters[j]->getChildren()[2], scope, typeMap); - std::cout << "Template param type: " << paramType->toString() << " : Needed Type: " << types[j].toString() << std::endl; + //std::cout << "Template param type: " << paramType->toString() << " : Needed Type: " << types[j].toString() << std::endl; // use test_equality so we can pass false and not care about references if (!paramType->test_equality(types[j], false)) { parameterTypesMatch = false; - std::cout << "Not equal template param: " << paramType->toString() << " : Needed Type actual param: " << types[j].toString() << std::endl; + //std::cout << "Not equal template param: " << paramType->toString() << " : Needed Type actual param: " << types[j].toString() << std::endl; break; } } @@ -1367,12 +1371,12 @@ NodeTree* ASTTransformation::templateFunctionLookup(NodeTree* //See if this is a better match than the current best if (currentTraitsSatisfied > bestNumTraitsSatisfied) { mostFittingTemplates.clear(); - std::cout << "Function satisfying " << currentTraitsSatisfied << " beats previous " << bestNumTraitsSatisfied << std::endl; + //std::cout << "Function satisfying " << currentTraitsSatisfied << " beats previous " << bestNumTraitsSatisfied << std::endl; bestNumTraitsSatisfied = currentTraitsSatisfied; } else if (currentTraitsSatisfied < bestNumTraitsSatisfied) continue; mostFittingTemplates.insert(i); - std::cout << "Current function fits, satisfying " << currentTraitsSatisfied << " traits" << std::endl; + //std::cout << "Current function fits, satisfying " << currentTraitsSatisfied << " traits" << std::endl; } if (!mostFittingTemplates.size()) { std::cout << "No template functions fit for " << lookup << "("; @@ -1415,7 +1419,7 @@ std::map ASTTransformation::makeTemplateFunctionTypeMap(Node std::cout << typePairs.size() << " " << types.size() << std::endl; for (auto i : typePairs) { typeMap[i.first] = types[typeIndex]; - std::cout << "Mapping " << i.first << " to " << types[typeIndex]->toString() << std::endl; + //std::cout << "Mapping " << i.first << " to " << types[typeIndex]->toString() << std::endl; typeIndex++; } return typeMap; @@ -1443,8 +1447,8 @@ std::vector*> ASTTransformation::scopeLookup(NodeTree } std::vector*> ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup, bool includeModules, std::set*> visited) { - std::cout << "Scp]|[e looking up " << lookup << std::endl; - std::cout << "current: " << scope->getDataRef()->toString() << std::endl; + //std::cout << "Scp]|[e looking up " << lookup << std::endl; + //std::cout << "current: " << scope->getDataRef()->toString() << std::endl; //for (auto i : scope->getDataRef()->scope) //std::cout << "\t" << i.first << std::endl; //std::cout << i.first << " : " << i.second->toString() << std::endl; @@ -1455,7 +1459,7 @@ std::vector*> ASTTransformation::scopeLookup(NodeTree //We first check to see if it's one of the special reserved identifiers (only this, for now) and return early if it is. auto LLElementIterator = languageLevelReservedWords.find(lookup); if (LLElementIterator != languageLevelReservedWords.end()) { - std::cout << "found it at language level as reserved word." << std::endl; + //std::cout << "found it at language level as reserved word." << std::endl; NodeTree* identifier = LLElementIterator->second[0]; if (lookup == "this") { identifier = generateThis(scope); @@ -1469,9 +1473,9 @@ std::vector*> ASTTransformation::scopeLookup(NodeTree size_t scopeOpPos = lookup.find("::"); size_t angleBrktPos = lookup.find("<"); if (scopeOpPos != std::string::npos && (angleBrktPos == std::string::npos || scopeOpPos < angleBrktPos)) { - std::cout << "Has :: operator, doing left then right" << std::endl; + //std::cout << "Has :: operator, doing left then right" << std::endl; for (auto scopeMatch : scopeLookup(scope, strSlice(lookup, 0, scopeOpPos), true)) { - std::cout << "Trying right side with found left side " << scopeMatch->getDataRef()->toString() << std::endl; + //std::cout << "Trying right side with found left side " << scopeMatch->getDataRef()->toString() << std::endl; auto addMatches = scopeLookup(scopeMatch, strSlice(lookup, scopeOpPos+2, -1), includeModules); matches.insert(matches.end(), addMatches.begin(), addMatches.end()); } @@ -1484,7 +1488,7 @@ std::vector*> ASTTransformation::scopeLookup(NodeTree for (auto i : possibleMatches->second) if (includeModules || i->getName() != "translation_unit") matches.push_back(i); - std::cout << "Found " << possibleMatches->second.size() << " match(s) at " << scope->getDataRef()->toString() << std::endl; + //std::cout << "Found " << possibleMatches->second.size() << " match(s) at " << scope->getDataRef()->toString() << std::endl; } // Add results from our enclosing scope, if it exists. // If it doesn't we should be at the top of a translation unit, and we should check the scope of import statements. @@ -1583,24 +1587,24 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreeclone(); templateTypeReplacement->modifyIndirection(indirection); templateTypeReplacement->is_reference = is_reference; return templateTypeReplacement; } - std::cout << edited << " was not found in templateTypeReplacements" << std::endl; - std::cout << "templateTypeReplacements consists of : "; - for (auto i : templateTypeReplacements) - std::cout << i.first << " "; - std::cout << std::endl; + //std::cout << edited << " was not found in templateTypeReplacements" << std::endl; + //std::cout << "templateTypeReplacements consists of : "; + //for (auto i : templateTypeReplacements) + //std::cout << i.first << " "; + //std::cout << std::endl; - std::cout << possibleMatches.size() << " " << typeNode->getChildren().size() << std::endl; - if (typeNode->getChildren().size() > 1) - std::cout << typeNode->getChildren()[1]->getDataRef()->getName() << std::endl; + //std::cout << possibleMatches.size() << " " << typeNode->getChildren().size() << std::endl; + //if (typeNode->getChildren().size() > 1) + //std::cout << typeNode->getChildren()[1]->getDataRef()->getName() << std::endl; //If not, we better instantiate it and then add it to the highest (not current) scope - if (possibleMatches.size() == 0 && typeNode->getChildren().size() > 1 && typeNode->getChildren()[1]->getData().getName() == "template_inst") { - std::cout << "Template type: " << edited << " not yet instantiated" << std::endl; + if (possibleMatches.size() == 0 && typeNode->getChildren().size() > 1 && typeNode->getChildren()[1]->getData().getName() == "template_inst") { + //std::cout << "Template type: " << edited << " not yet instantiated" << std::endl; //We pull out the replacement types first so that we can choose the correct possibly overloaded template std::vector*> templateParamInstantiationNodes = slice(typeNode->getChildren()[1]->getChildren(), 1, -2, 2); //same @@ -1630,9 +1634,9 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreegetDataRef()->valueType->traits; - std::cout << "Found already instantiated template of " << templateLookupName << " at second check" << std::endl; + //std::cout << "Found already instantiated template of " << templateLookupName << " at second check" << std::endl; } else { - std::cout << "Did not find already instantiated template of " << templateLookupName << " at second check" << std::endl; + //std::cout << "Did not find already instantiated template of " << templateLookupName << " at second check" << std::endl; //Look up this template's plain definition. It's type has the syntax tree that we need to parse NodeTree* templateDefinition = templateClassLookup(scope, concatSymbolTree(typeNode->getChildren()[0]), templateParamInstantiationTypes); @@ -1658,9 +1662,9 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreegetDataRef()->toString() << std::endl; + //std::cout << "UPPER TRANS for " << fullyInstantiatedName << " " << templateTopScope->getDataRef()->toString() << std::endl; templateTopScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition); templateTopScope->addChild(typeDefinition); // Add this object the the highest scope's @@ -1679,22 +1683,22 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreetemplateDefinition = templateSyntaxTree; //We're going to still need this when we finish instantiating selfType->templateTypeReplacement = newTemplateTypeReplacement; //Save the types for use when this is fully instantiated in pass 4 - for (auto daPair : selfType->templateTypeReplacement) { - std::cout << " BREAK HERE " << daPair.first << " : " << daPair.second->toString() << std::endl; - if (daPair.second == NULL) - std::cout << " BREAK HERE " << std::endl; - } + //for (auto daPair : selfType->templateTypeReplacement) { + //std::cout << " BREAK HERE " << daPair.first << " : " << daPair.second->toString() << std::endl; + //if (daPair.second == NULL) + //std::cout << " BREAK HERE " << std::endl; + //} secondPassDoClassInsides(typeDefinition, templateSyntaxTree->getChildren(), newTemplateTypeReplacement); //Use these types when instantiating data members } } else if (possibleMatches.size() == 0) { - std::cout << "Could not find type " << edited << ", returning NULL" << std::endl; + std::cout << "Could not find type " << edited << ", returning NULL" << std::endl; return NULL; } else { - std::cout << "Type: " << edited << " already instantiated with " << typeDefinition << ", will be " << Type(baseType, typeDefinition, indirection, is_reference, traits).toString() << std::endl; + //std::cout << "Type: " << edited << " already instantiated with " << typeDefinition << ", will be " << Type(baseType, typeDefinition, indirection, is_reference, traits).toString() << std::endl; } } Type* toReturn = new Type(baseType, typeDefinition, indirection, is_reference, traits); - std::cout << "Returning type " << toReturn->toString() << std::endl; + //std::cout << "Returning type " << toReturn->toString() << std::endl; return toReturn; } @@ -1715,7 +1719,7 @@ NodeTree* ASTTransformation::findOrInstantiateFunctionTemplate(std::str } NodeTree* ASTTransformation::findOrInstantiateFunctionTemplate(std::string functionName, std::vector*> children, NodeTree* scope, std::vector types, std::map templateTypeReplacements) { //First look to see if we can find this already instantiated - std::cout << "\n\nFinding or instantiating templated function\n\n" << std::endl; + //std::cout << "\n\nFinding or instantiating templated function\n\n" << std::endl; if (children.size()) functionName = concatSymbolTree(children[0]); std::string fullyInstantiatedName; @@ -1752,27 +1756,27 @@ NodeTree* ASTTransformation::findOrInstantiateFunctionTemplate(std::str instTypeString += (instTypeString == "" ? instType->toString() : "," + instType->toString()); templateActualTypes.push_back(instType); } - std::cout << "Size: " << templateParamInstantiationNodes.size() << std::endl; + //std::cout << "Size: " << templateParamInstantiationNodes.size() << std::endl; } fullyInstantiatedName = functionName + "<" + instTypeString + ">"; - std::cout << "Looking for " << fullyInstantiatedName << std::endl; - std::cout << "Types are : "; - for (auto i : types) - std::cout << " " << i.toString(); - std::cout << std::endl; + //std::cout << "Looking for " << fullyInstantiatedName << std::endl; + //std::cout << "Types are : "; + //for (auto i : types) + //std::cout << " " << i.toString(); + //std::cout << std::endl; NodeTree* instantiatedFunction = functionLookup(scope, fullyInstantiatedName, types); //If it already exists, return it if (instantiatedFunction) { - std::cout << fullyInstantiatedName << " already exists! Returning" << std::endl; + //std::cout << fullyInstantiatedName << " already exists! Returning" << std::endl; return instantiatedFunction; } else { instantiatedFunction = functionLookup(topScope, fullyInstantiatedName, types); if (instantiatedFunction) { - std::cout << fullyInstantiatedName << "already exists! Found in TopScope" << std::endl; + //std::cout << fullyInstantiatedName << "already exists! Found in TopScope" << std::endl; return instantiatedFunction; } - std::cout << fullyInstantiatedName << " does NOT exist" << std::endl; + //std::cout << fullyInstantiatedName << " does NOT exist" << std::endl; } //Otherwise, we're going to instantiate it @@ -1783,7 +1787,7 @@ NodeTree* ASTTransformation::findOrInstantiateFunctionTemplate(std::str if (!templateDefinition) templateDefinition = templateFunctionLookup(scope, functionName, &templateActualTypes, types, scopeTypeMap); if (templateDefinition == NULL) { - std::cout << functionName << " search turned up null, returing null" << std::endl; + //std::cout << functionName << " search turned up null, returing null" << std::endl; return NULL; } scopelessFullyInstantiatedName = templateDefinition->getDataRef()->symbol.getName() + "<" + instTypeString + ">"; @@ -1793,9 +1797,9 @@ NodeTree* ASTTransformation::findOrInstantiateFunctionTemplate(std::str std::map newTemplateTypeReplacement = makeTemplateFunctionTypeMap(templateSyntaxTree->getChildren()[1], templateActualTypes, scopeTypeMap); std::vector*> templateChildren = templateSyntaxTree->getChildren(); - for (int i = 0; i < templateChildren.size(); i++) - std::cout << ", " << i << " : " << templateChildren[i]->getDataRef()->getName(); - std::cout << std::endl; + //for (int i = 0; i < templateChildren.size(); i++) + //std::cout << ", " << i << " : " << templateChildren[i]->getDataRef()->getName(); + //std::cout << std::endl; // return type should be looked up in template's scope auto returnTypeNode = getNode("type", getNode("typed_return", templateChildren)); // if null, the typed_return had no children and we're supposed to automatically do a void type @@ -1805,7 +1809,7 @@ NodeTree* ASTTransformation::findOrInstantiateFunctionTemplate(std::str addToScope(scopelessFullyInstantiatedName, instantiatedFunction, templateDefinition->getDataRef()->scope["~enclosing_scope"][0]); templateDefinition->getDataRef()->scope["~enclosing_scope"][0]->addChild(instantiatedFunction); // Add this object the the highest scope's - std::cout << "About to do children of " << functionName << " to " << fullyInstantiatedName << std::endl; + //std::cout << "About to do children of " << functionName << " to " << fullyInstantiatedName << std::endl; std::set skipChildren; auto parameters = transformChildren(getNodes("typed_parameter", templateSyntaxTree->getChildren()), skipChildren, instantiatedFunction, std::vector(), false, newTemplateTypeReplacement); @@ -1814,7 +1818,7 @@ NodeTree* ASTTransformation::findOrInstantiateFunctionTemplate(std::str instantiatedFunction->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), instantiatedFunction->getDataRef()->valueType); instantiatedFunction->addChild(transform(getNode("statement", templateSyntaxTree->getChildren()), instantiatedFunction, std::vector(), false, newTemplateTypeReplacement)); - std::cout << "Fully Instantiated function " << functionName << " to " << fullyInstantiatedName << std::endl; + //std::cout << "Fully Instantiated function " << functionName << " to " << fullyInstantiatedName << std::endl; return instantiatedFunction; } @@ -1828,7 +1832,7 @@ NodeTree* ASTTransformation::addToScope(std::string name, NodeTree mapNodesToTypePointers(std::vector*> nodes) { std::vector types; for (auto i : nodes) { - std::cout << i->getDataRef()->toString() << std::endl; + //std::cout << i->getDataRef()->toString() << std::endl; types.push_back((i->getDataRef()->valueType)); } return types; @@ -1838,7 +1842,7 @@ std::vector mapNodesToTypePointers(std::vector*> nodes) std::vector mapNodesToTypes(std::vector*> nodes) { std::vector types; for (auto i : nodes) { - std::cout << i->getDataRef()->toString() << std::endl; + //std::cout << i->getDataRef()->toString() << std::endl; types.push_back(*(i->getDataRef()->valueType)); } return types; diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index a86af5c..75fc8eb 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -63,7 +63,8 @@ std::string CGenerator::generateTypeStruct(NodeTree* from) { structString = "struct __struct_dummy_"; structString += prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())+"__") + " {\n"; if (data.type == adt_def) { - structString = "typedef " + structString + "enum " + enumName + " flag;\n union { \n"; + structString = "typedef " + structString + " enum " + enumName + " flag;\n union { \n"; + tabLevel++; } tabLevel++; @@ -81,23 +82,52 @@ std::string CGenerator::generateTypeStruct(NodeTree* from) { enumString += tabs() + generate(child, nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n"); } else { if (data.type == adt_def) { - std::string fun_name = child->getDataRef()->symbol.getName(); + std::string orig_fun_name = child->getDataRef()->symbol.getName(); + std::string fun_name; std::string first_param; - if (fun_name == "operator==") { - fun_name = "fun_" + data.symbol.getName() + "__" + CifyName(fun_name); + if (orig_fun_name == "operator==" || orig_fun_name == "operator!=") { + fun_name = "fun_" + data.symbol.getName() + "__" + CifyName(orig_fun_name); first_param = ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0]->withIncreasedIndirectionPtr(), "this") + ", "; } else { - fun_name = "fun_" + fun_name; + fun_name = "fun_" + orig_fun_name; } + bool has_param = child->getDataRef()->valueType->parameterTypes.size(); functionString += "\n" + ValueTypeToCType(child->getDataRef()->valueType->returnType, fun_name) + "(" + first_param + - (child->getDataRef()->valueType->parameterTypes.size() ? ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0], "in") : "") + "); /*adt func*/\n"; + (has_param ? ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0], "in") : "") + ") { /*adt func*/\n"; + if (orig_fun_name == "operator==") { + functionString += " /* equality woop woop */\n"; + functionString += " if (this->flag != in.flag) return false;\n"; + + for (auto child : children) { + if (child->getName() != "function" && child->getDataRef()->valueType->typeDefinition != from) { + std::string option_name = child->getDataRef()->symbol.getName(); + functionString += " if (this->flag == " + option_name + ")\n"; + functionString += " return this->" + option_name + " == in." + option_name + ";\n"; + } + } + + functionString += " return true;\n"; + } else if (orig_fun_name == "operator!=") { + functionString += " /* inequality woop woop */\n"; + functionString += " return !fun_" + data.symbol.getName() + "__" + CifyName("operator==") + "(this, in);\n"; + } else { + // ok, is a constructor function + functionString += " /* constructor woop woop */\n"; + functionString += " " + data.symbol.getName() + " toRet;\n"; + functionString += " toRet.flag = " + orig_fun_name + ";\n"; + if (has_param) + functionString += " toRet." + orig_fun_name + " = in;\n"; + functionString += " return toRet;\n"; + } + functionString += "}\n"; } } } tabLevel--; if (data.type == adt_def) { //structString += "} data; /*end union*/ \n"; - structString += "}; /*end union*/\n } " + CifyName(data.symbol.getName()) + "; /* end struct */"; + tabLevel--; + structString += " }; /*end union*/\n} " + CifyName(data.symbol.getName()) + "; /* end struct */"; } else { structString += "};"; } @@ -268,7 +298,7 @@ std::pair CGenerator::generateTranslationUnit(std::str function_header + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName() + nameDecoration)); functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType->returnType, funName) + "(" + parameters + "); /*func*/\n"; // generate function - std::cout << "Generating " << prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) << std::endl; + //std::cout << "Generating " << prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) << std::endl; functionDefinitions += generate(declaration, nullptr).oneString(); } } @@ -294,7 +324,7 @@ std::pair CGenerator::generateTranslationUnit(std::str // We use a seperate string for this because we only include it if this is the file we're defined in std::string objectFunctionDefinitions = "/* Method Definitions for " + declarationData.symbol.getName() + " */\n"; for (int j = 0; j < decChildren.size(); j++) { - std::cout << decChildren[j]->getName() << std::endl; + //std::cout << decChildren[j]->getName() << std::endl; if (decChildren[j]->getName() == "function" && decChildren[j]->getDataRef()->valueType->baseType != template_type) //If object method and not template objectFunctionDefinitions += generateObjectMethod(declaration, decChildren[j], &functionPrototypes) + "\n"; @@ -361,7 +391,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc // first, get declaring function, if it exists if (enclosingFunction) { if (enclosingFunction->getDataRef()->closedVariables.size()) { - std::cout << "WHOH IS A CLOSER" << std::endl; + //std::cout << "WHOH IS A CLOSER" << std::endl; if (enclosingFunction->getDataRef()->closedVariables.find(from) != enclosingFunction->getDataRef()->closedVariables.end()) { preName += "(*closed_variables->"; postName += ")"; diff --git a/tests/test_adt.krak b/tests/test_adt.krak index b82a570..f07a450 100644 --- a/tests/test_adt.krak +++ b/tests/test_adt.krak @@ -1,4 +1,4 @@ -/*import io:**/ +import io:* adt options { option0, @@ -12,12 +12,12 @@ adt maybe_int { fun handle_possibility(it: maybe_int) { if (it == maybe_int::no_int()) { - /*println("no int")*/ + println("no int") } /*if (it == maybe_int::an_int) {*/ else { - /*print("an int: ")*/ - /*println(it.an_int)*/ + print("an int: ") + println(it.an_int) } } @@ -34,16 +34,25 @@ fun can_pass(it: options): options { fun main():int { var it: options = can_pass(options::option0()) if (it == options::option0()) { - /*println("nope")*/ + println("nope") } if (it == options::option1()) { - /*println("option1")*/ + println("option1") } var possibility = give_maybe(false) handle_possibility(possibility) possibility = give_maybe(true) handle_possibility(possibility) + if ( maybe_int::an_int(7) == maybe_int::an_int(7) ) + println("equality true works!") + else + println("equality true fails!") + + if ( maybe_int::an_int(7) != maybe_int::an_int(8) ) + println("equality false works!") + else + println("equality false fails!") return 0 } From e7a49bf2e5c49dd2e846c1334097babb028451c7 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sat, 14 Nov 2015 19:05:28 -0500 Subject: [PATCH 4/5] Match statements work with ADTs! (still no object stuff or anything though) --- include/ASTData.h | 6 +++--- krakenGrammer.kgm | 6 +++++- src/ASTTransformation.cpp | 24 ++++++++++++++++++++++++ src/CGenerator.cpp | 29 +++++++++++++++++++++++++++++ src/Importer.cpp | 3 ++- tests/test_adt.krak | 15 +++++++++++++++ 6 files changed, 78 insertions(+), 5 deletions(-) diff --git a/include/ASTData.h b/include/ASTData.h index 12bf354..ac3a328 100644 --- a/include/ASTData.h +++ b/include/ASTData.h @@ -16,9 +16,9 @@ class Type; enum ASTType {undef, translation_unit, interpreter_directive, import, identifier, type_def, adt_def, function, code_block, typed_parameter, expression, boolean_expression, statement, - if_statement, while_loop, for_loop, return_statement, break_statement, continue_statement, defer_statement, - assignment_statement, declaration_statement, if_comp, simple_passthrough, passthrough_params, - in_passthrough_params, out_passthrough_params, opt_string, param_assign, function_call, value}; + if_statement, match_statement, case_statement, while_loop, for_loop, return_statement, break_statement, + continue_statement, defer_statement, assignment_statement, declaration_statement, if_comp, simple_passthrough, + passthrough_params, in_passthrough_params, out_passthrough_params, opt_string, param_assign, function_call, value}; class ASTData { public: diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 122ae4c..ad918cc 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -95,6 +95,10 @@ adt_option = identifier | identifier WS dec_type ; if_statement = "if" WS "\(" WS boolean_expression WS "\)" WS statement | "if" WS "\(" WS boolean_expression WS "\)" WS statement WS "else" WS statement ; +match_statement = "match" WS "\(" WS boolean_expression WS "\)" WS "{" WS case_statement_list WS "}" ; +case_statement_list = case_statement WS case_statement_list | case_statement ; +case_statement = scoped_identifier WS "\(" WS identifier WS "\)" WS statement | scoped_identifier WS "\(" WS "\)" WS statement ; + while_loop = "while" WS boolean_expression WS statement ; for_loop = "for" WS "\(" WS statement WS boolean_expression line_end WS statement WS "\)" WS statement ; @@ -104,7 +108,7 @@ return_statement = "return" | "return" WS boolean_expression ; code_block = "{" WS statement_list WS "}" | "{" WS "}" ; statement_list = statement_list WS statement | statement ; -statement = if_statement | while_loop | for_loop | return_statement line_end | boolean_expression line_end | assignment_statement line_end | declaration_statement line_end | code_block | if_comp | simple_passthrough | break_statement | continue_statement | defer_statement ; +statement = if_statement | match_statement | while_loop | for_loop | return_statement line_end | boolean_expression line_end | assignment_statement line_end | declaration_statement line_end | code_block | if_comp | simple_passthrough | break_statement | continue_statement | defer_statement ; break_statement = "break" ; continue_statement = "continue" ; defer_statement = "defer" WS statement ; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 3718315..a3e22d7 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -662,6 +662,30 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode = new NodeTree(name, ASTData(statement)); } else if (name == "if_statement") { newNode = new NodeTree(name, ASTData(if_statement)); + } else if (name == "match_statement") { + newNode = new NodeTree(name, ASTData(match_statement)); + } else if (name == "case_statement") { + newNode = new NodeTree(name, ASTData(case_statement)); + std::string adtOptionStr = concatSymbolTree(getNodes("scoped_identifier", children)[0]); + auto optionDefPoss = scopeLookup(scope, adtOptionStr); + auto optionDef = optionDefPoss[0]; + //auto adtDef = optionDef->getDataRef()->scope["~enclosing_scope"][0]; + + addToScope("~enclosing_scope", scope, newNode); + newNode->addChild(optionDef); + + // we have a destructure + auto newIdentifierSymbolNodes = getNodes("identifier", children); + if (newIdentifierSymbolNodes.size()) { + std::string newIdentifierStr = concatSymbolTree(newIdentifierSymbolNodes[0]); + NodeTree* newIdentifier = new NodeTree("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), optionDef->getDataRef()->valueType)); + addToScope(newIdentifierStr, newIdentifier, newNode); + addToScope("~enclosing_scope", newNode, newIdentifier); + newNode->addChild(newIdentifier); + } + + newNode->addChild(transform(getNode("statement",children), newNode, types, limitToFunction, templateTypeReplacements)); + return newNode; } else if (name == "while_loop") { newNode = new NodeTree(name, ASTData(while_loop)); } else if (name == "for_loop") { diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 75fc8eb..2d34410 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -526,6 +526,35 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc if (children.size() > 2) output += " else { " + generate(children[2], enclosingObject, justFuncName, enclosingFunction).oneString() + " }"; return output; + case match_statement: + { + output += "/* match_statement */\n"; + CCodeTriple thingToMatch = generate(children[0], enclosingObject, false, enclosingFunction); + output.preValue += thingToMatch.preValue; + output.postValue += thingToMatch.postValue; + for (auto case_stmt : slice(children, 1, -1)) { + auto case_children = case_stmt->getChildren(); + std::string option = generate(case_children[0], enclosingObject, false, enclosingFunction).oneString(); + output += "/* case " + option + " if " + thingToMatch.value + " */\n"; + output += tabs() + "if (" + thingToMatch.value + ".flag == " + option + ") {\n"; + tabLevel++; + if (case_children.size() > 2) { + output += tabs() + ValueTypeToCType(case_children[1]->getData().valueType, generate(case_children[1], enclosingObject, false, enclosingFunction).oneString()) + + " = " + thingToMatch.value + "." + option + ";\n"; + output += generate(case_children[2], enclosingObject, false, enclosingFunction).oneString(); + } else { + output += generate(case_children[1], enclosingObject, false, enclosingFunction).oneString(); + } + tabLevel--; + output += "}\n"; + } + return output; + } + break; + case case_statement: + output += "/* case_statement */"; + throw "case statement isn't actually used, but is generated in match"; + break; case while_loop: { // we push on a new vector to hold while stuff that might need a destructor call diff --git a/src/Importer.cpp b/src/Importer.cpp index 34af861..5ddf49a 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -45,7 +45,8 @@ Importer::Importer(Parser* parserIn, std::vector includePaths, std: removeSymbols.push_back(Symbol("adt_nonterm", false)); removeSymbols.push_back(Symbol("template", true)); removeSymbols.push_back(Symbol("\\|", true)); - //collapseSymbols.push_back(Symbol("scoped_identifier", false)); + //removeSymbols.push_back(Symbol("match", true)); + collapseSymbols.push_back(Symbol("case_statement_list", false)); collapseSymbols.push_back(Symbol("opt_param_assign_list", false)); collapseSymbols.push_back(Symbol("param_assign_list", false)); collapseSymbols.push_back(Symbol("opt_typed_parameter_list", false)); diff --git a/tests/test_adt.krak b/tests/test_adt.krak index f07a450..6ac908e 100644 --- a/tests/test_adt.krak +++ b/tests/test_adt.krak @@ -53,6 +53,21 @@ fun main():int { println("equality false works!") else println("equality false fails!") + + match (maybe_int::an_int(11)) { + maybe_int::an_int(the_int) { + print("matched an int:") + print(the_int) + println(" correctly!") + } + maybe_int::no_int() { + println("matched no int incorrectly!") + } + } + match (maybe_int::no_int()) { + maybe_int::an_int(the_int) println("matched an int incorrectly!") + maybe_int::no_int() println("matched no int correctly!") + } return 0 } From 466b2310db857785ef6f1396d9d965d8660a4c70 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sat, 14 Nov 2015 20:13:42 -0500 Subject: [PATCH 5/5] Make the grammer test work again by updating grammer and parser to use the new adt syntax - I also messed up commenting out one of the cout lines making lambdas not work. --- src/ASTTransformation.cpp | 2 +- stdlib/grammer.krak | 44 ++++++++++++++++++++++++--------------- stdlib/parser.krak | 14 ++++++------- stdlib/regex.krak | 6 +++--- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index a3e22d7..473b8a1 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -555,7 +555,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree auto statement = transform(getNode("statement", children), scope, types, false, templateTypeReplacements); // definitly do not limit this statement to functions if (name == "lambda") newNode->getDataRef()->closedVariables = findVariablesToClose(newNode, statement, scope); - for (auto i : newNode->getDataRef()->closedVariables) + //for (auto i : newNode->getDataRef()->closedVariables) //std::cout << "OK, CLOSED: " << i->getDataRef()->toString() << std::endl; newNode->addChild(statement); //std::cout << "finished function" << functionName << std::endl; diff --git a/stdlib/grammer.krak b/stdlib/grammer.krak index c009a98..aeb4677 100644 --- a/stdlib/grammer.krak +++ b/stdlib/grammer.krak @@ -512,14 +512,24 @@ obj action { return act == other.act && state_or_rule == other.state_or_rule && rule_position == other.rule_position } fun print() { - if (act == action_type::push) - io::print("push ") - else if (act == action_type::reduce) - io::print("reduce ") - else if (act == action_type::accept) - io::print("accept ") - else if (act == action_type::reject) - io::print("reject ") + match (act) { + action_type::push() + io::print("push ") + action_type::reduce() + io::print("reduce ") + action_type::accept() + io::print("accept ") + action_type::reject() + io::print("reject ") + } + /*if (act == action_type::push)*/ + /*io::print("push ")*/ + /*else if (act == action_type::reduce)*/ + /*io::print("reduce ")*/ + /*else if (act == action_type::accept)*/ + /*io::print("accept ")*/ + /*else if (act == action_type::reject)*/ + /*io::print("reject ")*/ io::print(state_or_rule) io::print(" ") io::print(rule_position) @@ -566,25 +576,25 @@ obj table (Object, Serializable) { expand_to(from_state) var cleaned_symbol = clean_symbol(on_symbol) if (items[from_state].contains_key(cleaned_symbol)) - items[from_state][cleaned_symbol].addEnd(action(action_type::push, to_state)) + items[from_state][cleaned_symbol].addEnd(action(action_type::push(), to_state)) else - items[from_state].set(cleaned_symbol, vector::vector(action(action_type::push, to_state))) + items[from_state].set(cleaned_symbol, vector::vector(action(action_type::push(), to_state))) } fun add_reduce(from_state: int, on_symbol: ref symbol::symbol, by_rule_no: int, rule_position: int) { expand_to(from_state) var cleaned_symbol = clean_symbol(on_symbol) if (items[from_state].contains_key(cleaned_symbol)) - items[from_state][cleaned_symbol].addEnd(action(action_type::reduce, by_rule_no, rule_position)) + items[from_state][cleaned_symbol].addEnd(action(action_type::reduce(), by_rule_no, rule_position)) else - items[from_state].set(cleaned_symbol, vector::vector(action(action_type::reduce, by_rule_no, rule_position))) + items[from_state].set(cleaned_symbol, vector::vector(action(action_type::reduce(), by_rule_no, rule_position))) } fun add_accept(from_state: int, on_symbol: ref symbol::symbol) { expand_to(from_state) var cleaned_symbol = clean_symbol(on_symbol) if (items[from_state].contains_key(cleaned_symbol)) - items[from_state][cleaned_symbol].addEnd(action(action_type::accept, 0)) + items[from_state][cleaned_symbol].addEnd(action(action_type::accept(), 0)) else - items[from_state].set(cleaned_symbol, vector::vector(action(action_type::accept, 0))) + items[from_state].set(cleaned_symbol, vector::vector(action(action_type::accept(), 0))) } fun get(state: int, on_symbol: symbol::symbol): vector::vector { var cleaned_symbol = clean_symbol(on_symbol) @@ -593,17 +603,17 @@ obj table (Object, Serializable) { fun get_shift(state: int, on_symbol: symbol::symbol): action { var actions = get(state, on_symbol) for (var i = 0; i < actions.size; i++;) - if (actions[i].act == action_type::push) + if (actions[i].act == action_type::push()) return actions[i] io::println("tried to get a shift when none existed") io::print("for state ") io::print(state) io::print(" and symbol ") io::println(on_symbol.to_string()) - return action(action_type::invalid,-1) + return action(action_type::invalid(),-1) } fun get_reduces(state: int, on_symbol: symbol::symbol): vector::vector { - return get(state, on_symbol).filter(fun(act: action):bool { return act.act == action_type::reduce; }) + return get(state, on_symbol).filter(fun(act: action):bool { return act.act == action_type::reduce(); }) } fun print_string() { /*return string::string("woo a table of size: ") + items.size*/ diff --git a/stdlib/parser.krak b/stdlib/parser.krak index fe52345..07c9fa3 100644 --- a/stdlib/parser.krak +++ b/stdlib/parser.krak @@ -63,7 +63,7 @@ obj parser (Object) { // if the zero state contains any reductions for state 0 and eof, then // it must be reducing to the goal state println("checking the bidness") - if (inputStr == "" && gram.parse_table.get(0, eof_symbol()).contains(action(action_type::reduce, 0))) { + if (inputStr == "" && gram.parse_table.get(0, eof_symbol()).contains(action(action_type::reduce(), 0))) { println("Accept on no input for ") println(name) return new>()->construct(null_symbol()) @@ -92,11 +92,11 @@ obj parser (Object) { gram.parse_table.get(0, input[0]).for_each(fun(act: action) { println("for each action") act.print() - if (act.act == action_type::push) + if (act.act == action_type::push()) to_shift.push(make_pair(v0, act.state_or_rule)) /*else if (act.act == reduce && fully_reduces_to_null(gram.rules[act.state_or_rule])) {*/ - else if (act.act == action_type::reduce && act.rule_position == 0) { - print("act == reduce && == 0 Adding reduction from state: ") + else if (act.act == action_type::reduce() && act.rule_position == 0) { + print("act == reduce() && == 0 Adding reduction from state: ") println(v0->data) to_reduce.push(reduction(v0, gram.rules[act.state_or_rule].lhs, 0, null_symbol_tree, null_symbol_tree)) } @@ -197,7 +197,7 @@ obj parser (Object) { gram.parse_table.get(shift_to, input[i]).for_each(fun(act: action) { var reduce_rule = gram.rules[act.state_or_rule] /*if (act.act == reduce && !fully_reduces_to_null(reduce_rule)) {*/ - if (act.act == action_type::reduce && act.rule_position != 0) { + if (act.act == action_type::reduce() && act.rule_position != 0) { to_reduce.push(reduction(curr_reached, reduce_rule.lhs, act.rule_position, get_nullable_parts(reduce_rule), @@ -213,7 +213,7 @@ obj parser (Object) { gss.add_to_frontier(i, shift_to_node) gss.add_edge(shift_to_node, curr_reached, new_label) gram.parse_table.get(shift_to, input[i]).for_each(fun(act: action) { - if (act.act == action_type::push) { + if (act.act == action_type::push()) { to_shift.push(make_pair(shift_to_node, act.state_or_rule)) } else { var action_rule = gram.rules[act.state_or_rule] @@ -278,7 +278,7 @@ obj parser (Object) { println("post add edger") gram.parse_table.get(shift.second, input[i+1]).for_each(fun(action: action) { println("looking at an action") - if (action.act == action_type::push) { + if (action.act == action_type::push()) { println("is push") next_shifts.push(make_pair(shift_to_node, action.state_or_rule)) } else { diff --git a/stdlib/regex.krak b/stdlib/regex.krak index e903ac6..dba0349 100644 --- a/stdlib/regex.krak +++ b/stdlib/regex.krak @@ -33,7 +33,7 @@ obj regexState (Object) { fun destruct():void { next_states.destruct() } - fun match(input: char): vector::vector<*regexState> { + fun match_char(input: char): vector::vector<*regexState> { return next_states.filter(fun(it:*regexState):bool { return it->character == input; }) } fun is_end():bool { @@ -190,8 +190,8 @@ obj regex (Object, Serializable) { return longest if (next.any_true(fun(state: *regexState):bool { return state->is_end(); })) longest = i - //next = next.flatten_map<*regexState>(fun(state: *regexState): vector::vector<*regexState> { return state->match(to_match[i]); }) - next = next.flatten_map(fun(state: *regexState): vector::vector<*regexState> { return state->match(to_match[i]); }) + //next = next.flatten_map<*regexState>(fun(state: *regexState): vector::vector<*regexState> { return state->match_char(to_match[i]); }) + next = next.flatten_map(fun(state: *regexState): vector::vector<*regexState> { return state->match_char(to_match[i]); }) } if (next.any_true(fun(state: *regexState):bool { return state->is_end(); })) return to_match.length()