Almost have it working, but member function lookup through a typedef doesn't quite work. (I think the problem's in CGenerator)

This commit is contained in:
Nathan Braswell
2014-06-10 00:53:30 -07:00
parent 366bbb6432
commit 7dbfd8ca38
6 changed files with 39 additions and 25 deletions

View File

@@ -21,7 +21,7 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
//Second pass defines data inside objects, outside declaration statements, and function prototpyes (since we have type_defs now) //Second pass defines data inside objects, outside declaration statements, and function prototpyes (since we have type_defs now)
void secondPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* parseTree); void secondPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* parseTree);
void secondPassDoClassInsides(NodeTree<ASTData>* typeDef, std::vector<NodeTree<Symbol>*> typedefChildren); void secondPassDoClassInsides(NodeTree<ASTData>* typeDef, std::vector<NodeTree<Symbol>*> typedefChildren, std::map<std::string, Type*> templateTypeReplacements);
NodeTree<ASTData>* secondPassDeclaration(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements); NodeTree<ASTData>* secondPassDeclaration(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements);
NodeTree<ASTData>* secondPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements); NodeTree<ASTData>* secondPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements);

View File

@@ -21,7 +21,13 @@
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
std::vector<std::string> includePaths; std::vector<std::string> includePaths;
includePaths.push_back(""); //Local includePaths.push_back(""); //Local
if (argc <= 1) {
std::cout << "Kraken invocation: kraken sourceFile.krak grammerFile.kgm outputName" << std::endl;
std::cout << "Or for testing do: kraken --test [optional list of names of file (.krak .expected_results) without extentions to run]" << std::endl;
return 0;
}
if (argc >= 2 && std::string(argv[1]) == "--test") { if (argc >= 2 && std::string(argv[1]) == "--test") {
StringReader::test(); StringReader::test();
@@ -152,4 +158,4 @@ int main(int argc, char* argv[]) {
CGenerator().generateCompSet(ASTs, outputName); CGenerator().generateCompSet(ASTs, outputName);
return(0); return(0);
} }

View File

@@ -98,12 +98,16 @@ void ASTTransformation::secondPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* par
//It's an alias //It's an alias
if (typedefChildren[1]->getData().getName() == "type") { if (typedefChildren[1]->getData().getName() == "type") {
/*HERE*/ typeDef->getDataRef()->valueType = typeFromTypeNode(typedefChildren[1], ast, std::map<std::string, Type*>(), false); //No templates, we're in the traslation unit Type* aliasedType = typeFromTypeNode(typedefChildren[1], ast, std::map<std::string, Type*>(), false); //No templates, we're in the traslation unit
typeDef->getDataRef()->valueType = aliasedType;
typeDef->getDataRef()->scope["~enclosing_scope"][0] = aliasedType->typeDefinition; //So that object lookups find the right member. Note that this overrides translation_unit as a parent scope
std::cout << name << " alias's to " << aliasedType->typeDefinition << std::endl;
std::cout << "that is " << aliasedType->typeDefinition->getDataRef()->toString() << std::endl;
continue; continue;
} }
//Do the inside of classes here //Do the inside of classes here
typeDef->getDataRef()->valueType = new Type(typeDef); typeDef->getDataRef()->valueType = new Type(typeDef);
secondPassDoClassInsides(typeDef, typedefChildren); secondPassDoClassInsides(typeDef, typedefChildren, std::map<std::string, Type*>());
} else if (i->getDataRef()->getName() == "function") { } else if (i->getDataRef()->getName() == "function") {
//Do prototypes of functions //Do prototypes of functions
ast->addChild(secondPassFunction(i, ast, std::map<std::string, Type*>())); ast->addChild(secondPassFunction(i, ast, std::map<std::string, Type*>()));
@@ -114,15 +118,15 @@ void ASTTransformation::secondPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* par
} }
} }
void ASTTransformation::secondPassDoClassInsides(NodeTree<ASTData>* typeDef, std::vector<NodeTree<Symbol>*> typedefChildren) { void ASTTransformation::secondPassDoClassInsides(NodeTree<ASTData>* typeDef, std::vector<NodeTree<Symbol>*> typedefChildren, std::map<std::string, Type*> templateTypeReplacements) {
//We pull out this functionality into a new function because this is used in typeFromTypeNode to partially instantiate templates //We pull out this functionality into a new function because this is used in typeFromTypeNode to partially instantiate templates
for (NodeTree<Symbol>* j : typedefChildren) { for (NodeTree<Symbol>* j : typedefChildren) {
if (j->getDataRef()->getName() == "declaration_statement") { if (j->getDataRef()->getName() == "declaration_statement") {
//do declaration //do declaration
typeDef->addChild(secondPassDeclaration(j, typeDef, std::map<std::string, Type*>())); typeDef->addChild(secondPassDeclaration(j, typeDef, templateTypeReplacements));
} else if (j->getDataRef()->getName() == "function") { } else if (j->getDataRef()->getName() == "function") {
//do member method //do member method
typeDef->addChild(secondPassFunction(j, typeDef, std::map<std::string, Type*>())); typeDef->addChild(secondPassFunction(j, typeDef, templateTypeReplacements));
} }
} }
} }
@@ -214,11 +218,15 @@ void ASTTransformation::fourthPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* par
//First copy unfinished class templates into a new list and do them before anything else, so we know exactly which ones we need to do. //First copy unfinished class templates into a new list and do them before anything else, so we know exactly which ones we need to do.
std::vector<NodeTree<ASTData>*> classTemplates; std::vector<NodeTree<ASTData>*> classTemplates;
for (auto i : ast->getDataRef()->scope) for (auto i : ast->getDataRef()->scope) {
if (i.second[0]->getDataRef()->type == type_def && i.second[0]->getDataRef()->valueType->baseType == template_type) if (i.second[0]->getDataRef()->type == type_def && i.second[0]->getDataRef()->valueType->templateTypeReplacement.size()) {
classTemplates.push_back(i.second[0]); classTemplates.push_back(i.second[0]);
std::cout << "Saving " << i.second[0]->getDataRef()->toString() << " to instantiate." << std::endl;
}
}
for (auto i : classTemplates) { for (auto i : classTemplates) {
Type* classTemplateType = i->getDataRef()->valueType; Type* classTemplateType = i->getDataRef()->valueType;
std::cout << "Instantiating template " << i->getDataRef()->toString() << std::endl;
for (NodeTree<Symbol>* j : classTemplateType->templateDefinition->getChildren()) for (NodeTree<Symbol>* j : classTemplateType->templateDefinition->getChildren())
if (j->getDataRef()->getName() == "function") if (j->getDataRef()->getName() == "function")
fourthPassFunction(j, seachScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method fourthPassFunction(j, seachScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method
@@ -874,8 +882,10 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
typeDefinition->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition); typeDefinition->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition);
if (!instantiateTemplates) { if (!instantiateTemplates) {
selfType->templateTypeReplacement = newTemplateTypeReplacement; //Save the types for use when this is fully instantiated in pass 4 std::cout << "!instantiateTemplates, so only partially instantiating " << fullyInstantiatedName << std::endl;
secondPassDoClassInsides(typeDefinition, templateSyntaxTree->getChildren()); selfType->templateDefinition = templateSyntaxTree; //We're going to still need this when we finish instantiating
selfType->templateTypeReplacement = newTemplateTypeReplacement; //Save the types for use when this is fully instantiated in pass 4
secondPassDoClassInsides(typeDefinition, templateSyntaxTree->getChildren(), newTemplateTypeReplacement); //Use these types when instantiating data members
} else { } else {
//We're fully instantiating types. (we must be in pass 4) //We're fully instantiating types. (we must be in pass 4)
std::set<int> skipChildren; std::set<int> skipChildren;

View File

@@ -64,6 +64,8 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
//In case there are pointer dependencies. If the typedef has no children, then it is a simple renaming and we don't need to predeclare the class (maybe?) //In case there are pointer dependencies. If the typedef has no children, then it is a simple renaming and we don't need to predeclare the class (maybe?)
if (classChildren.size()) if (classChildren.size())
output += "struct " + CifyName(children[i]->getDataRef()->symbol.getName()) + ";\n"; output += "struct " + CifyName(children[i]->getDataRef()->symbol.getName()) + ";\n";
else if (children[i]->getDataRef()->valueType->typeDefinition != children[i] && !children[i]->getDataRef()->valueType->templateDefinition) //Isn't uninstantiated template or 0 parameter class, so must be alias
typedefPoset.addRelationship(children[i], children[i]->getDataRef()->valueType->typeDefinition); //An alias typedef depends on the type it aliases being declared before it
} }
} }
//Now generate the typedef's in the correct, topological order //Now generate the typedef's in the correct, topological order
@@ -82,7 +84,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
break; break;
case function: case function:
{ {
if (declarationData.valueType->baseType == template_type) if (declarationData.valueType->baseType == template_type)
output += "/* template function " + declarationData.symbol.toString() + " */\n"; output += "/* 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
output += "/* built in function: " + declarationData.symbol.toString() + " */\n"; output += "/* built in function: " + declarationData.symbol.toString() + " */\n";
@@ -95,7 +97,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], enclosingObject); parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], enclosingObject);
nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType); nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType);
} }
output += CifyName(declarationData.symbol.getName()) + nameDecoration + "(" + parameters + "); /*func*/\n"; output += CifyName(declarationData.symbol.getName() + nameDecoration) + "(" + parameters + "); /*func*/\n";
} }
} }
break; break;
@@ -165,7 +167,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
parameters += ValueTypeToCType(children[j]->getData().valueType) + " " + generate(children[j], enclosingObject); parameters += ValueTypeToCType(children[j]->getData().valueType) + " " + generate(children[j], enclosingObject);
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType); nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType);
} }
output += CifyName(data.symbol.getName()) + nameDecoration + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject); output += CifyName(data.symbol.getName() + nameDecoration) + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject);
return output; return output;
} }
case code_block: case code_block:
@@ -253,9 +255,9 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl; std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl;
for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++)
nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
/*HERE*/ return CifyName(possibleObjectType->getDataRef()->symbol.getName()) +"__" + CifyName(functionName) + nameDecoration + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ","; /*HERE*/ return CifyName(possibleObjectType->getDataRef()->symbol.getName()) +"__" + CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ",";
//The comma lets the upper function call know we already started the param list //The comma lets the upper function call know we already started the param list
//Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses //Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses
} else { } else {
std::cout << "Is not in scope or not type" << std::endl; std::cout << "Is not in scope or not type" << std::endl;
return "((" + generate(children[1], enclosingObject) + ")" + name + functionName + ")"; return "((" + generate(children[1], enclosingObject) + ")" + name + functionName + ")";
@@ -275,7 +277,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]); bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]);
if (isSelfObjectMethod) if (isSelfObjectMethod)
output += enclosingObject->getDataRef()->symbol.getName() +"__"; output += enclosingObject->getDataRef()->symbol.getName() +"__";
/*HERE*/ output += CifyName(name) + nameDecoration + "("; /*HERE*/ output += CifyName(name + nameDecoration) + "(";
if (isSelfObjectMethod) if (isSelfObjectMethod)
output += children.size() > 1 ? "self," : "self"; output += children.size() > 1 ? "self," : "self";
} }

View File

@@ -1 +1 @@
345Hello!Hello!Hello! 45Hello!Hello!Hello!

View File

@@ -2,7 +2,7 @@ import io;
import trivial_container; import trivial_container;
typedef RegularObject { typedef RegularObject {
MyInt num; int num;
trivialContainer<char*> innerContainer; trivialContainer<char*> innerContainer;
void set(char* message, int number) { void set(char* message, int number) {
innerContainer.data = message; innerContainer.data = message;
@@ -18,8 +18,6 @@ typedef RegularObject {
}; };
typedef MyIntContainer trivialContainer<int>; typedef MyIntContainer trivialContainer<int>;
typedef MyInt int;
MyInt c;
MyIntContainer roundabout; MyIntContainer roundabout;
RegularObject outsideDec; RegularObject outsideDec;
@@ -28,14 +26,12 @@ void print(trivialContainer<char*> toPrint) {
} }
int main() { int main() {
c = 3;
roundabout.data = 4; roundabout.data = 4;
outsideDec.set("Hello!", 5); outsideDec.set("Hello!", 5);
print(c);
roundabout.print(); roundabout.print();
outsideDec.print(); outsideDec.print();
print(outsideDec.get()); print(outsideDec.get());
print(outsideDec.innerContainer); print(outsideDec.innerContainer);
print("\n"); print("\n");
return 0; return 0;
} }