diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index 484452a..399e5d9 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -40,8 +40,8 @@ class ASTTransformation: public NodeTransformation { void thirdPassFunction(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements); virtual NodeTree* transform(NodeTree* from); - NodeTree* transform(NodeTree* from, NodeTree* scope, std::vector types, std::map templateTypeReplacements); - std::vector*> transformChildren(std::vector*> children, std::set skipChildren, NodeTree* scope, std::vector types, std::map templateTypeReplacements); + NodeTree* transform(NodeTree* from, NodeTree* scope, std::vector types, bool limitToFunction, std::map templateTypeReplacements); + std::vector*> transformChildren(std::vector*> children, std::set skipChildren, NodeTree* scope, std::vector types, bool limitToFunction, std::map templateTypeReplacements); std::vector mapNodesToTypes(std::vector*> nodes); std::vector mapNodesToTypePointers(std::vector*> nodes); std::string concatSymbolTree(NodeTree* root); diff --git a/include/CGenerator.h b/include/CGenerator.h index 6a615bf..954f200 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -45,6 +45,7 @@ class CGenerator { int tabLevel; int id; + std::string function_header; std::string generatorString; std::string linkerString; std::string functionTypedefString; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 7c4d782..08b33a5 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -102,7 +102,7 @@ NodeTree* ASTTransformation::firstPass(std::string fileName, NodeTreeaddChild(addToScope("~enclosing_scope", newNode, new NodeTree("identifier", ASTData(identifier, Symbol(concatSymbolTree(i->getChildren()[0]),true))))); std::set skipChildren; skipChildren.insert(0); //Don't do the identifier. The identifier lookup will fail. That's why we do it here. - newNode->addChildren(transformChildren(i->getChildren(), skipChildren, translationUnit, std::vector(), std::map())); + newNode->addChildren(transformChildren(i->getChildren(), skipChildren, translationUnit, std::vector(), false, std::map())); translationUnit->addChild(newNode); } } @@ -250,7 +250,7 @@ NodeTree* ASTTransformation::secondPassFunction(NodeTree* from, addToScope("~enclosing_scope", scope, functionDef); addToScope(functionName, functionDef, scope); //We only do the parameter nodes. We don't do the body yet, as this is the secondPass - auto transChildren = transformChildren(slice(children,1,-3, 2), std::set(), functionDef, std::vector(), templateTypeReplacements); + auto transChildren = transformChildren(slice(children,1,-3, 2), std::set(), functionDef, std::vector(), false, templateTypeReplacements); functionDef->addChildren(transChildren); // Swap the function type over to be the correct type (a function with parameter and return types, etc) @@ -296,12 +296,15 @@ void ASTTransformation::thirdPass(NodeTree* ast, NodeTree* pars // even inside of class templates. As its methods may cause partial instantiation of // other class templates, we need to do this until the size no longer changes. std::vector*> classTemplates; + std::set finishedClassTemplateTypes; int lastSize = 0; while (lastSize != ast->getDataRef()->scope.size()) { lastSize = ast->getDataRef()->scope.size(); classTemplates.clear(); for (auto i : ast->getDataRef()->scope) { - if (i.second[0]->getDataRef()->type == type_def && i.second[0]->getDataRef()->valueType->templateTypeReplacement.size()) { + // we actually keep track of the template type replacements now, and need them after they're instantiated, so we use a set to check if we've done it now + if (i.second[0]->getDataRef()->type == type_def && i.second[0]->getDataRef()->valueType->templateTypeReplacement.size() + && finishedClassTemplateTypes.find(i.second[0]->getDataRef()->valueType) == finishedClassTemplateTypes.end()) { classTemplates.push_back(i.second[0]); std::cout << "Saving " << i.second[0]->getDataRef()->toString() << " to instantiate." << std::endl; } @@ -312,7 +315,7 @@ void ASTTransformation::thirdPass(NodeTree* ast, NodeTree* pars for (NodeTree* j : classTemplateType->templateDefinition->getChildren()) if (j->getDataRef()->getName() == "function" && j->getChildren()[1]->getDataRef()->getName() != "template_dec") thirdPassFunction(j, searchScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method - classTemplateType->templateTypeReplacement.clear(); // This template has been fully instantiated, clear it's map so it won't be instantiated again + finishedClassTemplateTypes.insert(classTemplateType); } } } @@ -342,15 +345,15 @@ NodeTree* ASTTransformation::searchScopeForFunctionDef(NodeTree* from, NodeTree* functionDef, std::map templateTypeReplacements) { NodeTree* codeBlock = from->getChildren().back(); - functionDef->addChild(transform(codeBlock, functionDef, std::vector(), templateTypeReplacements)); + functionDef->addChild(transform(codeBlock, functionDef, std::vector(), false, templateTypeReplacements)); } NodeTree* ASTTransformation::transform(NodeTree* from) { //Set up top scope - return transform(from, NULL, std::vector(), std::map()); + return transform(from, NULL, std::vector(), false, std::map()); } -NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree* scope, std::vector types, std::map templateTypeReplacements) { +NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree* scope, std::vector types, bool limitToFunction, std::map templateTypeReplacements) { Symbol current = from->getData(); std::string name = current.getName(); NodeTree* newNode = NULL; @@ -361,7 +364,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree //Make sure we get the entire name std::string lookupName = concatSymbolTree(from); std::cout << "Looking up: " << lookupName << std::endl; - if (types.size()) { + if (limitToFunction) { newNode = functionLookup(scope, lookupName, types); if (newNode == NULL) { std::cout << "scope lookup failed! Could not find " << lookupName << " in identifier (functionLookup)" << std::endl; @@ -391,7 +394,19 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree std::cerr << "scope lookup error! Could not find " << lookupName << " in identifier (scopeLookup)" << std::endl; throw "LOOKUP ERROR: " + lookupName; } + // can't cull out functiokns b/c we might want them as values newNode = possibleMatches[0]; + //newNode = nullptr; + //for (auto i : possibleMatches) { + //if (i->getDataRef()->valueType->baseType != function_type) { + //newNode = i; + //break; + //} + //} + //if (!newNode) { + //std::cerr << "scope lookup error! only found functions for " << lookupName << " in identifier (scopeLookup)" << std::endl; + //throw "LOOKUP ERROR: " + lookupName; + //} } return newNode; } else if (name == "type_def") { @@ -449,7 +464,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree for (auto i : slice(children[1]->getChildren(), 1, -1, 2)) //skip commas yetToBeInstantiatedTemplateTypes[concatSymbolTree(i)] = new Type(template_type_type); //This may have to be combined with templateTypeReplacements if we do templated member functions inside of templated classes - auto transChildren = transformChildren(slice(children,3,-2), std::set(), newNode, types, yetToBeInstantiatedTemplateTypes); + auto transChildren = transformChildren(slice(children,3,-2), std::set(), newNode, types, limitToFunction, yetToBeInstantiatedTemplateTypes); std::cout << "Template function " << functionName << " has these parameters: "; for (auto i : transChildren) std::cout << "||" << i->getDataRef()->toString() << "|| "; @@ -471,11 +486,11 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree if (name == "lambda") addToScope(functionName, newNode, topScope); - auto parameters = transformChildren(getNodes("typed_parameter", children), skipChildren, scope, types, templateTypeReplacements); + auto parameters = transformChildren(getNodes("typed_parameter", children), skipChildren, scope, types, limitToFunction, templateTypeReplacements); newNode->addChildren(parameters); // update type with actual type newNode->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), newNode->getDataRef()->valueType); - newNode->addChild(transform(getNode("statement", children), scope, types, templateTypeReplacements)); + newNode->addChild(transform(getNode("statement", children), scope, types, limitToFunction, templateTypeReplacements)); std::cout << "finished function" << functionName << std::endl; return newNode; @@ -498,7 +513,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree if (children.size() > 1) { //We do children first so we can do appropriate scope searching with types (yay operator overloading!) skipChildren.insert(1); - std::vector*> transformedChildren = transformChildren(children, skipChildren, scope, types, templateTypeReplacements); + std::vector*> transformedChildren = transformChildren(children, skipChildren, scope, types, limitToFunction, templateTypeReplacements); std::string functionCallString = concatSymbolTree(children[1]); NodeTree* function = doFunction(scope, functionCallString, transformedChildren, templateTypeReplacements); if (function == NULL) { @@ -510,22 +525,22 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree // XXX What the heck is this if (children.size() == 0) return new NodeTree(); - return transform(children[0], scope, types, templateTypeReplacements); //Just a promoted term, so do child + return transform(children[0], scope, types, limitToFunction, templateTypeReplacements); //Just a promoted term, so do child } //Here's the order of ops stuff } else if (name == "expression" || name == "shiftand" || name == "term" || name == "unarad" || name == "access_operation") { //If this is an actual part of an expression, not just a premoted child if (children.size() > 2) { - NodeTree* lhs = transform(children[0], scope, std::vector(), templateTypeReplacements); //LHS does not inherit types + NodeTree* lhs = transform(children[0], scope, std::vector(),limitToFunction, templateTypeReplacements); //LHS does not inherit types NodeTree* rhs; if (name == "access_operation") { std::cout << "lhs is: " << lhs->getDataRef()->toString() << std::endl; - rhs = transform(children[2], lhs->getDataRef()->valueType->typeDefinition, types, templateTypeReplacements); //If an access operation, then the right side will be in the lhs's type's scope + rhs = transform(children[2], lhs->getDataRef()->valueType->typeDefinition, types, limitToFunction, templateTypeReplacements); //If an access operation, then the right side will be in the lhs's type's scope // this might be a template member function, so do like below would do, but make it our rhs if (rhs == nullptr) rhs = findOrInstantiateFunctionTemplate(slice(children,2,-1), lhs->getDataRef()->valueType->typeDefinition, types, templateTypeReplacements); } else - rhs = transform(children[2], scope, types, templateTypeReplacements); + rhs = transform(children[2], scope, types, limitToFunction, templateTypeReplacements); std::string functionCallName = concatSymbolTree(children[1]); if (functionCallName == "[") @@ -540,7 +555,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree return newNode; } if (children.size() == 1) { - newNode = transform(children[0], scope, types, templateTypeReplacements); //Just a promoted child, so do it instead + newNode = transform(children[0], scope, types, limitToFunction, templateTypeReplacements); //Just a promoted child, so do it instead if (newNode) return newNode; } @@ -558,9 +573,9 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree NodeTree* param; // I think this is where we look at pre vs post operators if (funcName == "*" || funcName == "&" || funcName == "++" || funcName == "--" || funcName == "+" || funcName == "-" || funcName == "!" || funcName == "~") - param = transform(children[1], scope, types, templateTypeReplacements); + param = transform(children[1], scope, types, limitToFunction, templateTypeReplacements); else - funcName = concatSymbolTree(children[1]), param = transform(children[0], scope, types, templateTypeReplacements); + funcName = concatSymbolTree(children[1]), param = transform(children[0], scope, types, limitToFunction, templateTypeReplacements); std::cout << "\t\t\t funcName= " << funcName << " param: " << param->getDataRef()->symbol.getName() << std::endl; //std::cout << "scope lookup from factor" << std::endl; @@ -574,7 +589,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree return function; } else { - return transform(children[0], scope, types, templateTypeReplacements); //Just a promoted child, so do it instead + return transform(children[0], scope, types, limitToFunction, templateTypeReplacements); //Just a promoted child, so do it instead } } else if (name == "statement") { newNode = new NodeTree(name, ASTData(statement)); @@ -594,8 +609,8 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode = new NodeTree(name, ASTData(defer_statement)); } else if (name == "assignment_statement") { std::string assignFuncName = concatSymbolTree(children[1]); - NodeTree* lhs = transform(children[0], scope, types, templateTypeReplacements); - NodeTree* rhs = transform(children[2], scope, types, templateTypeReplacements); + NodeTree* lhs = transform(children[0], scope, types, limitToFunction, templateTypeReplacements); + NodeTree* rhs = transform(children[2], scope, types, limitToFunction, templateTypeReplacements); std::vector*> transformedChildren; transformedChildren.push_back(lhs); transformedChildren.push_back(rhs); // see if this is an overloaded assignment @@ -640,8 +655,8 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree //This code is a simplified version of the code in function_call with respect to access_operation. //Note that in this case, what is lhs there is our newIdentifier here (the declaration of the left side of the access operation) auto sliced = slice(children, 3, -3); - std::vector*> initPositionFuncParams = transformChildren(sliced, std::set(), scope, types, templateTypeReplacements); - NodeTree* rhs = transform(children[2], identifierType->typeDefinition, mapNodesToTypes(initPositionFuncParams), templateTypeReplacements); //If an access operation, then the right side will be in the lhs's type's scope + std::vector*> initPositionFuncParams = transformChildren(sliced, std::set(), scope, types, limitToFunction, templateTypeReplacements); + NodeTree* rhs = transform(children[2], identifierType->typeDefinition, mapNodesToTypes(initPositionFuncParams), true, templateTypeReplacements); //If an access operation, then the right side will be in the lhs's type's scope std::vector*> transformedChildren; transformedChildren.push_back(newIdentifier); transformedChildren.push_back(rhs); NodeTree* accessFuncCall = doFunction(scope, ".", transformedChildren, templateTypeReplacements); accessFuncCall->getDataRef()->valueType = rhs->getDataRef()->valueType; @@ -657,7 +672,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree } auto boolExp = getNode("boolean_expression", children); - NodeTree* toAssign = boolExp ? transform(boolExp, scope, types, templateTypeReplacements) : nullptr; + NodeTree* toAssign = boolExp ? transform(boolExp, scope, types, limitToFunction, templateTypeReplacements) : nullptr; // for type inferencing if (!identifierType) { if (toAssign) @@ -703,12 +718,12 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode = new NodeTree(functionCallName, ASTData(function_call, Symbol(functionCallName, true))); skipChildren.insert(0); - std::vector*> transformedChildren = transformChildren(children, skipChildren, scope, types, templateTypeReplacements); + std::vector*> transformedChildren = transformChildren(children, skipChildren, scope, types, limitToFunction, templateTypeReplacements); std::cout << "scope lookup from function_call: " << functionCallName << std::endl; for (auto i : children) std::cout << i << " : " << i->getName() << " : " << i->getDataRef()->getName() << std::endl; - NodeTree* function = transform(children[0], scope, mapNodesToTypes(transformedChildren), templateTypeReplacements); + NodeTree* function = transform(children[0], scope, mapNodesToTypes(transformedChildren), true, templateTypeReplacements); std::cout << "The thing: " << function << " : " << function->getName() << std::endl; for (auto i : function->getChildren()) std::cout << i->getName() << " "; @@ -719,13 +734,13 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode->addChildren(transformedChildren); return newNode; } else if (name == "parameter") { - return transform(children[0], scope, types, templateTypeReplacements); //Don't need a parameter node, just the value + return transform(children[0], scope, types, limitToFunction, templateTypeReplacements); //Don't need a parameter node, just the value } else if (name == "type") { std::string theConcat = concatSymbolTree(from); //We have no symbol, so this will concat our children newNode = new NodeTree(name, ASTData(value, Symbol(theConcat, true), typeFromTypeNode(from, scope, templateTypeReplacements))); addToScope("~enclosing_scope", scope, newNode); } else if (name == "number") { - return transform(children[0], scope, types, templateTypeReplacements); + return transform(children[0], scope, types, limitToFunction, templateTypeReplacements); } else if (name == "integer") { newNode = new NodeTree(name, ASTData(value, Symbol(concatSymbolTree(from), true), new Type(integer))); } else if (name == "floating_literal") { @@ -760,17 +775,17 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree } //Do all children but the ones we skip - newNode->addChildren(transformChildren(children, skipChildren, scope, types, templateTypeReplacements)); + newNode->addChildren(transformChildren(children, skipChildren, scope, types, limitToFunction, templateTypeReplacements)); return newNode; } //We use this functionality a lot at different places -std::vector*> ASTTransformation::transformChildren(std::vector*> children, std::set skipChildren, NodeTree* scope, std::vector types, std::map templateTypeReplacements) { +std::vector*> ASTTransformation::transformChildren(std::vector*> children, std::set skipChildren, NodeTree* scope, std::vector types, bool limitToFunction, std::map templateTypeReplacements) { std::vector*> transformedChildren; // In general, iterate through children and do them. Might not do this for all children. for (int i = 0; i < children.size(); i++) { if (skipChildren.find(i) == skipChildren.end()) { - NodeTree* transChild = transform(children[i], scope, types, templateTypeReplacements); + NodeTree* transChild = transform(children[i], scope, types, limitToFunction, templateTypeReplacements); if (transChild->getDataRef()->type) //Only add the children that have a real ASTData::ASTType, that is, legit ASTData. transformedChildren.push_back(transChild); else @@ -1079,8 +1094,12 @@ void ASTTransformation::unifyType(NodeTree *syntaxType, Type type, std:: if (typeTemplateDefinition && concatSymbolTree(getNode("scoped_identifier", children)) == concatSymbolTree(getNode("identifier", typeTemplateDefinition->getChildren()))) { std::vector*> uninTypeInstTypes = getNodes("type", getNode("template_inst", children)); std::vector*> typeInstTypes = getNodes("template_param", getNode("template_dec", typeTemplateDefinition->getChildren())); - for (int i = 0; i < uninTypeInstTypes.size(); i++) + for (int i = 0; i < uninTypeInstTypes.size(); i++) { + std::cout << concatSymbolTree(uninTypeInstTypes[i]) << " : " << origionalType->toString() << " : " << concatSymbolTree(typeInstTypes[i]) << std::endl; + std::cout << "which is " << origionalType->templateTypeReplacement[concatSymbolTree(typeInstTypes[i])]->toString() << std::endl; + //std::cout << "which is " << *origionalType->templateTypeReplacement[concatSymbolTree(typeInstTypes[i])] << std::endl; unifyType(uninTypeInstTypes[i], *origionalType->templateTypeReplacement[concatSymbolTree(typeInstTypes[i])], templateTypeMap, typeMap); + } return; } @@ -1195,7 +1214,10 @@ NodeTree* ASTTransformation::templateFunctionLookup(NodeTree* std::cout << "Current function fits, satisfying " << currentTraitsSatisfied << " traits" << std::endl; } if (!mostFittingTemplates.size()) { - std::cerr << "No template functions fit for " << lookup << "!" << std::endl; + std::cerr << "No template functions fit for " << lookup << "("; + for (auto t : types) + std::cerr << t.toString() + ", "; + std::cerr << ")!" << std::endl; throw "No matching template functions"; } else if (mostFittingTemplates.size() > 1) { std::cerr << "Multiple template functions fit with equal number of traits satisfied for " << lookup << "!" << std::endl; @@ -1471,6 +1493,11 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreetemplateDefinition = templateSyntaxTree; //We're going to still need this when we finish instantiating selfType->templateTypeReplacement = newTemplateTypeReplacement; //Save the types for use when this is fully instantiated in pass 4 + for (auto daPair : selfType->templateTypeReplacement) { + std::cout << " BREAK HERE " << daPair.first << " : " << daPair.second->toString() << std::endl; + if (daPair.second == NULL) + std::cout << " BREAK HERE " << std::endl; + } secondPassDoClassInsides(typeDefinition, templateSyntaxTree->getChildren(), newTemplateTypeReplacement); //Use these types when instantiating data members } } else if (possibleMatches.size() == 0) { @@ -1577,11 +1604,11 @@ NodeTree* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec std::cout << "About to do children of " << functionName << " to " << fullyInstantiatedName << std::endl; std::set skipChildren; - auto parameters = transformChildren(getNodes("typed_parameter", templateSyntaxTree->getChildren()), skipChildren, instantiatedFunction, std::vector(), newTemplateTypeReplacement); + auto parameters = transformChildren(getNodes("typed_parameter", templateSyntaxTree->getChildren()), skipChildren, instantiatedFunction, std::vector(), false, newTemplateTypeReplacement); instantiatedFunction->addChildren(parameters); // update type with actual type instantiatedFunction->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), instantiatedFunction->getDataRef()->valueType); - instantiatedFunction->addChild(transform(getNode("statement", templateSyntaxTree->getChildren()), instantiatedFunction, std::vector(), newTemplateTypeReplacement)); + instantiatedFunction->addChild(transform(getNode("statement", templateSyntaxTree->getChildren()), instantiatedFunction, std::vector(), false, newTemplateTypeReplacement)); std::cout << "Fully Instantiated function " << functionName << " to " << fullyInstantiatedName << std::endl; return instantiatedFunction; diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 5e1a390..832356f 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -3,6 +3,7 @@ CGenerator::CGenerator() : generatorString("__C__") { tabLevel = 0; id = 0; + function_header = "fun_"; } CGenerator::~CGenerator() { } @@ -198,7 +199,7 @@ std::pair CGenerator::generateTranslationUnit(std::str parameters += ValueTypeToCType(decChildren[j]->getData().valueType, generate(decChildren[j], nullptr).oneString()); nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType); } - functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType->returnType, ((declarationData.symbol.getName() == "main") ? "" : scopePrefix(declaration)) + + functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType->returnType, ((declarationData.symbol.getName() == "main") ? "" : function_header + scopePrefix(declaration)) + CifyName(declarationData.symbol.getName() + nameDecoration)) + "(" + parameters + "); /*func*/\n"; // generate function @@ -305,19 +306,14 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc parameters += ValueTypeToCType(children[j]->getData().valueType, generate(children[j], enclosingObject, justFuncName).oneString()); nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType); // add parameters to distructDoubleStack so that their destructors will be called at return (if they exist) - std::cout << "HAHA: " << generate(children[j], enclosingObject, justFuncName).oneString() << std::endl; distructDoubleStack.back().push_back(children[j]); } - if (children.size() == 1) - std::cout << "HEHE: " << data.symbol.getName() << " has only one child" << std::endl; - else if (children.size() == 0) - std::cout << "HEHE: " << data.symbol.getName() << " has only 0 child" << std::endl; // this is for using functions as values if (justFuncName) { - output = ((data.symbol.getName() == "main") ? "" : scopePrefix(from)) + CifyName(data.symbol.getName() + nameDecoration); + output = ((data.symbol.getName() == "main") ? "" : function_header + scopePrefix(from)) + CifyName(data.symbol.getName() + nameDecoration); } else { // Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock - output = "\n" + ValueTypeToCType(data.valueType->returnType, ((data.symbol.getName() == "main") ? "" : scopePrefix(from)) + + output = "\n" + ValueTypeToCType(data.valueType->returnType, ((data.symbol.getName() == "main") ? "" : function_header + scopePrefix(from)) + CifyName(data.symbol.getName() + nameDecoration)) + "(" + parameters + ") {\n" + generate(children[children.size()-1], enclosingObject, justFuncName).oneString(); output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject); output += "}\n"; @@ -562,7 +558,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); // Note that we only add scoping to the object, as this specifies our member function too -/*HERE*/ return scopePrefix(unaliasedTypeDef) + CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" + +/*HERE*/ return function_header + scopePrefix(unaliasedTypeDef) + CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" + CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject, true).oneString() + ","; //The comma lets the upper function call know we already started the param list //Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses @@ -588,11 +584,11 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc //Check to see if we're inside of an object and this is a method call bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]); if (isSelfObjectMethod) { - output += scopePrefix(children[0]) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"; + output += function_header + scopePrefix(children[0]) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"; output += CifyName(name + nameDecoration) + "("; output += children.size() > 1 ? "this," : "this"; } else { - output += scopePrefix(children[0]) + CifyName(name + nameDecoration) + "("; + output += function_header + scopePrefix(children[0]) + CifyName(name + nameDecoration) + "("; } } } else { @@ -664,7 +660,7 @@ std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, distructDoubleStack.back().push_back(children[i]); } - std::string functionSignature = "\n" + ValueTypeToCType(data.valueType->returnType, scopePrefix(from) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__" + std::string functionSignature = "\n" + ValueTypeToCType(data.valueType->returnType, function_header + scopePrefix(from) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__" + CifyName(data.symbol.getName()) + nameDecoration) + "(" + ValueTypeToCType(&enclosingObjectType, "this") + parameters + ")"; *functionPrototype += functionSignature + ";\n"; // Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock @@ -714,7 +710,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 scopePrefix(typeDefinition) + CifyName(typeDefinition->getDataRef()->symbol.getName()) + "__" + method + nameDecoration + "(" + parameter + ");\n"; + return function_header + scopePrefix(typeDefinition) + CifyName(typeDefinition->getDataRef()->symbol.getName()) + "__" + method + nameDecoration + "(" + parameter + ");\n"; } return ""; } diff --git a/stdlib/conversions.krak b/stdlib/conversions.krak index a36021d..b4d087e 100644 --- a/stdlib/conversions.krak +++ b/stdlib/conversions.krak @@ -9,3 +9,13 @@ fun to_char(in: T) : char { return out; } +fun to_int(in: T) : int { + var out:int + __if_comp__ __C__ { + simple_passthrough(in = in: out = out:) """ + int out = (int) in; + """ + } + return out; +} + diff --git a/stdlib/regex.krak b/stdlib/regex.krak index 52e5099..2d214c9 100644 --- a/stdlib/regex.krak +++ b/stdlib/regex.krak @@ -31,7 +31,21 @@ obj regexState(Object) { next_states.destruct() } fun match(input: char): vector::vector { - return next_states.filter(fun(it:regexState*):bool { return it->character == input; } ) + return next_states.filter(fun(it:regexState*, input:char):bool { return it->character == input; }, input) + + io::print("in match for: "); io::println(character) + io::println("pre") + for (var i = 0; i < next_states.size; i++;) + io::println(next_states[i]->character) + var nx = next_states.filter(fun(it:regexState*, input:char):bool { return it->character == input; }, input) + io::println("next") + for (var i = 0; i < nx.size; i++;) + io::println(nx[i]->character) + //return next_states.filter(fun(it:regexState*, input:char):bool { return it->character == input; }, input) + return nx + } + fun is_end():bool { + return next_states.any_true(fun(state: regexState*):bool { return state->character == 1; }) } } @@ -45,10 +59,10 @@ obj regex(Object) { var traverse = &begin for (var i = 0; i < regexString.length(); i++;) { var next = mem::new()->construct(regexString[i]) - traverse->next_states->add(next) + traverse->next_states.add(next) traverse = next } - traverse->next_states->add(mem::new()->construct(conversions::to_char(1))) + traverse->next_states.add(mem::new()->construct(conversions::to_char(1))) return this } fun copy_construct(old:regex*):void { @@ -62,18 +76,23 @@ obj regex(Object) { fun long_match(to_match: char*): int { return long_match(string::string(to_match)); } fun long_match(to_match: string::string): int { var next = vector::vector(&begin) - //var next.construct() :vector::vector var longest = 0 for (var i = 0; i < to_match.length(); i++;) { if (next.size == 0) return longest - if (next.any_true(fun(state: regexState*):bool { return state->character == 1; })) + if (next.any_true(fun(state: regexState*):bool { return state->is_end(); })) longest = i //next = next.flatten_map(fun(state: regexState*): vector::vector { return state->match(to_match[i]); }) - next = next.flatten_map(fun(state: regexState*): vector::vector { return state->match('a'); }) + //next = next.flatten_map(fun(state: regexState*): vector::vector { return state->match('a'); }) //next = next.flatten_map(fun(state: regexState*): vector::vector { return state->match('a'); }) + next = next.flatten_map(fun(state: regexState*, c:char): vector::vector { return state->match(c); }, to_match[i]) } - if (next.any_true(fun(state: regexState*):bool { return state->character == 1; })) + /*io::println("ok, ending with")*/ + /*for (var i = 0; i < next.size; i++;) {*/ + /*io::println(next[i]->character)*/ + /*io::println(conversions::to_int(next[i]->next_states[0]->character))*/ + /*}*/ + if (next.any_true(fun(state: regexState*):bool { return state->is_end(); })) return to_match.length() return longest } diff --git a/stdlib/vector.krak b/stdlib/vector.krak index 54973d2..2081d17 100644 --- a/stdlib/vector.krak +++ b/stdlib/vector.krak @@ -131,6 +131,15 @@ obj vector (Object) { } return newVec } + fun flatten_map(func: fun(T,V):vector, extraParam:V):vector { + var newVec.construct(): vector + for (var i = 0; i < size; i++;) { + var to_add = func(data[i], extraParam) + for (var j = 0; j < to_add.size; j++;) + newVec.addEnd(to_add.get(j)) + } + return newVec + } fun filter(func: fun(T):bool):vector { var newVec.construct(): vector for (var i = 0; i < size; i++;) @@ -138,6 +147,13 @@ obj vector (Object) { newVec.addEnd(data[i]) return newVec } + fun filter(func: fun(T,U):bool, extraParam: U):vector { + var newVec.construct(): vector + for (var i = 0; i < size; i++;) + if (func(data[i], extraParam)) + newVec.addEnd(data[i]) + return newVec + } fun any_true(func: fun(T):bool):bool { for (var i = 0; i < size; i++;) if (func(data[i])) diff --git a/tests/test_conversions.expected_results b/tests/test_conversions.expected_results index f70f10e..b8439d7 100644 --- a/tests/test_conversions.expected_results +++ b/tests/test_conversions.expected_results @@ -1 +1,2 @@ A +66 diff --git a/tests/test_conversions.krak b/tests/test_conversions.krak index 542002a..ab110be 100644 --- a/tests/test_conversions.krak +++ b/tests/test_conversions.krak @@ -4,5 +4,6 @@ import conversions:* fun main():int { println(to_char(65)) + println(to_int('B')) return 0 } diff --git a/tests/test_regex.expected_results b/tests/test_regex.expected_results index 7898192..389e262 100644 --- a/tests/test_regex.expected_results +++ b/tests/test_regex.expected_results @@ -1 +1,2 @@ -a +2 +0 diff --git a/tests/test_regex.krak b/tests/test_regex.krak index f9a831d..85449ae 100644 --- a/tests/test_regex.krak +++ b/tests/test_regex.krak @@ -2,8 +2,8 @@ import io:* import regex:* fun main():int { - var reg = regex("a") - println(reg.regexString) - println(reg.long_match("a")) + var reg = regex("ab") + println(reg.long_match("abab")) + println(reg.long_match("aab")) return 0 } diff --git a/tests/test_regex/test_regex.results b/tests/test_regex/test_regex.results deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_sameName.expected_results b/tests/test_sameName.expected_results index 0719398..f00c965 100644 --- a/tests/test_sameName.expected_results +++ b/tests/test_sameName.expected_results @@ -7,3 +7,4 @@ 7 8 9 +10 diff --git a/tests/test_sameName.krak b/tests/test_sameName.krak index d4e52c9..c79bbe0 100644 --- a/tests/test_sameName.krak +++ b/tests/test_sameName.krak @@ -5,6 +5,8 @@ import sameNameTwo var sameVar: int; fun sameFun(): int { return 4; } +fun classTester(): int { return 10; } + obj classTester { fun method(): int { return 7 @@ -32,5 +34,7 @@ fun main(): int { println(class2.method()) println(class3.method()) + println(classTester()) + return 0 }