diff --git a/include/CGenerator.h b/include/CGenerator.h index eb2eaed..5d5645e 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -28,9 +28,9 @@ class CGenerator { std::pair generateTranslationUnit(std::string name, std::map*> ASTs); std::string generate(NodeTree* from, NodeTree* enclosingObject = NULL, bool justFuncName = false); std::string generateAliasChains(std::map*> ASTs, NodeTree* definition); - static std::string ValueTypeToCType(Type *type, std::string); - static std::string ValueTypeToCTypeDecoration(Type *type); - static std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr); + std::string ValueTypeToCType(Type *type, std::string); + std::string ValueTypeToCTypeDecoration(Type *type); + std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr); static std::string CifyName(std::string name); static std::string scopePrefix(NodeTree* from); std::string generateObjectMethod(NodeTree* enclosingObject, NodeTree* from, std::string *functionPrototype); @@ -40,6 +40,7 @@ class CGenerator { int tabLevel; std::string generatorString; std::string linkerString; + std::string functionTypedefString; std::vector*>> deferDoubleStack; std::stack loopDeferStackDepth; private: diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 27b02f0..10eeafc 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -2,9 +2,11 @@ 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 = type WS "\*" | "void" | "int" | "float" | "double" | "char" | scoped_identifier | scoped_identifier WS template_inst ; +type = type WS "\*" | "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 ; +opt_type_list = type_list | ; template_inst = "<" WS type_list WS ">" ; type_list = type_list WS "," WS type | type ; @@ -119,7 +121,7 @@ bool = "true" | "false" ; character = "'(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'| |z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|\"|Z|X|C|V|B|N|M|<|>|\?| )'" ; -keywords_also_identifiers = "obj" | "def" ; +keywords_also_identifiers = "obj" | "def" | "fun" | "var" ; alpha_alphanumeric = "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|_)(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|_|0|1|2|3|4|5|6|7|8|9)*" ; augmented_alpha_alphanumeric = alpha_alphanumeric augmented_alpha_alphanumeric | keywords_also_identifiers augmented_alpha_alphanumeric | alpha_alphanumeric | keywords_also_identifiers ; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 5d1f6bc..714a8e8 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -904,29 +904,23 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* scope, s //We're not looking for types if (i->getDataRef()->type == type_def) continue; + Type* functionType = i->getDataRef()->valueType; - std::vector*> children = i->getChildren(); - //We subtract one from the children to get the type size only if there is at least one child AND - // the last node is actually a body node, as it may not have been generated yet if we're in the body - //and this function is recursive or if this is a non-instantiated template function - int numTypes = (children.size() > 0 && children[children.size()-1]->getDataRef()->type == code_block) ? children.size()-1 : children.size(); + int numTypes = functionType->parameterTypes.size(); if (types.size() != numTypes) { std::cout << "Type sizes do not match between two " << lookup << "(" << types.size() << "," << numTypes << "), types are: "; for (auto j : types) std::cout << j.toString() << " "; std::cout << std::endl; std::cout << "Versus" << std::endl; - for (int j = 0; j < numTypes; j++) { - std::cout << " vs " << children[j]->getDataRef()->valueType->toString() << std::endl; - } - for (auto child: children) - std::cout << "\t" << child->getDataRef()->toString() << std::endl; + for (int j = 0; j < numTypes; j++) + std::cout << functionType->parameterTypes[j]->toString() << " "; std::cout << std::endl; continue; } bool typesMatch = true; for (int j = 0; j < types.size(); j++) { - Type* tmpType = children[j]->getDataRef()->valueType; + Type* tmpType = functionType->parameterTypes[j]; //Don't worry if types don't match if it's a template type //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 @@ -934,7 +928,7 @@ NodeTree* ASTTransformation::functionLookup(NodeTree* scope, s if (types[j] != *tmpType) { typesMatch = false; std::cout << "Types do not match between two " << lookup << " " << types[j].toString(); - std::cout << " vs " << children[j]->getDataRef()->valueType->toString() << std::endl; + std::cout << " vs " << tmpType->toString() << std::endl; break; } } @@ -1277,7 +1271,11 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTree* typeDefinition = NULL; std::set traits; - while (typeIn[typeIn.size() - indirection - 1] == '*') indirection++; + // To counter this, for every indirection we step down a level + while (typeIn[typeIn.size() - indirection - 1] == '*') { + indirection++; + typeNode = typeNode->getChildren()[0]; + }; std::string edited = strSlice(typeIn, 0, -(indirection + 1)); if (edited == "void") baseType = void_type; @@ -1291,7 +1289,13 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreegetChildren().size() && typeNode->getChildren()[0]->getDataRef()->getName() == "function_type") { + baseType = function_type; + std::vector 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()); + } else { baseType = none; auto possibleMatches = scopeLookup(scope, edited); @@ -1313,11 +1317,6 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreegetChildren()[0]; - std::cout << possibleMatches.size() << " " << typeNode->getChildren().size() << std::endl; if (typeNode->getChildren().size() > 1) std::cout << typeNode->getChildren()[1]->getDataRef()->getName() << std::endl; diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index c9e7e14..6cad067 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -126,6 +126,9 @@ std::pair CGenerator::generateTranslationUnit(std::str std::string classStructs = "/**\n * Class Structs\n */\n\n"; std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n"; std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n"; + // There also exists functionTypedefString which is a member variable that keeps + // track of utility typedefs that allow our C type generation to be more sane + // it is emitted in the h file right before functionPrototypes // And get the correct order for emiting classes, but not if they're not in our file, then they will get included @@ -242,7 +245,7 @@ std::pair CGenerator::generateTranslationUnit(std::str } } } - hOutput += plainTypedefs + importIncludes + topLevelCPassthrough + variableExternDeclarations + classStructs + functionPrototypes; + hOutput += plainTypedefs + importIncludes + topLevelCPassthrough + variableExternDeclarations + classStructs + functionTypedefString + functionPrototypes; cOutput += variableDeclarations + functionDefinitions; return std::make_pair(hOutput, cOutput); } @@ -568,19 +571,20 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl case function_type: { std::string indr_str; + std::string typedefStr = "typedef "; + std::string typedefID = "ID" + CifyName(type->toString(false)); 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 + ")("; + typedefStr += ValueTypeToCTypeThingHelper(type->returnType, ""); + typedefStr += " (*" + typedefID + ")("; if (type->parameterTypes.size() == 0) - return_type += "void"; + typedefStr += "void"; else for (int i = 0; i < type->parameterTypes.size(); i++) - return_type += (i != 0 ? ", " : "") + ValueTypeToCTypeThingHelper(type->parameterTypes[i], ""); - return_type += ")"; + typedefStr += (i != 0 ? ", " : "") + ValueTypeToCTypeThingHelper(type->parameterTypes[i], ""); + typedefStr += ");\n"; + functionTypedefString += typedefStr; + return_type = typedefID + indr_str + " " + declaration; do_ending = false; } break; diff --git a/src/Importer.cpp b/src/Importer.cpp index e498132..fbd3cfe 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -17,8 +17,6 @@ Importer::Importer(Parser* parserIn, std::vector includePaths, std: removeSymbols.push_back(Symbol("WS", false)); removeSymbols.push_back(Symbol("\\(", true)); removeSymbols.push_back(Symbol("\\)", true)); - //removeSymbols.push_back(Symbol("::", true)); - //removeSymbols.push_back(Symbol(":", true)); removeSymbols.push_back(Symbol("var", true)); removeSymbols.push_back(Symbol("fun", true)); @@ -53,6 +51,7 @@ Importer::Importer(Parser* parserIn, std::vector includePaths, std: collapseSymbols.push_back(Symbol("if_comp_pred", false)); collapseSymbols.push_back(Symbol("declaration_block", false)); collapseSymbols.push_back(Symbol("type_list", false)); + collapseSymbols.push_back(Symbol("opt_type_list", false)); collapseSymbols.push_back(Symbol("template_param_list", false)); collapseSymbols.push_back(Symbol("trait_list", false)); collapseSymbols.push_back(Symbol("dec_type", false)); diff --git a/tests/test_functionsValues.expected_results b/tests/test_functionsValues.expected_results index ec63514..4411e55 100644 --- a/tests/test_functionsValues.expected_results +++ b/tests/test_functionsValues.expected_results @@ -1 +1,8 @@ 9 +9 +7 +8 +11 +12 +13 +14 diff --git a/tests/test_functionsValues.krak b/tests/test_functionsValues.krak index 4d17122..6690273 100644 --- a/tests/test_functionsValues.krak +++ b/tests/test_functionsValues.krak @@ -4,9 +4,52 @@ fun test(): void { println(9) } +fun test2(toPrint: int): void { + println(toPrint) +} + +fun test3(): fun():void { + return test4; +} + +fun test4(): void { + println(11) +} + +fun doIt(fun: fun():void):void { + fun() +} + +fun itToBeDone():void { + println(12) +} + +fun doItParam(fun: fun(int):void, param:int):void { + fun(param) +} + +fun itToBeDoneParam(param:int):void { + println(param) +} + fun main(): int { var val = test + var val2: fun():void = test val() + val2() + + + var val3 = test2 + var val4: fun(int):void = test2 + val3(7) + val4(8) + + test3()() + doIt(itToBeDone) + doItParam(itToBeDoneParam, 13) + var indrdo = doItParam + var indrdoParam = itToBeDoneParam + indrdo(indrdoParam, 14) return 0 }