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:
@@ -24,11 +24,12 @@ class Type {
|
||||
Type(ValueType typeIn, std::set<std::string> traitsIn); //Mostly for template type type's
|
||||
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<ASTData>* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set<std::string> traitsIn);
|
||||
Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set<std::string> traitsIn, std::vector<Type*> parameterTypesIn, Type* returnTypeIn);
|
||||
Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn, bool referenceIn = false);
|
||||
Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn = std::set<std::string>());
|
||||
~Type();
|
||||
const bool test_equality(const Type &other, bool care_about_references) const;
|
||||
bool const operator==(const Type &other)const;
|
||||
bool const operator!=(const Type &other)const;
|
||||
bool const operator<(const Type &other)const;
|
||||
@@ -50,6 +51,7 @@ class Type {
|
||||
std::set<std::string> traits;
|
||||
std::vector<Type*> parameterTypes;
|
||||
Type *returnType;
|
||||
bool is_reference;;
|
||||
private:
|
||||
int indirection;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,8 @@ Goal = translation_unit ;
|
||||
translation_unit = WS unorderd_list_part WS ;
|
||||
unorderd_list_part = import WS unorderd_list_part | function WS unorderd_list_part | type_def line_end WS unorderd_list_part | if_comp WS unorderd_list_part | simple_passthrough WS unorderd_list_part | declaration_statement line_end WS unorderd_list_part | import | function | type_def line_end | if_comp | simple_passthrough | declaration_statement line_end ;
|
||||
|
||||
type = "\*" WS type | "void" | "int" | "float" | "double" | "char" | scoped_identifier | scoped_identifier WS template_inst | function_type ;
|
||||
type = "ref" WS pre_reffed | pre_reffed ;
|
||||
pre_reffed = "\*" WS pre_reffed | "void" | "int" | "float" | "double" | "char" | scoped_identifier | scoped_identifier WS template_inst | function_type ;
|
||||
function_type = "fun" WS "\(" WS opt_type_list WS "\)" WS ":" WS type ;
|
||||
dec_type = ":" WS type ;
|
||||
|
||||
|
||||
@@ -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;
|
||||
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.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 {
|
||||
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() {
|
||||
|
||||
1
tests/test_references.expected_results
Normal file
1
tests/test_references.expected_results
Normal file
@@ -0,0 +1 @@
|
||||
7
|
||||
23
tests/test_references.krak
Normal file
23
tests/test_references.krak
Normal file
@@ -0,0 +1,23 @@
|
||||
import io:*
|
||||
|
||||
/*fun byRef<T>(it: ref T) {*/
|
||||
/*it = it + 1*/
|
||||
/*}*/
|
||||
|
||||
/*fun byRef(it: * int) {*/
|
||||
/**it = *it + 1*/
|
||||
/*}*/
|
||||
|
||||
fun byRef(it: ref int) {
|
||||
it = it + 1
|
||||
}
|
||||
|
||||
// what about cosures closing over references?
|
||||
|
||||
fun main():int {
|
||||
var a = 6
|
||||
byRef(a)
|
||||
println(a)
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user