Dynamic Types

This extension adds dynamic typing to Bril. Here are some potential use cases:

  • Compiling from dynamic languages (where static types are not available).
  • Prototyping more complex language features that Bril’s simple type system cannot yet capture.
  • An “escape hatch” for situations where Bril’s type system is too conservative.

Types

The dynamic extension adds one new base type:

"any"

Any instruction’s result type may be any. Changing an existing instruction’s type from a different type to any does not change its run-time behavior (with one possible exception, outlined below). It is legal to use an any-typed variable as an argument to any instruction; the type checking must then occur at run time.

Well Formedness

Well-formed Bril programs using the any type must dynamically obey the typing constraints that would otherwise be enforced statically. For example, this program is ill-formed:

v: any = const 4;
b: bool = and v v;  # Attempting to use an int as a bool.

The main function may not have arguments with the any type (because these types control how to parse command-line arguments).

Constants

The any type may appear in const instructions. The type of the resulting value is inferred using the JSON type of the value field. For example, JSON Booleans become values of Bril’s bool type, and integer values use Bril’s int.

This leads to one possibly unexpected behavior. The floating point extension allows constants using any JSON numerical values, including integer literals. For example, both of these are legal and produce values of different types:

i: int = const 4;
f: float = const 4;

However, when using any, an integer literal always becomes a value of type int. So converting the latter instruction to this:

a: any = const 4;

Produces a value of type int, not float. Use a decimal literal in the value field instead, such as 4.0, to produce a float-typed value in an any-typed variable.

(This might be a mistake, and it may be a good idea to disallow any in const instructions in the same way that main parameters must come with a specific type.)

Interactions with the Memory Extension

The memory extension lets you allocate “a uniformly-typed region of values.” Using the ptr<any> type, you can create heterogeneously typed arrays. Here’s an example:

@main {
  v: int = const 2;
  o1: int = const 1;
  bp: ptr<any> = alloc v;
  bp2: ptr<any> = ptradd bp o1;
  b: bool = const true;
  i: int = const 0;
  store bp b;
  store bp2 i;
  b: bool = load bp;
  i: int = load bp2;
  print b i; # prints true 0
  free bp;
}