reference type added and very basic pass by reference works in CGenerator. Much more work to go to make sure complicated cases work and return by reference
This commit is contained in:
@@ -239,6 +239,8 @@ NodeTree<ASTData>* ASTTransformation::secondPassFunction(NodeTree<Symbol>* from,
|
||||
functionName = concatSymbolTree(children[0]);
|
||||
auto returnTypeNode = getNode("type", getNode("typed_return", children)); // if null, the typed_return had no children and we're supposed to automatically do a void type
|
||||
auto returnType = returnTypeNode ? typeFromTypeNode(returnTypeNode, scope, templateTypeReplacements): new Type(void_type);
|
||||
if (!returnType)
|
||||
throw "freakout";
|
||||
functionDef = new NodeTree<ASTData>("function", ASTData(function, Symbol(functionName, true), returnType));
|
||||
addToScope("~enclosing_scope", scope, functionDef);
|
||||
addToScope(functionName, functionDef, scope);
|
||||
@@ -1025,7 +1027,9 @@ NodeTree<ASTData>* ASTTransformation::functionLookup(NodeTree<ASTData>* scope, s
|
||||
//if (types[j] != *tmpType && tmpType->baseType != template_type_type) {
|
||||
// WE DO WORRY NOW B/C template type infrence is ugly and we need this to fail
|
||||
// for regular function lookups so that we know to retry with a template
|
||||
if (types[j] != *tmpType) {
|
||||
//
|
||||
// we use test_equality so that we can pass in a false to not care about references
|
||||
if (!types[j].test_equality(*tmpType, false)) {
|
||||
typesMatch = false;
|
||||
std::cout << "Types do not match between two " << lookup << " " << types[j].toString();
|
||||
std::cout << " vs " << tmpType->toString() << std::endl;
|
||||
@@ -1114,6 +1118,9 @@ NodeTree<ASTData>* ASTTransformation::templateClassLookup(NodeTree<ASTData>* sco
|
||||
}
|
||||
|
||||
void ASTTransformation::unifyType(NodeTree<Symbol> *syntaxType, Type type, std::map<std::string, Type>* templateTypeMap, std::map<std::string, Type*> typeMap) {
|
||||
// First, get rid of the reference part - we don't care for unification
|
||||
syntaxType = syntaxType->getChildren().back();
|
||||
|
||||
// Ok, 3 options for syntaxType here.
|
||||
// 1) This a basic type. (int, or object, etc)
|
||||
// THIS ONE will fall through and get put in the map, but it
|
||||
@@ -1287,7 +1294,8 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
|
||||
for (int j = 0; j < functionParameters.size(); j++) {
|
||||
auto paramType = typeFromTypeNode(functionParameters[j]->getChildren()[2], scope, typeMap);
|
||||
std::cout << "Template param type: " << paramType->toString() << " : Needed Type: " << types[j].toString() << std::endl;
|
||||
if (*paramType != types[j]) {
|
||||
// use test_equality so we can pass false and not care about references
|
||||
if (!paramType->test_equality(types[j], false)) {
|
||||
parameterTypesMatch = false;
|
||||
std::cout << "Not equal template param: " << paramType->toString() << " : Needed Type actual param: " << types[j].toString() << std::endl;
|
||||
break;
|
||||
@@ -1458,19 +1466,28 @@ NodeTree<ASTData>* ASTTransformation::getUpperTranslationUnit(NodeTree<ASTData>*
|
||||
|
||||
//Create a type from a syntax tree. This can get complicated with templates
|
||||
Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements) {
|
||||
std::string typeIn = concatSymbolTree(typeNode);
|
||||
|
||||
int indirection = 0;
|
||||
bool is_reference = false;
|
||||
ValueType baseType;
|
||||
NodeTree<ASTData>* typeDefinition = NULL;
|
||||
std::set<std::string> traits;
|
||||
// if this is a reference, we also have to step down a level
|
||||
if (typeNode->getChildren().size() && typeNode->getChildren().front()->getDataRef()->getValue() == "ref") {
|
||||
is_reference = true;
|
||||
}
|
||||
// always step down below the ref level
|
||||
typeNode = typeNode->getChildren().back();
|
||||
|
||||
std::string typeIn = concatSymbolTree(typeNode);
|
||||
|
||||
// To counter this, for every indirection we step down a level
|
||||
//while (typeIn[indirection] == '*') {
|
||||
//since fun(*T):int gets transformed to *T:int, the text based way doesn't work anymore
|
||||
while (typeNode->getChildren().size() && typeNode->getChildren().front()->getDataRef()->getValue() == "*") {
|
||||
indirection++;
|
||||
typeNode = typeNode->getChildren().back();
|
||||
};
|
||||
}
|
||||
std::string edited = strSlice(typeIn, indirection, -1);
|
||||
if (edited == "void")
|
||||
baseType = void_type;
|
||||
@@ -1489,7 +1506,7 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
|
||||
std::vector<Type*> types;
|
||||
for (auto typeSyntaxNode : getNodes("type", typeNode->getChildren()[0]->getChildren()))
|
||||
types.push_back(typeFromTypeNode(typeSyntaxNode, scope, templateTypeReplacements));
|
||||
return new Type(slice(types, 0, -2),types.back());
|
||||
return new Type(slice(types, 0, -2),types.back(), is_reference);
|
||||
} else {
|
||||
baseType = none;
|
||||
|
||||
@@ -1607,10 +1624,10 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
|
||||
std::cout << "Could not find type " << edited << ", returning NULL" << std::endl;
|
||||
return NULL;
|
||||
} else {
|
||||
std::cout << "Type: " << edited << " already instantiated with " << typeDefinition << ", will be " << Type(baseType, typeDefinition, indirection, traits).toString() << std::endl;
|
||||
std::cout << "Type: " << edited << " already instantiated with " << typeDefinition << ", will be " << Type(baseType, typeDefinition, indirection, is_reference, traits).toString() << std::endl;
|
||||
}
|
||||
}
|
||||
Type* toReturn = new Type(baseType, typeDefinition, indirection, traits);
|
||||
Type* toReturn = new Type(baseType, typeDefinition, indirection, is_reference, traits);
|
||||
std::cout << "Returning type " << toReturn->toString() << std::endl;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -291,8 +291,8 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
||||
if (data.symbol.getName() == "this") {
|
||||
if (enclosingObject)
|
||||
return CCodeTriple("this");
|
||||
else
|
||||
std::cerr << "Error: this used in non-object scope" << std::endl;
|
||||
std::cerr << "Error: this used in non-object scope" << std::endl;
|
||||
throw "Error: this used in non-object scope";
|
||||
}
|
||||
//If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the this reference.
|
||||
std::string preName;
|
||||
@@ -311,6 +311,11 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
||||
}
|
||||
if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end())
|
||||
preName += "this->";
|
||||
// dereference references, but only if inside a function
|
||||
if (enclosingFunction && data.valueType->is_reference) {
|
||||
preName += "(*";
|
||||
postName += ")";
|
||||
}
|
||||
// we're scope prefixing EVERYTHING
|
||||
return preName + scopePrefix(from) + CifyName(data.symbol.getName()) + postName; //Cifying does nothing if not an operator overload
|
||||
}
|
||||
@@ -734,18 +739,32 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
||||
}
|
||||
}
|
||||
CCodeTriple parameters;
|
||||
// see if we should copy_construct all the parameters
|
||||
// see if we should copy_construct / referencize all the parameters
|
||||
for (int i = 1; i < children.size(); i++) { //children[0] is the declaration
|
||||
Type* func_param_type = children[0]->getDataRef()->valueType->parameterTypes[i-1];
|
||||
Type *param_type = children[i]->getDataRef()->valueType;
|
||||
if (methodExists(children[i]->getDataRef()->valueType, "copy_construct", std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()})) {
|
||||
std::string tmpParamName = "param" + getID();
|
||||
CCodeTriple paramValue = generate(children[i], enclosingObject, true, enclosingFunction);
|
||||
parameters.preValue += paramValue.preValue;
|
||||
parameters.preValue += ValueTypeToCType(children[i]->getDataRef()->valueType, tmpParamName) + ";\n";
|
||||
parameters.preValue += generateMethodIfExists(children[i]->getDataRef()->valueType, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value, std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()});
|
||||
parameters.value += tmpParamName;
|
||||
parameters.preValue += ValueTypeToCType(param_type, tmpParamName) + ";\n";
|
||||
parameters.preValue += generateMethodIfExists(param_type, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value, std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()});
|
||||
if (func_param_type->is_reference)
|
||||
parameters.value += "&" + tmpParamName;
|
||||
else
|
||||
parameters.value += tmpParamName;
|
||||
parameters.postValue += paramValue.postValue;
|
||||
} else {
|
||||
parameters += generate(children[i], enclosingObject, true, enclosingFunction);
|
||||
if (func_param_type->is_reference) {
|
||||
//std::string tmpParamName = "param" + getID();
|
||||
//CCodeTriple paramValue = generate(children[i], enclosingObject, true, enclosingFunction);
|
||||
//parameters.preValue += paramValue.preValue;
|
||||
//parameters.preValue += ValueTypeToCType(param_type, tmpParamName) + " = " + paramValue.value + ";\n";
|
||||
//parameters.value += "&" + tmpParamName;
|
||||
parameters += "&" + generate(children[i], enclosingObject, true, enclosingFunction);
|
||||
} else {
|
||||
parameters += generate(children[i], enclosingObject, true, enclosingFunction);
|
||||
}
|
||||
}
|
||||
if (i < children.size()-1)
|
||||
parameters += ", ";
|
||||
@@ -1010,6 +1029,8 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl
|
||||
return return_type;
|
||||
for (int i = 0; i < type->getIndirection(); i++)
|
||||
return_type += "*";
|
||||
if (type->is_reference)
|
||||
return_type += " /*ref*/ *";
|
||||
return return_type + declaration;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ Importer::Importer(Parser* parserIn, std::vector<std::string> includePaths, std:
|
||||
collapseSymbols.push_back(Symbol("template_param_list", false));
|
||||
collapseSymbols.push_back(Symbol("trait_list", false));
|
||||
collapseSymbols.push_back(Symbol("dec_type", false));
|
||||
//collapseSymbols.push_back(Symbol("pre_reffed", false));
|
||||
}
|
||||
|
||||
Importer::~Importer() {
|
||||
|
||||
26
src/Type.cpp
26
src/Type.cpp
@@ -7,6 +7,7 @@ Type::Type() {
|
||||
templateDefinition = nullptr;
|
||||
returnType = nullptr;
|
||||
templateInstantiated = false;
|
||||
is_reference = false;
|
||||
}
|
||||
|
||||
Type::Type(ValueType typeIn, int indirectionIn) {
|
||||
@@ -16,6 +17,7 @@ Type::Type(ValueType typeIn, int indirectionIn) {
|
||||
templateDefinition = nullptr;
|
||||
returnType = nullptr;
|
||||
templateInstantiated = false;
|
||||
is_reference = false;
|
||||
}
|
||||
|
||||
Type::Type(ValueType typeIn, std::set<std::string> traitsIn) {
|
||||
@@ -26,6 +28,7 @@ Type::Type(ValueType typeIn, std::set<std::string> traitsIn) {
|
||||
templateDefinition = nullptr;
|
||||
returnType = nullptr;
|
||||
templateInstantiated = false;
|
||||
is_reference = false;
|
||||
}
|
||||
|
||||
Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) {
|
||||
@@ -35,6 +38,7 @@ Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) {
|
||||
templateDefinition = nullptr;
|
||||
returnType = nullptr;
|
||||
templateInstantiated = false;
|
||||
is_reference = false;
|
||||
}
|
||||
|
||||
Type::Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn) {
|
||||
@@ -45,9 +49,10 @@ Type::Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn)
|
||||
templateDefinition = nullptr;
|
||||
returnType = nullptr;
|
||||
templateInstantiated = false;
|
||||
is_reference = false;
|
||||
}
|
||||
|
||||
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn) {
|
||||
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set<std::string> traitsIn) {
|
||||
baseType = typeIn;
|
||||
indirection = indirectionIn;
|
||||
typeDefinition = typeDefinitionIn;
|
||||
@@ -55,9 +60,10 @@ Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectio
|
||||
templateDefinition = nullptr;
|
||||
returnType = nullptr;
|
||||
templateInstantiated = false;
|
||||
is_reference = referenceIn;
|
||||
}
|
||||
|
||||
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn, std::vector<Type*> parameterTypesIn, Type* returnTypeIn) {
|
||||
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set<std::string> traitsIn, std::vector<Type*> parameterTypesIn, Type* returnTypeIn) {
|
||||
baseType = typeIn;
|
||||
indirection = indirectionIn;
|
||||
typeDefinition = typeDefinitionIn;
|
||||
@@ -66,8 +72,9 @@ Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectio
|
||||
parameterTypes = parameterTypesIn;
|
||||
returnType = returnTypeIn;
|
||||
templateInstantiated = false;
|
||||
is_reference = referenceIn;
|
||||
}
|
||||
Type::Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn) {
|
||||
Type::Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn, bool referenceIn) {
|
||||
baseType = function_type;
|
||||
indirection = 0;
|
||||
typeDefinition = nullptr;
|
||||
@@ -75,6 +82,7 @@ Type::Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn) {
|
||||
parameterTypes = parameterTypesIn;
|
||||
returnType = returnTypeIn;
|
||||
templateInstantiated = false;
|
||||
is_reference = referenceIn;
|
||||
}
|
||||
|
||||
Type::Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn) {
|
||||
@@ -85,6 +93,7 @@ Type::Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<st
|
||||
traits = traitsIn;
|
||||
returnType = nullptr;
|
||||
templateInstantiated = false;
|
||||
is_reference = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +101,12 @@ Type::~Type() {
|
||||
}
|
||||
|
||||
const bool Type::operator==(const Type &other) const {
|
||||
return test_equality(other, true);
|
||||
}
|
||||
const bool Type::test_equality(const Type &other, bool care_about_references) const {
|
||||
bool first_part = ( baseType == other.baseType && indirection == other.indirection && typeDefinition == other.typeDefinition && templateDefinition == other.templateDefinition && other.traits == traits);
|
||||
if (care_about_references && is_reference != other.is_reference)
|
||||
return false;
|
||||
if (!first_part)
|
||||
return false;
|
||||
if ((returnType && !other.returnType) || (!returnType && other.returnType))
|
||||
@@ -116,6 +130,8 @@ const bool Type::operator<(const Type &other) const {
|
||||
return baseType < other.baseType;
|
||||
if (indirection != other.indirection)
|
||||
return indirection < other.indirection;
|
||||
if (is_reference != other.is_reference)
|
||||
return is_reference;
|
||||
if (typeDefinition != other.typeDefinition)
|
||||
return typeDefinition < other.typeDefinition;
|
||||
if (templateDefinition != other.templateDefinition)
|
||||
@@ -180,6 +196,8 @@ std::string Type::toString(bool showTraits) {
|
||||
else
|
||||
typeString = "unknown_type";
|
||||
}
|
||||
if (is_reference)
|
||||
typeString = "ref " + typeString;
|
||||
for (int i = 0; i < indirection; i++)
|
||||
typeString += "*";
|
||||
if (indirection < 0)
|
||||
@@ -195,7 +213,7 @@ std::string Type::toString(bool showTraits) {
|
||||
}
|
||||
|
||||
Type* Type::clone() {
|
||||
return new Type(baseType, typeDefinition, indirection, traits, parameterTypes, returnType);
|
||||
return new Type(baseType, typeDefinition, indirection, is_reference, traits, parameterTypes, returnType);
|
||||
}
|
||||
|
||||
int Type::getIndirection() {
|
||||
|
||||
Reference in New Issue
Block a user