Created
March 8, 2020 06:18
-
-
Save eleses/3e34af40443a7faab5d8f08a3d251ff3 to your computer and use it in GitHub Desktop.
Fixing the user-supplied cleanup function behavior in Pproto (working draft; there's an inherited "double cleanup.exit" bug unresolved)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PprotoU : Pattern { | |
var <>makeFunction, <>pattern, <>userCleanupFunc; // distinguish from the combo one we'll generate | |
*new { | makeFunction, pattern, cleanupFunc| | |
^super.newCopyArgs( makeFunction, pattern, cleanupFunc) | |
} | |
storeArgs { ^[makeFunction,pattern,userCleanupFunc] } | |
embedInStream { | event | | |
var stream, ev, evType; | |
var cleanup, cleanupList, eventCleanupFunc, comboCleanupFunc; | |
var proto; // temporary proto event used in allocation | |
var makeRoutine; // routine wrapper for function that makes protoEvent | |
var protoEvent; // protoEvent created by function | |
// Step 1: generate resources from function | |
proto = ( | |
delta: 0, // events occur simultaneously | |
finish: { ev = currentEnvironment} // get copy of event object actually played | |
); | |
protoEvent = (); | |
makeRoutine = Routine({ protoEvent.make (makeFunction) }); | |
while { | |
(ev = makeRoutine.next(ev)).notNil; | |
} { | |
event = ev.proto_(proto).yield; | |
ev.proto = nil; | |
cleanupList = cleanupList.add(ev) | |
}; | |
// Step 2: generate the default cleanup | |
cleanup = EventStreamCleanup.new; | |
eventCleanupFunc = { | flag | // generated purely from init event data | |
cleanupList.do { | ev | | |
EventTypesWithCleanup.cleanup(ev, flag) | |
} | |
}; | |
// Step 3: combine with user cleanup by passing the default cleanup produced above to userCleanupFunc. I.e. | |
// if there's a user-cleanup set, we pass the auto-gen'd eventCleanupFunc to the user cleanup function | |
// so they can call the default cleanup when they see fit in their cleanup logic. | |
// Addtionally, we pass userCleanupFunc the actual cleanupList, which gives the user even more control, e.g. | |
// they could reorder or filter the augo-gen'd cleanups. | |
// The userCleanupFunc is actually a functOR, i.e. we expect it to return a function that does the a cleanup | |
// when its return value is itself even'd (with .value) later on. | |
if (userCleanupFunc.isNil) { // could be written more cleverly | |
comboCleanupFunc = eventCleanupFunc; // but this makes the logic very explicit | |
} { // not sure if passing protoEvent and proto adds any useful info, but can't hurt... | |
comboCleanupFunc = userCleanupFunc.value(eventCleanupFunc, cleanupList, protoEvent, proto); | |
}; | |
cleanup.addFunction(event, comboCleanupFunc); | |
stream = Pfpar(pattern.asArray).asStream; | |
loop { | |
ev = event.copy.putAll(protoEvent); | |
ev = stream.next(ev) ?? { ^cleanup.exit(event) }; | |
event = ev.yield; | |
}; | |
^event | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment