diff --git a/.gitignore b/.gitignore index 8cf53c5..ea599cf 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ stats *.swp *.png *krakout* +kraklist.txt diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index 69686c8..ec823ec 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -29,13 +29,10 @@ class ASTTransformation: public NodeTransformation { NodeTree* secondPassDeclaration(NodeTree* from, NodeTree* scope, std::map templateTypeReplacements); NodeTree* secondPassFunction(NodeTree* from, NodeTree* scope, std::map templateTypeReplacements); - //Third pass redoes all imports to import the new function prototypes and identifiers - void thirdPass(NodeTree* ast); - - //The fourth pass finishes up by doing all function bodies - void fourthPass(NodeTree* ast, NodeTree* parseTree); + //The third pass finishes up by doing all function bodies + void thirdPass(NodeTree* ast, NodeTree* parseTree); NodeTree* searchScopeForFunctionDef(NodeTree* scope, NodeTree* parseTree, std::map templateTypeReplacements); - void fourthPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements); + void thirdPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements); virtual NodeTree* transform(NodeTree* from); NodeTree* transform(NodeTree* from, NodeTree* scope, std::vector types, std::map templateTypeReplacements); diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 313213a..e7059d9 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -38,7 +38,7 @@ ASTTransformation::~ASTTransformation() { // } -//First pass defines all type_defs (objects and ailises) +//First pass defines all type_defs (objects and ailises), and if_comp/simple_passthrough NodeTree* ASTTransformation::firstPass(std::string fileName, NodeTree* parseTree) { NodeTree* translationUnit = new NodeTree("translation_unit", ASTData(translation_unit)); std::vector*> children = parseTree->getChildren(); @@ -72,7 +72,15 @@ NodeTree* ASTTransformation::firstPass(std::string fileName, NodeTreeaddChild(firstDec); translationUnit->getDataRef()->scope[name].push_back(firstDec); firstDec->getDataRef()->scope["~enclosing_scope"].push_back(translationUnit); - } + } else if (i->getDataRef()->getName() == "if_comp") { + std::cout << "IF COMP" << std::endl; + NodeTree* newNode = new NodeTree(i->getDataRef()->getName(), ASTData(if_comp)); + newNode->addChild(new NodeTree("identifier", ASTData(identifier, Symbol(concatSymbolTree(i->getChildren()[0]),true)))); + std::set skipChildren; + skipChildren.insert(0); //Don't do the identifier. The identifier lookup will fail. That's why we do it here. + newNode->addChildren(transformChildren(i->getChildren(), skipChildren, translationUnit, std::vector(), std::map())); + translationUnit->addChild(newNode); + } } //Now go through and do all imports @@ -236,36 +244,8 @@ NodeTree* ASTTransformation::secondPassFunction(NodeTree* from, return functionDef; } - - -//Third pass redoes all imports to import the new function prototypes and identifiers -void ASTTransformation::thirdPass(NodeTree* ast) { - std::vector*> children = ast->getChildren(); - //Go through and do all imports again - for (NodeTree* i : children) { - if (i->getDataRef()->type == import) { - std::string toImport = i->getDataRef()->symbol.getName(); - NodeTree* outsideTranslationUnit = importer->getUnit(toImport + ".krak"); - //Now add all functions to scope - std::cout << "Trying to re-import from " << toImport << std::endl; - for (auto 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 " << j->first << std::endl; - } - } - } -} - -//The fourth pass finishes up by doing all function bodies -void ASTTransformation::fourthPass(NodeTree* ast, NodeTree* parseTree) { +//The third pass finishes up by doing all function bodies +void ASTTransformation::thirdPass(NodeTree* ast, NodeTree* parseTree) { topScope = ast; //Top scope is maintained for templates, which need to add themselves to the top scope from where ever they are instantiated std::vector*> children = parseTree->getChildren(); @@ -286,14 +266,14 @@ void ASTTransformation::fourthPass(NodeTree* ast, NodeTree* par //Do the inside of classes here for (NodeTree* j : typedefChildren) { if (j->getDataRef()->getName() == "function") { - fourthPassFunction(j, searchScopeForFunctionDef(typeDef, j, std::map()), std::map()); //do member method + thirdPassFunction(j, searchScopeForFunctionDef(typeDef, j, std::map()), std::map()); //do member method } } } else if (i->getDataRef()->getName() == "function") { //Do prototypes of functions if (i->getChildren()[0]->getData().getName() == "template_dec") continue; //We've already set up function templates - fourthPassFunction(i, searchScopeForFunctionDef(ast, i, std::map()), std::map()); + thirdPassFunction(i, searchScopeForFunctionDef(ast, i, std::map()), std::map()); } } @@ -316,7 +296,7 @@ void ASTTransformation::fourthPass(NodeTree* ast, NodeTree* par std::cout << "Instantiating template " << i->getDataRef()->toString() << std::endl; for (NodeTree* j : classTemplateType->templateDefinition->getChildren()) if (j->getDataRef()->getName() == "function") - fourthPassFunction(j, searchScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method + thirdPassFunction(j, searchScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method classTemplateType->templateTypeReplacement.clear(); // This template has been fully instantiated, clear it's map so it won't be instantiated again } } @@ -342,9 +322,9 @@ NodeTree* ASTTransformation::searchScopeForFunctionDef(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements) { +void ASTTransformation::thirdPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements) { NodeTree* codeBlock = from->getChildren()[from->getChildren().size()-1]; functionDef->addChild(transform(codeBlock, functionDef, std::vector(), templateTypeReplacements)); } diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 6ec7148..dd50b30 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -123,6 +123,7 @@ std::pair CGenerator::generateTranslationUnit(std::str // 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 topLevelCPassthrough = "/**\n * Top Level C Passthrough\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"; @@ -163,7 +164,14 @@ std::pair CGenerator::generateTranslationUnit(std::str // 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 c passthrough for (auto trans : ASTs) { + // First go through and emit all the passthroughs, etc + for (auto i : trans.second->getChildren()) { + if (i->getDataRef()->type == if_comp) + topLevelCPassthrough += generate(i, nullptr); + } + for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) { for (auto declaration : i->second) { std::vector*> decChildren = declaration->getChildren(); @@ -232,7 +240,7 @@ std::pair CGenerator::generateTranslationUnit(std::str } } } - hOutput += plainTypedefs + importIncludes + variableExternDeclarations + classStructs + functionPrototypes; + hOutput += plainTypedefs + importIncludes + topLevelCPassthrough + variableExternDeclarations + classStructs + functionPrototypes; cOutput += variableDeclarations + functionDefinitions; return std::make_pair(hOutput, cOutput); } diff --git a/src/Importer.cpp b/src/Importer.cpp index 3a836e6..4bbf81d 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -24,6 +24,7 @@ Importer::Importer(Parser* parserIn, std::vector includePaths, std: removeSymbols.push_back(Symbol("if", true)); removeSymbols.push_back(Symbol("while", true)); removeSymbols.push_back(Symbol("__if_comp__", true)); + removeSymbols.push_back(Symbol("__simple_passthrough__", true)); removeSymbols.push_back(Symbol("comp_simple_passthrough", true)); removeSymbols.push_back(Symbol("typedef", true)); removeSymbols.push_back(Symbol("template", true)); @@ -94,15 +95,11 @@ void Importer::import(std::string fileName) { std::cout << "\n\nSecond pass for: " << i.name << std::endl, ASTTransformer->secondPass(i.ast, i.syntaxTree); //function prototypes, and identifiers (as we now have all type defs) std::cout << "\n\n =====THIRD PASS===== \n\n" << std::endl; - for (importTriplet i : importedTrips) //Third pass redoes all imports to import the new function prototypes and identifiers - std::cout << "\n\nThird pass for: " << i.name << std::endl, ASTTransformer->thirdPass(i.ast); + for (importTriplet i : importedTrips) //Third pass finishes up by doing all function bodies + std::cout << "\n\nFourth pass for: " << i.name << std::endl, ASTTransformer->thirdPass(i.ast, i.syntaxTree); //With that, we're done - std::cout << "\n\n =====FOURTH PASS===== \n\n" << std::endl; - for (importTriplet i : importedTrips) //Fourth pass finishes up by doing all function bodies - std::cout << "\n\nFourth pass for: " << i.name << std::endl, ASTTransformer->fourthPass(i.ast, i.syntaxTree); //With that, we're done - - //Note that class template instantiation can happen in the second or fourth passes and that function template instantion - //can happen in the fourth pass. + //Note that class template instantiation can happen in the second or third passes and that function template instantion + //can happen in the third pass. std::ofstream outFileAST; for (importTriplet i : importedTrips) { diff --git a/tests/c_passthrough_diff.krak b/tests/c_passthrough_diff.krak new file mode 100644 index 0000000..a491b85 --- /dev/null +++ b/tests/c_passthrough_diff.krak @@ -0,0 +1,11 @@ + +__if_comp__ __C__ __simple_passthrough__ """ + #include + int diff = 7; +""" + +|void| print_it() { + __if_comp__ __C__ __simple_passthrough__ """ + printf("diff_file: %d\n", diff); + """ +} diff --git a/tests/test_c_passthrough.expected_results b/tests/test_c_passthrough.expected_results new file mode 100644 index 0000000..1822295 --- /dev/null +++ b/tests/test_c_passthrough.expected_results @@ -0,0 +1,2 @@ +same_file: 5 +diff_file: 7 diff --git a/tests/test_c_passthrough.krak b/tests/test_c_passthrough.krak new file mode 100644 index 0000000..589939a --- /dev/null +++ b/tests/test_c_passthrough.krak @@ -0,0 +1,19 @@ +import c_passthrough_diff + + +__if_comp__ __C__ __simple_passthrough__ """ + #include + int same = 5; +""" + +|int| main() { + + __if_comp__ __C__ __simple_passthrough__ """ + printf("same_file: %d\n", same); + """ + c_passthrough_diff::print_it() + return 0 +} + + +