From 5974deece2dd44cba0882cf341c30fbab1c82611 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 19 Aug 2014 01:24:28 -0400 Subject: [PATCH] in prog --- include/ASTData.h | 2 +- include/ASTTransformation.h | 11 ++- include/util.h | 11 --- krakenGrammer.kgm | 10 +-- src/ASTTransformation.cpp | 109 ++++++++++++++++++------------ src/Importer.cpp | 13 ++-- stdlib/io.krak | 15 ++++ stdlib/string.krak | 49 ++++++++++++++ stdlib/vector.krak | 8 +-- tests/vectorTest.expected_results | 1 + tests/vectorTest.krak | 5 +- 11 files changed, 153 insertions(+), 81 deletions(-) create mode 100644 stdlib/string.krak diff --git a/include/ASTData.h b/include/ASTData.h index 48bee63..d0aa09c 100644 --- a/include/ASTData.h +++ b/include/ASTData.h @@ -34,4 +34,4 @@ class ASTData { }; -#endif \ No newline at end of file +#endif diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index af5290a..9746a78 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -29,13 +29,10 @@ class ASTTransformation: public NodeTransformation { NodeTree* secondPassDeclaration(NodeTree* from, NodeTree* scope, std::map templateTypeReplacements); NodeTree* secondPassFunction(NodeTree* from, NodeTree* scope, std::map templateTypeReplacements); - //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); + //The third pass finishes up by doing all function bodies + void thirdPass(NodeTree* ast, NodeTree* parseTree); NodeTree* searchScopeForFunctionDef(NodeTree* scope, NodeTree* parseTree, std::map templateTypeReplacements); - void fourthPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements); + void thirdPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements); virtual NodeTree* transform(NodeTree* from); NodeTree* transform(NodeTree* from, NodeTree* scope, std::vector types, std::map templateTypeReplacements); @@ -47,6 +44,8 @@ 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 2a5c70d..3469385 100644 --- a/include/util.h +++ b/include/util.h @@ -21,7 +21,6 @@ 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) @@ -49,14 +48,4 @@ 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 a9af015..eb894b8 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" | identifier | identifier WS template_inst ; +type = type WS "\*" | "void" | "int" | "float" | "double" | "char" | scoped_identifier | scoped_identifier WS template_inst ; dec_type = "\|" WS type WS "\|" ; template_inst = "<" WS type_list WS ">" ; @@ -12,7 +12,8 @@ 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 = "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 ; interpreter_directive = "#!" WS path | ; @@ -37,10 +38,11 @@ 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 ; @@ -87,7 +89,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 | identifier | identifier WS template_inst | function_call | bool | string | character | "\(" WS boolean_expression WS "\)" | access_operation | unarad WS "[" WS expression WS "]" ; +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 "]" ; number = integer | floating_literal ; access_operation = unarad "." identifier | unarad "->" identifier ; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index c883adf..3a6f886 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -79,14 +79,20 @@ NodeTree* ASTTransformation::firstPass(std::string fileName, NodeTree* i : children) { if (i->getDataRef()->getName() == "import") { std::string toImport = concatSymbolTree(i->getChildren()[0]); - translationUnit->addChild(new NodeTree("import", ASTData(import, Symbol(toImport, true)))); + 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); //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); } } @@ -211,32 +217,8 @@ NodeTree* ASTTransformation::secondPassFunction(NodeTree* from, return functionDef; } - - -//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) { +//The third pass finishes up by doing all function bodies +void ASTTransformation::thirdPass(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(); @@ -257,14 +239,14 @@ void ASTTransformation::fourthPass(NodeTree* ast, NodeTree* par //Do the inside of classes here for (NodeTree* j : typedefChildren) { if (j->getDataRef()->getName() == "function") { - fourthPassFunction(j, searchScopeForFunctionDef(typeDef, j, std::map()), std::map()); //do member method + thirdPassFunction(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 - fourthPassFunction(i, searchScopeForFunctionDef(ast, i, std::map()), std::map()); + thirdPassFunction(i, searchScopeForFunctionDef(ast, i, std::map()), std::map()); } } @@ -287,7 +269,7 @@ void ASTTransformation::fourthPass(NodeTree* ast, NodeTree* par std::cout << "Instantiating template " << i->getDataRef()->toString() << std::endl; for (NodeTree* j : classTemplateType->templateDefinition->getChildren()) if (j->getDataRef()->getName() == "function") - fourthPassFunction(j, searchScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method + thirdPassFunction(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 } } @@ -299,7 +281,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); @@ -313,9 +295,9 @@ NodeTree* ASTTransformation::searchScopeForFunctionDef(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements) { +void ASTTransformation::thirdPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements) { NodeTree* codeBlock = from->getChildren()[from->getChildren().size()-1]; functionDef->addChild(transform(codeBlock, functionDef, std::vector(), templateTypeReplacements)); } @@ -332,7 +314,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree std::vector*> children = from->getChildren(); std::set skipChildren; - if (name == "identifier") { + 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; @@ -779,12 +761,14 @@ 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." << std::endl; + std::cout << "Function lookup of " << lookup << " has " << possibleMatches.size() << " possible matches at scope: " << scope->getDataRef()->toString() << std::endl; if (possibleMatches.size()) { for (auto i : possibleMatches) { //We're not looking for types @@ -1012,6 +996,44 @@ 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); @@ -1132,21 +1154,18 @@ 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 4th pass + // They are all fully instantiated in the loop at the end of the 3rd 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 4 + selfType->templateTypeReplacement = newTemplateTypeReplacement; //Save the types for use when this is fully instantiated in pass 3 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 7d6ac37..621af09 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -10,7 +10,6 @@ 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)); @@ -90,15 +89,11 @@ 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 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); + 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 - 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. + //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::ofstream outFileAST; for (importTriplet i : importedTrips) { diff --git a/stdlib/io.krak b/stdlib/io.krak index 552ec4d..7caa920 100644 --- a/stdlib/io.krak +++ b/stdlib/io.krak @@ -2,6 +2,10 @@ __if_comp__ __C__ __simple_passthrough__ """ #include """ +/* + *import string; + */ + |void| println() { print("\n"); } @@ -20,6 +24,17 @@ __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 new file mode 100644 index 0000000..cebbe0c --- /dev/null +++ b/stdlib/string.krak @@ -0,0 +1,49 @@ +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 0cf12df..8d2815b 100644 --- a/stdlib/vector.krak +++ b/stdlib/vector.krak @@ -27,12 +27,12 @@ typedef template vector (Destructable) { delete(data, 0); return true; } - - |T| at(|int| index) { - return get(index); + + |T| operator[](|int| index) { + return at(index); } - |T| get(|int| index) { + |T| at(|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 c7ae395..c6e986f 100644 --- a/tests/vectorTest.expected_results +++ b/tests/vectorTest.expected_results @@ -1,2 +1,3 @@ 1337 +1337 Destroyed! diff --git a/tests/vectorTest.krak b/tests/vectorTest.krak index 579fe24..932caf8 100644 --- a/tests/vectorTest.krak +++ b/tests/vectorTest.krak @@ -16,7 +16,10 @@ 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();