diff --git a/src/compiler.ts b/src/compiler.ts index f64fcfe5..da771374 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -2652,8 +2652,11 @@ export class Compiler extends DiagnosticEmitter { return this.module.createUnreachable(); } - /** Compiles a call to a function. If an instance method, `this` is the first element in `argumentExpressions`. */ - compileCall(functionInstance: Function, argumentExpressions: Expression[], reportNode: Node): ExpressionRef { + /** + * Compiles a call to a function. If an instance method, `this` is the first element in + * `argumentExpressions` or can be specified explicitly as the last argument. + */ + compileCall(functionInstance: Function, argumentExpressions: Expression[], reportNode: Node, thisArg: ExpressionRef = 0): ExpressionRef { // validate and compile arguments var parameters = functionInstance.parameters; @@ -2662,6 +2665,8 @@ export class Compiler extends DiagnosticEmitter { var numParametersInclThis = functionInstance.instanceMethodOf != null ? numParameters + 1 : numParameters; var numArgumentsInclThis = argumentExpressions.length; var numArguments = functionInstance.instanceMethodOf != null ? numArgumentsInclThis - 1 : numArgumentsInclThis; + if (thisArg) + numArgumentsInclThis++; if (numArgumentsInclThis > numParametersInclThis) { // too many arguments this.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, @@ -2672,13 +2677,18 @@ export class Compiler extends DiagnosticEmitter { } var operands = new Array(numParametersInclThis); var operandIndex = 0; - if (functionInstance.instanceMethodOf) - operands[operandIndex++] = this.compileExpression(argumentExpressions[0], functionInstance.instanceMethodOf.type); + var argumentIndex = 0; + if (functionInstance.instanceMethodOf) { + if (thisArg) + operands[operandIndex++] = thisArg; + else + operands[operandIndex++] = this.compileExpression(argumentExpressions[argumentIndex++], functionInstance.instanceMethodOf.type); + } for (; operandIndex < numParametersInclThis; ++operandIndex) { // argument has been provided if (numArgumentsInclThis > operandIndex) { - operands[operandIndex] = this.compileExpression(argumentExpressions[operandIndex], parameters[operandIndex + numParameters - numParametersInclThis].type); + operands[operandIndex] = this.compileExpression(argumentExpressions[argumentIndex++], parameters[operandIndex + numParameters - numParametersInclThis].type); // argument has been omitted } else { @@ -2866,7 +2876,6 @@ export class Compiler extends DiagnosticEmitter { // case LiteralKind.OBJECT: // case LiteralKind.REGEXP: - // case LiteralKind.STRING: } throw new Error("not implemented"); } @@ -2901,9 +2910,46 @@ export class Compiler extends DiagnosticEmitter { var prototype = resolved.element; var instance = prototype.resolveInclTypeArguments(expression.typeArguments, null, expression); // reports if (instance) { - // TODO: call constructor + var thisExpr = compileBuiltinAllocate(this, instance, expression); + var initializers = new Array(); + + // use a temp local for 'this' + var tempLocal = this.currentFunction.getTempLocal(this.options.usizeType); + initializers.push(this.module.createSetLocal(tempLocal.index, thisExpr)); + + // apply field initializers + if (instance.members) + for (var member of instance.members.values()) { + if (member.kind == ElementKind.FIELD) { + var field = member; + var fieldDeclaration = field.prototype.declaration; + if (field.is(ElementFlags.CONSTANT)) { + assert(false); // there are no built-in fields currently + } else if (fieldDeclaration && fieldDeclaration.initializer) { + initializers.push(this.module.createStore(field.type.byteSize, + this.module.createGetLocal(tempLocal.index, this.options.nativeSizeType), + this.compileExpression(fieldDeclaration.initializer, field.type), + field.type.toNativeType(), + field.memoryOffset + )); + } + } + } + + // apply constructor + var constructorInstance = instance.constructorInstance; + if (constructorInstance) + initializers.push(this.compileCall(constructorInstance, expression.arguments, expression, + this.module.createGetLocal(tempLocal.index, this.options.nativeSizeType) + )); + + // return 'this' + initializers.push(this.module.createGetLocal(tempLocal.index, this.options.nativeSizeType)); + this.currentFunction.freeTempLocal(tempLocal); + thisExpr = this.module.createBlock(null, initializers, this.options.nativeSizeType); + this.currentType = instance.type; - return compileBuiltinAllocate(this, instance, expression); + return thisExpr; } } else this.error(DiagnosticCode.Cannot_use_new_with_an_expression_whose_type_lacks_a_construct_signature, expression.expression.range); diff --git a/src/program.ts b/src/program.ts index 925d1d2b..b58e643e 100644 --- a/src/program.ts +++ b/src/program.ts @@ -436,13 +436,15 @@ export class Program extends DiagnosticEmitter { // if (classPrototype.isUnmanaged && instancePrototype.isAbstract) { // this.error( Unmanaged classes cannot declare abstract methods. ); // } - classPrototype.instanceMembers.set(name, prototype); if (declaration.name.kind == NodeKind.CONSTRUCTOR) { if (classPrototype.constructorPrototype) this.error(DiagnosticCode.Multiple_constructor_implementations_are_not_allowed, declaration.name.range); - else + else { + prototype.set(ElementFlags.CONSTRUCTOR); classPrototype.constructorPrototype = prototype; - } + } + } else + classPrototype.instanceMembers.set(name, prototype); } this.checkOperators(declaration.decorators, prototype, classPrototype); @@ -1075,7 +1077,6 @@ export class Program extends DiagnosticEmitter { case ElementKind.LOCAL: case ElementKind.FIELD: if (!(targetType = (target).type).classType) { - console.log(propertyAccess.property.name + " on " + targetType); this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName, targetType.toString()); return null; } @@ -1282,10 +1283,10 @@ export enum ElementFlags { PRIVATE = 1 << 15, /** Is an abstract member. */ ABSTRACT = 1 << 16, + /** Is a constructor. */ + CONSTRUCTOR = 1 << 17, /** Is an unmanaged class with limited capabilites. */ - UNMANAGED = 1 << 17, - /** Has already inherited base class static members. */ - HAS_STATIC_BASE_MEMBERS = 1 << 18, + UNMANAGED = 1 << 18, /** Is scoped. */ SCOPED = 1 << 19, /** Is the start function. */ @@ -1524,17 +1525,6 @@ export class FunctionPrototype extends Element { this.set(ElementFlags.INSTANCE); } - /** Whether a getter function or not. */ - get isGetter(): bool { return (this.flags & ElementFlags.GETTER) != 0; } - set isGetter(is: bool) { if (is) this.flags |= ElementFlags.GETTER; else this.flags &= ~ElementFlags.GETTER; } - - /** Whether a setter function or not. */ - get isSetter(): bool { return (this.flags & ElementFlags.SETTER) != 0; } - set isSetter(is: bool) { if (is) this.flags |= ElementFlags.SETTER; else this.flags &= ~ElementFlags.SETTER; } - - // Whether a getter/setter function or not. - get isAccessor(): bool { return (this.flags & (ElementFlags.GETTER | ElementFlags.SETTER)) != 0; } - resolve(functionTypeArguments: Type[] | null = null, contextualTypeArguments: Map | null = null): Function | null { var instanceKey = functionTypeArguments ? typesToString(functionTypeArguments) : ""; var instance = this.instances.get(instanceKey); @@ -1584,29 +1574,11 @@ export class FunctionPrototype extends Element { var parameterTypes = new Array(k); var typeNode: TypeNode | null; for (i = 0; i < k; ++i) { - if (typeNode = declaration.parameters[i].type) { - var parameterType = this.program.resolveType(typeNode, contextualTypeArguments, true); // reports - if (parameterType) { - parameters[i] = new Parameter(declaration.parameters[i].name.name, parameterType, declaration.parameters[i].initializer); - parameterTypes[i] = parameterType; - } else - return null; - } else - return null; - } - - // resolve return type - // TODO: 'this' type - var returnType: Type; - if (this.isSetter) { - returnType = Type.void; // not annotated - } else { - if (typeNode = declaration.returnType) { - var type = this.program.resolveType(typeNode, contextualTypeArguments, true); // reports - if (type) - returnType = type; - else - return null; + typeNode = assert(declaration.parameters[i].type); + var parameterType = this.program.resolveType(typeNode, contextualTypeArguments, true); // reports + if (parameterType) { + parameters[i] = new Parameter(declaration.parameters[i].name.name, parameterType, declaration.parameters[i].initializer); + parameterTypes[i] = parameterType; } else return null; } @@ -1620,6 +1592,21 @@ export class FunctionPrototype extends Element { if (!classInstance) return null; } + + // resolve return type + // TODO: 'this' type + var returnType: Type; + if (this.is(ElementFlags.SETTER) || this.is(ElementFlags.CONSTRUCTOR)) { + returnType = Type.void; // not annotated + } else { + typeNode = assert(declaration.returnType); + var type = this.program.resolveType(typeNode, contextualTypeArguments, true); // reports + if (type) + returnType = type; + else + return null; + } + instance = new Function(this, internalName, functionTypeArguments, parameters, returnType, classInstance); instance.contextualTypeArguments = contextualTypeArguments; this.instances.set(instanceKey, instance); @@ -1965,8 +1952,7 @@ export class ClassPrototype extends Element { this.program.error(DiagnosticCode.Structs_cannot_extend_classes_and_vice_versa, Range.join(declaration.name.range, declaration.extendsType.range)); return null; } - } else - this.flags |= ElementFlags.HAS_STATIC_BASE_MEMBERS; // fwiw + } // override call specific contextual type arguments if provided var i: i32, k: i32; @@ -1996,6 +1982,13 @@ export class ClassPrototype extends Element { } } + if (this.constructorPrototype) { + var partialConstructor = this.constructorPrototype.resolvePartial(typeArguments); // reports + if (partialConstructor) + instance.constructorInstance = partialConstructor.resolve(); // reports + // TODO: ^ doesn't know the return type, hence returns null + } + if (this.instanceMembers) for (var member of this.instanceMembers.values()) { switch (member.kind) { @@ -2086,6 +2079,8 @@ export class Class extends Element { contextualTypeArguments: Map | null = null; /** Current member memory offset. */ currentMemoryOffset: u32 = 0; + /** Constructor instance. */ + constructorInstance: Function | null = null; /** Constructs a new class. */ constructor(prototype: ClassPrototype, internalName: string, typeArguments: Type[] | null = null, base: Class | null = null) { diff --git a/std/assembly.d.ts b/std/assembly.d.ts index 71168780..648fa9e3 100644 --- a/std/assembly.d.ts +++ b/std/assembly.d.ts @@ -237,6 +237,7 @@ declare class String { concat(other: string): string; endsWith(other: string): bool; indexOf(other: string): u32; + includes(other: string): bool; startsWith(other: string): bool; substr(start: u32, length?: u32): string; substring(start: u32, end?: u32): string; diff --git a/std/portable.d.ts b/std/portable.d.ts index 5baf54ca..1f4a5ae3 100644 --- a/std/portable.d.ts +++ b/std/portable.d.ts @@ -176,6 +176,7 @@ declare class String { readonly length: i32; private constructor(); indexOf(subject: string): i32; + includes(other: string): bool; lastIndexOf(subject: string): i32; charAt(index: i32): string; charCodeAt(index: i32): i32; diff --git a/tests/compiler/new.optimized.wast b/tests/compiler/new.optimized.wast deleted file mode 100644 index 8c4f7716..00000000 --- a/tests/compiler/new.optimized.wast +++ /dev/null @@ -1,20 +0,0 @@ -(module - (type $ii (func (param i32) (result i32))) - (type $v (func)) - (import "env" "allocate_memory" (func $new/allocate_memory (param i32) (result i32))) - (memory $0 1) - (export "test" (func $new/test)) - (export "memory" (memory $0)) - (func $new/test (; 1 ;) (type $v) - (drop - (call $new/allocate_memory - (i32.const 4) - ) - ) - (drop - (call $new/allocate_memory - (i32.const 8) - ) - ) - ) -) diff --git a/tests/compiler/new.ts b/tests/compiler/new.ts deleted file mode 100644 index 6c329c81..00000000 --- a/tests/compiler/new.ts +++ /dev/null @@ -1,15 +0,0 @@ -class Simple { - field: i32; -} - -class Generic { - field: T; -} - -@global -declare function allocate_memory(size: usize): usize; - -export function test(): void { - var simple = new Simple(); - var generic = new Generic(); -} diff --git a/tests/compiler/new.wast b/tests/compiler/new.wast deleted file mode 100644 index 0874ea8f..00000000 --- a/tests/compiler/new.wast +++ /dev/null @@ -1,76 +0,0 @@ -(module - (type $ii (func (param i32) (result i32))) - (type $v (func)) - (import "env" "allocate_memory" (func $new/allocate_memory (param i32) (result i32))) - (global $HEAP_BASE i32 (i32.const 4)) - (memory $0 1) - (export "test" (func $new/test)) - (export "memory" (memory $0)) - (func $new/test (; 1 ;) (type $v) - (local $0 i32) - (local $1 i32) - (set_local $0 - (call $new/allocate_memory - (i32.const 4) - ) - ) - (set_local $1 - (call $new/allocate_memory - (i32.const 8) - ) - ) - ) -) -(; -[program.elements] - GLOBAL: NaN - GLOBAL: Infinity - FUNCTION_PROTOTYPE: isNaN - FUNCTION_PROTOTYPE: isFinite - FUNCTION_PROTOTYPE: clz - FUNCTION_PROTOTYPE: ctz - FUNCTION_PROTOTYPE: popcnt - FUNCTION_PROTOTYPE: rotl - FUNCTION_PROTOTYPE: rotr - FUNCTION_PROTOTYPE: abs - FUNCTION_PROTOTYPE: max - FUNCTION_PROTOTYPE: min - FUNCTION_PROTOTYPE: ceil - FUNCTION_PROTOTYPE: floor - FUNCTION_PROTOTYPE: copysign - FUNCTION_PROTOTYPE: nearest - FUNCTION_PROTOTYPE: reinterpret - FUNCTION_PROTOTYPE: sqrt - FUNCTION_PROTOTYPE: trunc - FUNCTION_PROTOTYPE: load - FUNCTION_PROTOTYPE: store - FUNCTION_PROTOTYPE: sizeof - FUNCTION_PROTOTYPE: select - FUNCTION_PROTOTYPE: unreachable - FUNCTION_PROTOTYPE: current_memory - FUNCTION_PROTOTYPE: grow_memory - FUNCTION_PROTOTYPE: changetype - FUNCTION_PROTOTYPE: assert - FUNCTION_PROTOTYPE: i8 - FUNCTION_PROTOTYPE: i16 - FUNCTION_PROTOTYPE: i32 - FUNCTION_PROTOTYPE: i64 - FUNCTION_PROTOTYPE: u8 - FUNCTION_PROTOTYPE: u16 - FUNCTION_PROTOTYPE: u32 - FUNCTION_PROTOTYPE: u64 - FUNCTION_PROTOTYPE: bool - FUNCTION_PROTOTYPE: f32 - FUNCTION_PROTOTYPE: f64 - FUNCTION_PROTOTYPE: isize - FUNCTION_PROTOTYPE: usize - GLOBAL: HEAP_BASE - CLASS_PROTOTYPE: new/Simple - CLASS_PROTOTYPE: new/Generic - FUNCTION_PROTOTYPE: new/allocate_memory - FUNCTION_PROTOTYPE: allocate_memory - FUNCTION_PROTOTYPE: new/test -[program.exports] - FUNCTION_PROTOTYPE: allocate_memory - FUNCTION_PROTOTYPE: new/test -;) diff --git a/tests/compiler/std/new.optimized.wast b/tests/compiler/std/new.optimized.wast new file mode 100644 index 00000000..b8159730 --- /dev/null +++ b/tests/compiler/std/new.optimized.wast @@ -0,0 +1,138 @@ +(module + (type $ii (func (param i32) (result i32))) + (type $v (func)) + (global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0)) + (global $std/new/aClass (mut i32) (i32.const 0)) + (global $HEAP_BASE i32 (i32.const 4)) + (memory $0 1) + (export "memory" (memory $0)) + (start $start) + (func $std:heap/allocate_memory (; 0 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (if + (i32.eqz + (get_local $0) + ) + (return + (i32.const 0) + ) + ) + (set_local $1 + (current_memory) + ) + (if + (i32.gt_u + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + (i32.shl + (get_local $1) + (i32.const 16) + ) + ) + (if + (i32.lt_s + (grow_memory + (select + (tee_local $2 + (i32.trunc_s/f64 + (f64.ceil + (f64.div + (f64.convert_u/i32 + (get_local $0) + ) + (f64.const 65536) + ) + ) + ) + ) + (tee_local $1 + (i32.sub + (i32.mul + (get_local $1) + (i32.const 2) + ) + (get_local $1) + ) + ) + (i32.gt_s + (get_local $2) + (get_local $1) + ) + ) + ) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_local $1 + (get_global $std:heap/HEAP_OFFSET) + ) + (if + (block (result i32) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + ) + (i32.and + (get_global $std:heap/HEAP_OFFSET) + (i32.const 7) + ) + ) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (i32.or + (get_global $std:heap/HEAP_OFFSET) + (i32.const 7) + ) + (i32.const 1) + ) + ) + ) + (get_local $1) + ) + (func $start (; 1 ;) (type $v) + (local $0 i32) + (local $1 i32) + (set_global $std:heap/HEAP_OFFSET + (get_global $HEAP_BASE) + ) + (set_global $std/new/aClass + (block (result i32) + (i32.store + (tee_local $0 + (call $std:heap/allocate_memory + (i32.const 8) + ) + ) + (i32.const 1) + ) + (f32.store offset=4 + (get_local $0) + (f32.const 2) + ) + (i32.store + (tee_local $1 + (get_local $0) + ) + (i32.add + (i32.load + (get_local $1) + ) + (i32.const 1) + ) + ) + (f32.store offset=4 + (get_local $1) + (f32.const 3) + ) + (get_local $0) + ) + ) + ) +) diff --git a/tests/compiler/std/new.ts b/tests/compiler/std/new.ts new file mode 100644 index 00000000..2eecae5e --- /dev/null +++ b/tests/compiler/std/new.ts @@ -0,0 +1,11 @@ +class AClass { + static aStaticField: i32 = 0; + aField: i32 = 1; + anotherField: f32 = 2; + constructor(value: f32) { + this.aField += 1; + this.anotherField = value; + } +} + +var aClass = new AClass(3); diff --git a/tests/compiler/std/new.wast b/tests/compiler/std/new.wast new file mode 100644 index 00000000..c4b42cb3 --- /dev/null +++ b/tests/compiler/std/new.wast @@ -0,0 +1,273 @@ +(module + (type $i (func (result i32))) + (type $ii (func (param i32) (result i32))) + (type $ifv (func (param i32 f32))) + (type $v (func)) + (global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0)) + (global $std:heap/ALIGN_LOG2 i32 (i32.const 3)) + (global $std:heap/ALIGN_SIZE i32 (i32.const 8)) + (global $std:heap/ALIGN_MASK i32 (i32.const 7)) + (global $std/new/aClass (mut i32) (i32.const 0)) + (global $HEAP_BASE i32 (i32.const 4)) + (memory $0 1) + (export "memory" (memory $0)) + (start $start) + (func $std:heap/allocate_memory (; 0 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (if + (i32.eqz + (get_local $0) + ) + (return + (i32.const 0) + ) + ) + (set_local $1 + (current_memory) + ) + (if + (i32.gt_u + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + (i32.shl + (get_local $1) + (i32.const 16) + ) + ) + (if + (i32.lt_s + (grow_memory + (select + (tee_local $2 + (i32.trunc_s/f64 + (f64.ceil + (f64.div + (f64.convert_u/i32 + (get_local $0) + ) + (f64.const 65536) + ) + ) + ) + ) + (tee_local $3 + (i32.sub + (i32.mul + (get_local $1) + (i32.const 2) + ) + (get_local $1) + ) + ) + (i32.gt_s + (get_local $2) + (get_local $3) + ) + ) + ) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_local $4 + (get_global $std:heap/HEAP_OFFSET) + ) + (if + (i32.and + (block (result i32) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + ) + (get_global $std:heap/HEAP_OFFSET) + ) + (i32.const 7) + ) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (i32.or + (get_global $std:heap/HEAP_OFFSET) + (i32.const 7) + ) + (i32.const 1) + ) + ) + ) + (return + (get_local $4) + ) + ) + (func $std/new/AClass#constructor (; 1 ;) (type $ifv) (param $0 i32) (param $1 f32) + (i32.store + (get_local $0) + (i32.add + (i32.load + (get_local $0) + ) + (i32.const 1) + ) + ) + (f32.store offset=4 + (get_local $0) + (get_local $1) + ) + ) + (func $start (; 2 ;) (type $v) + (local $0 i32) + (set_global $std:heap/HEAP_OFFSET + (get_global $HEAP_BASE) + ) + (set_global $std/new/aClass + (block (result i32) + (set_local $0 + (call $std:heap/allocate_memory + (i32.const 8) + ) + ) + (i32.store + (get_local $0) + (i32.const 1) + ) + (f32.store offset=4 + (get_local $0) + (f32.const 2) + ) + (call $std/new/AClass#constructor + (get_local $0) + (f32.const 3) + ) + (get_local $0) + ) + ) + ) +) +(; +[program.elements] + GLOBAL: NaN + GLOBAL: Infinity + FUNCTION_PROTOTYPE: isNaN + FUNCTION_PROTOTYPE: isFinite + FUNCTION_PROTOTYPE: clz + FUNCTION_PROTOTYPE: ctz + FUNCTION_PROTOTYPE: popcnt + FUNCTION_PROTOTYPE: rotl + FUNCTION_PROTOTYPE: rotr + FUNCTION_PROTOTYPE: abs + FUNCTION_PROTOTYPE: max + FUNCTION_PROTOTYPE: min + FUNCTION_PROTOTYPE: ceil + FUNCTION_PROTOTYPE: floor + FUNCTION_PROTOTYPE: copysign + FUNCTION_PROTOTYPE: nearest + FUNCTION_PROTOTYPE: reinterpret + FUNCTION_PROTOTYPE: sqrt + FUNCTION_PROTOTYPE: trunc + FUNCTION_PROTOTYPE: load + FUNCTION_PROTOTYPE: store + FUNCTION_PROTOTYPE: sizeof + FUNCTION_PROTOTYPE: select + FUNCTION_PROTOTYPE: unreachable + FUNCTION_PROTOTYPE: current_memory + FUNCTION_PROTOTYPE: grow_memory + FUNCTION_PROTOTYPE: changetype + FUNCTION_PROTOTYPE: assert + FUNCTION_PROTOTYPE: i8 + FUNCTION_PROTOTYPE: i16 + FUNCTION_PROTOTYPE: i32 + FUNCTION_PROTOTYPE: i64 + FUNCTION_PROTOTYPE: u8 + FUNCTION_PROTOTYPE: u16 + FUNCTION_PROTOTYPE: u32 + FUNCTION_PROTOTYPE: u64 + FUNCTION_PROTOTYPE: bool + FUNCTION_PROTOTYPE: f32 + FUNCTION_PROTOTYPE: f64 + FUNCTION_PROTOTYPE: isize + FUNCTION_PROTOTYPE: usize + GLOBAL: HEAP_BASE + CLASS_PROTOTYPE: std:array/Array + PROPERTY: std:array/Array#length + CLASS_PROTOTYPE: Array + CLASS_PROTOTYPE: std:array/CArray + CLASS_PROTOTYPE: CArray + CLASS_PROTOTYPE: std:error/Error + CLASS_PROTOTYPE: Error + CLASS_PROTOTYPE: std:error/RangeError + CLASS_PROTOTYPE: RangeError + GLOBAL: std:heap/ALIGN_LOG2 + GLOBAL: std:heap/ALIGN_SIZE + GLOBAL: std:heap/ALIGN_MASK + GLOBAL: std:heap/HEAP_OFFSET + FUNCTION_PROTOTYPE: std:heap/allocate_memory + FUNCTION_PROTOTYPE: allocate_memory + FUNCTION_PROTOTYPE: std:heap/free_memory + FUNCTION_PROTOTYPE: free_memory + FUNCTION_PROTOTYPE: std:heap/copy_memory + FUNCTION_PROTOTYPE: std:heap/move_memory + FUNCTION_PROTOTYPE: move_memory + FUNCTION_PROTOTYPE: std:heap/set_memory + FUNCTION_PROTOTYPE: set_memory + FUNCTION_PROTOTYPE: std:heap/compare_memory + FUNCTION_PROTOTYPE: compare_memory + CLASS_PROTOTYPE: std:map/Map + CLASS_PROTOTYPE: Map + CLASS_PROTOTYPE: std:regexp/RegExp + CLASS_PROTOTYPE: RegExp + CLASS_PROTOTYPE: std:set/Set + PROPERTY: std:set/Set#size + CLASS_PROTOTYPE: Set + GLOBAL: std:string/EMPTY + GLOBAL: std:string/HEAD + FUNCTION_PROTOTYPE: std:string/allocate + CLASS_PROTOTYPE: std:string/String + FUNCTION_PROTOTYPE: std:string/String.__concat + FUNCTION_PROTOTYPE: std:string/String.__eq + CLASS_PROTOTYPE: String + FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator + FUNCTION_PROTOTYPE: std:string/parseInt + FUNCTION_PROTOTYPE: parseInt + FUNCTION_PROTOTYPE: std:string/parseFloat + FUNCTION_PROTOTYPE: parseFloat + CLASS_PROTOTYPE: std/new/AClass + GLOBAL: std/new/AClass.aStaticField + GLOBAL: std/new/aClass +[program.exports] + CLASS_PROTOTYPE: std:array/Array + CLASS_PROTOTYPE: Array + CLASS_PROTOTYPE: std:array/CArray + CLASS_PROTOTYPE: CArray + CLASS_PROTOTYPE: std:error/Error + CLASS_PROTOTYPE: Error + CLASS_PROTOTYPE: std:error/RangeError + CLASS_PROTOTYPE: RangeError + FUNCTION_PROTOTYPE: allocate_memory + FUNCTION_PROTOTYPE: std:heap/allocate_memory + FUNCTION_PROTOTYPE: free_memory + FUNCTION_PROTOTYPE: std:heap/free_memory + FUNCTION_PROTOTYPE: move_memory + FUNCTION_PROTOTYPE: std:heap/move_memory + FUNCTION_PROTOTYPE: set_memory + FUNCTION_PROTOTYPE: std:heap/set_memory + FUNCTION_PROTOTYPE: compare_memory + FUNCTION_PROTOTYPE: std:heap/compare_memory + CLASS_PROTOTYPE: std:map/Map + CLASS_PROTOTYPE: Map + CLASS_PROTOTYPE: std:regexp/RegExp + CLASS_PROTOTYPE: RegExp + CLASS_PROTOTYPE: std:set/Set + CLASS_PROTOTYPE: Set + CLASS_PROTOTYPE: std:string/String + CLASS_PROTOTYPE: String + FUNCTION_PROTOTYPE: parseInt + FUNCTION_PROTOTYPE: std:string/parseInt + FUNCTION_PROTOTYPE: parseFloat + FUNCTION_PROTOTYPE: std:string/parseFloat +;)