Alternative Naming and Projections/Injections

Projections and injections allow defining cross-cutting functionality using alternative naming.

In the previous posts, a general term "transformations" was used. So far transformations look actually consisting of: projections/injections, productions and generations. All kinds of transformations have selectors to specify for what code elements they are applied.

Paml syntax for transformations is just to specify formal semantics of the transformation terms. Actual working with Paml source code requires powerful support from development tooling like IDE. Paml source code is not a plain colored text, but a hybrid text and projection source code editor. Transformations are a feature of meta-programming that allows manipulating code elements to produce output code instead of writing it manually.

Projections and injections are similar to the terms of aspects and advices from AOP respectively. A projection is a point of view to a modeling system from some cross-cutting concern. An injection is a piece of code that is injected into injection points.

In the previous posts "join point" term was used, but now "injection point" is used instead to have consistent terminology with "injection" term. Also, projections and injections terms are used to avoid confusing with AOP aspects/advices ones.

In modern object-oriented (and seems not only object-oriented) programming languages, such code elements as methods usually have a single name. Names are chosen according semantics from the modeling domain, and this looks like primary names. The idea is that a method should have explicit alternative names, one alternative name for each cross-cutting concern. This allows to look to the method from different points of views, that’s projections, each of which represents some cross-cutting concern.

In Paml, alternative naming and projections are a language feature. Routines and messages can have tags, which are alternative names for them. A projection defines some cross-cutting concern, and its injections via selectors are assigned (weaved in AOP terminology) to target routines/messages according alternative names and the semantics of the projection.

Projections can have collaborators and state. Injections are a kind of routines. As result, projections and injections are targets for other possible projections (projections higher level), so the process of projecting is theoretically (but seems not practically) iterative.

A projection has an instantiating policy, which specifies how the projection is instantiated and disposed. Actual implementations of instantiating policies are defined in productions.

For now, there are 5 kinds of injection points: 4 for routines (before block, before body, after body, and after block) and one for variables (variable initialization).

It seems that "message call" injection point will be required?

Routine is a block with a body inside it, so before block and before body injection points are different places.

Variable initialization is a generalization of the following elements: constructor call, assign a value and converting variable semantic. So, the variable initialization injection point is applied to variable, collaborator and data declarations, as well as for arguments (not for parameters).

abstraction
{
message Persist ( val data : array );
}
object
{
collaborator : Alonzo.Banking.Storage;
data : string;
or
data = AZ1234567890; String literal is specified by the style, but not by quotes. Moreover, the quotes are result of the string literal style, so no restrictions/escaping to characters in string literals.
message ( val amount : decimal )
{
Kind Routine
Id
Name
Tags
this.Storage->Persist ( : this ); "data" is an argument, and it's an injection point for varInit injection.
}
}
projection Name Instantiating policy
{
This is variable initialization injection.
varInit Name Data: Name is Alonzo.Banking.Account.Number -> string
{
Kind Routine
Id
Name
Tags
return XYZ0123456789;
}
Selectors are actually a language to describe source code elements.
varInit Name MessageArgument: Id is MA-001 ( obj account : Alonzo.Banking.Account ) -> array
{
Kind Routine
Id
Name
Tags
val : array;
TODO:
return array;
}
varInit Name Collaborator: Name is Alonzo.Banking.Account.Storage -> Alonzo.Banking.Storage
{
Kind Routine
Id RN-001
Name
Tags
obj : Alonzo.Banking.Storage;
TODO:
return storage;
}
}
projection Name Instantiating policy
{
beforeBody Message: Name is Alonzo.Banking.Account.Withdraw ( obj account: Alonzo.Banking.Account, val amount: decimal )
{
Kind Routine
Id
Name
Tags
TODO:
}
}

Write a comment

Comments: 0

Pallada project, Copyright © 2015 - 2021.

For any mentions and citations of the site materials, a link to the Pallada project site is obligatory.