diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85f38a8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +_site +build +*.comp +stats +*.swp +*.png diff --git a/README.md b/README.md index 07ffdc7..d9e4a77 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Kraken The Kraken Programming Language +(more info and examples at http://limvot.github.io/kraken/) + The Kraken Programming Language is in its infancy. Currently, it consists of a RNGLALR parser written in C++, an experimental grammer that is evolving, and a C code generator. When compiled, the kraken compiler will take in a text file to be parsed, the grammer file to use, and an output file name. diff --git a/future_features.txt b/future_features.txt index 88b0a92..0a26ad2 100644 --- a/future_features.txt +++ b/future_features.txt @@ -1,5 +1,12 @@ -Declaration of a pointer and multiplication are ambigious! -( T* a; maybe either a declaration or a multiplication) +correctly importing / running tests is a nightmare with relative paths. + +Namespaces +Imports allow renaming of either entire scope or individual members, and can import from within a scope + +correct c genration for triple mutually recursive types across 2 files (wehre +A depends on B depends on C, but two of them are in the same file and there's +also pointers for the other two) Will need splitting into multiple C files to +be cleanest, I think) Fix destructors being placed after return. Fix functions before declaration? (in class? (this is from an old file)) diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index af5290a..e063b83 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -47,6 +47,7 @@ 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*> scopeLookup(NodeTree* scope, std::string lookup, bool includeModules, std::vector*> visited); Type* typeFromTypeNode(NodeTree* typeNode, NodeTree* scope, std::map templateTypeReplacements); NodeTree* templateClassLookup(NodeTree* scope, std::string name, std::vector templateInstantiationTypes); diff --git a/include/CGenerator.h b/include/CGenerator.h index a0472fb..13103e4 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "NodeTree.h" #include "ASTData.h" @@ -12,6 +14,7 @@ #include "util.h" #include "Poset.h" +// 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. class CGenerator { public: @@ -19,12 +22,16 @@ class CGenerator { ~CGenerator(); void generateCompSet(std::map*> ASTs, std::string outputName); std::string generateClassStruct(NodeTree* from); + bool isUnderTranslationUnit(NodeTree* from, NodeTree* typeDefinition); + NodeTree* highestScope(NodeTree* node); + std::pair generateTranslationUnit(NodeTree* from); std::string generate(NodeTree* from, NodeTree* enclosingObject = NULL); std::string generateAliasChains(NodeTree* scopeNode, NodeTree* definition); static std::string ValueTypeToCType(Type *type); static std::string ValueTypeToCTypeDecoration(Type *type); + static std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr); static std::string CifyName(std::string name); - std::string generateObjectMethod(NodeTree* enclosingObject, NodeTree* from, std::string *functionPrototype); + std::string generateObjectMethod(NodeTree* enclosingObject, NodeTree* from, std::string *functionPrototype); NodeTree* getMethodsObjectType(NodeTree* scope, std::string functionName); std::string generatorString; private: diff --git a/include/Tester.h b/include/Tester.h index 7bf1815..6aa6be2 100644 --- a/include/Tester.h +++ b/include/Tester.h @@ -15,7 +15,7 @@ class Tester { int ssystem(std::string command); bool run(std::string fileName); bool compareFiles(std::string file1Path, std::string file2Path); - void cleanExtras(std::string fileName); + void cleanExtras(std::string path); private: std::string krakenInvocation; @@ -27,5 +27,7 @@ class Tester { std::string shell; std::string changePermissions; std::string redirect; + std::string sep; + std::string cd; }; #endif diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index a9af015..732a2eb 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,8 +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 "\*" WS ";" | "import" WS identifier WS ":" WS import_list WS ";" ; +import_list = identifier | identifier WS "," WS import_list ; interpreter_directive = "#!" WS path | ; path = path path_part | path_part ; @@ -37,6 +37,7 @@ 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 = ">" ">" ; @@ -56,7 +57,7 @@ type_def = "typedef" WS identifier WS type | "typedef" WS template_dec WS identi declaration_block = declaration_statement WS ";" WS declaration_block | function WS declaration_block | declaration_statement WS ";" | function | ; traits = "\(" WS trait_list WS "\)" ; -trait_list = trait_list WS "," WS identifier | identifier ; +trait_list = trait_list WS "," WS scoped_identifier | scoped_identifier ; #Older rule for stuff with visibility labels - this should be added sometime #type_def = "typedef" WS identifier WS type | "typedef" WS template_dec WS identifier WS "{" WS class_innerds WS "}" | "typedef" WS identifier WS "{" WS class_innerds WS "}" | "typedef" WS template_dec WS identifier WS "{" WS declaration_block WS "}" | "typedef" WS identifier WS "{" WS declaration_block WS "}" ; @@ -87,7 +88,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..fae16d4 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -78,15 +78,38 @@ 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)))); + auto importChildren = i->getChildren(); + std::string toImport = concatSymbolTree(importChildren[0]); + auto importNode = new NodeTree("import", ASTData(import, Symbol(toImport, 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); + // Now go through and handle anything like import asdf: a; or import asdf: a,b; or import asdf: *; + // We do this by looping through the children and adding links to them as the scope in the import node. If it's *, we add the entire translationUnit link. + // Note that import affects scope in two ways: + // (1) The other file's translationUnit is added to our translationUnit's scope under it's name + // (2) The import node's scope contains the nodes indicated by the qualifiers after the import (i.e. the import a:b; or import a:*;) + for (auto importQualifer : slice(importChildren, 1, -1)) { // Not the first child, that's the name of the file + auto name = concatSymbolTree(importQualifer); + if (name == "*") { + std::vector*> tmp; + tmp.push_back(outsideTranslationUnit); + importNode->getDataRef()->scope["*"] = tmp; + } else { + bool found = false; + for (auto outsideScopeEntry : outsideTranslationUnit->getDataRef()->scope) { + if (name == outsideScopeEntry.first) { + importNode->getDataRef()->scope[outsideScopeEntry.first] = outsideScopeEntry.second; + found = true; + } + } + // If it's not found yet, put it in as a empty vector for pass 3. + // This makes sure that it does appear in the scope map, which is what we iterate through later. + if (!found) + importNode->getDataRef()->scope[name] = std::vector*>(); + } + } } } @@ -223,13 +246,17 @@ void ASTTransformation::thirdPass(NodeTree* ast) { 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); + for (auto j = outsideTranslationUnit->getDataRef()->scope.begin(); j != outsideTranslationUnit->getDataRef()->scope.end(); j++) { + std::cout << "Looking at " << j->first << std::endl; + // If we're supposed to import this... (meaning that this name is in the scope already) + if (i->getDataRef()->scope.find(j->first) == i->getDataRef()->scope.end()) + continue; + std::cout << "Looking through " << j->first << std::endl; + for (auto k : j->second) + if (k->getDataRef()->type == function || k->getDataRef()->type == identifier) + std::cout << "Copying " << j->first << std::endl, i->getDataRef()->scope[j->first].push_back(k); else - std::cout << "Not Copying " << i->first << std::endl; + std::cout << "Not Copying " << j->first << std::endl; } } } @@ -332,7 +359,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; @@ -350,6 +377,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree } newNode = possibleMatches[0]; } + return newNode; } else if (name == "type_def") { //If it is an alisis of a type std::string typeAlias; @@ -416,6 +444,8 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree return newNode; } functionName = concatSymbolTree(children[1]); + for (auto child: children) + std::cout << "Function child: " << child->getDataRef()->toString() << std::endl; newNode = new NodeTree(name, ASTData(function, Symbol(functionName, true), typeFromTypeNode(children[0], scope, templateTypeReplacements))); skipChildren.insert(0); skipChildren.insert(1); @@ -795,11 +825,19 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* scope, s //We subtract one from the children to get the type size only if there is at least one child AND // the last node is actually a body node, as it may not have been generated yet if we're in the body //and this function is recursive or if this is a non-instantiated template function - if (types.size() != ((children.size() > 0 && children[children.size()-1]->getDataRef()->type == code_block) ? children.size()-1 : children.size())) { - std::cout << "Type sizes do not match between two " << lookup << "(" << types.size() << "," << ((children.size() > 0 && children[children.size()-1]->getDataRef()->type == code_block) ? children.size()-1 : children.size()) << "), types are: "; + int numTypes = (children.size() > 0 && children[children.size()-1]->getDataRef()->type == code_block) ? children.size()-1 : children.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 << " vs " << children[j]->getDataRef()->valueType->toString() << std::endl; + } + for (auto child: children) + std::cout << "\t" << child->getDataRef()->toString() << std::endl; + std::cout << std::endl; continue; } bool typesMatch = true; @@ -1005,7 +1043,15 @@ 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::vector*>()); +} + +std::vector*> ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup, bool includeModules, std::vector*> visited) { + std::cout << "Scp[e looking up " << lookup << std::endl; + // Don't visit this node again when looking for the smae lookup. Note that we don't prevent coming back for the scope operator, as that should be able to come back. + visited.push_back(scope); //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()) { @@ -1013,6 +1059,20 @@ std::vector*> ASTTransformation::scopeLookup(NodeTree return LLElementIterator->second; } std::vector*> matches; + // First, we check for scope operator (::) but only if occurs before a "<" as this would signal the beginning of a template instatiation inside type + // If we find it, we look up the left side of the :: and then use the resuts as the scope for looking up the right side, recursively. + 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; + for (auto scopeMatch : scopeLookup(scope, strSlice(lookup, 0, scopeOpPos), true)) { + 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()); + } + return matches; + } + std::map*>> scopeMap = scope->getDataRef()->scope; auto possibleMatches = scopeMap.find(lookup); if (possibleMatches != scopeMap.end()) { @@ -1021,11 +1081,33 @@ std::vector*> ASTTransformation::scopeLookup(NodeTree matches.push_back(i); std::cout << "Found " << possibleMatches->second.size() << " match(s) at " << scope->getDataRef()->toString() << std::endl; } - // Add results from our enclosing scope, if it exists + // 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. auto enclosingIterator = scopeMap.find("~enclosing_scope"); if (enclosingIterator != scopeMap.end()) { - std::vector*> upperResult = scopeLookup(enclosingIterator->second[0], lookup); + std::vector*> upperResult = scopeLookup(enclosingIterator->second[0], lookup, includeModules, visited); matches.insert(matches.end(), upperResult.begin(), upperResult.end()); + } else { + // Ok, let's iterate through and check for imports + for (auto child : scope->getChildren()) { + if (child->getDataRef()->type == import) { + auto importScope = child->getDataRef()->scope; + // Check if there is a match named explicily in the import's scope (i.e. looking for a and the import is import somefile: a;) + // If so, add it's members to our matches + auto importLookupItr = importScope.find(lookup); + if (importLookupItr != importScope.end()) { + auto addMatches = importLookupItr->second; + matches.insert(matches.end(), addMatches.begin(), addMatches.end()); + } + // Check if there is an uncionditional import to follow (i.e. import somefile: *;) + // If so, continue the search in that scope + auto importStarItr = importScope.find("*"); + if (importStarItr != importScope.end()) { + auto addMatches = scopeLookup(importStarItr->second[0], lookup, includeModules, visited); + matches.insert(matches.end(), addMatches.begin(), addMatches.end()); + } + } + } } return matches; } diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 6234d7a..b2969bc 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -7,24 +7,35 @@ 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 -std=c99 "; + std::cout << "\n\n =====GENERATE PASS===== \n\n" << std::endl; + if (mkdir(("./" + outputName).c_str(), 0755)) { + std::cout << "Could not make directory " << outputName << std::endl; + //throw "could not make directory "; + } for (auto i = ASTs.begin(); i != ASTs.end(); i++) { + std::cout << "\n\nGenerate pass for: " << i->first << std::endl; buildString += i->first + ".c "; - std::ofstream outputCFile; - outputCFile.open(i->first + ".c"); - if (outputCFile.is_open()) { + std::ofstream outputCFile, outputHFile; + outputCFile.open(outputName + "/" + i->first + ".c"); + outputHFile.open(outputName + "/" + i->first + ".h"); + if (outputCFile.is_open() || outputHFile.is_open()) { // Prequel common to all files - outputCFile << "#include \n#include \n#include \n" << generate(i->second); + auto chPair = generateTranslationUnit(i->second); + outputHFile << "#include \n#include \n#include \n" << chPair.first; + outputCFile << "#include \"" + i->first + ".h\"\n\n" << chPair.second; } else { - std::cout << "Cannot open file " << i->first << ".c" << std::endl; + std::cout << "Cannot open file " << i->first << ".c/h" << std::endl; } outputCFile.close(); + outputHFile.close(); } buildString += "-o " + outputName; std::ofstream outputBuild; - outputBuild.open(outputName + ".sh"); + outputBuild.open(outputName + "/" + split(outputName, '/').back() + ".sh"); outputBuild << buildString; outputBuild.close(); } @@ -70,6 +81,164 @@ std::string CGenerator::generateAliasChains(NodeTree* scopeNode, NodeTr return output; } +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 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; +} + +// 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(NodeTree* from) { + ASTData data = from->getData(); + std::vector*> children = from->getChildren(); + 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. + + std::string importIncludes = "/**\n * Import Includes\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"; + + // Ok, let's handle the included files + for (auto i : from->getChildren()) + if (i->getDataRef()->type == import) + importIncludes += "#include \"" + i->getDataRef()->symbol.getName() + ".krak.h\" //woo importing!\n"; + + // And get the correct order for emiting classes, but not if they're not in our file, then they will get included + // Note that this is not sufsticated enough for some multiple file mutually recursive types, but I want to get this simple version working first + Poset*> typedefPoset; + 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 && isUnderTranslationUnit(from, decType->typeDefinition)) // If this is a custom type and not a pointer and actually should be defined in this file + typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency + } + } + } + } + //Now generate the typedef's in the correct, topological order + for (NodeTree* i : typedefPoset.getTopoSort()) + classStructs += generateClassStruct(i) + "\n"; + + // Declare everything in translation unit scope here. (allows stuff from other files, automatic forward declarations) + // Also, everything in all of the import's scopes + std::map*>> combinedMap; + combinedMap = from->getDataRef()->scope; // Actually, just do this file. We're moving back to using include files + for (auto i = combinedMap.begin(); i != combinedMap.end(); i++) { + for (auto declaration : i->second) { + std::vector*> decChildren = declaration->getChildren(); + ASTData declarationData = declaration->getData(); + switch(declarationData.type) { + case identifier: + variableDeclarations += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n"; + variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*extern identifier*/\n"; + break; + case function: + { + if (declarationData.valueType->baseType == template_type) + functionPrototypes += "/* template function " + declarationData.symbol.toString() + " */\n"; + else if (decChildren.size() == 0) //Not a real function, must be a built in passthrough + functionPrototypes += "/* built in function: " + declarationData.symbol.toString() + " */\n"; + else { + functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType) + " "; + std::string nameDecoration, parameters; + for (int j = 0; j < decChildren.size()-1; j++) { + if (j > 0) + parameters += ", "; + parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], nullptr); + nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType); + } + functionPrototypes += CifyName(declarationData.symbol.getName() + nameDecoration) + "(" + parameters + "); /*func*/\n"; + // Only generate function if this is the unit it was defined in + std::cout << "Generating " << CifyName(declarationData.symbol.getName()) << std::endl; + if (contains(children, declaration)) + functionDefinitions += generate(declaration, nullptr); + } + } + break; + case type_def: + //type + plainTypedefs += "/*typedef " + declarationData.symbol.getName() + " */\n"; + + if (declarationData.valueType->baseType == template_type) { + plainTypedefs += "/* non instantiated template " + declarationData.symbol.getName() + " */"; + } else if (declarationData.valueType->typeDefinition != declaration) { + if (declarationData.valueType->typeDefinition) + 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) + " " + CifyName(declarationData.symbol.getName()) + ";\n"; + plainTypedefs += generateAliasChains(from, declaration); + } else { + plainTypedefs += "typedef struct __struct_dummy_" + CifyName(declarationData.symbol.getName()) + "__ " + 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"; + for (int j = 0; j < decChildren.size(); j++) { + std::cout << decChildren[j]->getName() << std::endl; + if (decChildren[j]->getName() == "function") //If object method + objectFunctionDefinitions += generateObjectMethod(declaration, decChildren[j], &functionPrototypes) + "\n"; + } + // Add all aliases to the plain typedefs. This will add any alias that aliases to this object, and any alias that aliases to that, and so on + plainTypedefs += generateAliasChains(from, declaration); + functionPrototypes += "/* Done with " + declarationData.symbol.getName() + " */\n"; + // If this is the file the object is defined in, include methods + if (contains(children, declaration)) + functionDefinitions += objectFunctionDefinitions + "/* Done with " + declarationData.symbol.getName() + " */\n"; + } + 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"; + hOutput += "/*unknown declaration named " + declaration->getName() + "*/\n"; + } + } + } + hOutput += plainTypedefs + importIncludes + variableExternDeclarations + classStructs + functionPrototypes; + cOutput += variableDeclarations + functionDefinitions; + return std::make_pair(hOutput, cOutput); +} + //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 std::string CGenerator::generate(NodeTree* from, NodeTree* enclosingObject) { ASTData data = from->getData(); @@ -78,127 +247,17 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc switch (data.type) { case translation_unit: { - // 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. - - 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"; - - Poset*> typedefPoset; - 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 - } - } - } - } - //Now generate the typedef's in the correct, topological order - for (NodeTree* i : typedefPoset.getTopoSort()) - classStructs += generateClassStruct(i) + "\n"; - - //Declare everything in translation unit scope here. (allows stuff from other files, automatic forward declarations) - for (auto i = data.scope.begin(); i != data.scope.end(); i++) { - for (auto declaration : i->second) { - std::vector*> decChildren = declaration->getChildren(); - ASTData declarationData = declaration->getData(); - switch(declarationData.type) { - case identifier: - variableDeclarations += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n"; - break; - case function: - { - if (declarationData.valueType->baseType == template_type) - functionPrototypes += "/* template function " + declarationData.symbol.toString() + " */\n"; - else if (decChildren.size() == 0) //Not a real function, must be a built in passthrough - functionPrototypes += "/* built in function: " + declarationData.symbol.toString() + " */\n"; - else { - functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType) + " "; - std::string nameDecoration, parameters; - for (int j = 0; j < decChildren.size()-1; j++) { - if (j > 0) - parameters += ", "; - parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], enclosingObject); - nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType); - } - functionPrototypes += CifyName(declarationData.symbol.getName() + nameDecoration) + "(" + parameters + "); /*func*/\n"; - // Only generate function if this is the unit it was defined in - std::cout << "Generating " << CifyName(declarationData.symbol.getName()) << std::endl; - if (contains(children, declaration)) - functionDefinitions += generate(declaration, enclosingObject); - } - } - break; - case type_def: - //type - plainTypedefs += "/*typedef " + declarationData.symbol.getName() + " */\n"; - - if (declarationData.valueType->baseType == template_type) { - plainTypedefs += "/* non instantiated template " + declarationData.symbol.getName() + " */"; - } else if (declarationData.valueType->typeDefinition != declaration) { - if (declarationData.valueType->typeDefinition) - 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) + " " + CifyName(declarationData.symbol.getName()) + ";\n"; - plainTypedefs += generateAliasChains(from, declaration); - } else { - plainTypedefs += "typedef struct __struct_dummy_" + CifyName(declarationData.symbol.getName()) + "__ " + 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"; - for (int j = 0; j < decChildren.size(); j++) { - std::cout << decChildren[j]->getName() << std::endl; - if (decChildren[j]->getName() == "function") //If object method - objectFunctionDefinitions += generateObjectMethod(declaration, decChildren[j], &functionPrototypes) + "\n"; - } - // Add all aliases to the plain typedefs. This will add any alias that aliases to this object, and any alias that aliases to that, and so on - plainTypedefs += generateAliasChains(from, declaration); - functionPrototypes += "/* Done with " + declarationData.symbol.getName() + " */\n"; - // If this is the file the object is defined in, include methods - if (contains(children, declaration)) - functionDefinitions += objectFunctionDefinitions + "/* Done with " + declarationData.symbol.getName() + " */\n"; - } - break; - default: - //std::cout << "Declaration? named " << declaration->getName() << " of unknown type " << ASTData::ASTTypeToString(declarationData.type) << " in translation unit scope" << std::endl; - output += "/*unknown declaration named " + declaration->getName() + "*/\n"; - } - } - } - output += plainTypedefs + variableDeclarations + classStructs + functionPrototypes + functionDefinitions; - return output; + // Should not happen! We do this in it's own function now! + std::cout << "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 "/* would import \"" + data.symbol.getName() + "\" but....*/\n"; + return "/* never reached import? */\n"; + //return "include \"" + data.symbol.getName() + ".h\" //woo importing!\n"; //return "#include <" + data.symbol.getName() + ">\n"; case identifier: { @@ -421,7 +480,9 @@ std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, return functionSignature + "\n" + generate(children[children.size()-1], enclosingObject); //Pass in the object so we can properly handle access to member stuff } -std::string CGenerator::ValueTypeToCType(Type *type) { +std::string CGenerator::ValueTypeToCType(Type *type) { return ValueTypeToCTypeThingHelper(type, "*"); } +std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return ValueTypeToCTypeThingHelper(type, "_P__"); } +std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr) { std::string return_type; switch (type->baseType) { case none: @@ -453,43 +514,7 @@ std::string CGenerator::ValueTypeToCType(Type *type) { break; } for (int i = 0; i < type->getIndirection(); i++) - return_type += "*"; - return return_type; -} - -std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { - std::string return_type; - switch (type->baseType) { - case none: - if (type->typeDefinition) - return_type = CifyName(type->typeDefinition->getDataRef()->symbol.getName()); - else - return_type = "none"; - 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; - } - for (int i = 0; i < type->getIndirection(); i++) - return_type += "_P__"; + return_type += ptrStr; return return_type; } @@ -510,6 +535,7 @@ std::string CGenerator::CifyName(std::string name) { "--", "doubleminus", "<<", "doubleleft", ">>", "doubleright", + "::", "scopeop", "==", "doubleequals", "!=", "notequals", "&&", "doubleamprsnd", diff --git a/src/Importer.cpp b/src/Importer.cpp index 7d6ac37..36b84d2 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -10,7 +10,8 @@ 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)); removeSymbols.push_back(Symbol("{", true)); removeSymbols.push_back(Symbol("}", true)); @@ -26,6 +27,7 @@ Importer::Importer(Parser* parserIn, std::vector includePaths) { removeSymbols.push_back(Symbol("template", true)); removeSymbols.push_back(Symbol("\\|", true)); + //collapseSymbols.push_back(Symbol("scoped_identifier", false)); collapseSymbols.push_back(Symbol("opt_typed_parameter_list", false)); collapseSymbols.push_back(Symbol("opt_parameter_list", false)); collapseSymbols.push_back(Symbol("opt_import_list", false)); diff --git a/src/Tester.cpp b/src/Tester.cpp index 3f4cbdf..99642fc 100644 --- a/src/Tester.cpp +++ b/src/Tester.cpp @@ -2,13 +2,15 @@ Tester::Tester(std::string krakenInvocation, std::string krakenGrammerLocation) : krakenInvocation(krakenInvocation), krakenGrammerLocation(krakenGrammerLocation) { //initlization list - removeCmd = "rm"; + removeCmd = "rm -r"; resultsExtention = ".results"; expectedExtention = ".expected_results"; krakenExtention = ".krak"; changePermissions = "chmod 755"; shell = "sh"; + cd = "cd"; redirect = ">"; + sep = "/"; } Tester::~Tester() { @@ -21,27 +23,24 @@ int Tester::ssystem(std::string command) { void Tester::cleanExtras(std::string fileName) { ssystem(removeCmd + " " + fileName); - ssystem(removeCmd + " " + fileName + krakenExtention + "out*"); - ssystem(removeCmd + " " + fileName + krakenExtention + ".c"); - ssystem(removeCmd + " " + fileName + ".sh"); - ssystem(removeCmd + " " + fileName + resultsExtention); } -bool Tester::run(std::string fileName) { +bool Tester::run(std::string path) { + std::string fileName = split(path, *sep.c_str()).back(); std::cout << "Testing: " << fileName << " with " << krakenInvocation << " and " << krakenGrammerLocation << std::endl; - - cleanExtras(fileName); - - ssystem(changePermissions + " " + fileName); - ssystem(krakenInvocation + " " + fileName + krakenExtention + " " + krakenGrammerLocation + " " + fileName); - ssystem(shell + " " + fileName + ".sh"); - ssystem(fileName + " " + redirect + " " + fileName + resultsExtention); - bool result = compareFiles(fileName + expectedExtention, fileName + resultsExtention); - + cleanExtras(path); + ssystem(krakenInvocation + " " + path + krakenExtention + " " + krakenGrammerLocation + " " + path); + ssystem(changePermissions + " " + path + sep + fileName + ".sh"); + ssystem(cd + " " + path + "; " + "./" + fileName + ".sh"); + ssystem(changePermissions + " " + path + sep + fileName); + ssystem(path + sep + fileName + " " + redirect + " " + path + sep + fileName + resultsExtention); + + bool result = compareFiles(fileName + expectedExtention, path + sep + fileName + resultsExtention); + //If the test was succesful, we don't need all the extra files if (result) - cleanExtras(fileName); + cleanExtras(path); return result; } diff --git a/stdlib/trivial_container.krak b/stdlib/trivial_container.krak index 80bebeb..4b70141 100644 --- a/stdlib/trivial_container.krak +++ b/stdlib/trivial_container.krak @@ -3,7 +3,7 @@ import io; typedef template trivialContainer { |T| data; |void| print() { - print(data); + io::print(data); } }; diff --git a/tests/OperatorOverloadTest.krak b/tests/OperatorOverloadTest.krak index bcc1d78..4218ba2 100644 --- a/tests/OperatorOverloadTest.krak +++ b/tests/OperatorOverloadTest.krak @@ -1,4 +1,4 @@ -import io; +import io:*; typedef Vec2 { |int| x; diff --git a/tests/RecursiveTest.krak b/tests/RecursiveTest.krak index 03c8b9f..87deed8 100644 --- a/tests/RecursiveTest.krak +++ b/tests/RecursiveTest.krak @@ -1,4 +1,4 @@ -import io; +import io:*; |int| fibanacci(|int| num) { if (num < 2) diff --git a/tests/commentFirstTest.krak b/tests/commentFirstTest.krak index 0cd8f27..4030ec5 100644 --- a/tests/commentFirstTest.krak +++ b/tests/commentFirstTest.krak @@ -1,5 +1,5 @@ /* Comment first! */ -import io; +import io:*; |int| main() { println(1337); diff --git a/tests/declarationsTest.krak b/tests/declarationsTest.krak index 4e29cc4..84e8ee3 100644 --- a/tests/declarationsTest.krak +++ b/tests/declarationsTest.krak @@ -1,5 +1,5 @@ -import io; -import mem; +import io:*; +import mem:*; typedef ClassWithConstructor { |int| data; diff --git a/tests/destructorTest.krak b/tests/destructorTest.krak index a63276f..65223f1 100644 --- a/tests/destructorTest.krak +++ b/tests/destructorTest.krak @@ -1,4 +1,4 @@ -import io; +import io:*; typedef DestructorPrint { |char*| myStr; diff --git a/tests/emptyBracesFunction.krak b/tests/emptyBracesFunction.krak index d02cbd7..1413c75 100644 --- a/tests/emptyBracesFunction.krak +++ b/tests/emptyBracesFunction.krak @@ -4,6 +4,6 @@ import io; |int| main() { nothing(); - println("It was nothing"); + io::println("It was nothing"); return 0; } diff --git a/tests/functionMultipleTemplateTest.krak b/tests/functionMultipleTemplateTest.krak index a30f9d5..e6ff2dc 100644 --- a/tests/functionMultipleTemplateTest.krak +++ b/tests/functionMultipleTemplateTest.krak @@ -1,4 +1,4 @@ -import io; +import io:*; template |void| addAndPrint(|T| a, |J| b) { print(a+b); diff --git a/tests/functionOrderingTest.krak b/tests/functionOrderingTest.krak index c26f5a9..9c89e95 100644 --- a/tests/functionOrderingTest.krak +++ b/tests/functionOrderingTest.krak @@ -1,4 +1,4 @@ -import io; +import io:*; |int| ret1() { return ret2() / 2; diff --git a/tests/functionTemplateTest.krak b/tests/functionTemplateTest.krak index e6b2597..e104d20 100644 --- a/tests/functionTemplateTest.krak +++ b/tests/functionTemplateTest.krak @@ -1,13 +1,13 @@ import io; template |T| addAndPrint(|T| a, |T| b) { - print(a+b); + io::print(a+b); return a+b; } |int| main() { addAndPrint(10,12); - print("\n"); + io::print("\n"); return 0; } diff --git a/tests/memTest.krak b/tests/memTest.krak index 6ddbac9..b9a2c41 100644 --- a/tests/memTest.krak +++ b/tests/memTest.krak @@ -1,5 +1,5 @@ -import mem; -import io; +import mem:*; +import io:*; typedef AnObject { |int| a; diff --git a/tests/moreComplexObjectTest.krak b/tests/moreComplexObjectTest.krak index 2c06e6b..59fe0df 100644 --- a/tests/moreComplexObjectTest.krak +++ b/tests/moreComplexObjectTest.krak @@ -1,4 +1,4 @@ -import io; +import io:*; typedef firstObject { |int| objectNum; diff --git a/tests/moreObjectTemplateTest.krak b/tests/moreObjectTemplateTest.krak index 6c7ae78..e4be5b2 100644 --- a/tests/moreObjectTemplateTest.krak +++ b/tests/moreObjectTemplateTest.krak @@ -1,5 +1,5 @@ -import io; -import trivial_container; +import io:*; +import trivial_container:*; typedef RegularObject { |int| num; diff --git a/tests/newScoping.expected_results b/tests/newScoping.expected_results new file mode 100644 index 0000000..2d170cc --- /dev/null +++ b/tests/newScoping.expected_results @@ -0,0 +1,13 @@ +Qualified io! +0 +9 +11 +Qualified Container! +Even template functions qualified! + +Unqualified io! +0 +10 +12 +Unqualified Container! +Even template functions unqualified! diff --git a/tests/newScoping.krak b/tests/newScoping.krak new file mode 100644 index 0000000..9a081af --- /dev/null +++ b/tests/newScoping.krak @@ -0,0 +1,32 @@ +import io; +import scopeQualified; +import scopeUnqualified : * ; + +|int| main() { + io::println("Qualified io!"); + + // Defined in scopeQualified + io::println(scopeQualified::qualified_variable); + io::println(scopeQualified::qualified_func()); + |scopeQualified::qualified_class| qClass.construct(11); + io::println(qClass.get()); + + |scopeQualified::qualified_container| sayQualified.construct("Qualified Container!"); + io::println(sayQualified.get()); + io::println(scopeQualified::qualified_id("Even template functions qualified!")); + + io::println(); + + io::println("Unqualified io!"); + // Defined in scopeUnqualified + io::println(unqualifed_variable); + io::println(unqualified_func()); + |unqualified_class| uqClass.construct(12); + io::println(uqClass.get()); + + |unqualified_container| sayUnqualified.construct("Unqualified Container!"); + io::println(sayUnqualified.get()); + io::println(unqualified_id("Even template functions unqualified!")); + + return 0; +} diff --git a/tests/objectOrderingTest.krak b/tests/objectOrderingTest.krak index 4812bb8..7fb978f 100644 --- a/tests/objectOrderingTest.krak +++ b/tests/objectOrderingTest.krak @@ -1,4 +1,4 @@ -import io; +import io:*; typedef objectA { |int| a; diff --git a/tests/runTests.sh b/tests/runTests.sh index f86e0bf..26182d2 100755 --- a/tests/runTests.sh +++ b/tests/runTests.sh @@ -1,7 +1,8 @@ #!/bin/bash krakenPath="../build/kraken" -testDir=${1:-"../tests"} +#testDir=${1:-"../tests"} +testDir="." ext=${2:-"krak"} fileList="" diff --git a/tests/scopeQualified.krak b/tests/scopeQualified.krak new file mode 100644 index 0000000..c862136 --- /dev/null +++ b/tests/scopeQualified.krak @@ -0,0 +1,27 @@ +|int| qualified_variable = 7; +|int| qualified_func() { return 9; } + +typedef qualified_class { + |int| number; + |qualified_class*| construct(|int| num) { + number = num; + return this; + } + |int| get() { + return number; + } +}; + +typedef template qualified_container { + |T| data; + |qualified_container*| construct(|T| dataIn) { + data = dataIn; + } + |T| get() { + return data; + } +}; + +template |T| qualified_id(|T| it) { + return it; +} diff --git a/tests/scopeUnqualified.krak b/tests/scopeUnqualified.krak new file mode 100644 index 0000000..f540dbf --- /dev/null +++ b/tests/scopeUnqualified.krak @@ -0,0 +1,27 @@ +|int| unqualifed_variable = 8; +|int| unqualified_func() { return 10; } + +typedef unqualified_class { + |int| number; + |unqualified_class*| construct(|int| num) { + number = num; + return this; + } + |int| get() { + return number; + } +}; + +typedef template unqualified_container { + |T| data; + |unqualified_container*| construct(|T| dataIn) { + data = dataIn; + } + |T| get() { + return data; + } +}; + +template |T| unqualified_id(|T| it) { + return it; +} diff --git a/tests/simpleFunctionTest.krak b/tests/simpleFunctionTest.krak index 2e45927..146e497 100644 --- a/tests/simpleFunctionTest.krak +++ b/tests/simpleFunctionTest.krak @@ -1,4 +1,4 @@ -import io; +import io:*; |int| addAndPrintInt(|int| a, |int| b) { print(a+b); diff --git a/tests/simpleObjectMultipleTemplateTest.krak b/tests/simpleObjectMultipleTemplateTest.krak index f3615e4..c67136f 100644 --- a/tests/simpleObjectMultipleTemplateTest.krak +++ b/tests/simpleObjectMultipleTemplateTest.krak @@ -5,12 +5,12 @@ typedef template TemplateTest { |T| a; |J| b; |void| print() { - print("a: "); - print(a); - print("\n"); - print("b: "); - print(b); - print("\n"); + io::print("a: "); + io::print(a); + io::print("\n"); + io::print("b: "); + io::print(b); + io::print("\n"); } }; diff --git a/tests/simpleObjectTemplateTest.krak b/tests/simpleObjectTemplateTest.krak index 7aeebc2..396e6ff 100644 --- a/tests/simpleObjectTemplateTest.krak +++ b/tests/simpleObjectTemplateTest.krak @@ -5,12 +5,12 @@ typedef template TemplateTest { |int| a; |T| b; |void| print() { - print("a: "); - print(a); - print("\n"); - print("b: "); - print(b); - print("\n"); + io::print("a: "); + io::print(a); + io::print("\n"); + io::print("b: "); + io::print(b); + io::print("\n"); } }; diff --git a/tests/simpleObjectTest.krak b/tests/simpleObjectTest.krak index 3e8f14f..a06ed8a 100644 --- a/tests/simpleObjectTest.krak +++ b/tests/simpleObjectTest.krak @@ -1,11 +1,10 @@ - import io; typedef FirstObject { |int| objectNum; |void| PrintSelf(|int| a) { - print(objectNum); - print(a); + io::print(objectNum); + io::print(a); } }; @@ -13,6 +12,6 @@ typedef FirstObject { |FirstObject| wooObject; wooObject.objectNum = 5; wooObject.PrintSelf(7); - print("\n"); + io::print("\n"); return 0; } diff --git a/tests/templateTest.krak b/tests/templateTest.krak index 8843126..91b4fef 100644 --- a/tests/templateTest.krak +++ b/tests/templateTest.krak @@ -1,5 +1,5 @@ -import io; -import trivial_container; +import io:*; +import trivial_container:*; typedef template TemplateTest { |int| a; diff --git a/tests/testArrayNotation.krak b/tests/testArrayNotation.krak index 9b04b25..02402f3 100644 --- a/tests/testArrayNotation.krak +++ b/tests/testArrayNotation.krak @@ -1,5 +1,5 @@ -import io; -import mem; +import io:*; +import mem:*; |int| main() { |int| b; diff --git a/tests/topLevelVarInit.expected_results b/tests/topLevelVarInit.expected_results new file mode 100644 index 0000000..d81cc07 --- /dev/null +++ b/tests/topLevelVarInit.expected_results @@ -0,0 +1 @@ +42 diff --git a/tests/topLevelVarInit.krak b/tests/topLevelVarInit.krak new file mode 100644 index 0000000..9f8aa92 --- /dev/null +++ b/tests/topLevelVarInit.krak @@ -0,0 +1,8 @@ +import io; + +|int| a = 42; + +|int| main() { + io::println(a); + return 0; +} diff --git a/tests/traitsTest.krak b/tests/traitsTest.krak index 566e5ed..b9b55b0 100644 --- a/tests/traitsTest.krak +++ b/tests/traitsTest.krak @@ -1,4 +1,4 @@ -import io; +import io:*; typedef NoTraits {}; @@ -48,13 +48,13 @@ typedef template OneTwoObj {}; |Trait2| c; |TwoTrait| d; |AlreadySpecilized| e; - + OneTwoFunc(a); OneTwoFunc(b); OneTwoFunc(c); OneTwoFunc(d); // OneTwoFunc(e); - + println(); |OneTwoObj| alpha; diff --git a/tests/typeExpr.krak b/tests/typeExpr.krak index e7dcae2..4b2db33 100644 --- a/tests/typeExpr.krak +++ b/tests/typeExpr.krak @@ -7,7 +7,7 @@ typedef ClassWithConstructor { return this; } |void| printData() { - println(data); + io::println(data); } }; @@ -15,6 +15,6 @@ typedef ClassWithConstructor { |ClassWithConstructor| object.construct(4); object.printData(); |int| a = 8; - println(a); + io::println(a); return 0; } diff --git a/tests/vectorTest.krak b/tests/vectorTest.krak index 579fe24..c47e3de 100644 --- a/tests/vectorTest.krak +++ b/tests/vectorTest.krak @@ -1,6 +1,6 @@ -import io; -import mem; -import vector; +import io:*; +import mem:*; +import vector:*; typedef AbleToBeDestroyed (Destructable) { |void| destruct() { @@ -16,9 +16,9 @@ typedef AbleToBeDestroyed (Destructable) { intVec.addEnd(7); for (|int| i = 0; i < intVec.size; i++;) print(intVec.at(i)); - + println(); - + |vector*| desVec = new>()->construct(); |AbleToBeDestroyed| testDestruct; desVec->addEnd(testDestruct);