WOOO compiles all in one file! Dependencies resolved! Next up, C name mangeling for scoping

This commit is contained in:
Nathan Braswell
2015-03-11 01:58:10 -04:00
parent 9e9b4371da
commit 6a311fb237
14 changed files with 230 additions and 133 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
_site _site
build build
build-ninja
*.comp *.comp
stats stats
*.swp *.swp

View File

@@ -49,6 +49,7 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules = false); std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules = false);
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules, std::vector<NodeTree<ASTData>*> visited); std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules, std::vector<NodeTree<ASTData>*> visited);
NodeTree<ASTData>* getUpperTranslationUnit(NodeTree<ASTData>* node);
Type* typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements); Type* typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements);
NodeTree<ASTData>* templateClassLookup(NodeTree<ASTData>* scope, std::string name, std::vector<Type*> templateInstantiationTypes); NodeTree<ASTData>* templateClassLookup(NodeTree<ASTData>* scope, std::string name, std::vector<Type*> templateInstantiationTypes);
NodeTree<ASTData>* findOrInstantiateFunctionTemplate(std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements); NodeTree<ASTData>* findOrInstantiateFunctionTemplate(std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);

View File

@@ -24,9 +24,9 @@ class CGenerator {
std::string generateClassStruct(NodeTree<ASTData>* from); std::string generateClassStruct(NodeTree<ASTData>* from);
bool isUnderTranslationUnit(NodeTree<ASTData>* from, NodeTree<ASTData>* typeDefinition); bool isUnderTranslationUnit(NodeTree<ASTData>* from, NodeTree<ASTData>* typeDefinition);
NodeTree<ASTData>* highestScope(NodeTree<ASTData>* node); NodeTree<ASTData>* highestScope(NodeTree<ASTData>* node);
std::pair<std::string, std::string> generateTranslationUnit(NodeTree<ASTData>* from); std::pair<std::string, std::string> generateTranslationUnit(std::string name, std::map<std::string, NodeTree<ASTData>*> ASTs);
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(std::map<std::string, NodeTree<ASTData>*> ASTs, 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 ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr);

View File

@@ -1112,6 +1112,18 @@ std::vector<NodeTree<ASTData>*> ASTTransformation::scopeLookup(NodeTree<ASTData>
return matches; return matches;
} }
// Find the translation unit that is the top of the passed in node
NodeTree<ASTData>* ASTTransformation::getUpperTranslationUnit(NodeTree<ASTData>* node) {
auto scope = node->getDataRef()->scope;
auto iter = scope.find("~enclosing_scope");
while(iter != scope.end()) {
node = iter->second[0];
scope = node->getDataRef()->scope;
iter = scope.find("~enclosing_scope");
}
return node;
}
//Create a type from a syntax tree. This can get complicated with templates //Create a type from a syntax tree. This can get complicated with templates
Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements) { Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements) {
std::string typeIn = concatSymbolTree(typeNode); std::string typeIn = concatSymbolTree(typeNode);
@@ -1180,16 +1192,16 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
//Finish creating the new name for this instantiation //Finish creating the new name for this instantiation
std::string classNameWithoutTemplate = concatSymbolTree(typeNode->getChildren()[0]); std::string classNameWithoutTemplate = concatSymbolTree(typeNode->getChildren()[0]);
std::string fullyInstantiatedName = classNameWithoutTemplate + "<" + instTypeString + ">"; std::string templateLookupName = classNameWithoutTemplate + "<" + instTypeString + ">";
// Recheck for prior definition here, now that we have the true name. // Recheck for prior definition here, now that we have the true name.
possibleMatches = scopeLookup(scope, fullyInstantiatedName); possibleMatches = scopeLookup(scope, templateLookupName);
if (possibleMatches.size()) { if (possibleMatches.size()) {
typeDefinition = possibleMatches[0]; typeDefinition = possibleMatches[0];
traits = typeDefinition->getDataRef()->valueType->traits; traits = typeDefinition->getDataRef()->valueType->traits;
std::cout << "Found already instantiated template of " << fullyInstantiatedName << " at second check" << std::endl; std::cout << "Found already instantiated template of " << templateLookupName << " at second check" << std::endl;
} else { } else {
std::cout << "Did not find already instantiated template of " << fullyInstantiatedName << " at second check" << std::endl; std::cout << "Did not find already instantiated template of " << templateLookupName << " at second check" << std::endl;
//Look up this template's plain definition. It's type has the syntax tree that we need to parse //Look up this template's plain definition. It's type has the syntax tree that we need to parse
NodeTree<ASTData>* templateDefinition = templateClassLookup(scope, concatSymbolTree(typeNode->getChildren()[0]), templateParamInstantiationTypes); NodeTree<ASTData>* templateDefinition = templateClassLookup(scope, concatSymbolTree(typeNode->getChildren()[0]), templateParamInstantiationTypes);
if (templateDefinition == NULL) if (templateDefinition == NULL)
@@ -1197,6 +1209,8 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
else else
std::cout << "Template definition is not null!" << std::endl; std::cout << "Template definition is not null!" << std::endl;
std::string fullyInstantiatedName = templateDefinition->getDataRef()->symbol.getName() + "<" + instTypeString + ">";
NodeTree<Symbol>* templateSyntaxTree = templateDefinition->getDataRef()->valueType->templateDefinition; NodeTree<Symbol>* templateSyntaxTree = templateDefinition->getDataRef()->valueType->templateDefinition;
//Create a new map of template type names to actual types. //Create a new map of template type names to actual types.
std::vector<NodeTree<Symbol>*> templateParamPlaceholderNodes = slice(templateSyntaxTree->getChildren()[0]->getChildren(), 1, -2, 2); //Don't get beginning or end for < or >, skip commas in the middle std::vector<NodeTree<Symbol>*> templateParamPlaceholderNodes = slice(templateSyntaxTree->getChildren()[0]->getChildren(), 1, -2, 2); //Don't get beginning or end for < or >, skip commas in the middle
@@ -1211,9 +1225,17 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
//Note that we're adding to the current top scope. This makes it more efficient by preventing multiple instantiation and should not cause any problems //Note that we're adding to the current top scope. This makes it more efficient by preventing multiple instantiation and should not cause any problems
//It also makes sure it gets generated in the right place //It also makes sure it gets generated in the right place
std::cout << "Adding to top scope and template's origional scope with fullyInstantiatedName " << fullyInstantiatedName << std::endl; //std::cout << "Adding to top scope and template's origional scope with fullyInstantiatedName " << fullyInstantiatedName << std::endl;
topScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition); //topScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition);
topScope->addChild(typeDefinition); //Add this object the the highest scope's //topScope->addChild(typeDefinition); Add this object the the highest scope's
// Actually, let's just put it in the scope of the origional template, which should work just fine under the new scoping rules and will ACTUALLY prevent multiple instantiation.
// At least, hopefully it will if we also check it's scope for it. Which I think it should be anyway. Yeah, I think it should work.
std::cout << "Adding to template top scope and template's origional scope with fullyInstantiatedName " << fullyInstantiatedName << std::endl;
auto templateTopScope = getUpperTranslationUnit(templateDefinition);
templateTopScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition);
templateTopScope->addChild(typeDefinition); // Add this object the the highest scope's
//NodeTree<ASTData>* templateHighScope = templateDefinition->getDataRef()->scope["~enclosing_scope"][0]; //NodeTree<ASTData>* templateHighScope = templateDefinition->getDataRef()->scope["~enclosing_scope"][0];
//if (topScope != templateHighScope) //if (topScope != templateHighScope)
//templateHighScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition); //templateHighScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition);
@@ -1304,8 +1326,13 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
skipChildren.insert(2); skipChildren.insert(2);
//scope->getDataRef()->scope[fullyInstantiatedName].push_back(instantiatedFunction); //scope->getDataRef()->scope[fullyInstantiatedName].push_back(instantiatedFunction);
instantiatedFunction->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition->getDataRef()->scope["~enclosing_scope"][0]); //Instantiated Template Function's scope is it's template's definition's scope instantiatedFunction->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition->getDataRef()->scope["~enclosing_scope"][0]); //Instantiated Template Function's scope is it's template's definition's scope
topScope->getDataRef()->scope[fullyInstantiatedName].push_back(instantiatedFunction); // Arrrrrgh this has a hard time working because the functions will need to see their parameter once they are emitted as C.
topScope->addChild(instantiatedFunction); //Add this object the the highest scope's // HAHAHAHAHA DOESN'T MATTER ALL ONE C FILE NOW, swap back to old way
auto templateTopScope = getUpperTranslationUnit(templateDefinition);
templateTopScope->getDataRef()->scope[fullyInstantiatedName].push_back(instantiatedFunction);
templateTopScope->addChild(instantiatedFunction); // Add this object the the highest scope's
//topScope->getDataRef()->scope[fullyInstantiatedName].push_back(instantiatedFunction);
//topScope->addChild(instantiatedFunction); //Add this object the the highest scope's
std::cout << "About to do children of " << functionName << " to " << fullyInstantiatedName << std::endl; std::cout << "About to do children of " << functionName << " to " << fullyInstantiatedName << std::endl;
instantiatedFunction->addChildren(transformChildren(templateSyntaxTree->getChildren(), skipChildren, instantiatedFunction, std::vector<Type>(), newTemplateTypeReplacement)); instantiatedFunction->addChildren(transformChildren(templateSyntaxTree->getChildren(), skipChildren, instantiatedFunction, std::vector<Type>(), newTemplateTypeReplacement));

View File

@@ -4,7 +4,6 @@ CGenerator::CGenerator() : generatorString("__C__") {
tabLevel = 0; tabLevel = 0;
} }
CGenerator::~CGenerator() { 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. // 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.
@@ -16,23 +15,23 @@ void CGenerator::generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs,
std::cout << "Could not make directory " << outputName << std::endl; std::cout << "Could not make directory " << outputName << std::endl;
//throw "could not make directory "; //throw "could not make directory ";
} }
for (auto i = ASTs.begin(); i != ASTs.end(); i++) {
std::cout << "\n\nGenerate pass for: " << i->first << std::endl; std::cout << "\n\nGenerate pass for: " << outputName << std::endl;
buildString += i->first + ".c "; buildString += outputName + ".c ";
std::ofstream outputCFile, outputHFile; std::ofstream outputCFile, outputHFile;
outputCFile.open(outputName + "/" + i->first + ".c"); outputCFile.open(outputName + "/" + outputName + ".c");
outputHFile.open(outputName + "/" + i->first + ".h"); outputHFile.open(outputName + "/" + outputName + ".h");
if (outputCFile.is_open() || outputHFile.is_open()) { if (outputCFile.is_open() || outputHFile.is_open()) {
// Prequel common to all files // Prequel common to all files
auto chPair = generateTranslationUnit(i->second); auto chPair = generateTranslationUnit(outputName, ASTs);
outputHFile << "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n" << chPair.first; outputHFile << "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n" << chPair.first;
outputCFile << "#include \"" + i->first + ".h\"\n\n" << chPair.second; outputCFile << "#include \"" + outputName + ".h\"\n\n" << chPair.second;
} else { } else {
std::cout << "Cannot open file " << i->first << ".c/h" << std::endl; std::cout << "Cannot open file " << outputName << ".c/h" << std::endl;
} }
outputCFile.close(); outputCFile.close();
outputHFile.close(); outputHFile.close();
}
buildString += "-o " + outputName; buildString += "-o " + outputName;
std::ofstream outputBuild; std::ofstream outputBuild;
outputBuild.open(outputName + "/" + split(outputName, '/').back() + ".sh"); outputBuild.open(outputName + "/" + split(outputName, '/').back() + ".sh");
@@ -63,18 +62,19 @@ std::string CGenerator::generateClassStruct(NodeTree<ASTData>* from) {
} }
// This method recurseivly generates all aliases of some definition // This method recurseivly generates all aliases of some definition
std::string CGenerator::generateAliasChains(NodeTree<ASTData>* scopeNode, NodeTree<ASTData>* definition) { std::string CGenerator::generateAliasChains(std::map<std::string, NodeTree<ASTData>*> ASTs, NodeTree<ASTData>* definition) {
auto scope = scopeNode->getDataRef()->scope;
std::string output; std::string output;
for (auto i = scope.begin(); i != scope.end(); i++) { for (auto trans : ASTs) {
for (auto declaration : i->second) { for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) {
auto declarationData = declaration->getDataRef(); for (auto declaration : i->second) {
if (declarationData->type == type_def auto declarationData = declaration->getDataRef();
&& declarationData->valueType->typeDefinition != declaration if (declarationData->type == type_def
&& declarationData->valueType->typeDefinition == definition) { && declarationData->valueType->typeDefinition != declaration
output += "typedef " + CifyName(definition->getDataRef()->symbol.getName()) + " " + CifyName(declarationData->symbol.getName()) + ";\n"; && declarationData->valueType->typeDefinition == definition) {
// Recursively add the ones that depend on this one output += "typedef " + CifyName(definition->getDataRef()->symbol.getName()) + " " + CifyName(declarationData->symbol.getName()) + ";\n";
output += generateAliasChains(scopeNode, declaration); // Recursively add the ones that depend on this one
output += generateAliasChains(ASTs, declaration);
}
} }
} }
} }
@@ -104,9 +104,8 @@ NodeTree<ASTData>* CGenerator::highestScope(NodeTree<ASTData>* 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 // 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) { std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::string name, std::map<std::string, NodeTree<ASTData>*> ASTs) {
ASTData data = from->getData(); // We now pass in the entire map of ASTs and loop through them so that we generate out into a single file
std::vector<NodeTree<ASTData>*> children = from->getChildren();
std::string cOutput, hOutput; std::string cOutput, hOutput;
// Ok, so we've got to do this in passes to preserve mututally recursive definitions. // Ok, so we've got to do this in passes to preserve mututally recursive definitions.
// //
@@ -129,30 +128,29 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(NodeTree
std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n"; std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n";
std::string functionDefinitions = "/**\n * Function Definitions\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 // 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 // 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; Poset<NodeTree<ASTData>*> typedefPoset;
for (int i = 0; i < children.size(); i++) { for (auto trans : ASTs) {
if (children[i]->getDataRef()->type == type_def) { auto children = trans.second->getChildren();
// If we're an alias type, continue. We handle those differently for (int i = 0; i < children.size(); i++) {
if (children[i]->getDataRef()->valueType->typeDefinition != children[i]) if (children[i]->getDataRef()->type == type_def) {
continue; // 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. 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 // 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 // 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. // we will add a dependency from this definition to that definition in the poset.
std::vector<NodeTree<ASTData>*> classChildren = children[i]->getChildren(); std::vector<NodeTree<ASTData>*> classChildren = children[i]->getChildren();
for (auto j : classChildren) { for (auto j : classChildren) {
if (j->getDataRef()->type == declaration_statement) { if (j->getDataRef()->type == declaration_statement) {
Type* decType = j->getChildren()[0]->getDataRef()->valueType; // Type of the declaration 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 if (decType->typeDefinition && decType->getIndirection() == 0) // If this is a custom type and not a pointer
typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency
}
} }
} }
} }
@@ -161,76 +159,74 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(NodeTree
for (NodeTree<ASTData>* i : typedefPoset.getTopoSort()) for (NodeTree<ASTData>* i : typedefPoset.getTopoSort())
classStructs += generateClassStruct(i) + "\n"; classStructs += generateClassStruct(i) + "\n";
// Declare everything in translation unit scope here. (allows stuff from other files, automatic forward declarations) // Declare everything in translation unit scope here (now for ALL translation units). (allows stuff from other files, automatic forward declarations)
// Also, everything in all of the import's scopes // Also, everything in all of the import's scopes
std::map<std::string, std::vector<NodeTree<ASTData>*>> combinedMap; for (auto trans : ASTs) {
combinedMap = from->getDataRef()->scope; // Actually, just do this file. We're moving back to using include files for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) {
for (auto i = combinedMap.begin(); i != combinedMap.end(); i++) { for (auto declaration : i->second) {
for (auto declaration : i->second) { std::vector<NodeTree<ASTData>*> decChildren = declaration->getChildren();
std::vector<NodeTree<ASTData>*> decChildren = declaration->getChildren(); ASTData declarationData = declaration->getData();
ASTData declarationData = declaration->getData(); switch(declarationData.type) {
switch(declarationData.type) { case identifier:
case identifier: variableDeclarations += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n";
variableDeclarations += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n"; variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*extern identifier*/\n";
variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*extern identifier*/\n"; break;
break; case function:
case function: {
{ if (declarationData.valueType->baseType == template_type)
if (declarationData.valueType->baseType == template_type) functionPrototypes += "/* template function " + declarationData.symbol.toString() + " */\n";
functionPrototypes += "/* template function " + declarationData.symbol.toString() + " */\n"; else if (decChildren.size() == 0) //Not a real function, must be a built in passthrough
else if (decChildren.size() == 0) //Not a real function, must be a built in passthrough functionPrototypes += "/* built in function: " + declarationData.symbol.toString() + " */\n";
functionPrototypes += "/* built in function: " + declarationData.symbol.toString() + " */\n"; else {
else { functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType) + " ";
functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType) + " "; std::string nameDecoration, parameters;
std::string nameDecoration, parameters; for (int j = 0; j < decChildren.size()-1; j++) {
for (int j = 0; j < decChildren.size()-1; j++) { if (j > 0)
if (j > 0) parameters += ", ";
parameters += ", "; parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], nullptr);
parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], nullptr); nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType);
nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType); }
} functionPrototypes += CifyName(declarationData.symbol.getName() + nameDecoration) + "(" + parameters + "); /*func*/\n";
functionPrototypes += CifyName(declarationData.symbol.getName() + nameDecoration) + "(" + parameters + "); /*func*/\n"; // generate function
// Only generate function if this is the unit it was defined in std::cout << "Generating " << CifyName(declarationData.symbol.getName()) << std::endl;
std::cout << "Generating " << CifyName(declarationData.symbol.getName()) << std::endl;
if (contains(children, declaration))
functionDefinitions += generate(declaration, nullptr); functionDefinitions += generate(declaration, nullptr);
}
} }
} break;
break; case type_def:
case type_def: //type
//type plainTypedefs += "/*typedef " + declarationData.symbol.getName() + " */\n";
plainTypedefs += "/*typedef " + declarationData.symbol.getName() + " */\n";
if (declarationData.valueType->baseType == template_type) { if (declarationData.valueType->baseType == template_type) {
plainTypedefs += "/* non instantiated template " + declarationData.symbol.getName() + " */"; plainTypedefs += "/* non instantiated template " + declarationData.symbol.getName() + " */";
} else if (declarationData.valueType->typeDefinition != declaration) { } else if (declarationData.valueType->typeDefinition != declaration) {
if (declarationData.valueType->typeDefinition) if (declarationData.valueType->typeDefinition)
continue; // Aliases of objects are done with the thing it alises continue; // Aliases of objects are done with the thing it alises
// Otherwise, we're actually a renaming of a primitive, can generate here // Otherwise, we're actually a renaming of a primitive, can generate here
plainTypedefs += "typedef " + ValueTypeToCType(declarationData.valueType) + " " + CifyName(declarationData.symbol.getName()) + ";\n"; plainTypedefs += "typedef " + ValueTypeToCType(declarationData.valueType) + " " + CifyName(declarationData.symbol.getName()) + ";\n";
plainTypedefs += generateAliasChains(from, declaration); plainTypedefs += generateAliasChains(ASTs, declaration);
} else { } else {
plainTypedefs += "typedef struct __struct_dummy_" + CifyName(declarationData.symbol.getName()) + "__ " + CifyName(declarationData.symbol.getName()) + ";\n"; plainTypedefs += "typedef struct __struct_dummy_" + CifyName(declarationData.symbol.getName()) + "__ " + CifyName(declarationData.symbol.getName()) + ";\n";
functionPrototypes += "/* Method Prototypes for " + 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 // 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"; std::string objectFunctionDefinitions = "/* Method Definitions for " + declarationData.symbol.getName() + " */\n";
for (int j = 0; j < decChildren.size(); j++) { for (int j = 0; j < decChildren.size(); j++) {
std::cout << decChildren[j]->getName() << std::endl; std::cout << decChildren[j]->getName() << std::endl;
if (decChildren[j]->getName() == "function") //If object method if (decChildren[j]->getName() == "function") //If object method
objectFunctionDefinitions += generateObjectMethod(declaration, decChildren[j], &functionPrototypes) + "\n"; 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 // 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); plainTypedefs += generateAliasChains(ASTs, declaration);
functionPrototypes += "/* Done with " + declarationData.symbol.getName() + " */\n"; functionPrototypes += "/* Done with " + declarationData.symbol.getName() + " */\n";
// If this is the file the object is defined in, include methods // include methods
if (contains(children, declaration))
functionDefinitions += objectFunctionDefinitions + "/* Done with " + declarationData.symbol.getName() + " */\n"; functionDefinitions += objectFunctionDefinitions + "/* Done with " + declarationData.symbol.getName() + " */\n";
} }
break; break;
default: default:
//std::cout << "Declaration? named " << declaration->getName() << " of unknown type " << ASTData::ASTTypeToString(declarationData.type) << " in translation unit scope" << std::endl; //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"; cOutput += "/*unknown declaration named " + declaration->getName() + "*/\n";
hOutput += "/*unknown declaration named " + declaration->getName() + "*/\n"; hOutput += "/*unknown declaration named " + declaration->getName() + "*/\n";
}
} }
} }
} }
@@ -262,11 +258,12 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
case identifier: case identifier:
{ {
//but first, if we're this, we should just emit. (assuming enclosing object) (note that technically this would fall through, but for errors) //but first, if we're this, we should just emit. (assuming enclosing object) (note that technically this would fall through, but for errors)
if (data.symbol.getName() == "this") if (data.symbol.getName() == "this") {
if (enclosingObject) if (enclosingObject)
return "this"; return "this";
else else
std::cout << "Error: this used in non-object scope" << std::endl; std::cout << "Error: this used in non-object scope" << std::endl;
}
//If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the this reference. //If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the this reference.
std::string preName; std::string preName;
if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end()) if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end())
@@ -480,6 +477,7 @@ 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) { return ValueTypeToCTypeThingHelper(type, "*"); } std::string CGenerator::ValueTypeToCType(Type *type) { return ValueTypeToCTypeThingHelper(type, "*"); }
std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return ValueTypeToCTypeThingHelper(type, "_P__"); } std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return ValueTypeToCTypeThingHelper(type, "_P__"); }
std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr) { std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr) {
@@ -557,6 +555,7 @@ std::string CGenerator::CifyName(std::string name) {
"[", "openbracket", "[", "openbracket",
"]", "closebracket", "]", "closebracket",
" ", "space", " ", "space",
".", "dot",
"->", "arrow" }; "->", "arrow" };
int length = sizeof(operatorsToReplace)/sizeof(std::string); int length = sizeof(operatorsToReplace)/sizeof(std::string);
//std::cout << "Length is " << length << std::endl; //std::cout << "Length is " << length << std::endl;

View File

@@ -167,6 +167,7 @@ NodeTree<Symbol>* Importer::parseAndTrim(std::string fileName) {
} else { } else {
std::cout << "ParseTree returned from parser for " << fileName << " is NULL!" << std::endl; std::cout << "ParseTree returned from parser for " << fileName << " is NULL!" << std::endl;
outFile.close(); outFileTransformed.close(); outFile.close(); outFileTransformed.close();
throw "unexceptablblllll";
return NULL; return NULL;
} }
outFile.close(); outFile.close();

View File

@@ -1,3 +1,5 @@
import string:*;
__if_comp__ __C__ __simple_passthrough__ """ __if_comp__ __C__ __simple_passthrough__ """
#include <stdio.h> #include <stdio.h>
""" """
@@ -20,6 +22,14 @@ __if_comp__ __C__ __simple_passthrough__ """
println(); println();
} }
|void| print(|string| toPrint) {
print(toPrint.toCharArray());
}
|void| println(|string| toPrint) {
println(toPrint.toCharArray());
}
|void| print(|int| toPrint) { |void| print(|int| toPrint) {
__if_comp__ __C__ { __if_comp__ __C__ {
__simple_passthrough__ """ __simple_passthrough__ """

27
stdlib/string.krak Normal file
View File

@@ -0,0 +1,27 @@
import vector;
import mem;
typedef string (Destructable) {
|vector::vector<char>| data;
|string*| construct() {
data.construct();
return this;
}
|string*| construct(|char*| str) {
data.construct();
while(*str) {
data.addEnd(*str);
str += 1;
}
return this;
}
|char*| toCharArray() {
|char*| out = mem::new<char>(data.size);
for (|int| i = 0; i < data.size; i++;)
out[i] = data.get(i);
return out;
}
};

View File

@@ -1,6 +1,6 @@
import mem:*; import mem:*;
import util:*; import util:*;
import io:*; //import io:*;
typedef template<T> vector (Destructable) { typedef template<T> vector (Destructable) {
|T*| data; |T*| data;
@@ -25,6 +25,8 @@ typedef template<T> vector (Destructable) {
for (|int| i = 0; i < lesser<int>(size, newSize); i++;) for (|int| i = 0; i < lesser<int>(size, newSize); i++;)
newData[i] = data[i]; newData[i] = data[i];
delete<T>(data, 0); delete<T>(data, 0);
data = newData;
available = newSize;
return true; return true;
} }
@@ -34,21 +36,22 @@ typedef template<T> vector (Destructable) {
|T| get(|int| index) { |T| get(|int| index) {
if (index < 0 || index >= size) { if (index < 0 || index >= size) {
println("Vector access out of bounds! Retuning 0th element as sanest option"); // println("Vector access out of bounds! Retuning 0th element as sanest option");
return data[0]; return data[0];
} }
return data[index]; return data[index];
} }
|T*| getBackingMemory() { return data; }
|void| set(|int| index, |T| dataIn) { |void| set(|int| index, |T| dataIn) {
if (index < 0 || index >= size) if (index < 0 || index >= size)
return; return;
data[index] = dataIn; data[index] = dataIn;
} }
|void| addEnd(|T| dataIn) { |void| addEnd(|T| dataIn) {
if (size < available) size++;
size++; if (size >= available)
else
resize(size*2); resize(size*2);
data[size-1] = dataIn; data[size-1] = dataIn;
} }

15
tests/runTests-ninja.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
krakenPath="../build-ninja/kraken"
#testDir=${1:-"../tests"}
testDir="."
ext=${2:-"krak"}
fileList=""
for dir in `find ${testDir} -type f -name "test_*.${ext}"`; do
filename=$(basename ${dir})
filename="${filename%.*}"
fileList+=\ $testDir\/$filename
done
${krakenPath} "--test" ${fileList}

View File

@@ -0,0 +1 @@
hello strings

10
tests/test_string.krak Normal file
View File

@@ -0,0 +1,10 @@
import io;
import string;
|int| main() {
|string::string| str.construct("hello strings");
io::println(str);
return 0;
}

View File

@@ -1,2 +1,3 @@
4
1337 1337
Destroyed! Destroyed!

View File

@@ -14,6 +14,7 @@ typedef AbleToBeDestroyed (Destructable) {
intVec.addEnd(3); intVec.addEnd(3);
intVec.addEnd(3); intVec.addEnd(3);
intVec.addEnd(7); intVec.addEnd(7);
println(intVec.size);
for (|int| i = 0; i < intVec.size; i++;) for (|int| i = 0; i < intVec.size; i++;)
print(intVec.at(i)); print(intVec.at(i));