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)
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>* 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[]) {
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") {
StringReader::test();
@@ -152,4 +158,4 @@ int main(int argc, char* argv[]) {
CGenerator().generateCompSet(ASTs, outputName);
return(0);
}

View File

@@ -98,12 +98,16 @@ void ASTTransformation::secondPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* par
//It's an alias
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;
}
//Do the inside of classes here
typeDef->getDataRef()->valueType = new Type(typeDef);
secondPassDoClassInsides(typeDef, typedefChildren);
secondPassDoClassInsides(typeDef, typedefChildren, std::map<std::string, Type*>());
} else if (i->getDataRef()->getName() == "function") {
//Do prototypes of functions
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
for (NodeTree<Symbol>* j : typedefChildren) {
if (j->getDataRef()->getName() == "declaration_statement") {
//do declaration
typeDef->addChild(secondPassDeclaration(j, typeDef, std::map<std::string, Type*>()));
typeDef->addChild(secondPassDeclaration(j, typeDef, templateTypeReplacements));
} else if (j->getDataRef()->getName() == "function") {
//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.
std::vector<NodeTree<ASTData>*> classTemplates;
for (auto i : ast->getDataRef()->scope)
if (i.second[0]->getDataRef()->type == type_def && i.second[0]->getDataRef()->valueType->baseType == template_type)
for (auto i : ast->getDataRef()->scope) {
if (i.second[0]->getDataRef()->type == type_def && i.second[0]->getDataRef()->valueType->templateTypeReplacement.size()) {
classTemplates.push_back(i.second[0]);
std::cout << "Saving " << i.second[0]->getDataRef()->toString() << " to instantiate." << std::endl;
}
}
for (auto i : classTemplates) {
Type* classTemplateType = i->getDataRef()->valueType;
std::cout << "Instantiating template " << i->getDataRef()->toString() << std::endl;
for (NodeTree<Symbol>* j : classTemplateType->templateDefinition->getChildren())
if (j->getDataRef()->getName() == "function")
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);
if (!instantiateTemplates) {
selfType->templateTypeReplacement = newTemplateTypeReplacement; //Save the types for use when this is fully instantiated in pass 4
secondPassDoClassInsides(typeDefinition, templateSyntaxTree->getChildren());
std::cout << "!instantiateTemplates, so only partially instantiating " << fullyInstantiatedName << std::endl;
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 {
//We're fully instantiating types. (we must be in pass 4)
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?)
if (classChildren.size())
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
@@ -82,7 +84,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
break;
case function:
{
if (declarationData.valueType->baseType == template_type)
if (declarationData.valueType->baseType == template_type)
output += "/* template function " + declarationData.symbol.toString() + " */\n";
else if (decChildren.size() == 0) //Not a real function, must be a built in passthrough
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);
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;
@@ -165,7 +167,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
parameters += ValueTypeToCType(children[j]->getData().valueType) + " " + generate(children[j], enclosingObject);
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;
}
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;
for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++)
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
//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 {
std::cout << "Is not in scope or not type" << std::endl;
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]);
if (isSelfObjectMethod)
output += enclosingObject->getDataRef()->symbol.getName() +"__";
/*HERE*/ output += CifyName(name) + nameDecoration + "(";
/*HERE*/ output += CifyName(name + nameDecoration) + "(";
if (isSelfObjectMethod)
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;
typedef RegularObject {
MyInt num;
int num;
trivialContainer<char*> innerContainer;
void set(char* message, int number) {
innerContainer.data = message;
@@ -18,8 +18,6 @@ typedef RegularObject {
};
typedef MyIntContainer trivialContainer<int>;
typedef MyInt int;
MyInt c;
MyIntContainer roundabout;
RegularObject outsideDec;
@@ -28,14 +26,12 @@ void print(trivialContainer<char*> toPrint) {
}
int main() {
c = 3;
roundabout.data = 4;
outsideDec.set("Hello!", 5);
print(c);
roundabout.print();
outsideDec.print();
print(outsideDec.get());
print(outsideDec.innerContainer);
print("\n");
return 0;
}
}