Decorators work more like actual compiler annotations in AssemblyScript.
Annotation | Description |
@inline | Requests inlining of a constant or function. |
@lazy | Requests lazy compilation of a variable. Useful to avoid unnecessary globals. |
@global | Registers an element to be part of the global scope. |
@external | Changes the external name of an imported element. |
@operator, @operator.binary | Annotates a method as a binary operator overload. See below. |
@operator.prefix | Annotates a method as a unary prefix operator overload. See below. |
@operator.postfix | Annotates a method as a unary postfix operator overload. See below. |
Custom decorators can be given meaning by using a transform.
Operator overloads can only be used on class methods. The respective argument types must match the class type.
@operator(OP)static __op(left: T, right :T): T { ... }​@operator(OP)__op(right: T): T { ... }
OP | Description |
| Checked indexed get |
| Checked indexed set |
| Unchecked indexed get |
| Unchecked indexed set |
| Equality |
| Inequality |
| Greater than |
| Greater than or equal |
| Less than |
| Less than or equal |
| Arithmetic right shift |
| Logical right shift |
| Left shift |
| Bitwise AND |
| Bitwise OR |
| Bitwise XOR |
| Addition |
| Subtraction |
| Multiplication |
| Division |
| Exponentiation |
| Remainder |
The ===
operation cannot be overloaded (is identity equality).
@operator.prefix(OP)static __op(self: T): T { ... }​@operator.prefix(OP)__op(): T { ... }
OP | Description | Notes |
| Logical NOT | ​ |
| Bitwise NOT | ​ |
| Unary plus | ​ |
| Unary negation | ​ |
| Prefix increment | Instance overload reassigns |
| Prefix decrement | Instance overload reassigns |
Note that increment and decrement overloads can have slightly different semantics. If the overload is declared as an instance method, on ++a
the compiler does emit code that reassigns the resulting value to a
while if the overload is declared static, the overload behaves like any other overload, skipping the otherwise implicit assignment.
@operator.postfix(OP)static __op(self: T): T { ... }​@operator.postfix(OP)__op(): T { ... }
OP | Description | Notes |
| Postfix increment | Instance overload reassigns |
| Postfix decrement | Instance overload reassigns |
Overloaded postfix operations do not preserve the original value automatically.
The following range limits are present as global constants for convenience:
Constant | Value |
i8.MIN_VALUE: | -128 |
i8.MAX_VALUE: | 127 |
i16.MIN_VALUE: | -32768 |
i16.MAX_VALUE: | 32767 |
i32.MIN_VALUE: | -2147483648 |
i32.MAX_VALUE: | 2147483647 |
i64.MIN_VALUE: | -9223372036854775808 |
i64.MAX_VALUE: | 9223372036854775807 |
isize.MIN_VALUE: | target specific: either |
isize.MAX_VALUE: | target specific: either |
u8.MIN_VALUE: | 0 |
u8.MAX_VALUE: | 255 |
u16.MIN_VALUE: | 0 |
u16.MAX_VALUE: | 65535 |
u32.MIN_VALUE: | 0 |
u32.MAX_VALUE: | 4294967295 |
u64.MIN_VALUE: | 0 |
u64.MAX_VALUE: | 18446744073709551615 |
usize.MIN_VALUE: | 0 |
usize.MAX_VALUE: | target specific: either |
bool.MIN_VALUE: | 0 |
bool.MAX_VALUE: | 1 |
f32.MIN_VALUE: | -3.40282347e+38 |
f32.MAX_VALUE: | 3.40282347e+38 |
f32.MIN_SAFE_INTEGER: | -16777215 |
f32.MAX_SAFE_INTEGER: | 16777215 |
f32.EPSILON: | 1.19209290e-07 |
f64.MIN_VALUE: | -1.7976931348623157e+308 |
f64.MAX_VALUE: | 1.7976931348623157e+308 |
f64.MIN_SAFE_INTEGER: | -9007199254740991 |
f64.MAX_SAFE_INTEGER: | 9007199254740991 |
f64.EPSILON: | 2.2204460492503131e-16 |
The compiler only compiles elements reachable from the entry file and ignores everything that remains unused. This is very similar to a JavaScript VM's behavior when running a JavaScript file, but unlike in TypeScript it also affects checking of types. Helps to reduce compilation times and binary sizes significantly.
In addition to module-level tree-shaking, the compiler ignores branches that it can prove won't be taken. Works with constants, built-ins that compile to a constant, expressions that can be precomputed to a constant, plus the following globals to detect specific compiler flags or features:
Constant | Description |
ASC_TARGET | 0 = WASM32, 1 = WASM64, 2 = JS (portable) |
ASC_NO_ASSERT | Whether |
ASC_MEMORY_BASE | The value of |
ASC_OPTIMIZE_LEVEL | The value of |
ASC_SHRINK_LEVEL | The value of |
ASC_FEATURE_SIGN_EXTENSION | Whether sign extension operations are enabled |
ASC_FEATURE_MUTABLE_GLOBALS | Whether mutable globals are enabled |
ASC_FEATURE_NONTRAPPING_F2I | Whether non-trapping float-to-int operations are enabled |
ASC_FEATURE_BULK_MEMORY | Whether bulk memory operations are enabled |
ASC_FEATURE_SIMD | Whether SIMD operations are enabled |
ASC_FEATURE_THREADS | Whether threads are enabled |
ASC_FEATURE_EXCEPTION_HANDLING | Whether exception handling is enabled |
ASC_FEATURE_TAIL_CALLS | Whether tail-calls are enabled |
ASC_FEATURE_REFERENCE_TYPES | Whether reference types are enabled |
For example, if a library supports SIMD but also provides a fallback:
if (ASC_FEATURE_SIMD) {// compute with SIMD operations} else {// fallback without SIMD operations}
The compiler frontend (asc) provides hooking into the compilation process by means of transforms. Specifying --transform myTransform
on the command line will load the node module pointed to by myTransform
and the compiler will call the following hooks during the compilation process:
afterParse(parser: Parser
): void
Called with the parsing result of all relevant files once parsing is complete. Useful to modify the AST before it becomes compiled, for example by looking for custom decorators and injecting actual logic.
afterCompile(module: Module
): void
Called with the resulting Binaryen module before it is being emitted. Useful to modify the IR before it becomes emitted, for example to replace imports with actual functionality or to add custom sections.
Also see the transform examples. The set of hooks is intentionally minimal at this point. If you need something special, please let us know about your use case.