Initial work for functions as values. Actually works, but you can't write out the type and thus can only declare function pointer variables with type inference.

This commit is contained in:
Nathan Braswell
2015-05-18 04:46:03 -04:00
parent 65fd2ed9b7
commit 911b25f78b
8 changed files with 172 additions and 111 deletions

View File

@@ -43,6 +43,7 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
NodeTree<ASTData>* transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements); NodeTree<ASTData>* transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
std::vector<NodeTree<ASTData>*> transformChildren(std::vector<NodeTree<Symbol>*> children, std::set<int> skipChildren, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements); std::vector<NodeTree<ASTData>*> transformChildren(std::vector<NodeTree<Symbol>*> children, std::set<int> skipChildren, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
std::vector<Type> mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes); std::vector<Type> mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes);
std::vector<Type*> mapNodesToTypePointers(std::vector<NodeTree<ASTData>*> nodes);
std::string concatSymbolTree(NodeTree<Symbol>* root); std::string concatSymbolTree(NodeTree<Symbol>* root);
NodeTree<ASTData>* doFunction(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes, std::map<std::string, Type*> templateTypeReplacements); NodeTree<ASTData>* doFunction(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes, std::map<std::string, Type*> templateTypeReplacements);

View File

@@ -26,9 +26,9 @@ class CGenerator {
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(std::string name, std::map<std::string, NodeTree<ASTData>*> ASTs); 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, bool justFuncName = false);
std::string generateAliasChains(std::map<std::string, NodeTree<ASTData>*> ASTs, 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, std::string);
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);
static std::string CifyName(std::string name); static std::string CifyName(std::string name);

View File

@@ -14,7 +14,7 @@ class ASTData;
#include "ASTData.h" #include "ASTData.h"
#include "util.h" #include "util.h"
enum ValueType {none, template_type, template_type_type, void_type, boolean, integer, floating, double_percision, character }; enum ValueType {none, template_type, template_type_type, void_type, boolean, integer, floating, double_percision, character, function_type };
class Type { class Type {
@@ -25,6 +25,8 @@ class Type {
Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn = 0); Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn = 0);
Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn); Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn);
Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn); Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn);
Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn, std::vector<Type*> parameterTypesIn, Type* returnTypeIn);
Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn);
Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn = std::set<std::string>()); Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn = std::set<std::string>());
~Type(); ~Type();
bool const operator==(const Type &other)const; bool const operator==(const Type &other)const;
@@ -42,6 +44,8 @@ class Type {
NodeTree<Symbol>* templateDefinition; NodeTree<Symbol>* templateDefinition;
std::map<std::string, Type*> templateTypeReplacement; std::map<std::string, Type*> templateTypeReplacement;
std::set<std::string> traits; std::set<std::string> traits;
std::vector<Type*> parameterTypes;
Type *returnType;
private: private:
int indirection; int indirection;
}; };

View File

@@ -259,13 +259,9 @@ NodeTree<ASTData>* ASTTransformation::secondPassFunction(NodeTree<Symbol>* from,
//We only do the parameter nodes. We don't do the body yet, as this is the secondPass //We only do the parameter nodes. We don't do the body yet, as this is the secondPass
auto transChildren = transformChildren(slice(children,1,-3, 2), std::set<int>(), functionDef, std::vector<Type>(), templateTypeReplacements); auto transChildren = transformChildren(slice(children,1,-3, 2), std::set<int>(), functionDef, std::vector<Type>(), templateTypeReplacements);
// std::cout << "REGULAR function " << functionName << " has " << transChildren.size() << " parameters: ";
// for (auto i : transChildren)
// std::cout << "||" << i->getDataRef()->toString() << "|| ";
// std::cout << "DoneList" << std::endl;
functionDef->addChildren(transChildren); functionDef->addChildren(transChildren);
// Swap the function type over to be the correct type (a function with parameter and return types, etc)
functionDef->getDataRef()->valueType = new Type(mapNodesToTypePointers(transChildren), functionDef->getDataRef()->valueType);
return functionDef; return functionDef;
} }
@@ -351,7 +347,6 @@ NodeTree<ASTData>* ASTTransformation::searchScopeForFunctionDef(NodeTree<ASTData
//It is used in the third pass to finish things up //It is used in the third pass to finish things up
//Note that it may instantiate class OR function templates, which need to be fully instantiated //Note that it may instantiate class OR function templates, which need to be fully instantiated
void ASTTransformation::thirdPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* functionDef, std::map<std::string, Type*> templateTypeReplacements) { void ASTTransformation::thirdPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* functionDef, std::map<std::string, Type*> templateTypeReplacements) {
//NodeTree<Symbol>* codeBlock = from->getChildren()[from->getChildren().size()-1];
NodeTree<Symbol>* codeBlock = from->getChildren().back(); NodeTree<Symbol>* codeBlock = from->getChildren().back();
functionDef->addChild(transform(codeBlock, functionDef, std::vector<Type>(), templateTypeReplacements)); functionDef->addChild(transform(codeBlock, functionDef, std::vector<Type>(), templateTypeReplacements));
} }
@@ -386,7 +381,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
// pass // pass
NodeTree<ASTData>* perenOp = functionLookup(typeDefinition, "operator", types); NodeTree<ASTData>* perenOp = functionLookup(typeDefinition, "operator", types);
if (perenOp) { if (perenOp) {
NodeTree<ASTData>* dotFunctionCall = new NodeTree<ASTData>(".", ASTData(function_call, Symbol(".", true))); NodeTree<ASTData>* dotFunctionCall = new NodeTree<ASTData>(".", ASTData(function_call, Symbol(".", true), perenOp->getDataRef()->valueType));
dotFunctionCall->addChild(languageLevelOperators["."][0]); //function definition dotFunctionCall->addChild(languageLevelOperators["."][0]); //function definition
dotFunctionCall->addChild(possibleObj); // The object whose method we're calling dotFunctionCall->addChild(possibleObj); // The object whose method we're calling
dotFunctionCall->addChild(perenOp); //The method we're calling dotFunctionCall->addChild(perenOp); //The method we're calling
@@ -440,9 +435,6 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
} }
newNode->getDataRef()->valueType = objectType; //Type is self-referential since this is the definition newNode->getDataRef()->valueType = objectType; //Type is self-referential since this is the definition
} }
// ?? why not this?
//scope->getDataRef()->scope[typeAlias].push_back(newNode);
//newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope);
addToScope("~enclosing_scope", scope, newNode); addToScope("~enclosing_scope", scope, newNode);
@@ -477,21 +469,18 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
for (auto child: children) for (auto child: children)
std::cout << "Function child: " << child->getDataRef()->toString() << std::endl; std::cout << "Function child: " << child->getDataRef()->toString() << std::endl;
newNode = new NodeTree<ASTData>(name, ASTData(function, Symbol(functionName, true), typeFromTypeNode(children[children.size()-2], scope, templateTypeReplacements))); newNode = new NodeTree<ASTData>(name, ASTData(function, Symbol(functionName, true), typeFromTypeNode(children[children.size()-2], scope, templateTypeReplacements)));
skipChildren.insert(0);
skipChildren.insert(children.size()-1);
addToScope(functionName, newNode, scope); addToScope(functionName, newNode, scope);
addToScope("~enclosing_scope", scope, newNode); addToScope("~enclosing_scope", scope, newNode);
scope = newNode; scope = newNode;
// auto transChildren = transformChildren(children, skipChildren, scope, types); auto parameters = transformChildren(getNodes("typed_parameter", children), skipChildren, scope, types, templateTypeReplacements);
// std::cout << functionName << " "; newNode->addChildren(parameters);
// for (auto i : transChildren) // update type with actual type
// std::cout << "||" << i->getDataRef()->toString() << "|| "; newNode->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), newNode->getDataRef()->valueType);
// std::cout << "??||" << std::endl; newNode->addChild(transform(getNode("code_block", children), scope, types, templateTypeReplacements));
// newNode->addChildren(transChildren); std::cout << "finished function" << functionName << std::endl;
// return newNode; return newNode;
std::cout << "finished function (kinda, not children) " << functionName << std::endl;
} else if (name == "code_block") { } else if (name == "code_block") {
newNode = new NodeTree<ASTData>(name, ASTData(code_block)); newNode = new NodeTree<ASTData>(name, ASTData(code_block));
addToScope("~enclosing_scope", scope, newNode); addToScope("~enclosing_scope", scope, newNode);
@@ -519,11 +508,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
throw "LOOKUP ERROR: " + functionCallString; throw "LOOKUP ERROR: " + functionCallString;
} }
newNode = function; newNode = function;
// newNode = new NodeTree<ASTData>(functionCallString, ASTData(function_call, function->getDataRef()->valueType));
// newNode->addChild(function); // First child of function call is a link to the function
// newNode->addChildren(transformedChildren);
} else { } else {
//std::cout << children.size() << std::endl;
// XXX What the heck is this // XXX What the heck is this
if (children.size() == 0) if (children.size() == 0)
return new NodeTree<ASTData>(); return new NodeTree<ASTData>();
@@ -591,7 +576,6 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
return transform(children[0], scope, types, templateTypeReplacements); //Just a promoted child, so do it instead return transform(children[0], scope, types, templateTypeReplacements); //Just a promoted child, so do it instead
} }
} else if (name == "statement") { } else if (name == "statement") {
//XXX
newNode = new NodeTree<ASTData>(name, ASTData(statement)); newNode = new NodeTree<ASTData>(name, ASTData(statement));
} else if (name == "if_statement") { } else if (name == "if_statement") {
newNode = new NodeTree<ASTData>(name, ASTData(if_statement)); newNode = new NodeTree<ASTData>(name, ASTData(if_statement));
@@ -688,13 +672,11 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
} else if (name == "if_comp") { } else if (name == "if_comp") {
newNode = new NodeTree<ASTData>(name, ASTData(if_comp)); newNode = new NodeTree<ASTData>(name, ASTData(if_comp));
newNode->addChild(addToScope("~enclosing_scope", scope, new NodeTree<ASTData>("identifier", ASTData(identifier, Symbol(concatSymbolTree(children[0]),true))))); newNode->addChild(addToScope("~enclosing_scope", scope, new NodeTree<ASTData>("identifier", ASTData(identifier, Symbol(concatSymbolTree(children[0]),true)))));
std::cout << "XXX scope is " << scope << std::endl;
addToScope("~enclosing_scope", scope, newNode); addToScope("~enclosing_scope", scope, newNode);
skipChildren.insert(0); //Don't do the identifier. The identifier lookup will fail. That's why we do it here. skipChildren.insert(0); //Don't do the identifier. The identifier lookup will fail. That's why we do it here.
} else if (name == "simple_passthrough") { } else if (name == "simple_passthrough") {
newNode = new NodeTree<ASTData>(name, ASTData(simple_passthrough)); newNode = new NodeTree<ASTData>(name, ASTData(simple_passthrough));
addToScope("~enclosing_scope", scope, newNode); addToScope("~enclosing_scope", scope, newNode);
std::cout << "XXX scope is " << scope << std::endl;
} else if (name == "passthrough_params") { } else if (name == "passthrough_params") {
newNode = new NodeTree<ASTData>(name, ASTData(passthrough_params)); newNode = new NodeTree<ASTData>(name, ASTData(passthrough_params));
addToScope("~enclosing_scope", scope, newNode); addToScope("~enclosing_scope", scope, newNode);
@@ -726,7 +708,8 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
std::cout << i->getName() << " "; std::cout << i->getName() << " ";
std::cout << std::endl; std::cout << std::endl;
newNode->addChild(function); newNode->addChild(function);
newNode->getDataRef()->valueType = function->getDataRef()->valueType; // note that we now get the return type from the function call's type
newNode->getDataRef()->valueType = function->getDataRef()->valueType->returnType;
newNode->addChildren(transformedChildren); newNode->addChildren(transformedChildren);
return newNode; return newNode;
} else if (name == "parameter") { } else if (name == "parameter") {
@@ -790,6 +773,16 @@ std::vector<NodeTree<ASTData>*> ASTTransformation::transformChildren(std::vector
return transformedChildren; return transformedChildren;
} }
//Extract types from already transformed nodes
std::vector<Type*> ASTTransformation::mapNodesToTypePointers(std::vector<NodeTree<ASTData>*> nodes) {
std::vector<Type*> types;
for (auto i : nodes) {
std::cout << i->getDataRef()->toString() << std::endl;
types.push_back((i->getDataRef()->valueType));
}
return types;
}
//Extract types from already transformed nodes //Extract types from already transformed nodes
std::vector<Type> ASTTransformation::mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes) { std::vector<Type> ASTTransformation::mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes) {
std::vector<Type> types; std::vector<Type> types;
@@ -831,7 +824,7 @@ NodeTree<ASTData>* ASTTransformation::doFunction(NodeTree<ASTData>* scope, std::
std::cout << "Early method level operator was found" << std::endl; std::cout << "Early method level operator was found" << std::endl;
//return operatorMethod; //return operatorMethod;
NodeTree<ASTData>* newNode = new NodeTree<ASTData>(lookupOp, ASTData(function_call, Symbol(lookupOp, true))); NodeTree<ASTData>* newNode = new NodeTree<ASTData>(lookupOp, ASTData(function_call, Symbol(lookupOp, true)));
NodeTree<ASTData>* dotFunctionCall = new NodeTree<ASTData>(".", ASTData(function_call, Symbol(".", true))); NodeTree<ASTData>* dotFunctionCall = new NodeTree<ASTData>(".", ASTData(function_call, Symbol(".", true), operatorMethod->getDataRef()->valueType));
dotFunctionCall->addChild(languageLevelOperators["."][0]); //function definition dotFunctionCall->addChild(languageLevelOperators["."][0]); //function definition
dotFunctionCall->addChild(nodes[0]); // The object whose method we're calling dotFunctionCall->addChild(nodes[0]); // The object whose method we're calling
dotFunctionCall->addChild(operatorMethod); //The method we're calling dotFunctionCall->addChild(operatorMethod); //The method we're calling
@@ -840,7 +833,7 @@ NodeTree<ASTData>* ASTTransformation::doFunction(NodeTree<ASTData>* scope, std::
//Set the value of this function call //Set the value of this function call
newNode->getDataRef()->valueType = operatorMethod->getDataRef()->valueType; newNode->getDataRef()->valueType = operatorMethod->getDataRef()->valueType->returnType;
return newNode; return newNode;
} }
std::cout << "Early method level operator was NOT found" << std::endl; std::cout << "Early method level operator was NOT found" << std::endl;
@@ -874,7 +867,9 @@ NodeTree<ASTData>* ASTTransformation::doFunction(NodeTree<ASTData>* scope, std::
newNode->getDataRef()->valueType = newType, std::cout << "Operator " + lookup << " is altering indirection from " << oldTypes[0].toString() << " to " << newType->toString() << std::endl; newNode->getDataRef()->valueType = newType, std::cout << "Operator " + lookup << " is altering indirection from " << oldTypes[0].toString() << " to " << newType->toString() << std::endl;
} else { } else {
newNode->getDataRef()->valueType = function->getDataRef()->valueType, std::cout << "Some other ||" << lookup << "||" << std::endl; std::cout << "Some other ||" << lookup << "||" << std::endl;
if (function->getDataRef()->valueType)
newNode->getDataRef()->valueType = function->getDataRef()->valueType->returnType;
} }
// Set the value of this function call if it has not already been set // Set the value of this function call if it has not already been set
@@ -1496,13 +1491,14 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
addToScope(fullyInstantiatedName, instantiatedFunction, templateTopScope); addToScope(fullyInstantiatedName, instantiatedFunction, templateTopScope);
templateTopScope->addChild(instantiatedFunction); // Add this object the the highest scope's templateTopScope->addChild(instantiatedFunction); // Add this object the the highest scope's
std::set<int> skipChildren;
skipChildren.insert(0);
skipChildren.insert(1);
skipChildren.insert(templateSyntaxTree->getChildren().size()-3);
skipChildren.insert(templateSyntaxTree->getChildren().size()-2);
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));
std::set<int> skipChildren;
auto parameters = transformChildren(getNodes("typed_parameter", templateSyntaxTree->getChildren()), skipChildren, instantiatedFunction, std::vector<Type>(), newTemplateTypeReplacement);
instantiatedFunction->addChildren(parameters);
// update type with actual type
instantiatedFunction->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), instantiatedFunction->getDataRef()->valueType);
instantiatedFunction->addChild(transform(getNode("code_block", templateSyntaxTree->getChildren()), instantiatedFunction, std::vector<Type>(), newTemplateTypeReplacement));
std::cout << "Fully Instantiated function " << functionName << " to " << fullyInstantiatedName << std::endl; std::cout << "Fully Instantiated function " << functionName << " to " << fullyInstantiatedName << std::endl;
return instantiatedFunction; return instantiatedFunction;

View File

@@ -174,8 +174,8 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
ASTData declarationData = declaration->getData(); ASTData declarationData = declaration->getData();
switch(declarationData.type) { switch(declarationData.type) {
case identifier: case identifier:
variableDeclarations += ValueTypeToCType(declarationData.valueType) + " " + scopePrefix(declaration) + declarationData.symbol.getName() + "; /*identifier*/\n"; variableDeclarations += ValueTypeToCType(declarationData.valueType, scopePrefix(declaration) + 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:
{ {
@@ -184,16 +184,15 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
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) + " ";
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 += ((declarationData.symbol.getName() == "main") ? "" : scopePrefix(declaration)) + functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType->returnType, ((declarationData.symbol.getName() == "main") ? "" : scopePrefix(declaration)) +
CifyName(declarationData.symbol.getName() + nameDecoration) + CifyName(declarationData.symbol.getName() + nameDecoration)) +
"(" + parameters + "); /*func*/\n"; "(" + parameters + "); /*func*/\n";
// generate function // generate function
std::cout << "Generating " << scopePrefix(declaration) + std::cout << "Generating " << scopePrefix(declaration) +
@@ -212,9 +211,9 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
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) + " " + plainTypedefs += "typedef " + ValueTypeToCType(declarationData.valueType,
scopePrefix(declaration) + scopePrefix(declaration) +
CifyName(declarationData.symbol.getName()) + ";\n"; CifyName(declarationData.symbol.getName())) + ";\n";
plainTypedefs += generateAliasChains(ASTs, declaration); plainTypedefs += generateAliasChains(ASTs, declaration);
} else { } else {
plainTypedefs += "typedef struct __struct_dummy_" + plainTypedefs += "typedef struct __struct_dummy_" +
@@ -249,7 +248,7 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
} }
//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, bool justFuncName) {
ASTData data = from->getData(); ASTData data = from->getData();
std::vector<NodeTree<ASTData>*> children = from->getChildren(); std::vector<NodeTree<ASTData>*> children = from->getChildren();
std::string output; std::string output;
@@ -288,17 +287,18 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
{ {
if (data.valueType->baseType == template_type) if (data.valueType->baseType == template_type)
return "/* template function: " + data.symbol.getName() + " */"; return "/* template function: " + data.symbol.getName() + " */";
output += "\n" + ValueTypeToCType(data.valueType) + " ";
std::string nameDecoration, parameters; std::string nameDecoration, parameters;
for (int j = 0; j < children.size()-1; j++) { for (int j = 0; j < children.size()-1; j++) {
if (j > 0) if (j > 0)
parameters += ", "; parameters += ", ";
parameters += ValueTypeToCType(children[j]->getData().valueType) + " " + generate(children[j], enclosingObject); parameters += ValueTypeToCType(children[j]->getData().valueType, generate(children[j], enclosingObject, justFuncName));
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType); nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType);
} }
// this is for using functions as values
output += ((data.symbol.getName() == "main") ? "" : scopePrefix(from)) + if (justFuncName)
CifyName(data.symbol.getName() + nameDecoration) + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject); return ((data.symbol.getName() == "main") ? "" : scopePrefix(from)) + CifyName(data.symbol.getName() + nameDecoration);
output += "\n" + ValueTypeToCType(data.valueType->returnType, ((data.symbol.getName() == "main") ? "" : scopePrefix(from)) +
CifyName(data.symbol.getName() + nameDecoration)) + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject, justFuncName);
return output; return output;
} }
case code_block: case code_block:
@@ -308,10 +308,10 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
// we push on a new vector to hold deferred statements // we push on a new vector to hold deferred statements
deferDoubleStack.push_back(std::vector<NodeTree<ASTData>*>()); deferDoubleStack.push_back(std::vector<NodeTree<ASTData>*>());
for (int i = 0; i < children.size(); i++) for (int i = 0; i < children.size(); i++)
output += generate(children[i], enclosingObject); output += generate(children[i], enclosingObject, justFuncName);
// we pop off the vector and go through them in reverse emitting them // we pop off the vector and go through them in reverse emitting them
for (auto iter = deferDoubleStack.back().rbegin(); iter != deferDoubleStack.back().rend(); iter++) for (auto iter = deferDoubleStack.back().rbegin(); iter != deferDoubleStack.back().rend(); iter++)
output += generate(*iter, enclosingObject); output += generate(*iter, enclosingObject, justFuncName);
deferDoubleStack.pop_back(); deferDoubleStack.pop_back();
tabLevel--; tabLevel--;
output += tabs() + "}"; output += tabs() + "}";
@@ -322,31 +322,31 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
case boolean_expression: case boolean_expression:
output += " " + data.symbol.getName() + " "; output += " " + data.symbol.getName() + " ";
case statement: case statement:
return tabs() + generate(children[0], enclosingObject) + ";\n"; return tabs() + generate(children[0], enclosingObject, justFuncName) + ";\n";
case if_statement: case if_statement:
output += "if (" + generate(children[0], enclosingObject) + ")\n\t"; output += "if (" + generate(children[0], enclosingObject, true) + ")\n\t";
// We have to see if the then statement is a regular single statement or a block. // We have to see if the then statement is a regular single statement or a block.
// If it's a block, because it's also a statement a semicolon will be emitted even though // If it's a block, because it's also a statement a semicolon will be emitted even though
// we don't want it to be, as if (a) {b}; else {c}; is not legal C, but if (a) {b} else {c}; is. // we don't want it to be, as if (a) {b}; else {c}; is not legal C, but if (a) {b} else {c}; is.
if (children[1]->getChildren()[0]->getDataRef()->type == code_block) { if (children[1]->getChildren()[0]->getDataRef()->type == code_block) {
std::cout << "Then statement is a block, emitting the block not the statement so no trailing semicolon" << std::endl; std::cout << "Then statement is a block, emitting the block not the statement so no trailing semicolon" << std::endl;
output += generate(children[1]->getChildren()[0], enclosingObject); output += generate(children[1]->getChildren()[0], enclosingObject, justFuncName);
} else { } else {
// ALSO we always emit blocks now, to handle cases like defer when several statements need to be // ALSO we always emit blocks now, to handle cases like defer when several statements need to be
// run in C even though it is a single Kraken statement // run in C even though it is a single Kraken statement
std::cout << "Then statement is a simple statement, regular emitting the statement so trailing semicolon" << std::endl; std::cout << "Then statement is a simple statement, regular emitting the statement so trailing semicolon" << std::endl;
output += "{ " + generate(children[1], enclosingObject) + " }"; output += "{ " + generate(children[1], enclosingObject, justFuncName) + " }";
} }
// Always emit blocks here too // Always emit blocks here too
if (children.size() > 2) if (children.size() > 2)
output += " else { " + generate(children[2], enclosingObject) + " }"; output += " else { " + generate(children[2], enclosingObject, justFuncName) + " }";
return output; return output;
case while_loop: case while_loop:
// keep track of the current size of the deferDoubleStack so that statements that // keep track of the current size of the deferDoubleStack so that statements that
// break or continue inside this loop can correctly emit all of the defers through // break or continue inside this loop can correctly emit all of the defers through
// all of the inbetween scopes // all of the inbetween scopes
loopDeferStackDepth.push(deferDoubleStack.size()); loopDeferStackDepth.push(deferDoubleStack.size());
output += "while (" + generate(children[0], enclosingObject) + ")\n\t" + generate(children[1], enclosingObject); output += "while (" + generate(children[0], enclosingObject, true) + ")\n\t" + generate(children[1], enclosingObject, justFuncName);
// and pop it off again // and pop it off again
loopDeferStackDepth.pop(); loopDeferStackDepth.pop();
return output; return output;
@@ -356,7 +356,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
// all of the inbetween scopes // all of the inbetween scopes
loopDeferStackDepth.push(deferDoubleStack.size()); loopDeferStackDepth.push(deferDoubleStack.size());
//The strSlice's are there to get ride of an unwanted return and an unwanted semicolon(s) //The strSlice's are there to get ride of an unwanted return and an unwanted semicolon(s)
output += "for (" + strSlice(generate(children[0], enclosingObject),0,-3) + generate(children[1], enclosingObject) + ";" + strSlice(generate(children[2], enclosingObject),0,-3) + ")\n\t" + generate(children[3], enclosingObject); output += "for (" + strSlice(generate(children[0], enclosingObject, true),0,-3) + generate(children[1], enclosingObject, true) + ";" + strSlice(generate(children[2], enclosingObject, true),0,-3) + ")\n\t" + generate(children[3], enclosingObject, justFuncName);
// and pop it off again // and pop it off again
loopDeferStackDepth.pop(); loopDeferStackDepth.pop();
return output; return output;
@@ -365,43 +365,43 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
// through all of both arrays, as return will go through all scopes // through all of both arrays, as return will go through all scopes
for (auto topItr = deferDoubleStack.rbegin(); topItr != deferDoubleStack.rend(); topItr++) for (auto topItr = deferDoubleStack.rbegin(); topItr != deferDoubleStack.rend(); topItr++)
for (auto iter = (*topItr).rbegin(); iter != (*topItr).rend(); iter++) for (auto iter = (*topItr).rbegin(); iter != (*topItr).rend(); iter++)
output += generate(*iter, enclosingObject); output += generate(*iter, enclosingObject, justFuncName);
if (children.size()) if (children.size())
return "return " + generate(children[0], enclosingObject); return "return " + generate(children[0], enclosingObject, true);
else else
return "return"; return "return";
case break_statement: case break_statement:
// handle everything that's been deferred all the way back to the loop's scope // handle everything that's been deferred all the way back to the loop's scope
for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--) for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--)
for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++) for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
output += generate(*iter, enclosingObject); output += generate(*iter, enclosingObject, justFuncName);
return output + "break"; return output + "break";
case continue_statement: case continue_statement:
// handle everything that's been deferred all the way back to the loop's scope // handle everything that's been deferred all the way back to the loop's scope
for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--) for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--)
for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++) for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
output += generate(*iter, enclosingObject); output += generate(*iter, enclosingObject, justFuncName);
return output + "continue"; return output + "continue";
case defer_statement: case defer_statement:
deferDoubleStack.back().push_back(children[0]); deferDoubleStack.back().push_back(children[0]);
return "/*defer " + generate(children[0], enclosingObject) + "*/"; return "/*defer " + generate(children[0], enclosingObject, justFuncName) + "*/";
case assignment_statement: case assignment_statement:
return generate(children[0], enclosingObject) + " = " + generate(children[1], enclosingObject); return generate(children[0], enclosingObject, justFuncName) + " = " + generate(children[1], enclosingObject, true);
case declaration_statement: case declaration_statement:
if (children.size() == 1) if (children.size() == 1)
return ValueTypeToCType(children[0]->getData().valueType) + " " + generate(children[0], enclosingObject) + ";"; return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName)) + ";";
else if (children[1]->getChildren().size() && children[1]->getChildren()[0]->getChildren().size() > 1 else if (children[1]->getChildren().size() && children[1]->getChildren()[0]->getChildren().size() > 1
&& children[1]->getChildren()[0]->getChildren()[1] == children[0]) { && children[1]->getChildren()[0]->getChildren()[1] == children[0]) {
//That is, if we're a declaration with an init position call (Object a.construct()) //That is, if we're a declaration with an init position call (Object a.construct())
//We can tell if our function call (children[1])'s access operation([0])'s lhs ([1]) is the thing we just declared (children[0]) //We can tell if our function call (children[1])'s access operation([0])'s lhs ([1]) is the thing we just declared (children[0])
return ValueTypeToCType(children[0]->getData().valueType) + " " + generate(children[0], enclosingObject) + "; " + generate(children[1]) + "/*Init Position Call*/"; return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName)) + "; " + generate(children[1]) + "/*Init Position Call*/";
} else } else
return ValueTypeToCType(children[0]->getData().valueType) + " " + generate(children[0], enclosingObject) + " = " + generate(children[1], enclosingObject) + ";"; return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName)) + " = " + generate(children[1], enclosingObject, true) + ";";
case if_comp: case if_comp:
// Lol, this doesn't work because the string gets prefixed now // Lol, this doesn't work because the string gets prefixed now
//if (generate(children[0], enclosingObject) == generatorString) //if (generate(children[0], enclosingObject) == generatorString)
if (children[0]->getDataRef()->symbol.getName() == generatorString) if (children[0]->getDataRef()->symbol.getName() == generatorString)
return generate(children[1], enclosingObject); return generate(children[1], enclosingObject, justFuncName);
return ""; return "";
case simple_passthrough: case simple_passthrough:
{ {
@@ -414,17 +414,17 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
for (auto assign : in_or_out->getChildren()) { for (auto assign : in_or_out->getChildren()) {
auto assignChildren = assign->getChildren(); auto assignChildren = assign->getChildren();
if (in_or_out->getDataRef()->type == in_passthrough_params) if (in_or_out->getDataRef()->type == in_passthrough_params)
pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType) + " " + assignChildren[1]->getDataRef()->symbol.getName() + " = " + generate(assignChildren[0], enclosingObject) + ";\n"; pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, assignChildren[1]->getDataRef()->symbol.getName()) + " = " + generate(assignChildren[0], enclosingObject) + ";\n";
else if (in_or_out->getDataRef()->type == out_passthrough_params) else if (in_or_out->getDataRef()->type == out_passthrough_params)
post_passthrough += generate(assignChildren[0], enclosingObject) + " = " + assignChildren[1]->getDataRef()->symbol.getName() + ";\n"; post_passthrough += generate(assignChildren[0], enclosingObject, justFuncName) + " = " + assignChildren[1]->getDataRef()->symbol.getName() + ";\n";
else else
linkerString += " " + strSlice(generate(in_or_out, enclosingObject), 1, -2) + " "; linkerString += " " + strSlice(generate(in_or_out, enclosingObject, justFuncName), 1, -2) + " ";
} }
} }
} }
// The actual passthrough string is the last child now, as we might // The actual passthrough string is the last child now, as we might
// have passthrough_params be the first child // have passthrough_params be the first child
return pre_passthrough + strSlice(generate(children.back(), enclosingObject), 3, -4) + post_passthrough; return pre_passthrough + strSlice(generate(children.back(), enclosingObject, justFuncName), 3, -4) + post_passthrough;
} }
case function_call: case function_call:
{ {
@@ -440,19 +440,19 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
//Test for specail functions only if what we're testing is, indeed, the definition, not a function call that returns a callable function pointer //Test for specail functions only if what we're testing is, indeed, the definition, not a function call that returns a callable function pointer
if (funcType == function) { if (funcType == function) {
if (name == "++" || name == "--") if (name == "++" || name == "--")
return generate(children[1], enclosingObject) + name; return generate(children[1], enclosingObject, true) + name;
if ( (name == "*" || name == "&" || name == "!" || name == "-" || name == "+" ) && children.size() == 2) //Is dereference, not multiplication, address-of, or other unary operator if ( (name == "*" || name == "&" || name == "!" || name == "-" || name == "+" ) && children.size() == 2) //Is dereference, not multiplication, address-of, or other unary operator
return name + "(" + generate(children[1], enclosingObject) + ")"; return name + "(" + generate(children[1], enclosingObject, true) + ")";
if (name == "[]") if (name == "[]")
return "(" + generate(children[1], enclosingObject) + ")[" +generate(children[2],enclosingObject) + "]"; return "(" + generate(children[1], enclosingObject, true) + ")[" +generate(children[2],enclosingObject, true) + "]";
if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!="
|| name == "<" || name == ">" || name == "%" || name == "+=" || name == "-=" || name == "*=" || name == "/=" || name == "||" || name == "<" || name == ">" || name == "%" || name == "+=" || name == "-=" || name == "*=" || name == "/=" || name == "||"
|| name == "&&") { || name == "&&") {
std::cout << "THIS IS IT NAME: " << name << std::endl; std::cout << "THIS IS IT NAME: " << name << std::endl;
return "((" + generate(children[1], enclosingObject) + ")" + name + "(" + generate(children[2], enclosingObject) + "))"; return "((" + generate(children[1], enclosingObject, true) + ")" + name + "(" + generate(children[2], enclosingObject, true) + "))";
} else if (name == "." || name == "->") { } else if (name == "." || name == "->") {
if (children.size() == 1) if (children.size() == 1)
return "/*dot operation with one child*/" + generate(children[0], enclosingObject) + "/*end one child*/"; return "/*dot operation with one child*/" + generate(children[0], enclosingObject, true) + "/*end one child*/";
//If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method //If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method
if (children[2]->getDataRef()->type == function) { if (children[2]->getDataRef()->type == function) {
std::string functionName = children[2]->getDataRef()->symbol.getName(); std::string functionName = children[2]->getDataRef()->symbol.getName();
@@ -468,20 +468,20 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
// Note that we only add scoping to the object, as this specifies our member function too // Note that we only add scoping to the object, as this specifies our member function too
/*HERE*/ return scopePrefix(unaliasedTypeDef) + CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" + /*HERE*/ return scopePrefix(unaliasedTypeDef) + CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" +
CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ","; CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject, true) + ",";
//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, true) + ")" + name + functionName + ")";
} }
} 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, true) + ")" + name + functionName + ")";
} }
} else { } else {
//return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")"; //return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")";
return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2]) + ")"; return "((" + generate(children[1], enclosingObject, true) + ")" + name + generate(children[2], nullptr, true) + ")";
} }
} else { } else {
//It's a normal function call, not a special one or a method or anything. Name decorate. //It's a normal function call, not a special one or a method or anything. Name decorate.
@@ -503,7 +503,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
} else { } else {
//This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function) //This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function)
//It's probabally the result of an access function call (. or ->) to access an object method. //It's probabally the result of an access function call (. or ->) to access an object method.
std::string functionCallSource = generate(children[0], enclosingObject); std::string functionCallSource = generate(children[0], enclosingObject, true);
if (functionCallSource[functionCallSource.size()-1] == ',') //If it's a member method, it's already started the parameter list. if (functionCallSource[functionCallSource.size()-1] == ',') //If it's a member method, it's already started the parameter list.
output += children.size() > 1 ? functionCallSource : functionCallSource.substr(0, functionCallSource.size()-1); output += children.size() > 1 ? functionCallSource : functionCallSource.substr(0, functionCallSource.size()-1);
else else
@@ -511,9 +511,9 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
} }
for (int i = 1; i < children.size(); i++) //children[0] is the declaration for (int i = 1; i < children.size(); i++) //children[0] is the declaration
if (i < children.size()-1) if (i < children.size()-1)
output += generate(children[i], enclosingObject) + ", "; output += generate(children[i], enclosingObject, true) + ", ";
else else
output += generate(children[i], enclosingObject); output += generate(children[i], enclosingObject, true);
output += ") "; output += ") ";
return output; return output;
} }
@@ -524,7 +524,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
std::cout << "Nothing!" << std::endl; std::cout << "Nothing!" << std::endl;
} }
for (int i = 0; i < children.size(); i++) for (int i = 0; i < children.size(); i++)
output += generate(children[i], enclosingObject); output += generate(children[i], enclosingObject, justFuncName);
return output; return output;
} }
@@ -543,21 +543,21 @@ std::string CGenerator::generateObjectMethod(NodeTree<ASTData>* enclosingObject,
std::vector<NodeTree<ASTData>*> children = from->getChildren(); std::vector<NodeTree<ASTData>*> children = from->getChildren();
std::string nameDecoration, parameters; std::string nameDecoration, parameters;
for (int i = 0; i < children.size()-1; i++) { for (int i = 0; i < children.size()-1; i++) {
parameters += ", " + ValueTypeToCType(children[i]->getData().valueType) + " " + generate(children[i]); parameters += ", " + ValueTypeToCType(children[i]->getData().valueType, generate(children[i]));
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType); nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType);
} }
std::string functionSignature = "\n" + ValueTypeToCType(data.valueType) + " " + scopePrefix(from) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__" std::string functionSignature = "\n" + ValueTypeToCType(data.valueType->returnType, scopePrefix(from) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"
+ CifyName(data.symbol.getName()) + nameDecoration + "(" + ValueTypeToCType(&enclosingObjectType) + CifyName(data.symbol.getName()) + nameDecoration) + "(" + ValueTypeToCType(&enclosingObjectType, "this") + parameters + ")";
+ " this" + parameters + ")";
*functionPrototype += functionSignature + ";\n"; *functionPrototype += functionSignature + ";\n";
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, std::string declaration) { return ValueTypeToCTypeThingHelper(type, " " + declaration); }
std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return ValueTypeToCTypeThingHelper(type, "_P__"); } std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return CifyName(ValueTypeToCTypeThingHelper(type, "")); }
std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr) { std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string declaration) {
std::string return_type; std::string return_type;
bool do_ending = true;
switch (type->baseType) { switch (type->baseType) {
case none: case none:
if (type->typeDefinition) if (type->typeDefinition)
@@ -565,6 +565,25 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string ptrS
else else
return_type = "none"; return_type = "none";
break; break;
case function_type:
{
std::string indr_str;
for (int i = 0; i < type->getIndirection(); i++)
indr_str += "*";
return_type = ValueTypeToCTypeThingHelper(type->returnType, "");
if (type->getIndirection())
return_type += " (" + indr_str + "(*" + declaration + "))(";
else
return_type += " (*" + declaration + ")(";
if (type->parameterTypes.size() == 0)
return_type += "void";
else
for (int i = 0; i < type->parameterTypes.size(); i++)
return_type += (i != 0 ? ", " : "") + ValueTypeToCTypeThingHelper(type->parameterTypes[i], "");
return_type += ")";
do_ending = false;
}
break;
case void_type: case void_type:
return_type = "void"; return_type = "void";
break; break;
@@ -587,9 +606,11 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string ptrS
return_type = "unknown_ValueType"; return_type = "unknown_ValueType";
break; break;
} }
if (!do_ending)
return return_type;
for (int i = 0; i < type->getIndirection(); i++) for (int i = 0; i < type->getIndirection(); i++)
return_type += ptrStr; return_type += "*";
return return_type; return return_type + declaration;
} }
std::string CGenerator::CifyName(std::string name) { std::string CGenerator::CifyName(std::string name) {
@@ -610,6 +631,7 @@ std::string CGenerator::CifyName(std::string name) {
"<<", "doubleleft", "<<", "doubleleft",
">>", "doubleright", ">>", "doubleright",
"::", "scopeop", "::", "scopeop",
":", "colon",
"==", "doubleequals", "==", "doubleequals",
"!=", "notequals", "!=", "notequals",
"&&", "doubleamprsnd", "&&", "doubleamprsnd",

View File

@@ -3,30 +3,30 @@
Type::Type() { Type::Type() {
indirection = 0; indirection = 0;
baseType = none; baseType = none;
typeDefinition = NULL; typeDefinition = nullptr;
templateDefinition = NULL; templateDefinition = nullptr;
} }
Type::Type(ValueType typeIn, int indirectionIn) { Type::Type(ValueType typeIn, int indirectionIn) {
indirection = indirectionIn; indirection = indirectionIn;
baseType = typeIn; baseType = typeIn;
typeDefinition = NULL; typeDefinition = nullptr;
templateDefinition = NULL; templateDefinition = nullptr;
} }
Type::Type(ValueType typeIn, std::set<std::string> traitsIn) { Type::Type(ValueType typeIn, std::set<std::string> traitsIn) {
indirection = 0; indirection = 0;
baseType = typeIn; baseType = typeIn;
traits = traitsIn; traits = traitsIn;
typeDefinition = NULL; typeDefinition = nullptr;
templateDefinition = NULL; templateDefinition = nullptr;
} }
Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) { Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) {
indirection = indirectionIn; indirection = indirectionIn;
baseType = none; baseType = none;
typeDefinition = typeDefinitionIn; typeDefinition = typeDefinitionIn;
templateDefinition = NULL; templateDefinition = nullptr;
} }
Type::Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn) { Type::Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn) {
@@ -34,7 +34,7 @@ Type::Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn)
baseType = none; baseType = none;
typeDefinition = typeDefinitionIn; typeDefinition = typeDefinitionIn;
traits = traitsIn; traits = traitsIn;
templateDefinition = NULL; templateDefinition = nullptr;
} }
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn) { Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn) {
@@ -42,13 +42,31 @@ Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectio
indirection = indirectionIn; indirection = indirectionIn;
typeDefinition = typeDefinitionIn; typeDefinition = typeDefinitionIn;
traits = traitsIn; traits = traitsIn;
templateDefinition = NULL; templateDefinition = nullptr;
}
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn, std::vector<Type*> parameterTypesIn, Type* returnTypeIn) {
baseType = typeIn;
indirection = indirectionIn;
typeDefinition = typeDefinitionIn;
traits = traitsIn;
templateDefinition = nullptr;
parameterTypes = parameterTypesIn;
returnType = returnTypeIn;
}
Type::Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn) {
baseType = function_type;
indirection = 0;
typeDefinition = nullptr;
templateDefinition = nullptr;
parameterTypes = parameterTypesIn;
returnType = returnTypeIn;
} }
Type::Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn) { Type::Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn) {
indirection = 0; indirection = 0;
baseType = typeIn; baseType = typeIn;
typeDefinition = NULL; typeDefinition = nullptr;
templateDefinition = templateDefinitionIn; templateDefinition = templateDefinitionIn;
traits = traitsIn; traits = traitsIn;
} }
@@ -98,6 +116,12 @@ std::string Type::toString(bool showTraits) {
case character: case character:
typeString = "char"; typeString = "char";
break; break;
case function_type:
typeString = "function(";
for (Type *param : parameterTypes)
typeString += param->toString();
typeString += "): " + returnType->toString();
break;
default: default:
if (typeDefinition) if (typeDefinition)
typeString = typeDefinition->getDataRef()->symbol.getName(); typeString = typeDefinition->getDataRef()->symbol.getName();
@@ -117,7 +141,7 @@ std::string Type::toString(bool showTraits) {
} }
Type* Type::clone() { Type* Type::clone() {
return new Type(baseType, typeDefinition, indirection, traits); return new Type(baseType, typeDefinition, indirection, traits, parameterTypes, returnType);
} }
int Type::getIndirection() { int Type::getIndirection() {

View File

@@ -0,0 +1 @@
9

View File

@@ -0,0 +1,13 @@
import io:*
fun test(): void {
println(9)
}
fun main(): int {
var val = test
val()
return 0
}