Got the new scoping working! Still some odd stuff happening to certian templates, and I think vector is having problems with new/traits. Really need to get canonnical filenames and what not worked out

This commit is contained in:
Nathan Braswell
2014-12-30 01:22:09 -05:00
parent 417e5ed898
commit aaca71a211
35 changed files with 282 additions and 232 deletions

View File

@@ -1,5 +1,12 @@
Declaration of a pointer and multiplication are ambigious! correctly importing / running tests is a nightmare with relative paths.
( T* a; maybe either a declaration or a multiplication)
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 destructors being placed after return.
Fix functions before declaration? (in class? (this is from an old file)) Fix functions before declaration? (in class? (this is from an old file))

Binary file not shown.

View File

@@ -4,6 +4,8 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <utility>
#include <sys/stat.h>
#include "NodeTree.h" #include "NodeTree.h"
#include "ASTData.h" #include "ASTData.h"
@@ -12,6 +14,7 @@
#include "util.h" #include "util.h"
#include "Poset.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 { class CGenerator {
public: public:
@@ -19,12 +22,16 @@ class CGenerator {
~CGenerator(); ~CGenerator();
void generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs, std::string outputName); void generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs, std::string outputName);
std::string generateClassStruct(NodeTree<ASTData>* from); std::string generateClassStruct(NodeTree<ASTData>* from);
bool isUnderTranslationUnit(NodeTree<ASTData>* from, NodeTree<ASTData>* typeDefinition);
NodeTree<ASTData>* highestScope(NodeTree<ASTData>* node);
std::pair<std::string, std::string> generateTranslationUnit(NodeTree<ASTData>* from);
std::string generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject = NULL); std::string generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject = NULL);
std::string generateAliasChains(NodeTree<ASTData>* scopeNode, NodeTree<ASTData>* definition); std::string generateAliasChains(NodeTree<ASTData>* scopeNode, NodeTree<ASTData>* definition);
static std::string ValueTypeToCType(Type *type); static std::string ValueTypeToCType(Type *type);
static std::string ValueTypeToCTypeDecoration(Type *type); static std::string ValueTypeToCTypeDecoration(Type *type);
static std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr);
static std::string CifyName(std::string name); static std::string CifyName(std::string name);
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype); std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype);
NodeTree<ASTData>* getMethodsObjectType(NodeTree<ASTData>* scope, std::string functionName); NodeTree<ASTData>* getMethodsObjectType(NodeTree<ASTData>* scope, std::string functionName);
std::string generatorString; std::string generatorString;
private: private:

View File

@@ -15,7 +15,7 @@ class Tester {
int ssystem(std::string command); int ssystem(std::string command);
bool run(std::string fileName); bool run(std::string fileName);
bool compareFiles(std::string file1Path, std::string file2Path); bool compareFiles(std::string file1Path, std::string file2Path);
void cleanExtras(std::string fileName); void cleanExtras(std::string path);
private: private:
std::string krakenInvocation; std::string krakenInvocation;
@@ -27,5 +27,7 @@ class Tester {
std::string shell; std::string shell;
std::string changePermissions; std::string changePermissions;
std::string redirect; std::string redirect;
std::string sep;
std::string cd;
}; };
#endif #endif

Binary file not shown.

View File

@@ -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<std::string, NodeTree<ASTData>*> ASTs, std::string outputName) { void CGenerator::generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs, std::string outputName) {
//Generate an entire set of files //Generate an entire set of files
std::string buildString = "#!/bin/sh\ncc -std=c99 "; 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++) { for (auto i = ASTs.begin(); i != ASTs.end(); i++) {
std::cout << "\n\nGenerate pass for: " << i->first << std::endl;
buildString += i->first + ".c "; buildString += i->first + ".c ";
std::ofstream outputCFile; std::ofstream outputCFile, outputHFile;
outputCFile.open(i->first + ".c"); outputCFile.open(outputName + "/" + i->first + ".c");
if (outputCFile.is_open()) { outputHFile.open(outputName + "/" + i->first + ".h");
if (outputCFile.is_open() || outputHFile.is_open()) {
// Prequel common to all files // Prequel common to all files
outputCFile << "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n" << generate(i->second); auto chPair = generateTranslationUnit(i->second);
outputHFile << "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n" << chPair.first;
outputCFile << "#include \"" + i->first + ".h\"\n\n" << chPair.second;
} else { } else {
std::cout << "Cannot open file " << i->first << ".c" << std::endl; std::cout << "Cannot open file " << i->first << ".c/h" << std::endl;
} }
outputCFile.close(); outputCFile.close();
outputHFile.close();
} }
buildString += "-o " + outputName; buildString += "-o " + outputName;
std::ofstream outputBuild; std::ofstream outputBuild;
outputBuild.open(outputName + ".sh"); outputBuild.open(outputName + "/" + split(outputName, '/').back() + ".sh");
outputBuild << buildString; outputBuild << buildString;
outputBuild.close(); outputBuild.close();
} }
@@ -70,6 +81,164 @@ std::string CGenerator::generateAliasChains(NodeTree<ASTData>* scopeNode, NodeTr
return output; return output;
} }
bool CGenerator::isUnderTranslationUnit(NodeTree<ASTData>* from, NodeTree<ASTData>* 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<ASTData>* CGenerator::highestScope(NodeTree<ASTData>* 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<std::string, std::string> CGenerator::generateTranslationUnit(NodeTree<ASTData>* from) {
ASTData data = from->getData();
std::vector<NodeTree<ASTData>*> 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<NodeTree<ASTData>*> 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<NodeTree<ASTData>*> 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<ASTData>* 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<std::string, std::vector<NodeTree<ASTData>*>> 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<NodeTree<ASTData>*> 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 //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<ASTData>* from, NodeTree<ASTData>* enclosingObject) { std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject) {
ASTData data = from->getData(); ASTData data = from->getData();
@@ -78,127 +247,17 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
switch (data.type) { switch (data.type) {
case translation_unit: case translation_unit:
{ {
// Ok, so we've got to do this in passes to preserve mututally recursive definitions. // 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;
// First Pass: All classes get "struct dummy_thing; typedef struct dummy_thing thing;". throw "That's not gonna work";
// 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<NodeTree<ASTData>*> 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<NodeTree<ASTData>*> 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<ASTData>* 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<NodeTree<ASTData>*> 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;
} }
break; break;
case interpreter_directive: case interpreter_directive:
//Do nothing //Do nothing
break; break;
case import: 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"; //return "#include <" + data.symbol.getName() + ">\n";
case identifier: case identifier:
{ {
@@ -421,7 +480,9 @@ std::string CGenerator::generateObjectMethod(NodeTree<ASTData>* enclosingObject,
return functionSignature + "\n" + generate(children[children.size()-1], enclosingObject); //Pass in the object so we can properly handle access to member stuff 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; std::string return_type;
switch (type->baseType) { switch (type->baseType) {
case none: case none:
@@ -453,43 +514,7 @@ std::string CGenerator::ValueTypeToCType(Type *type) {
break; break;
} }
for (int i = 0; i < type->getIndirection(); i++) for (int i = 0; i < type->getIndirection(); i++)
return_type += "*"; return_type += ptrStr;
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 return_type; return return_type;
} }
@@ -510,6 +535,7 @@ std::string CGenerator::CifyName(std::string name) {
"--", "doubleminus", "--", "doubleminus",
"<<", "doubleleft", "<<", "doubleleft",
">>", "doubleright", ">>", "doubleright",
"::", "scopeop",
"==", "doubleequals", "==", "doubleequals",
"!=", "notequals", "!=", "notequals",
"&&", "doubleamprsnd", "&&", "doubleamprsnd",

View File

@@ -2,13 +2,15 @@
Tester::Tester(std::string krakenInvocation, std::string krakenGrammerLocation) : krakenInvocation(krakenInvocation), krakenGrammerLocation(krakenGrammerLocation) { Tester::Tester(std::string krakenInvocation, std::string krakenGrammerLocation) : krakenInvocation(krakenInvocation), krakenGrammerLocation(krakenGrammerLocation) {
//initlization list //initlization list
removeCmd = "rm"; removeCmd = "rm -r";
resultsExtention = ".results"; resultsExtention = ".results";
expectedExtention = ".expected_results"; expectedExtention = ".expected_results";
krakenExtention = ".krak"; krakenExtention = ".krak";
changePermissions = "chmod 755"; changePermissions = "chmod 755";
shell = "sh"; shell = "sh";
cd = "cd";
redirect = ">"; redirect = ">";
sep = "/";
} }
Tester::~Tester() { Tester::~Tester() {
@@ -21,27 +23,24 @@ int Tester::ssystem(std::string command) {
void Tester::cleanExtras(std::string fileName) { void Tester::cleanExtras(std::string fileName) {
ssystem(removeCmd + " " + 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; std::cout << "Testing: " << fileName << " with " << krakenInvocation << " and " << krakenGrammerLocation << std::endl;
cleanExtras(fileName); 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);
ssystem(changePermissions + " " + fileName); bool result = compareFiles(fileName + expectedExtention, path + sep + fileName + resultsExtention);
ssystem(krakenInvocation + " " + fileName + krakenExtention + " " + krakenGrammerLocation + " " + fileName);
ssystem(shell + " " + fileName + ".sh");
ssystem(fileName + " " + redirect + " " + fileName + resultsExtention);
bool result = compareFiles(fileName + expectedExtention, fileName + resultsExtention);
//If the test was succesful, we don't need all the extra files //If the test was succesful, we don't need all the extra files
if (result) if (result)
cleanExtras(fileName); cleanExtras(path);
return result; return result;
} }

View File

@@ -3,7 +3,7 @@ import io;
typedef template <T> trivialContainer { typedef template <T> trivialContainer {
|T| data; |T| data;
|void| print() { |void| print() {
print(data); io::print(data);
} }
}; };

View File

@@ -1,4 +1,4 @@
import io; import io:*;
typedef Vec2 { typedef Vec2 {
|int| x; |int| x;

View File

@@ -1,4 +1,4 @@
import io; import io:*;
|int| fibanacci(|int| num) { |int| fibanacci(|int| num) {
if (num < 2) if (num < 2)

View File

@@ -1,5 +1,5 @@
/* Comment first! */ /* Comment first! */
import io; import io:*;
|int| main() { |int| main() {
println(1337); println(1337);

View File

@@ -1,5 +1,5 @@
import io; import io:*;
import mem; import mem:*;
typedef ClassWithConstructor { typedef ClassWithConstructor {
|int| data; |int| data;

View File

@@ -1,4 +1,4 @@
import io; import io:*;
typedef DestructorPrint { typedef DestructorPrint {
|char*| myStr; |char*| myStr;

View File

@@ -4,6 +4,6 @@ import io;
|int| main() { |int| main() {
nothing(); nothing();
println("It was nothing"); io::println("It was nothing");
return 0; return 0;
} }

View File

@@ -1,4 +1,4 @@
import io; import io:*;
template <T,J> |void| addAndPrint(|T| a, |J| b) { template <T,J> |void| addAndPrint(|T| a, |J| b) {
print(a+b); print(a+b);

View File

@@ -1,4 +1,4 @@
import io; import io:*;
|int| ret1() { |int| ret1() {
return ret2() / 2; return ret2() / 2;

View File

@@ -1,13 +1,13 @@
import io; import io;
template <T> |T| addAndPrint(|T| a, |T| b) { template <T> |T| addAndPrint(|T| a, |T| b) {
print(a+b); io::print(a+b);
return a+b; return a+b;
} }
|int| main() { |int| main() {
addAndPrint<int>(10,12); addAndPrint<int>(10,12);
print("\n"); io::print("\n");
return 0; return 0;
} }

View File

@@ -1,5 +1,5 @@
import mem; import mem:*;
import io; import io:*;
typedef AnObject { typedef AnObject {
|int| a; |int| a;

View File

@@ -1,4 +1,4 @@
import io; import io:*;
typedef firstObject { typedef firstObject {
|int| objectNum; |int| objectNum;

View File

@@ -1,5 +1,5 @@
import io; import io:*;
import trivial_container; import trivial_container:*;
typedef RegularObject { typedef RegularObject {
|int| num; |int| num;

View File

@@ -1,12 +1,12 @@
Qualified io! Qualified io!
7 0
9 9
11 11
Qualified Container! Qualified Container!
Even template functions qualified! Even template functions qualified!
Unqualified io! Unqualified io!
8 0
10 10
12 12
Unqualified Container! Unqualified Container!

View File

@@ -1,4 +1,4 @@
import io; import io:*;
typedef objectA { typedef objectA {
|int| a; |int| a;

View File

@@ -1,7 +1,8 @@
#!/bin/bash #!/bin/bash
krakenPath="../build/kraken" krakenPath="../build/kraken"
testDir=${1:-"../tests"} #testDir=${1:-"../tests"}
testDir="."
ext=${2:-"krak"} ext=${2:-"krak"}
fileList="" fileList=""

View File

@@ -3,7 +3,7 @@
typedef unqualified_class { typedef unqualified_class {
|int| number; |int| number;
|qualified_class*| construct(|int| num) { |unqualified_class*| construct(|int| num) {
number = num; number = num;
return this; return this;
} }

View File

@@ -1,4 +1,4 @@
import io; import io:*;
|int| addAndPrintInt(|int| a, |int| b) { |int| addAndPrintInt(|int| a, |int| b) {
print(a+b); print(a+b);

View File

@@ -5,12 +5,12 @@ typedef template <T,J> TemplateTest {
|T| a; |T| a;
|J| b; |J| b;
|void| print() { |void| print() {
print("a: "); io::print("a: ");
print(a); io::print(a);
print("\n"); io::print("\n");
print("b: "); io::print("b: ");
print(b); io::print(b);
print("\n"); io::print("\n");
} }
}; };

View File

@@ -5,12 +5,12 @@ typedef template <T> TemplateTest {
|int| a; |int| a;
|T| b; |T| b;
|void| print() { |void| print() {
print("a: "); io::print("a: ");
print(a); io::print(a);
print("\n"); io::print("\n");
print("b: "); io::print("b: ");
print(b); io::print(b);
print("\n"); io::print("\n");
} }
}; };

View File

@@ -1,11 +1,10 @@
import io; import io;
typedef FirstObject { typedef FirstObject {
|int| objectNum; |int| objectNum;
|void| PrintSelf(|int| a) { |void| PrintSelf(|int| a) {
print(objectNum); io::print(objectNum);
print(a); io::print(a);
} }
}; };
@@ -13,6 +12,6 @@ typedef FirstObject {
|FirstObject| wooObject; |FirstObject| wooObject;
wooObject.objectNum = 5; wooObject.objectNum = 5;
wooObject.PrintSelf(7); wooObject.PrintSelf(7);
print("\n"); io::print("\n");
return 0; return 0;
} }

View File

@@ -1,5 +1,5 @@
import io; import io:*;
import trivial_container; import trivial_container:*;
typedef template <T> TemplateTest { typedef template <T> TemplateTest {
|int| a; |int| a;

View File

@@ -1,5 +1,5 @@
import io; import io:*;
import mem; import mem:*;
|int| main() { |int| main() {
|int| b; |int| b;

View File

@@ -0,0 +1 @@
42

View File

@@ -0,0 +1,8 @@
import io;
|int| a = 42;
|int| main() {
io::println(a);
return 0;
}

View File

@@ -1,4 +1,4 @@
import io; import io:*;
typedef NoTraits {}; typedef NoTraits {};

View File

@@ -7,7 +7,7 @@ typedef ClassWithConstructor {
return this; return this;
} }
|void| printData() { |void| printData() {
println(data); io::println(data);
} }
}; };
@@ -15,6 +15,6 @@ typedef ClassWithConstructor {
|ClassWithConstructor| object.construct(4); |ClassWithConstructor| object.construct(4);
object.printData(); object.printData();
|int| a = 8; |int| a = 8;
println(a); io::println(a);
return 0; return 0;
} }

View File

@@ -1,6 +1,6 @@
import io; import io:*;
import mem; import mem:*;
import vector; import vector:*;
typedef AbleToBeDestroyed (Destructable) { typedef AbleToBeDestroyed (Destructable) {
|void| destruct() { |void| destruct() {