From 21f4824a0143d75677b1721f3b1f2b7a86a6f2ae Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Thu, 19 Nov 2015 16:27:36 -0500 Subject: [PATCH] proper scoping for ADTs, I think --- src/CGenerator.cpp | 128 ++++++++++++++++++++++------------------ tests/test_adt.krak | 71 ++++++++++++++++++++++ tests/test_grammer.krak | 3 +- 3 files changed, 142 insertions(+), 60 deletions(-) diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 2d34410..43cdf94 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -57,7 +57,8 @@ std::string CGenerator::getID() { std::string CGenerator::generateTypeStruct(NodeTree* from) { auto data = from->getData(); auto children = from->getChildren(); - std::string structString, enumString, functionString; + //std::string structString, enumString, functionString; + std::string structString, enumString; std::string enumName = "__enum_dummy_" + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())+"__"); enumString = "enum " + enumName + " {\n"; structString = "struct __struct_dummy_"; @@ -79,48 +80,7 @@ std::string CGenerator::generateTypeStruct(NodeTree* from) { } else { structString += tabs() + generate(child, nullptr).oneString() + "\n"; } - enumString += tabs() + generate(child, nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n"); - } else { - if (data.type == adt_def) { - std::string orig_fun_name = child->getDataRef()->symbol.getName(); - std::string fun_name; - std::string first_param; - if (orig_fun_name == "operator==" || orig_fun_name == "operator!=") { - fun_name = "fun_" + data.symbol.getName() + "__" + CifyName(orig_fun_name); - first_param = ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0]->withIncreasedIndirectionPtr(), "this") + ", "; - } else { - fun_name = "fun_" + orig_fun_name; - } - bool has_param = child->getDataRef()->valueType->parameterTypes.size(); - functionString += "\n" + ValueTypeToCType(child->getDataRef()->valueType->returnType, fun_name) + "(" + first_param + - (has_param ? ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0], "in") : "") + ") { /*adt func*/\n"; - if (orig_fun_name == "operator==") { - functionString += " /* equality woop woop */\n"; - functionString += " if (this->flag != in.flag) return false;\n"; - - for (auto child : children) { - if (child->getName() != "function" && child->getDataRef()->valueType->typeDefinition != from) { - std::string option_name = child->getDataRef()->symbol.getName(); - functionString += " if (this->flag == " + option_name + ")\n"; - functionString += " return this->" + option_name + " == in." + option_name + ";\n"; - } - } - - functionString += " return true;\n"; - } else if (orig_fun_name == "operator!=") { - functionString += " /* inequality woop woop */\n"; - functionString += " return !fun_" + data.symbol.getName() + "__" + CifyName("operator==") + "(this, in);\n"; - } else { - // ok, is a constructor function - functionString += " /* constructor woop woop */\n"; - functionString += " " + data.symbol.getName() + " toRet;\n"; - functionString += " toRet.flag = " + orig_fun_name + ";\n"; - if (has_param) - functionString += " toRet." + orig_fun_name + " = in;\n"; - functionString += " return toRet;\n"; - } - functionString += "}\n"; - } + enumString += tabs() + data.symbol.getName() + "__" + generate(child, nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n"); } } tabLevel--; @@ -133,7 +93,7 @@ std::string CGenerator::generateTypeStruct(NodeTree* from) { } enumString += "};\n"; if (data.type == adt_def) - return enumString + structString + functionString; + return enumString + structString; return structString; } @@ -338,16 +298,57 @@ std::pair CGenerator::generateTranslationUnit(std::str break; case adt_def: { - //type - //don't even need to do this anymore, it's all earlier - //plainTypedefs += "/* adt " + declarationData.symbol.getName() + " */\n"; - //plainTypedefs += "typedef struct __struct_dummy_" + - //prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())+ "__") + " " + - //prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) + ";\n"; - //// skip the name of the thing - //for (int j = 1; j < decChildren.size(); j++) { - //std::cout << decChildren[j]->getName() << std::endl; - //} + for (auto child : decChildren) { + if (child->getName() == "function") { + std::string orig_fun_name = child->getDataRef()->symbol.getName(); + std::string fun_name = "fun_" + declarationData.symbol.getName() + "__" + CifyName(orig_fun_name); + std::string first_param; + if (orig_fun_name == "operator==" || orig_fun_name == "operator!=") { + //fun_name = "fun_" + declarationData.symbol.getName() + "__" + CifyName(orig_fun_name); + first_param = ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0]->withIncreasedIndirectionPtr(), "this") + ", "; + } else { + //fun_name = "fun_" + orig_fun_name; + } + bool has_param = child->getDataRef()->valueType->parameterTypes.size(); + std::string first_part = "\n" + ValueTypeToCType(child->getDataRef()->valueType->returnType, fun_name) + "(" + first_param + + (has_param ? ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0], "in") : "") + ")"; + functionPrototypes += first_part + "; /*adt func*/\n"; + functionDefinitions += first_part + "{ /*adt func*/\n"; + if (orig_fun_name == "operator==") { + functionDefinitions += " /* equality woop woop */\n"; + functionDefinitions += " if (this->flag != in.flag) return false;\n"; + + for (auto child : decChildren) { + if (child->getName() != "function" && child->getDataRef()->valueType->typeDefinition != declaration) { + std::string option_name = child->getDataRef()->symbol.getName(); + functionDefinitions += " if (this->flag == " + declarationData.symbol.getName() + "__" + option_name + ") {\n"; + NodeTree* method = nullptr; + if (method = getMethod(child->getDataRef()->valueType, "operator==", std::vector{*child->getDataRef()->valueType})) { + functionDefinitions += " return " + generateMethodIfExists(child->getDataRef()->valueType, "operator==", + "&this->" + option_name + ", " + (method->getDataRef()->valueType->parameterTypes[0]->is_reference ? "&" : "") + "in." + option_name, + std::vector{*child->getDataRef()->valueType}) + ";\n}\n"; + } else { + functionDefinitions += " return this->" + option_name + " == in." + option_name + ";\n}\n"; + } + } + } + + functionDefinitions += " return true;\n"; + } else if (orig_fun_name == "operator!=") { + functionDefinitions += " /* inequality woop woop */\n"; + functionDefinitions += " return !fun_" + declarationData.symbol.getName() + "__" + CifyName("operator==") + "(this, in);\n"; + } else { + // ok, is a constructor function + functionDefinitions += " /* constructor woop woop */\n"; + functionDefinitions += " " + declarationData.symbol.getName() + " toRet;\n"; + functionDefinitions += " toRet.flag = " + declarationData.symbol.getName() + "__" + orig_fun_name + ";\n"; + if (has_param) + functionDefinitions += " toRet." + orig_fun_name + " = in;\n"; + functionDefinitions += " return toRet;\n"; + } + functionDefinitions += "}\n"; + } + } break; } default: @@ -440,10 +441,11 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc // this is for using functions as values if (justFuncName) { std::string funcName; - if (data.symbol.getName() != "main") + if (data.symbol.getName() != "main") { funcName += function_header + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName() + nameDecoration)); - else + } else { funcName += CifyName(data.symbol.getName() + nameDecoration); + } if (from->getDataRef()->closedVariables.size()) { std::string tmpStruct = "closureStruct" + getID(); output.preValue += closureStructType(data.closedVariables) + " " + tmpStruct + " = {"; @@ -535,8 +537,9 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc for (auto case_stmt : slice(children, 1, -1)) { auto case_children = case_stmt->getChildren(); std::string option = generate(case_children[0], enclosingObject, false, enclosingFunction).oneString(); + std::string parentName = case_children[0]->getDataRef()->scope["~enclosing_scope"][0]->getDataRef()->symbol.getName(); output += "/* case " + option + " if " + thingToMatch.value + " */\n"; - output += tabs() + "if (" + thingToMatch.value + ".flag == " + option + ") {\n"; + output += tabs() + "if (" + thingToMatch.value + ".flag == " + parentName + "__" + option + ") {\n"; tabLevel++; if (case_children.size() > 2) { output += tabs() + ValueTypeToCType(case_children[1]->getData().valueType, generate(case_children[1], enclosingObject, false, enclosingFunction).oneString()) @@ -866,7 +869,14 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc output += CifyName(name + nameDecoration) + "("; output += std::string(addClosedOver ? "(*closed_variables->this)" : "this") + (children.size() > 1 ? "," : ""); } else { - output += function_header + prefixIfNeeded(scopePrefix(children[0]), CifyName(name + nameDecoration)) + "("; + // ha, I think this is the normal function call one. Had a little trouble finding it + // darned if we don't have to special case ADT psudo-constructors + auto possibleParentADTVector = children[0]->getDataRef()->scope["~enclosing_scope"]; + NodeTree* possibleParentADT = possibleParentADTVector.size() ? possibleParentADTVector[0] : nullptr; + std::string adtAdditional = ""; + if (possibleParentADT && possibleParentADT->getDataRef()->type == adt_def) + adtAdditional = possibleParentADT->getDataRef()->symbol.getName() + "__"; + output += function_header + prefixIfNeeded(scopePrefix(children[0]), CifyName(adtAdditional + name + nameDecoration)) + "("; } } } @@ -1045,7 +1055,7 @@ std::string CGenerator::generateMethodIfExists(Type* type, std::string method, s std::string nameDecoration; for (Type *paramType : methodDef->getDataRef()->valueType->parameterTypes) nameDecoration += "_" + ValueTypeToCTypeDecoration(paramType); - return function_header + prefixIfNeeded(scopePrefix(typeDefinition), CifyName(typeDefinition->getDataRef()->symbol.getName())) + "__" + method + nameDecoration + "(" + parameter + ");\n"; + return function_header + prefixIfNeeded(scopePrefix(typeDefinition), CifyName(typeDefinition->getDataRef()->symbol.getName())) + "__" + CifyName(method) + nameDecoration + "(" + parameter + ");\n"; } return ""; } diff --git a/tests/test_adt.krak b/tests/test_adt.krak index 6ac908e..0e93bc4 100644 --- a/tests/test_adt.krak +++ b/tests/test_adt.krak @@ -10,6 +10,41 @@ adt maybe_int { an_int: int } +fun TestObj(num: int): TestObj { + print("gonna makke object in function ") + println(num) + var toRet.construct(num): TestObj + return toRet +} +obj TestObj (Object) { + var obj_num: int + fun construct(num:int): *TestObj { + obj_num = num + print("constructed object ") + println(obj_num) + } + fun copy_construct(old: *TestObj) { + obj_num = old->obj_num + 100 + print("copy constructed object ") + print(obj_num) + print(" from ") + println(old->obj_num) + } + fun destruct() { + print("destructed object ") + println(obj_num) + } + fun operator==(other: ref TestObj): bool { + return obj_num == other.obj_num; + } +} + +adt maybe_object { + no_obj, + an_obj: TestObj, + an_int: int +} + fun handle_possibility(it: maybe_int) { if (it == maybe_int::no_int()) { println("no int") @@ -68,6 +103,42 @@ fun main():int { maybe_int::an_int(the_int) println("matched an int incorrectly!") maybe_int::no_int() println("matched no int correctly!") } + var obj_item = maybe_object::no_obj() + match (obj_item) { + maybe_object::no_obj() println("matched no_obj correctly") + maybe_object::an_obj(obj_instance) { + print("matched an_obj incorrectly ") + println(obj_instance.obj_num) + } + maybe_object::an_int(int_thiny) { + print("matched an_intj incorrectly ") + println(int_thiny) + } + } + obj_item = maybe_object::an_obj(TestObj(100)) + match (obj_item) { + maybe_object::no_obj() println("matched no_obj incorrectly") + maybe_object::an_obj(obj_instance) { + print("matched an_obj correctly ") + println(obj_instance.obj_num) + } + maybe_object::an_int(int_thiny) { + print("matched an_intj incorrectly ") + println(int_thiny) + } + } + obj_item = maybe_object::an_int(1337) + match (obj_item) { + maybe_object::no_obj() println("matched no_obj incorrectly") + maybe_object::an_obj(obj_instance) { + print("matched an_obj incorrectly ") + println(obj_instance.obj_num) + } + maybe_object::an_int(int_thiny) { + print("matched an_int correctly ") + println(int_thiny) + } + } return 0 } diff --git a/tests/test_grammer.krak b/tests/test_grammer.krak index 8164b31..6192467 100644 --- a/tests/test_grammer.krak +++ b/tests/test_grammer.krak @@ -119,7 +119,8 @@ fun main():int { var parse.construct(a): parser /*var result = parse.parse_input(string("a"), string("fun name"))*/ - var result = parse.parse_input(read_file(string("to_parse.krak")), string("fun name")) + var result = parse.parse_input(read_file(string("test_adt.krak")), string("fun name")) + /*var result = parse.parse_input(read_file(string("to_parse.krak")), string("fun name"))*/ /*var result = parse.parse_input(string("inport a;"), string("fun name"))*/ /*var result = parse.parse_input(string("fun main():int { return 0; }"), string("fun name"))*/ /*var result = parse.parse_input(string("ad"), string("fun name"))*/