Skip to content

genc transformations

Simon Krajewski edited this page Feb 18, 2014 · 3 revisions

Class Initialization

Basic

  1. Turn Method MethDynamic to Var and add default implementation as static field. Also add assignment to the constructor (for instance dynamic functions) or to cl_init (for static ones).
  2. Turn instance methods to static methods, add this argument to function and replace TConst (TThis | TSuper) accordingly. (expr mapping)
  3. Detect all TFun variable fields and change their type to c.Closure<FieldType>.
  4. Infer type of all non-nullable optional basic type (Int, Float, Bool) to Null<T>.

VTable

  1. Determine VTable information and store them in static VTable field.
  2. Add instance VTable field to class.

Constructor

Split constructor in three parts:

  1. A hx_alloc method allocating memory, assigning the instance VTable field and returning a pointer to it (called by Type.createEmptyInstance).
  2. A hx_initInstance method containing the original user code (called through super() from a child class).
  3. The normal new method calling hx_alloc, hx_initInstance and returning a pointer to this.

Expression pass 1

Node reduction

  1. Replace TFor with TWhile.
  2. Replace TTry with switch over setjmp.
  3. Replace TThrow with call to longjmp.
  4. Replace TArrayDecl with initialization call.
  5. Replace TSwitch over string with something that compiles.

After running this reduction, we should not add any of the replaced nodes.

Default value handling

  1. Determine functions for which we can generate _known variants: These are functions with optional arguments where each optional argument has a default value.
  2. Handle default values in original function with if (arg == null) arg = defaultValue, then make it call the _known variant.

Expression pass 2

Known calls

Find calls to fields that had a _known variant found in previous pass. If we can be sure that all arguments are either == null or != null, make a call to the _known variant instead, replacing definite null values with the default values at call-site.

String handling

  1. Wrap any string literal (but guard against recursion).
  2. Replace string == string and string != string with a call to String.equals.
  3. Replace string + string and string += string with a call to `String.concat.

Array handling

TODO

Var declarations

Find all variables that are not declared at the beginning of a block, move declaration to beginning of block and replace with assignment if exists.

This should probably be the last filter to run.

Type checking

  1. Detect assignment of basic types to Null<T> and (un)wrap accordingly.
  2. Detect assignment of non-dynamic types to Dynamic and (un)wrap accordingly.
  3. Detect assignment of wrapped string literal to const char* or vararg and remove wrapping.
  4. Detect assignment of wrapped string to const char* and vararg and unwrap.
  5. Detect assignment of smaller structure to larger one (optional fields) and pad with null.

Closure handling

  1. Detect local TFunction and TField(_,FClosure) nodes, add closure field and replace with call to constructor of wrap-object.
  2. Detect non-call TField(_,FStatic) nodes and replace with call to constructor of wrap-object.