diff --git a/include/ASTData.h b/include/ASTData.h index d0aa09c..48bee63 100644 --- a/include/ASTData.h +++ b/include/ASTData.h @@ -34,4 +34,4 @@ class ASTData { }; -#endif +#endif \ No newline at end of file diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index 9746a78..af5290a 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -29,10 +29,13 @@ class ASTTransformation: public NodeTransformation { NodeTree* secondPassDeclaration(NodeTree* from, NodeTree* scope, std::map templateTypeReplacements); NodeTree* secondPassFunction(NodeTree* from, NodeTree* scope, std::map templateTypeReplacements); - //The third pass finishes up by doing all function bodies - void thirdPass(NodeTree* ast, NodeTree* parseTree); + //Third pass redoes all imports to import the new function prototypes and identifiers + void thirdPass(NodeTree* ast); + + //The fourth pass finishes up by doing all function bodies + void fourthPass(NodeTree* ast, NodeTree* parseTree); NodeTree* searchScopeForFunctionDef(NodeTree* scope, NodeTree* parseTree, std::map templateTypeReplacements); - void thirdPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements); + void fourthPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements); virtual NodeTree* transform(NodeTree* from); NodeTree* transform(NodeTree* from, NodeTree* scope, std::vector types, std::map templateTypeReplacements); @@ -44,8 +47,6 @@ class ASTTransformation: public NodeTransformation { NodeTree* functionLookup(NodeTree* scope, std::string lookup, std::vector types); NodeTree* templateFunctionLookup(NodeTree* scope, std::string lookup, std::vector templateInstantiationTypes, std::vector types); std::vector*> scopeLookup(NodeTree* scope, std::string lookup, bool includeModules = false); - std::vector*> moduleTraversingScopeLookup(std::vector*> scopes, std::vector lookupChain); - std::vector*> simpleScopeLookup(NodeTree* scope, std::string lookup, bool includeModules); Type* typeFromTypeNode(NodeTree* typeNode, NodeTree* scope, std::map templateTypeReplacements); NodeTree* templateClassLookup(NodeTree* scope, std::string name, std::vector templateInstantiationTypes); diff --git a/include/util.h b/include/util.h index 3469385..2a5c70d 100644 --- a/include/util.h +++ b/include/util.h @@ -21,6 +21,7 @@ std::vector split(const std::string &str, char delim); std::string join(const std::vector &strVec, std::string joinStr); std::string readFile(std::istream &file); + template bool contains(std::vector vec, T item) { for (auto i : vec) @@ -48,4 +49,14 @@ bool subset(std::set a, std::set b) { return false; return true; } +/* +std::vector split(std::string str, char delim) { + std::stringstream stream(str); + std::string item; + std::vector results; + while(std::getline(stream, item, delim)) + results.push_back(item); + return results; +} +*/ #endif diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index eb894b8..a9af015 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -2,7 +2,7 @@ Goal = translation_unit ; translation_unit = interpreter_directive WS unorderd_list_part WS ; unorderd_list_part = import WS unorderd_list_part | function WS unorderd_list_part | type_def WS ";" WS unorderd_list_part | if_comp WS unorderd_list_part | simple_passthrough WS unorderd_list_part | declaration_statement WS ";" WS unorderd_list_part | import | function | type_def WS ";" | if_comp | simple_passthrough | declaration_statement WS ";" ; -type = type WS "\*" | "void" | "int" | "float" | "double" | "char" | scoped_identifier | scoped_identifier WS template_inst ; +type = type WS "\*" | "void" | "int" | "float" | "double" | "char" | identifier | identifier WS template_inst ; dec_type = "\|" WS type WS "\|" ; template_inst = "<" WS type_list WS ">" ; @@ -12,8 +12,7 @@ template_dec = "template" WS "<" WS template_param_list WS ">" ; template_param_list = template_param_list WS "," WS template_param | template_param ; template_param = identifier WS traits | identifier ; -import = "import" WS identifier WS ";" | "import" WS identifier WS ":" WS import_list WS ";" | "import" WS identifier WS ":" WS "\*" WS ";" ; -import_list = import_list WS "," WS scoped_identifier | scoped_identifier ; +import = "import" WS identifier WS ";" ; interpreter_directive = "#!" WS path | ; @@ -38,11 +37,10 @@ triple_quoted_string = "\"\"\"((\"\"(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i |z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|Z|X|C|V|B|N|M|<|>|\?| )+))*\"\"\"" ; identifier = alpha | alpha alphanumeric ; -scoped_identifier = scoped_identifier WS "::" WS identifier | identifier ; #Note that to prevent confilct with nested templates (T>) it is a nonterminal contructed as follows right_shift = ">" ">" ; -overloadable_operator = "\+" | "-" | "\*" | "/" | "%" | "^" | "&" | "\|" | "~" | "!" | "," | "=" | "\+\+" | "--" | "<<" | right_shift | "==" | "!=" | "&&" | "\|\|" | "\+=" | "-=" | "/=" | "%=" | "^=" | "&=" | "\|=" | "\*=" | "<<=" | ">>=" | "->" | "[]" ; +overloadable_operator = "\+" | "-" | "\*" | "/" | "%" | "^" | "&" | "\|" | "~" | "!" | "," | "=" | "\+\+" | "--" | "<<" | right_shift | "==" | "!=" | "&&" | "\|\|" | "\+=" | "-=" | "/=" | "%=" | "^=" | "&=" | "\|=" | "\*=" | "<<=" | ">>=" | "->" ; func_identifier = identifier | identifier overloadable_operator ; function = template_dec WS dec_type WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" WS code_block | dec_type WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" WS code_block ; @@ -89,7 +87,7 @@ expression = expression WS "<<" WS term | expression WS right_shift WS shiftand shiftand = shiftand WS "-" WS term | shiftand WS "\+" WS term | term ; term = term WS forward_slash WS factor | term WS "\*" WS factor | term WS "%" WS factor | factor ; factor = "\+\+" WS unarad | unarad WS "\+\+" | "--" WS unarad | unarad WS "--" | "\+" WS unarad | "-" WS unarad | "!" WS unarad | "~" WS unarad | "\(" WS type WS "\)" WS unarad | "\*" WS unarad | "&" WS unarad | unarad ; -unarad = number | scoped_identifier | scoped_identifier WS template_inst | function_call | bool | string | character | "\(" WS boolean_expression WS "\)" | access_operation | unarad WS "[" WS expression WS "]" ; +unarad = number | identifier | identifier WS template_inst | function_call | bool | string | character | "\(" WS boolean_expression WS "\)" | access_operation | unarad WS "[" WS expression WS "]" ; number = integer | floating_literal ; access_operation = unarad "." identifier | unarad "->" identifier ; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 3a6f886..c883adf 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -79,20 +79,14 @@ NodeTree* ASTTransformation::firstPass(std::string fileName, NodeTree* i : children) { if (i->getDataRef()->getName() == "import") { std::string toImport = concatSymbolTree(i->getChildren()[0]); - NodeTree* importNode = new NodeTree("import", ASTData(import, Symbol(toImport, true))); - // If there are named things to import, import them (some identifiers, or *) - if (i->getChildren().size() > 2) { - std::cout << "Things to import from " << toImport << "!" << std::endl; - for (auto importThing : slice(i->getChildren(), 1, -1, 1)) { - std::string identifierToImport = concatSymbolTree(i); - std::cout << " pulling in " << identifierToImport << std::endl; - importNode->addChild(new NodeTree(identifierToImport, ASTData(identifier, Symbol(identifierToImport, true)))); - } - } - translationUnit->addChild(importNode); + translationUnit->addChild(new NodeTree("import", ASTData(import, Symbol(toImport, true)))); //Do the imported file too NodeTree* outsideTranslationUnit = importer->importFirstPass(toImport + ".krak"); translationUnit->getDataRef()->scope[toImport].push_back(outsideTranslationUnit); //Put this transation_unit in the scope as it's files name + //Now add it to scope + for (auto i = outsideTranslationUnit->getDataRef()->scope.begin(); i != outsideTranslationUnit->getDataRef()->scope.end(); i++) + for (auto j : i->second) + translationUnit->getDataRef()->scope[i->first].push_back(j); } } @@ -217,8 +211,32 @@ NodeTree* ASTTransformation::secondPassFunction(NodeTree* from, return functionDef; } -//The third pass finishes up by doing all function bodies -void ASTTransformation::thirdPass(NodeTree* ast, NodeTree* parseTree) { + + +//Third pass redoes all imports to import the new function prototypes and identifiers +void ASTTransformation::thirdPass(NodeTree* ast) { + std::vector*> children = ast->getChildren(); + //Go through and do all imports again + for (NodeTree* i : children) { + if (i->getDataRef()->type == import) { + std::string toImport = i->getDataRef()->symbol.getName(); + NodeTree* outsideTranslationUnit = importer->getUnit(toImport + ".krak"); + //Now add all functions to scope + std::cout << "Trying to re-import from " << toImport << std::endl; + for (auto i = outsideTranslationUnit->getDataRef()->scope.begin(); i != outsideTranslationUnit->getDataRef()->scope.end(); i++) { + std::cout << "Looking through " << i->first << std::endl; + for (auto j : i->second) + if (j->getDataRef()->type == function || j->getDataRef()->type == identifier) + std::cout << "Copying " << i->first << std::endl, ast->getDataRef()->scope[i->first].push_back(j); + else + std::cout << "Not Copying " << i->first << std::endl; + } + } + } +} + +//The fourth pass finishes up by doing all function bodies +void ASTTransformation::fourthPass(NodeTree* ast, NodeTree* parseTree) { topScope = ast; //Top scope is maintained for templates, which need to add themselves to the top scope from where ever they are instantiated std::vector*> children = parseTree->getChildren(); @@ -239,14 +257,14 @@ void ASTTransformation::thirdPass(NodeTree* ast, NodeTree* pars //Do the inside of classes here for (NodeTree* j : typedefChildren) { if (j->getDataRef()->getName() == "function") { - thirdPassFunction(j, searchScopeForFunctionDef(typeDef, j, std::map()), std::map()); //do member method + fourthPassFunction(j, searchScopeForFunctionDef(typeDef, j, std::map()), std::map()); //do member method } } } else if (i->getDataRef()->getName() == "function") { //Do prototypes of functions if (i->getChildren()[0]->getData().getName() == "template_dec") continue; //We've already set up function templates - thirdPassFunction(i, searchScopeForFunctionDef(ast, i, std::map()), std::map()); + fourthPassFunction(i, searchScopeForFunctionDef(ast, i, std::map()), std::map()); } } @@ -269,7 +287,7 @@ void ASTTransformation::thirdPass(NodeTree* ast, NodeTree* pars std::cout << "Instantiating template " << i->getDataRef()->toString() << std::endl; for (NodeTree* j : classTemplateType->templateDefinition->getChildren()) if (j->getDataRef()->getName() == "function") - thirdPassFunction(j, searchScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method + fourthPassFunction(j, searchScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method classTemplateType->templateTypeReplacement.clear(); // This template has been fully instantiated, clear it's map so it won't be instantiated again } } @@ -281,7 +299,7 @@ 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[1]) << ", children size is " << children.size() << std::endl; + std::cout << "\n Searching scope for function def, function is :" << concatSymbolTree(children[1]) << ", children size is " << children.size() << std::endl; for (int i = 2; i < children.size()-1; i+=2) { //Skip over commas std::cout << "Making type for lookup ||" << concatSymbolTree(children[i]) << "||" << std::endl; Type type = *typeFromTypeNode(children[i]->getChildren()[0], scope, templateTypeReplacements); @@ -295,9 +313,9 @@ NodeTree* ASTTransformation::searchScopeForFunctionDef(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements) { +void ASTTransformation::fourthPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements) { NodeTree* codeBlock = from->getChildren()[from->getChildren().size()-1]; functionDef->addChild(transform(codeBlock, functionDef, std::vector(), templateTypeReplacements)); } @@ -314,7 +332,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree std::vector*> children = from->getChildren(); std::set skipChildren; - if (name == "identifier" || name == "scoped_identifier") { + if (name == "identifier") { //Make sure we get the entire name std::string lookupName = concatSymbolTree(from); std::cout << "Looking up: " << lookupName << std::endl; @@ -761,14 +779,12 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* scope, s } //We search the languageLevelOperators to see if it's an operator. If so, we modifiy the lookup with a preceding "operator" LLElementIterator = languageLevelOperators.find(lookup); - if (LLElementIterator != languageLevelOperators.end()) { + if (LLElementIterator != languageLevelOperators.end()) lookup = "operator" + lookup; - std::cout << "Is an operator, prepending operator. Lookup is now: " << lookup << std::endl; - } //Look up the name std::vector*> possibleMatches = scopeLookup(scope, lookup); - std::cout << "Function lookup of " << lookup << " has " << possibleMatches.size() << " possible matches at scope: " << scope->getDataRef()->toString() << std::endl; + std::cout << "Function lookup of " << lookup << " has " << possibleMatches.size() << " possible matches." << std::endl; if (possibleMatches.size()) { for (auto i : possibleMatches) { //We're not looking for types @@ -996,44 +1012,6 @@ std::vector*> ASTTransformation::scopeLookup(NodeTree std::cout << "found it at language level as reserved word." << std::endl; return LLElementIterator->second; } - std::vector scopeStringVec = slice(split(lookup, ':'), 0, -1, 2); - std::vector*> matches; - // If this is unscoped, look up in current scope too - if (scopeStringVec.size() == 1) { - auto simpleMatches = simpleScopeLookup(scope, lookup, includeModules); - matches.insert(matches.end(), simpleMatches.begin(), simpleMatches.end()) - } - // Otherwise we use our more powerful module traversing scope lookup - std::vector*> modules; - module.push_back(topScope); - std::set*> moduleTraversedResults = moduleTraversingScopeLookup(modules, scopeStringVec, includeModules); - for (auto i : moduleTraversedResults) - matches.push_back(i); - return matches; -} - -std::set*> ASTTransformation::moduleTraversingScopeLookup(std::vector*> scopes, std::vector lookupChain, bool includeModules) { - std::string head = lookupChain[0]; - std::vector tail = slice(lookupChain, 1, -1); - std::vector*> matches; - // In addition to the scopes passed in, we want all the scopes reachable through import a: name/* too. - - // For every one of our scopes, add its results to matches - for (auto scope : scopes) { - auto scopeMap = scope->getDataRef()->scope; - auto possibleMatches = scopeMap.find(head); - if (possibleMatches != scopeMap.end()) - for (auto i : possibleMatches->second) - if (tail.size() || includeModules || i->getName() != "translation_unit") // If this isn't the end of the module lookup, we want to include modules regardless - matches.insert(i); - - } - if (tail.size()) - return moduleTraversingScopeLookup(matches, tail); - return matches; -} - -std::vector*> ASTTransformation::simpleScopeLookup(NodeTree* scope, std::string lookup, bool includeModules) { std::vector*> matches; std::map*>> scopeMap = scope->getDataRef()->scope; auto possibleMatches = scopeMap.find(lookup); @@ -1154,18 +1132,21 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreegetDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition); topScope->addChild(typeDefinition); //Add this object the the highest scope's + //NodeTree* templateHighScope = templateDefinition->getDataRef()->scope["~enclosing_scope"][0]; + //if (topScope != templateHighScope) + //templateHighScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition); // We put it in the scope of the template so that it can find itself (as it's scope is its template definition) templateDefinition->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition); //Note that the instantiated template's scope is the template's definition. typeDefinition->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition); // We only partially instantiate templates no matter what now - // They are all fully instantiated in the loop at the end of the 3rd pass + // They are all fully instantiated in the loop at the end of the 4th pass // This is done for code simplicity and so that that loop can do template class methods // that instantiate other templates that instantiate other templates while still retaining the // deferred method allowing us to correctly instantiate multiple levels of mututally recursive definitions. selfType->templateDefinition = 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 3 + selfType->templateTypeReplacement = newTemplateTypeReplacement; //Save the types for use when this is fully instantiated in pass 4 secondPassDoClassInsides(typeDefinition, templateSyntaxTree->getChildren(), newTemplateTypeReplacement); //Use these types when instantiating data members } } else if (possibleMatches.size() == 0) { diff --git a/src/Importer.cpp b/src/Importer.cpp index 621af09..7d6ac37 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -10,6 +10,7 @@ Importer::Importer(Parser* parserIn, std::vector includePaths) { removeSymbols.push_back(Symbol("WS", false)); removeSymbols.push_back(Symbol("\\(", true)); removeSymbols.push_back(Symbol("\\)", true)); + removeSymbols.push_back(Symbol("::", true)); removeSymbols.push_back(Symbol(";", true)); removeSymbols.push_back(Symbol("{", true)); removeSymbols.push_back(Symbol("}", true)); @@ -89,11 +90,15 @@ void Importer::import(std::string fileName) { std::cout << "\n\nSecond pass for: " << i.name << std::endl, ASTTransformer->secondPass(i.ast, i.syntaxTree); //function prototypes, and identifiers (as we now have all type defs) std::cout << "\n\n =====THIRD PASS===== \n\n" << std::endl; - for (importTriplet i : importedTrips) // Third pass finishes up by doing all function bodies - std::cout << "\n\nThird pass for: " << i.name << std::endl, ASTTransformer->thirdPass(i.ast, i.syntaxTree); //With that, we're done + for (importTriplet i : importedTrips) //Third pass redoes all imports to import the new function prototypes and identifiers + std::cout << "\n\nThird pass for: " << i.name << std::endl, ASTTransformer->thirdPass(i.ast); - //Note that class template instantiation can happen in the second or third passes and that function template instantion - //can happen in the third pass. + std::cout << "\n\n =====FOURTH PASS===== \n\n" << std::endl; + for (importTriplet i : importedTrips) //Fourth pass finishes up by doing all function bodies + std::cout << "\n\nFourth pass for: " << i.name << std::endl, ASTTransformer->fourthPass(i.ast, i.syntaxTree); //With that, we're done + + //Note that class template instantiation can happen in the second or fourth passes and that function template instantion + //can happen in the fourth pass. std::ofstream outFileAST; for (importTriplet i : importedTrips) { diff --git a/stdlib/io.krak b/stdlib/io.krak index 7caa920..552ec4d 100644 --- a/stdlib/io.krak +++ b/stdlib/io.krak @@ -2,10 +2,6 @@ __if_comp__ __C__ __simple_passthrough__ """ #include """ -/* - *import string; - */ - |void| println() { print("\n"); } @@ -24,17 +20,6 @@ __if_comp__ __C__ __simple_passthrough__ """ println(); } -/* - *|void| print(|String| toPrint) { - * print(toPrint.c_str()); - *} - * - *|void| println(|String| toPrint) { - * print(toPrint); - * println(); - *} - */ - |void| print(|int| toPrint) { __if_comp__ __C__ { __simple_passthrough__ """ diff --git a/stdlib/string.krak b/stdlib/string.krak deleted file mode 100644 index cebbe0c..0000000 --- a/stdlib/string.krak +++ /dev/null @@ -1,49 +0,0 @@ -import vector; -import mem; - -typedef String (Destructable) { - |vector| charVec; - - |String*| construct() { - charVec.construct(); - return this; - } - - |void| destruct() { - charVec.destruct(); - } - - |String*| construct(|char*| stringInput) { - charVec.construct(); - append(stringInput); - return this; - } - - |char| operator[](|int| index) { - return charVec[index]; - } - - |void| append(|String| toAppend) { - for (|int| i = 0; i < toAppend.size(); i++;) - charVec.addEnd(toAppend[i]); - } - - |void| append(|char*| toAppend) { - while(toAppend) - charVec.addEnd(toAppend++); - } - - |String| operator+(|String| other) { - |String| self = clone(); - self.append(other); - return self; - } - - |char*| c_str() { - |char*| toReturn = new(charVec.size()+1); - for (|int| i = 0; i < charVec.size(); i++;) - toReturn[i] = charVec[i]; - toReturn[charVec.size()] = 0; - return toReturn; - } -}; diff --git a/stdlib/vector.krak b/stdlib/vector.krak index 8d2815b..0cf12df 100644 --- a/stdlib/vector.krak +++ b/stdlib/vector.krak @@ -27,12 +27,12 @@ typedef template vector (Destructable) { delete(data, 0); return true; } - - |T| operator[](|int| index) { - return at(index); - } |T| at(|int| index) { + return get(index); + } + + |T| get(|int| index) { if (index < 0 || index >= size) { println("Vector access out of bounds! Retuning 0th element as sanest option"); return data[0]; diff --git a/tests/vectorTest.expected_results b/tests/vectorTest.expected_results index c6e986f..c7ae395 100644 --- a/tests/vectorTest.expected_results +++ b/tests/vectorTest.expected_results @@ -1,3 +1,2 @@ 1337 -1337 Destroyed! diff --git a/tests/vectorTest.krak b/tests/vectorTest.krak index 932caf8..579fe24 100644 --- a/tests/vectorTest.krak +++ b/tests/vectorTest.krak @@ -16,10 +16,7 @@ typedef AbleToBeDestroyed (Destructable) { intVec.addEnd(7); for (|int| i = 0; i < intVec.size; i++;) print(intVec.at(i)); - println(); - - for (|int| i = 0; i < intVec.size; i++;) - print(intVec[i]); + println(); |vector*| desVec = new>()->construct();