-
Notifications
You must be signed in to change notification settings - Fork 57
JS Metamodel quirks
Since most of the metamodel stuff is native in both backends, and the JS one is particularly messy, here's some insight for anyone who dares touch that crap.
Type information for type arguments and such, is stored as simple JSON objects, referring to the type function (every type is a function in JS, i.e. Iterable
, Object
, List
, etc). This allows for type arguments to be included. The names for the type parameters include the type owner, so that type arguments for different types can coexist within the same type.
{t:List, a:{List$Element:{t:Integer}}}
Type arguments for function are very similar; they are passed as the last argument to the function:
{Type$type:{t:List,a:{List$Element:{t:Integer}}}}
For a given type Foo
:
Key | Description |
---|---|
Foo.$$ |
constructor function |
Foo.$$.T$name |
type name, such as com.pkg::Foo
|
Foo.$$.T$all |
a map for supertype by name |
Foo.$$.T$all[typeName] |
Foo (this type) |
Foo.$crtmm$ |
The runtime metamodel function (see below) |
The constructor proto is enhanced with two functions (that can then be called on every instance):
Key | Description |
---|---|
Foo.$$.prototype.getT$name |
the type name |
Foo.$$.prototype.getT$all |
the supertypes |
Watch out, there are two sorts of metamodel in JS: the compile-time metamodel which likes in name-version-model.js
files, and the runtime metamodel which is included in the main name-version.js
file.
Every function has a property called $crtmm$
which contains its runtime metamodel information. It's a function which returns an object with all the data for the function or type; the function need only be called once. There's a helper function called getrtmm$$
which replaces the function with its returned object and stored it under the same property:
var mm=getrtmm$$($_String);
(certain type names such as Object and String have a $_
prepended to them because they're reserved in JS).
The metamodel object keys can vary depending on what they're describing, but all have these keys in common:
Key | Description |
---|---|
mod | A reference to the compile-time model. |
d | The path to the model inside the compile-time model, as a list of keys. |
tp | (optional) for generic stuff, this key contains the type parameter information. |
an | The annotations that have arguments or cannot be packed into a bitmap for whatever reason. |
pa | The packed annotations. |
$cont | (optional) A reference to the containing type or function. |
Mask | Description |
---|---|
1 | shared |
2 | actual |
4 | formal |
8 | default |
16 | sealed |
32 | final |
64 | native |
128 | late |
256 | abstract |
512 | annotation |
1024 | variable |
2048 | serializable |
Type metamodel objects have these keys in addition to the common ones:
Key | Description |
---|---|
sts | The list of satisfied types. |
of | The list of algebraic types (references to their definitions), or the name of the self-type. |
super | The type's supertype. |
ps | For constructors or classes with initializers, the parameter list. |
Function metamodel objects have these keys:
Key | Description |
---|---|
$t | The outermost return type. For functions with MPL this is the "full type": a Callable which is the return type of the outermost function. |
$rt | The innermost return type. For functions with MPL this is the return type of the innermost function. |
ps | The parameter list. For functions with MPL this is the parameter list of the outermost function. |
Value metamodel objects have these keys:
Key | Description |
---|---|
$t | The value type. |
name | The value name. |
The pa
key contains a numeric value indicating the presence of certain annotations. Starting from least significant, the packed annotations are: shared
, actual
, formal
, default
, sealed
, final
, native
, late
, abstract
, annotation
, variable
and serializable
. So if the value of pa
is 5, it means shared
and formal
.
Toplevel attributes are implemented as functions, so they contain a metamodel just like any other model object. However, member attributes are implemented using JS properties, so there is a separate property in the attribute's container, prefixed $prop$get
. For example for the string
property of a type, the metamodel is under $prop$getString
.
Stuffed in .meta
fields.
Public members are found by name as properties. Unshared members are found in the '$pkgunsh$'+this.name.$_replace('.','$')
object member by name as properties.