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);
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*> mapNodesToTypePointers(std::vector<NodeTree<ASTData>*> nodes);
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);

View File

@@ -26,9 +26,9 @@ class CGenerator {
bool isUnderTranslationUnit(NodeTree<ASTData>* from, NodeTree<ASTData>* typeDefinition);
NodeTree<ASTData>* highestScope(NodeTree<ASTData>* node);
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);
static std::string ValueTypeToCType(Type *type);
static std::string ValueTypeToCType(Type *type, std::string);
static std::string ValueTypeToCTypeDecoration(Type *type);
static std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr);
static std::string CifyName(std::string name);

View File

@@ -14,7 +14,7 @@ class ASTData;
#include "ASTData.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 {
@@ -25,6 +25,8 @@ class Type {
Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn = 0);
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, 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();
bool const operator==(const Type &other)const;
@@ -42,6 +44,8 @@ class Type {
NodeTree<Symbol>* templateDefinition;
std::map<std::string, Type*> templateTypeReplacement;
std::set<std::string> traits;
std::vector<Type*> parameterTypes;
Type *returnType;
private:
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
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);
// 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;
}
@@ -351,7 +347,6 @@ NodeTree<ASTData>* ASTTransformation::searchScopeForFunctionDef(NodeTree<ASTData
//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
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();
functionDef->addChild(transform(codeBlock, functionDef, std::vector<Type>(), templateTypeReplacements));
}
@@ -386,7 +381,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
// pass
NodeTree<ASTData>* perenOp = functionLookup(typeDefinition, "operator", types);
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(possibleObj); // The object whose 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
}
// ?? why not this?
//scope->getDataRef()->scope[typeAlias].push_back(newNode);
//newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope);
addToScope("~enclosing_scope", scope, newNode);
@@ -477,21 +469,18 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
for (auto child: children)
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)));
skipChildren.insert(0);
skipChildren.insert(children.size()-1);
addToScope(functionName, newNode, scope);
addToScope("~enclosing_scope", scope, newNode);
scope = newNode;
// auto transChildren = transformChildren(children, skipChildren, scope, types);
// std::cout << functionName << " ";
// for (auto i : transChildren)
// std::cout << "||" << i->getDataRef()->toString() << "|| ";
// std::cout << "??||" << std::endl;
// newNode->addChildren(transChildren);
// return newNode;
auto parameters = transformChildren(getNodes("typed_parameter", children), skipChildren, scope, types, templateTypeReplacements);
newNode->addChildren(parameters);
// update type with actual type
newNode->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), newNode->getDataRef()->valueType);
newNode->addChild(transform(getNode("code_block", children), scope, types, templateTypeReplacements));
std::cout << "finished function" << functionName << std::endl;
return newNode;
std::cout << "finished function (kinda, not children) " << functionName << std::endl;
} else if (name == "code_block") {
newNode = new NodeTree<ASTData>(name, ASTData(code_block));
addToScope("~enclosing_scope", scope, newNode);
@@ -519,11 +508,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
throw "LOOKUP ERROR: " + functionCallString;
}
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 {
//std::cout << children.size() << std::endl;
// XXX What the heck is this
if (children.size() == 0)
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
}
} else if (name == "statement") {
//XXX
newNode = new NodeTree<ASTData>(name, ASTData(statement));
} else if (name == "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") {
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)))));
std::cout << "XXX scope is " << scope << std::endl;
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.
} else if (name == "simple_passthrough") {
newNode = new NodeTree<ASTData>(name, ASTData(simple_passthrough));
addToScope("~enclosing_scope", scope, newNode);
std::cout << "XXX scope is " << scope << std::endl;
} else if (name == "passthrough_params") {
newNode = new NodeTree<ASTData>(name, ASTData(passthrough_params));
addToScope("~enclosing_scope", scope, newNode);
@@ -726,7 +708,8 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
std::cout << i->getName() << " ";
std::cout << std::endl;
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);
return newNode;
} else if (name == "parameter") {
@@ -790,6 +773,16 @@ std::vector<NodeTree<ASTData>*> ASTTransformation::transformChildren(std::vector
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
std::vector<Type> ASTTransformation::mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes) {
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;
//return operatorMethod;
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(nodes[0]); // The object whose 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
newNode->getDataRef()->valueType = operatorMethod->getDataRef()->valueType;
newNode->getDataRef()->valueType = operatorMethod->getDataRef()->valueType->returnType;
return newNode;
}
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;
} 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
@@ -1496,13 +1491,14 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
addToScope(fullyInstantiatedName, instantiatedFunction, templateTopScope);
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;
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;
return instantiatedFunction;

View File

@@ -174,8 +174,8 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
ASTData declarationData = declaration->getData();
switch(declarationData.type) {
case identifier:
variableDeclarations += ValueTypeToCType(declarationData.valueType) + " " + scopePrefix(declaration) + declarationData.symbol.getName() + "; /*identifier*/\n";
variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*extern identifier*/\n";
variableDeclarations += ValueTypeToCType(declarationData.valueType, scopePrefix(declaration) + declarationData.symbol.getName()) + "; /*identifier*/\n";
variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType, declarationData.symbol.getName()) + "; /*extern identifier*/\n";
break;
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
functionPrototypes += "/* built in function: " + declarationData.symbol.toString() + " */\n";
else {
functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType) + " ";
std::string nameDecoration, parameters;
for (int j = 0; j < decChildren.size()-1; j++) {
if (j > 0)
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);
}
functionPrototypes += ((declarationData.symbol.getName() == "main") ? "" : scopePrefix(declaration)) +
CifyName(declarationData.symbol.getName() + nameDecoration) +
functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType->returnType, ((declarationData.symbol.getName() == "main") ? "" : scopePrefix(declaration)) +
CifyName(declarationData.symbol.getName() + nameDecoration)) +
"(" + parameters + "); /*func*/\n";
// generate function
std::cout << "Generating " << scopePrefix(declaration) +
@@ -212,9 +211,9 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
if (declarationData.valueType->typeDefinition)
continue; // Aliases of objects are done with the thing it alises
// Otherwise, we're actually a renaming of a primitive, can generate here
plainTypedefs += "typedef " + ValueTypeToCType(declarationData.valueType) + " " +
plainTypedefs += "typedef " + ValueTypeToCType(declarationData.valueType,
scopePrefix(declaration) +
CifyName(declarationData.symbol.getName()) + ";\n";
CifyName(declarationData.symbol.getName())) + ";\n";
plainTypedefs += generateAliasChains(ASTs, declaration);
} else {
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
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();
std::vector<NodeTree<ASTData>*> children = from->getChildren();
std::string output;
@@ -288,17 +287,18 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
{
if (data.valueType->baseType == template_type)
return "/* template function: " + data.symbol.getName() + " */";
output += "\n" + ValueTypeToCType(data.valueType) + " ";
std::string nameDecoration, parameters;
for (int j = 0; j < children.size()-1; j++) {
if (j > 0)
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);
}
output += ((data.symbol.getName() == "main") ? "" : scopePrefix(from)) +
CifyName(data.symbol.getName() + nameDecoration) + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject);
// this is for using functions as values
if (justFuncName)
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;
}
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
deferDoubleStack.push_back(std::vector<NodeTree<ASTData>*>());
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
for (auto iter = deferDoubleStack.back().rbegin(); iter != deferDoubleStack.back().rend(); iter++)
output += generate(*iter, enclosingObject);
output += generate(*iter, enclosingObject, justFuncName);
deferDoubleStack.pop_back();
tabLevel--;
output += tabs() + "}";
@@ -322,31 +322,31 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
case boolean_expression:
output += " " + data.symbol.getName() + " ";
case statement:
return tabs() + generate(children[0], enclosingObject) + ";\n";
return tabs() + generate(children[0], enclosingObject, justFuncName) + ";\n";
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.
// 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.
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;
output += generate(children[1]->getChildren()[0], enclosingObject);
output += generate(children[1]->getChildren()[0], enclosingObject, justFuncName);
} else {
// 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
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
if (children.size() > 2)
output += " else { " + generate(children[2], enclosingObject) + " }";
output += " else { " + generate(children[2], enclosingObject, justFuncName) + " }";
return output;
case while_loop:
// 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
// all of the inbetween scopes
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
loopDeferStackDepth.pop();
return output;
@@ -356,7 +356,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
// all of the inbetween scopes
loopDeferStackDepth.push(deferDoubleStack.size());
//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
loopDeferStackDepth.pop();
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
for (auto topItr = deferDoubleStack.rbegin(); topItr != deferDoubleStack.rend(); topItr++)
for (auto iter = (*topItr).rbegin(); iter != (*topItr).rend(); iter++)
output += generate(*iter, enclosingObject);
output += generate(*iter, enclosingObject, justFuncName);
if (children.size())
return "return " + generate(children[0], enclosingObject);
return "return " + generate(children[0], enclosingObject, true);
else
return "return";
case break_statement:
// 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 (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
output += generate(*iter, enclosingObject);
output += generate(*iter, enclosingObject, justFuncName);
return output + "break";
case continue_statement:
// 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 (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
output += generate(*iter, enclosingObject);
output += generate(*iter, enclosingObject, justFuncName);
return output + "continue";
case defer_statement:
deferDoubleStack.back().push_back(children[0]);
return "/*defer " + generate(children[0], enclosingObject) + "*/";
return "/*defer " + generate(children[0], enclosingObject, justFuncName) + "*/";
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:
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
&& children[1]->getChildren()[0]->getChildren()[1] == children[0]) {
//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])
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
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:
// Lol, this doesn't work because the string gets prefixed now
//if (generate(children[0], enclosingObject) == generatorString)
if (children[0]->getDataRef()->symbol.getName() == generatorString)
return generate(children[1], enclosingObject);
return generate(children[1], enclosingObject, justFuncName);
return "";
case simple_passthrough:
{
@@ -414,17 +414,17 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
for (auto assign : in_or_out->getChildren()) {
auto assignChildren = assign->getChildren();
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)
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
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
// 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:
{
@@ -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
if (funcType == function) {
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
return name + "(" + generate(children[1], enclosingObject) + ")";
return name + "(" + generate(children[1], enclosingObject, true) + ")";
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 == "!="
|| name == "<" || name == ">" || name == "%" || name == "+=" || name == "-=" || name == "*=" || name == "/=" || name == "||"
|| name == "&&") {
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 == "->") {
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 (children[2]->getDataRef()->type == function) {
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);
// 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()) +"__" +
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
//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 + ")";
return "((" + generate(children[1], enclosingObject, true) + ")" + name + functionName + ")";
}
} else {
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 {
//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 {
//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 {
//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.
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.
output += children.size() > 1 ? functionCallSource : functionCallSource.substr(0, functionCallSource.size()-1);
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
if (i < children.size()-1)
output += generate(children[i], enclosingObject) + ", ";
output += generate(children[i], enclosingObject, true) + ", ";
else
output += generate(children[i], enclosingObject);
output += generate(children[i], enclosingObject, true);
output += ") ";
return output;
}
@@ -524,7 +524,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
std::cout << "Nothing!" << std::endl;
}
for (int i = 0; i < children.size(); i++)
output += generate(children[i], enclosingObject);
output += generate(children[i], enclosingObject, justFuncName);
return output;
}
@@ -543,21 +543,21 @@ std::string CGenerator::generateObjectMethod(NodeTree<ASTData>* enclosingObject,
std::vector<NodeTree<ASTData>*> children = from->getChildren();
std::string nameDecoration, parameters;
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);
}
std::string functionSignature = "\n" + ValueTypeToCType(data.valueType) + " " + scopePrefix(from) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"
+ CifyName(data.symbol.getName()) + nameDecoration + "(" + ValueTypeToCType(&enclosingObjectType)
+ " this" + parameters + ")";
std::string functionSignature = "\n" + ValueTypeToCType(data.valueType->returnType, scopePrefix(from) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"
+ CifyName(data.symbol.getName()) + nameDecoration) + "(" + ValueTypeToCType(&enclosingObjectType, "this") + parameters + ")";
*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
}
std::string CGenerator::ValueTypeToCType(Type *type) { return ValueTypeToCTypeThingHelper(type, "*"); }
std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return ValueTypeToCTypeThingHelper(type, "_P__"); }
std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr) {
std::string CGenerator::ValueTypeToCType(Type *type, std::string declaration) { return ValueTypeToCTypeThingHelper(type, " " + declaration); }
std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return CifyName(ValueTypeToCTypeThingHelper(type, "")); }
std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string declaration) {
std::string return_type;
bool do_ending = true;
switch (type->baseType) {
case none:
if (type->typeDefinition)
@@ -565,6 +565,25 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string ptrS
else
return_type = "none";
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:
return_type = "void";
break;
@@ -587,9 +606,11 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string ptrS
return_type = "unknown_ValueType";
break;
}
if (!do_ending)
return return_type;
for (int i = 0; i < type->getIndirection(); i++)
return_type += ptrStr;
return return_type;
return_type += "*";
return return_type + declaration;
}
std::string CGenerator::CifyName(std::string name) {
@@ -610,6 +631,7 @@ std::string CGenerator::CifyName(std::string name) {
"<<", "doubleleft",
">>", "doubleright",
"::", "scopeop",
":", "colon",
"==", "doubleequals",
"!=", "notequals",
"&&", "doubleamprsnd",

View File

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