diff --git a/include/Type.h b/include/Type.h index 673dcaf..04b289a 100644 --- a/include/Type.h +++ b/include/Type.h @@ -24,11 +24,12 @@ class Type { Type(ValueType typeIn, std::set traitsIn); //Mostly for template type type's Type(NodeTree* typeDefinitionIn, int indirectionIn = 0); Type(NodeTree* typeDefinitionIn, std::set traitsIn); - Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn, std::set traitsIn); - Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn, std::set traitsIn, std::vector parameterTypesIn, Type* returnTypeIn); - Type(std::vector parameterTypesIn, Type* returnTypeIn); + Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set traitsIn); + Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set traitsIn, std::vector parameterTypesIn, Type* returnTypeIn); + Type(std::vector parameterTypesIn, Type* returnTypeIn, bool referenceIn = false); Type(ValueType typeIn, NodeTree* templateDefinitionIn, std::set traitsIn = std::set()); ~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 traits; std::vector parameterTypes; Type *returnType; + bool is_reference;; private: int indirection; }; diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index b84579c..4981c6b 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -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 ; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 106ac7b..6cd1bd4 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -239,6 +239,8 @@ NodeTree* ASTTransformation::secondPassFunction(NodeTree* 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("function", ASTData(function, Symbol(functionName, true), returnType)); addToScope("~enclosing_scope", scope, functionDef); addToScope(functionName, functionDef, scope); @@ -1025,7 +1027,9 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* 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* ASTTransformation::templateClassLookup(NodeTree* sco } void ASTTransformation::unifyType(NodeTree *syntaxType, Type type, std::map* templateTypeMap, std::map 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* ASTTransformation::templateFunctionLookup(NodeTree* 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* ASTTransformation::getUpperTranslationUnit(NodeTree* //Create a type from a syntax tree. This can get complicated with templates Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTree* scope, std::map templateTypeReplacements) { - std::string typeIn = concatSymbolTree(typeNode); int indirection = 0; + bool is_reference = false; ValueType baseType; NodeTree* typeDefinition = NULL; std::set 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* typeNode, NodeTree 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* typeNode, NodeTreetoString() << std::endl; return toReturn; } diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index f82ed0d..c2d4bfa 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -291,8 +291,8 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* 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* from, NodeTree* 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* from, NodeTree* 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{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{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{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; } diff --git a/src/Importer.cpp b/src/Importer.cpp index 09b4142..7b99f98 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -58,6 +58,7 @@ Importer::Importer(Parser* parserIn, std::vector 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() { diff --git a/src/Type.cpp b/src/Type.cpp index ad01dde..512706a 100644 --- a/src/Type.cpp +++ b/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 traitsIn) { @@ -26,6 +28,7 @@ Type::Type(ValueType typeIn, std::set traitsIn) { templateDefinition = nullptr; returnType = nullptr; templateInstantiated = false; + is_reference = false; } Type::Type(NodeTree* typeDefinitionIn, int indirectionIn) { @@ -35,6 +38,7 @@ Type::Type(NodeTree* typeDefinitionIn, int indirectionIn) { templateDefinition = nullptr; returnType = nullptr; templateInstantiated = false; + is_reference = false; } Type::Type(NodeTree* typeDefinitionIn, std::set traitsIn) { @@ -45,9 +49,10 @@ Type::Type(NodeTree* typeDefinitionIn, std::set traitsIn) templateDefinition = nullptr; returnType = nullptr; templateInstantiated = false; + is_reference = false; } -Type::Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn, std::set traitsIn) { +Type::Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set traitsIn) { baseType = typeIn; indirection = indirectionIn; typeDefinition = typeDefinitionIn; @@ -55,9 +60,10 @@ Type::Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectio templateDefinition = nullptr; returnType = nullptr; templateInstantiated = false; + is_reference = referenceIn; } -Type::Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn, std::set traitsIn, std::vector parameterTypesIn, Type* returnTypeIn) { +Type::Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set traitsIn, std::vector parameterTypesIn, Type* returnTypeIn) { baseType = typeIn; indirection = indirectionIn; typeDefinition = typeDefinitionIn; @@ -66,8 +72,9 @@ Type::Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectio parameterTypes = parameterTypesIn; returnType = returnTypeIn; templateInstantiated = false; + is_reference = referenceIn; } -Type::Type(std::vector parameterTypesIn, Type* returnTypeIn) { +Type::Type(std::vector parameterTypesIn, Type* returnTypeIn, bool referenceIn) { baseType = function_type; indirection = 0; typeDefinition = nullptr; @@ -75,6 +82,7 @@ Type::Type(std::vector parameterTypesIn, Type* returnTypeIn) { parameterTypes = parameterTypesIn; returnType = returnTypeIn; templateInstantiated = false; + is_reference = referenceIn; } Type::Type(ValueType typeIn, NodeTree* templateDefinitionIn, std::set traitsIn) { @@ -85,6 +93,7 @@ Type::Type(ValueType typeIn, NodeTree* templateDefinitionIn, std::set(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 +} +