2.9. Extension Declaration

Figure 2.14. Concrete Syntax for Extension Declaration

[64] <extension> ::= "extension" <ext-id> <ext-impl> "{" <ext-def>* "}"  
[65] <ext-impl> ::= "for" <java-class-name>  
[66] <java-class-name> ::= <basic-id> ("." <basic-id>)*  
[67] <ext-def> ::= <ext-type-def> | <ext-exp-def> | <ext-action-def>  
[68] <ext-type-def> ::= "ptypedef" <prim-ext-type-id> <type-params>? ";" | "typedef" <non-prim-ext-type-id> <type-params>? ";"  
[69] <type-params> ::= "<" <type-var-id> ("," <type-var-id>)* ">"  
[70] <ext-exp-def> ::= "expdef" <ext-ret-type> <ext-exp-id> <type-params>? "(" <ext-params>? ")" ";"  
[71] <ext-ret-type> ::= <basic-type> | <generic-type> | <type-var-id>  
[72] <ext-exp-id> ::= <basic-id>  
[73] <ext-params> ::= <ext-param-type> <param-id>? ("," <ext-param-type> <param-id>?)* ("," <ext-param-type> "...")? | <ext-param-type> "..."  
[74] <ext-param-type> ::= "lazy"? (<basic-type> | <generic-type> | <type-var-id>) | <fun-type>  
[75] <ext-action-def> ::= "actiondef" <ext-action-id> <type-params>? "(" <ext-params>? ")" ";"  
[76] <ext-action-id> ::= <basic-id>  

Figure 2.14, “Concrete Syntax for Extension Declaration” presents the concrete syntax for extension declaration. Extension declaration is used to introduce new first-class constructs. An extension declaration begins with the declaration of the extension identifier, followed by the Java class that implements it and the language extension definitions. There are three kind of language extension definition for BIR: (1) type extension, (2) expression extension, and (3) action extension. Each extension definition's fully qualified name is prefixed with the name extension identifier <ext-id> and dot (".") and it can only referred using its fully qualified name (even when used in declaring other language extension definitions within the same extension). We describe each extension definition in the following subsections.

Namespace. The namespace for extensions is the global namespace that is shared with constants, enumerations, records, type-aliases, global variables, threads and functions, virtual tables, and functional expressions. Each extension has its own namespace for its language extension definitions.

Abstract Syntax Tree. 

Figure 2.15. Java AST for Extension Declaration

Java AST for Extension Declaration
[ .gif, .svg ]

The Java AST class for extension declaration is the ExtensionDefinition class.

2.9.1. Type Extension Declaration

Type extension is used to introduce new data types. Following the categories of BIR basic types, there are two kinds of type extension: (1) primitive type extension using the "ptypedef" keyword, and (2) non-primitive (reference) type extension using the "typedef" keyword. Regardless of the kind, each type can be declared as a generic type by specifying the parameters of the type using type variables.

In general, a type variable can be substituted by any basic type when the extension (generic) type is instantiated. However, there are special prefixes for type variable identifiers to constraint the kind of types that they may match

  • "`integral$", constrains a type variable to only accepts integral types,

  • "`real$", constrains a type variable to only accepts real types,

  • "`numeral$", constrains a type variable to only accepts integral or real types,

  • "`enum$", constrains a type variable to only accepts enumeration types,

  • "`record$", constrains a type variables to only accepts record types,

  • "`array$", constrains a type variables to only accepts array types.

Generic type is used to conveniently reduce redundant extension declarations. For example, one can contribute a set type that works for all BIR types. A non-generic type solution would reguire one to declare the set extensions for every element type instance that is used in a model. Instead, a generic solution allows the possibility of the generic set to be instantiated with any basic type for its element. However, we limit the use of generic types only for extensions because all types in closed systems (i.e., BIR models) should be known. Thus, all other constructs in BIR only need to work with non-generic types or instances of generic types.

Examples. 

  extension MyExtension for mypackage.MyExtensionModule {
    typedef type1; // non-primitive extension type
    typedef type2<'a>; // parametric non-primitive extension type
    typedef type3<'enum$a, 'rec$a>; // parametric non-primitive extension type
    ptypedef type4; // primitive extension type
    ptypedef type5<'numeral$a>; // parametric primitive extension type
    ptypedef type6<'array$a, 'real$a>; // parametric primitive extension type
  }

Abstract Syntax Tree.  The Java AST class for type extension is the TypeExtension class.

2.9.2. Expression Extension Declaration

Expression extension is used to introduce new BIR expressions. Following the spirit of BIR expression, the new expression constructs should be side-effect free, but they are allowed to be non-deterministic. Note that an expression can create a new object because the object creation does not change the state (until the new object is assigned to a variable). An expression extension can also be defined to be polymorphic by specifying type parameters using type variables similar to generic type extension. If the expression extension takes or returns a parametric type, then it has to be declared to be parametric. In addition, expression extension parameters can be defined as lazy parameters. Arguments to lazy parameters are not evaluated, instead the argument expression ASTs are passed. Furthermore, expression extension can take a functional expression as its parameter.

Examples. 

  extension MyExtension for mypackage.MyExtensionModule {
    typedef type<'a>; // parametric non-primitive extension type

    // foo is parameterized by 'a and 'b, takes two parameters 
    // and returns an int
    expdef int foo<'a, 'b>(MyExtension.type<'a>, MyExtension.type<'b>);
    
    // bar takes zero or more int parameters and returns an int
    expdef int bar(int ...);

    // bar takes one or more int parameters and returns an int
    expdef int baz(int, int...);
    
    // bazz takes two lazy expressions of type boolean
    expdef boolean bazz(lazy boolean, lazy boolean);
    
    // bazzz takes: (1) a function that takes an int and 
    // returns boolean and (2) one or more ints
    expdef int bazzz(int -> boolean, int, int ...);
  }

Abstract Syntax Tree.  The Java AST class for exp extension is the ExpExtension class.

2.9.3. Action Extension Declaration

Action extension is similar to expression extension. However, it is allowed to have side-effect, but cannot return values.

Examples. 

  extension MyExtension for mypackage.MyExtensionModule {
    typedef type<'a>; // parametric non-primitive extension type

    // foo is parameterized by 'a and 'b, takes two parameters 
    actiondef foo<'a, 'b>(MyExtension.type<'a>, MyExtension.type<'b>);
    
    // bar takes zero or more int parameters
    actiondef bar(MyExtension.type<int>, int ...);

    // bazz takes two expressions of type boolean
    actiondef bazz(lazy boolean, boolean);
    
    // bazzz takes: (1) a function that takes an int and 
    // (2) one or more ints
    actiondef bazzz(int -> boolean, int, int ...);
  }

Abstract Syntax Tree.  The Java AST class for action extension is the ActionExtension class.