| # The unmixin Decomposition Tool

unmixin is a tool that decomposes a mixin-produced .jak file(s) and propagates changes made to this file back to the constituent layer files. To invoke unmixin via a command line:

>     > unmixin <names of one or more files>

Without unmixin, changes must be propagated manually, which is tedious and error prone. While unmixin can't propagate every change, it certainly can do a lot and save considerable time.

unmixin has a few simple rules of operation:

- the file that whose changes it will back-propagate must be produced by mixin. Inside this file are SoUrCe declarations. A SoUrCe declaration prefaces each interface, class, or state machine definition that was instantiated by mixin; the SoUrCe declaration identifies the layer file from which this definition was derived.
- changes that are back-propagated are:
  - the body of that definition, i.e., the contents within { ... },
  - the parents of that definition (e.g., the declarations of the extends clause).
- changes that are not propagated are:
  - modifiers added to interface, class, or state machine definitions,
  - comments that preface the interface, class or state machine definitions,
  - changes to local identifiers (whose names are mangled).

When using unmixin, remember the following:

- do not change the contents of SoUrCe lines!
- remember to always refer to variables that have locally mangled names with these names. During back-propagation, unmixin unmangles these names.

unmixin will propagate changes to a .jak file only if changes have been made. Thus, if you produce file f by mixin composition, but do not change its contents, "unmixin f" will examine f and the files that it references, but will not update these files.

Illustrations of unmixin are in the following sections:

- updating interface declarations
- updating class declarations
- updating state machine declarations
- limitations, future versions and known problems

## Updating Interface Declarations

Consider the following interface (top.jak) and refinement (mid.jak):

>     layer first;

>     interface MyInt extends FooInterface {
>         int Silent = 0;
>         void foo() throws AFit;
>         SomeType bar( int x );
>     }

>     layer second;

>     public transient refines interface MyInt extends yyy, java.io.Serializable {
>        int Terse = 2;
>        void foo() throws SomeException;
>        int increment( int i );
>     }

Shown below is the mixin composition of these files, along with hand-made changes highlighted in yellow:

>     layer first;

>     SoUrCe RooT first "top.jak";

>     abstract interface MyInt$$first extends FooInterface {
>         int Silent = 0;
>         void foo() throws AFit, moreFits;
>         SomeType bar( int x );
>     }

>     SoUrCe  second "mid.jak";

>     public transient  interface MyInt extends yyy, java.io.Serializable, MyInt$$first {
>        int Terse = 3;
>        void foo() throws SomeException;
>        int increment( int i );
>     }

To back-propagate these changes, execute

>     > unmixin Result.jak

unmixin takes a single file as its argument and has no optional parameters.

#### Exercise

Try the example above.

## Updating Class Declarations

Consider the following class declaration (top.jak) and refinement (mid.jak):

>     layer first;

>     class top {
>        int jj;

>        top(int rj) { jj = rj; }

>        void foo(float x, float y) { /* do something */ }
>     }

>     layer second;

>     refines class top implements java.io.Serializable, xxx {
>        static int k;

>        top(float x) { /* do something */ }

>        float foobar() { Super(float,float).foo(0, 0); }

>        public void foo( float x, float y ) { /* something more */ }
>     }

The result of their composition using mixin is shown below, along with hand-made changes indicated in yellow.

>     layer first;

>     SoUrCe RooT first "top.jak";

>     abstract class top$$first {
>        int jj;

>        top$$first(int rj) { jj = rj; }

>        void foo(float x, float y) { /* do something */ }

>        void biff() { /* a new method */ }
>     }

>     SoUrCe  second "mid.jak";

>     class top extends top$$first implements java.io.Serializable, xxx, yyy {
>        static int k;

>        public int global = 0; // a new variable

>        top(float x) { /* do something */ }

>        float foobar() { Super(float,float).foo(0, 0); }

>        public void foo( float x, float y ) { /* something more */ /* extra */ }
>     }

Let the resulting file above be Result.jak. To back-propagate these changes, execute

>     > unmixin Result.jak

#### Exercise

Try the example above.

## Updating State Machine Declarations

Consider the following state machine declaration (top.jak) and refinement (mid.jak):

>     layer first;

>     state_machine root {

>        event_delivery mymessage( M m );
>        no_transition { ignore(m); }

>        states g, h, i;

>        edge e1 : g -> h conditions m!=null do { gh(); }

>        edge e2 : h -> i conditions true do { /*nothing*/ }

>        void gh() { /* gh action */ }
>     }

>     layer second;

>     refines state_machine root {

>        states j, k;

>        edge e3 : g -> j conditions m!=null do { anotherAction(5); }

>        edge e66 : j -> k conditions true do { gh(); }

>        void anotherAction(int f) { /* do something */ }
>     }

The result of their composition using mixin is shown below, along with hand-made changes indicated in yellow:

>     layer first;

>     SoUrCe RooT first "top.jak";

>     abstract state_machine root$$first {

>        event_delivery mymessage( M m );
>        no_transition { ignore(m); }

>        states g, h, i;

>        edge e1 : g -> h conditions m!=null do { gh(); }

>        edge e2 : h -> i conditions true do { /*nothing*/ }

>        edge newedge : g -> h conditions true do { gh(); }  // new edge

>        void gh() { /* gh action */ }
>     }

>     SoUrCe  second "mid.jak";

>     state_machine root extends root$$first {

>        states j, k, g;

>        edge e3 : g -> j conditions m!=null do { anotherAction(5); }

>        edge e66 : j -> k conditions true do { gh(); }

>        void anotherAction(int f) { /* do something */ }

>        public static void main( String args[] ) { /* main */ }
>     }

Let the resulting file above be Result.jak. To back-propagate these changes, execute

>     > unmixin Result.jak

#### Exercise

Try the example above.

## Limitations, Future Versions and Known Problems

- when unmixin processes a file that was not produced by mixin, no error results. Actually nothing happens, but at least a warning should be issued.

ATS Home Page

Copyright © Software Systems Generator Research Group. All rights reserved.
Revised: January 25, 2006.