diff --git a/src/minlam_uncurry.c b/src/minlam_uncurry.c index e857744..f4f3bbb 100644 --- a/src/minlam_uncurry.c +++ b/src/minlam_uncurry.c @@ -266,28 +266,6 @@ static MinExp *makeSaturatedApplication(HashSymbol *name, MinExprList *args) { return result; } -// TODO consider generating this -static MinExprList *takeMinExprList(MinExprList *list, int count) { - if (count <= 0) - return NULL; - if (list == NULL) - return NULL; - MinExprList *rest = takeMinExprList(list->next, count - 1); - int save = PROTECT(rest); - MinExprList *this = newMinExprList(CPI(list), list->exp, rest); - UNPROTECT(save); - return this; -} - -// TODO consider generating this -static MinExprList *dropMinExprList(MinExprList *list, int count) { - if (count <= 0) - return list; - if (list == NULL) - return NULL; - return dropMinExprList(list->next, count - 1); -} - // fn process_apply(head, args) { // switch (head) { // (M.var(s)) { diff --git a/tools/generate.py b/tools/generate.py index 52f9357..c9bb8d3 100755 --- a/tools/generate.py +++ b/tools/generate.py @@ -259,8 +259,10 @@ def generate_header(args, catalog, document, packageName, includes, limited_incl catalog.printHelperNewDeclarations() printSection("access declarations") catalog.printAccessDeclarations() - printSection("count declarations") + printSection("list helper declarations") catalog.printCountDeclarations() + catalog.printTakeDeclarations() + catalog.printDropDeclarations() printSection("name declarations") catalog.printNameFunctionDeclarations() printSection("discriminated union getter declarations") @@ -331,8 +333,10 @@ def generate_implementation(args, catalog, document, packageName): catalog.printGetFunctions() catalog.printSetFunctions() catalog.printIteratorFunctions() - printSection("count functions") + printSection("list helper functions") catalog.printCountFunctions() + catalog.printTakeFunctions() + catalog.printDropFunctions() printSection("mark functions") catalog.printMarkFunctions() printSection("generic mark function") diff --git a/tools/generate/base.py b/tools/generate/base.py index 4591e28..9350343 100644 --- a/tools/generate/base.py +++ b/tools/generate/base.py @@ -324,6 +324,18 @@ def printExtendFunction(self, catalog): def printCountFunction(self, catalog): pass + def printTakeDeclaration(self, catalog): + pass + + def printTakeFunction(self, catalog): + pass + + def printDropDeclaration(self, catalog): + pass + + def printDropFunction(self, catalog): + pass + def isEnum(self): return False diff --git a/tools/generate/catalog.py b/tools/generate/catalog.py index 61ef092..cdde88f 100644 --- a/tools/generate/catalog.py +++ b/tools/generate/catalog.py @@ -168,6 +168,18 @@ def printCountDeclarations(self): def printCountFunctions(self): self._dispatch('printCountFunction', self) + def printTakeDeclarations(self): + self._dispatch('printTakeDeclaration', self) + + def printTakeFunctions(self): + self._dispatch('printTakeFunction', self) + + def printDropDeclarations(self): + self._dispatch('printDropDeclaration', self) + + def printDropFunctions(self): + self._dispatch('printDropFunction', self) + def printAccessDeclarations(self): self._dispatch('printAccessDeclarations', self) diff --git a/tools/generate/simple_struct.py b/tools/generate/simple_struct.py index efb6265..7945016 100644 --- a/tools/generate/simple_struct.py +++ b/tools/generate/simple_struct.py @@ -103,6 +103,86 @@ def printCountFunction(self, catalog): print(f'}} {c}') print('') + def getTakeSignature(self, catalog): + myType = self.getTypeDeclaration(catalog) + myName = self.getName() + return f'{myType} take{myName}({myType} list, Integer count)' + + def getDropSignature(self, catalog): + myType = self.getTypeDeclaration(catalog) + myName = self.getName() + return f'{myType} drop{myName}({myType} list, Integer count)' + + def printTakeDeclaration(self, catalog): + if self.isSinglySelfReferential(catalog): + c = self.comment('printTakeDeclaration') + print(f'{self.getTakeSignature(catalog)}; {c}') + + def printDropDeclaration(self, catalog): + if self.isSinglySelfReferential(catalog): + c = self.comment('printDropDeclaration') + print(f'{self.getDropSignature(catalog)}; {c}') + + def _getConstructorActualsForCopy(self, catalog, sourceVar, restVar): + args = [] + if catalog.getParserInfo(self.name): + args.append(f'CPI({sourceVar})') + selfRefField = self.getSelfReferentialField(catalog) + for field in self.getNewArgs(catalog): + fieldName = field.getFieldName() + if fieldName == selfRefField: + args.append(restVar) + else: + args.append(f'{sourceVar}->{fieldName}') + return ', '.join(args) + + def _printImplicitFieldCopies(self, catalog, sourceVar, targetVar, tailVar): + c = self.comment('_printImplicitFieldCopies') + selfRefField = self.getSelfReferentialField(catalog) + for field in self.getDefaultArgs(catalog): + fieldName = field.getFieldName() + value = tailVar if fieldName == selfRefField else f'{sourceVar}->{fieldName}' + print(f' {targetVar}->{fieldName} = {value}; {c}') + + def printTakeFunction(self, catalog): + if not self.isSinglySelfReferential(catalog): + return + c = self.comment('printTakeFunction') + decl = self.getTakeSignature(catalog) + selfRefField = self.getSelfReferentialField(catalog) + print('/**') + print(f' * Creates a shallow copy of the first `count` nodes in the {self.getName()} list.') + print(' */') + print(f'{decl} {{ {c}') + print(f' if (count <= 0) return NULL; {c}') + print(f' if (list == NULL) return NULL; {c}') + myType = self.getTypeDeclaration(catalog) + print(f' {myType} rest = take{self.getName()}(list->{selfRefField}, count - 1); {c}') + print(f' int save = PROTECT(rest); {c}') + ctorArgs = self._getConstructorActualsForCopy(catalog, 'list', 'rest') + print(f' {myType} result = new{self.getName()}({ctorArgs}); {c}') + self._printImplicitFieldCopies(catalog, 'list', 'result', 'rest') + print(f' UNPROTECT(save); {c}') + print(f' return result; {c}') + print(f'}} {c}') + print('') + + def printDropFunction(self, catalog): + if not self.isSinglySelfReferential(catalog): + return + c = self.comment('printDropFunction') + decl = self.getDropSignature(catalog) + selfRefField = self.getSelfReferentialField(catalog) + print('/**') + print(f' * Skips the first `count` nodes in the {self.getName()} list.') + print(' */') + print(f'{decl} {{ {c}') + print(f' if (count <= 0) return list; {c}') + print(f' if (list == NULL) return NULL; {c}') + print(f' return drop{self.getName()}(list->{selfRefField}, count - 1); {c}') + print(f'}} {c}') + print('') + def getMarkSignature(self, catalog): myType = self.getTypeDeclaration(catalog) return SignatureHelper.mark_signature(self.getName(), myType)