On splicing in bocca
Bocca understands babel splicer blocks and leverages those conventions as much as possible to manage bocca-generated code inside those blocks while never stepping on user-written code. This note is primarily for the users to understand the lengths we go to to preserve their code and for the developers to gain a common understanding of how splicing is handled in the bocca implementation. Background
To generalize the above delimiters, they consist of a tag in parentheses and a leading key string that is always followed by .begin(tag) or .end(tag). The key string examples here would be "DO-NOT-DELETE splicer", "bocca.protected", and "DO-NOT-DELETE bocca.splicer". Delimited block tags are always well-nested; ill-nested blocks cause splicers to generate errors and cancel any overwrites that would occur in a successful splicing. Summary: KEY.begin(TAG)/KEY.end(TAG) is the delimiter pair. Handling SIDL
Handling Impl files Bocca must handle a component's impl files when a component is created and any time the bocca-information is changed, such as when a new CCA port is added to update the bocca-generated methods. Most of the Babel splicer blocks in a Component implementation file are application-related methods that only the component writer knows how to implement. Bocca does not touch these methods at all. Bocca can (and normally does) generate default implementations for methods of the CCA interfaces gov.cca.Component, gov.cca.ComponentRelease, gov.cca.ports.GoPort (at the user's request) and portions of the component's private data. Bocca does not claim ownership of any method normally required by babel or cca specifications; bocca merely provides suggested implementations that the user may edit or discard. Invoking the splicer to keep users happy The bocca splicer is almost always be invoked with identical keys for source and target if replacement is intended and distinct keys if insertion is intended. In normal operations (generate a component, update a component for new ports) only the identical keys case is needed. For initial definition of a method or methods, both keys are "DO-NOT-DELETE splicer"; for subsequent rewrite of the bocca-owned sections only, both keys are "bocca.protected". When the tags match, the source block will be inserted (or appended if insertFirst=True is not passed). To handle multiple bocca.protected in a single Babel splicer block, simply splice to the same target. To handle multiple bocca tags inside a single bocca block, note that this requires no reference to a babel splicer key at all. Simply use extended bocca protected keys. In an example suited to setServices targetKey="DO-NOT-DELETE bocca.protected", sourceKey="DO-NOT-DELETE bocca.protected.port" In any operation in which any user code might be replaced, rejectSave=True should be passed and the .rej file generated should be put in the appropriate Trash directory and a warning issued about where old code can be found. There are no such operations currently. Algorithms We distinguish for clarity (not because they are unique) several cases and explain what happens with splicing in each:
The sidl is generated. From sidl the impl is generated with babel. The bocca generates and inserts the setServices method default block and protected auxiliary function splices. The generated auxiliaries contain bocca.protected keyed splices which the user should never edit. The user can insert code in the cca standard-specified functions and their code will never be molested (1). If the user removes calls to the cca auxilary methods, they must provide alternative equivalent functionality.
The sidl file is regenerated, leaving user additions to the component inside the bocca.splicer block unchanged. The bocca.protected blocks for the component are regenerated and replaced, given the new information. If the user has manually deleted one of the bocca.protected blocks, it will not be reinserted unless the user inserts at least the needed delimiters. If the user simply deletes the bocca.protected delimiters around a bocca code block, this has the effect of freezing that code in spite of any future changes bocca normally manages; the generated code has been promoted to user code.
The user's sidl description of the component is copied into the bocca project. The original sidl file (outside the bocca project) is never again referenced. If there is also an impl file or files, they are: used as the source for a second splicing after the initial bocca impl generation. The default bocca code for setServices and go() is inserted unless suppressed by using --import-impl-exact --exclude-impl-symbols=None. Special cases of code changes outside bocca.protected splicers:
All the CCA-related calls in the impl file which use the old port instance name as a literal string (e.g. "myport") will be replaced with string literals of the new port instance name. This is independent of where the literals are located. Both user code and bocca-generated code will be updated with the new port name, but only in the CCA functions handling port instance names. If the port instance name is somehow computed instead of specified as a literal, manual repairs may be needed when a port instance name is changed.
A babel default "not implemented exception" throw is always deleted when the bocca splicer inserts code to an unimplemented setServices or other bocca-managed function. Default exceptions are left in place by bocca in all other functions. Splicing for power users
Created by: baallan last modification: Friday 21 of September, 2007 [06:44:59 UTC] by baallan |
Login Online users
19
online users
|