| # The mixin Composition Tool

mixin is a tool to compose .jak files. Another document presents the big picture of how and where mixin is used, the syntax and semantics of .jak files, and how mixin differs from the jampack composition tool. This document discusses detailed use and features of mixin.

- command-line
- interface composition rules
- class composition rules
- state machine composition rules
- local declarations

## Command-Line Invocation

To call mixin from the command line:

>     > mixin

>     Usage: mixin [options] baseFile extensionFile1 extensionFile2 ...
>     Options: -t (ignored)
>              -k (ignored)
>              -a <layerName> name of layer to generate
>              -f <fileName> name file to generate

- options -t and -k are ignored by mixin, and are present only to be compatible with jampack.
- if option -a is selected, you must also supply layerName. This is the name of the composite layer that is produced. By default, the layer name is the same as the root file.
- if option -f is selected, you must also supply fileName. This is the name of the file in which the composite layer is to be stored. If f is not selected, output is sent to standard out.
- files to be composed are listed base-file first. So for the composition A(B(C)), the files are listed C B A on the mixin command line.

## Interface Composition Rules

The rules of interface composition that are specific to mixin are:

- a root interface is transcribed unchanged, although the name of the interface may eventually be mangled.
- refinement interfaces are rewritten as Java interfaces that extend the parent interface. The name of the parent interface will be mangled.
- the bodies of the root interface and refinement interfaces remain intact -- there are no changes.
- each root interface and refinement is prefaced by a SoUrCe declaration that specifies:
  - whether the original specification is a root or refinement,
  - the name of the layer from which the specification originates,
  - and a quoted absolute path to the original layer file.

An example root interface and refinement are:

>     layer IRoot1;

>     import java.io.Serializable;

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

>     layer Iext1;

>     public transient refines interface MyInt extends yyyInterface {
>        int Terse = 2;
>        void foo() throws SomeException;
>        int increment( int i );
>     }

The mixin composition of the IRoot1 and Iext1 files above is shown below, where the yellow-highlighted text is generated by mixin:

>     layer IRoot1;

>     import java.io.Serializable;

>     SoUrCe Base IRoot1 "../Iroot1.jak";

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

>     SoUrCe  Iext1 "../Iext1.jak";

>     public transient interface MyInt extends yyyInterface, MyInt$$IRoot1 {
>        int Terse = 2;
>        void foo() throws SomeException;
>        int increment( int i );
>     }

Note that mixin simply makes explicit the inheritance hierarchy that the composition of these two files represents. That is, the MyInt interface of layer Iext1 extends the MyInt interface of layer IRoot1. You'll note that the name of the MyInt interface of IRoot1 has changed to MyInt$$IRoot1 -- because in Java, interface names must be unique. The bottom-most interface of the refinement chain is MyInt (the name that we wanted). The mangling of a "name" is always "name$$name-of-layer". Note the bottom-most interface is public, whereas the other interfaces are abstract.

#### Exercise

Create separate files IRoot1.jak and Iext1.jak to hold the above definitions. Compose them into C.jak by the command:

>     > mixin IRoot1.jak Iext1.jak > C.jak

Caveat. Note: the file naming convention used in this example isn't typical. Usually IRoot1.jak would be a file in the IRoot1 layer (i.e., it would have the pathname IRoot1/MyInt.jak) and Iext1.jak would be a file in the Iext1 layer (i.e., it would have the pathname Iext1/MyInt.jak). So a more typical invocation would be:

>     > mixin IRoot1/MyInt.jak IIext1/MyInt.jak > C.jak

## Class Composition Rules

mixin composes classes much the same way as it does interfaces. (See the rules for interfaces). A single file is produced that contains an inheritance hierarchy of classes. The last class that is listed is the public class, all other classes are abstract whose names have been mangled.

Consider the following root class and a refinement:

>     layer Ctop;

>     import jakarta.util.*;

>     class top {
>        static int i,j;

>        top() {  ii = 5; }

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

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

>     layer Cmid;

>     import AnotherPackage;

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

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

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

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

Their mixin composition is shown below. The yellow-highlighted text is generated by mixin.

>     layer Ctop;

>     import jakarta.util.*;
>     import AnotherPackage;

>     SoUrCe RooT Ctop "../Ctop.jak";

>     abstract class top$$Ctop {
>        static int i,j;

>        top$$Ctop() { ii = 5; }

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

>     SoUrCe Cmid "../Cmid.jak";

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

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

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

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

#### Exercise

Create separate files top.jak and mid.jak to hold the definitions above. Compose them into combined.jak by the command:

>     > mixin top.jak mid.jak > combined.jak

Don't forget the caveat.

## State Machine Composition Rules

mixin composes state machine definitions much the same way as it does interfaces. (See the rules for interfaces). A single file is produced that contains an inheritance hierarchy of state machines. The last class that is listed is the public state machine, all others are abstract whose names have been mangled. Here is an example root state machine and a refinement:

>     layer rootSm;

>     State_machine root {

>        Delivery_parameters( M m );
>        Unrecognizable_state { ignore(m); }

>        States g, h, i;

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

>     layer extSm;

>     refines State_machine root {

>        States j, k;

>        Transition e3 : g -> j
>        condition m!=null
>        do { Super(int).anotherAction(6); }
>     }

The mixin composition of the above files is shown below. The lines in yellow were generated by mixin:

>     layer rootSm;

>     SoUrCe RooT rootSm "../RootSm.jak";

>     abstract State_machine root$$rootSm {

>        Delivery_parameters( M m );
>        Unrecognizable_state { ignore(m); }

>        States g, h, i;

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

>     SoUrCe extSm "../ExtSm.jak";

>     State_machine root extends root$$rootSm {

>        States j, k;

>        Transition e3 : g -> j
>        condition m!=null
>        do { Super(int).anotherAction(6); }
>     }

#### Exercise

Create separate files root.jak and mid.jak to hold the above definitions. Compose them into result.jak by the command:

>     > mixin root.jak mid.jak > result.jak

Don't forget the caveat.

## Local Declarations

Local_Id declarations are used to avoid inadvertent capture. Consider the following root specification with local identifiers i, j, ii, jj, and foo.

>     layer Ctopp;

>     Local_Id i, jj, foo;

>     class topp {
>        static int i;
>        int jj;

>        void foo(float x, float y) { i = jj = x+y; }
>     }

Now consider an refinement that uses exactly the same identifiers locally:

>     layer Cmidd;

>     Local_Id i, jj, foo;

>     refines class topp {
>        static int i;
>        int jj;

>        void foo(float x, float y) { i = jj = x*y; }
>     }

mixin composes these two specifications to yield:

>     layer Foo;

>     SoUrCe RooT Ctopp "../Ctopp.jak";

>     abstract class topp$$Ctopp {
>        static int i$$Ctopp;
>        int jj$$Ctopp;

>        void foo$$Ctopp(float x, float y) { i$$Ctopp = jj$$Ctopp = x+y; }
>     }

>     SoUrCe Cmidd "../Cmidd.jak";

>     class topp extends topp$$Ctopp {
>        static int i$$Cmidd;
>        int jj$$Cmidd;

>        void foo$$Cmidd(float x, float y) { i$$Cmidd = jj$$Cmidd = x*y; }
>     }

#### Exercise

Create separate files topp.jak and extp.jak to hold the definitions above. Compose them into result.jak by the command:

>     > mixin -a Foo topp.jak extp.jak > result.jak

ATS Home Page

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