mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-05-02 10:22:15 +00:00
Fix external names of class exports and similar; Support a few more kinds in TSDBuilder, see #74
This commit is contained in:
parent
78a679759a
commit
81223977d0
2
dist/assemblyscript.js
vendored
2
dist/assemblyscript.js
vendored
File diff suppressed because one or more lines are too long
2
dist/assemblyscript.js.map
vendored
2
dist/assemblyscript.js.map
vendored
File diff suppressed because one or more lines are too long
296
src/compiler.ts
296
src/compiler.ts
@ -7,7 +7,7 @@ import {
|
||||
compileCall as compileBuiltinCall,
|
||||
compileGetConstant as compileBuiltinGetConstant,
|
||||
compileAllocate as compileBuiltinAllocate,
|
||||
compileAbort
|
||||
compileAbort as compileBuiltinAbort
|
||||
} from "./builtins";
|
||||
|
||||
import {
|
||||
@ -32,6 +32,7 @@ import {
|
||||
Program,
|
||||
ClassPrototype,
|
||||
Class,
|
||||
Element,
|
||||
ElementKind,
|
||||
Enum,
|
||||
Field,
|
||||
@ -52,7 +53,11 @@ import {
|
||||
DecoratorFlags,
|
||||
|
||||
PATH_DELIMITER,
|
||||
INNER_DELIMITER
|
||||
INNER_DELIMITER,
|
||||
INSTANCE_DELIMITER,
|
||||
STATIC_DELIMITER,
|
||||
GETTER_PREFIX,
|
||||
SETTER_PREFIX
|
||||
} from "./program";
|
||||
|
||||
import {
|
||||
@ -272,10 +277,14 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// compile the start function if not empty
|
||||
var startFunctionBody = this.startFunctionBody;
|
||||
if (startFunctionBody.length) {
|
||||
let typeRef = this.ensureFunctionType(startFunctionInstance.signature);
|
||||
let signature = startFunctionInstance.signature;
|
||||
let funcRef = module.addFunction(
|
||||
startFunctionInstance.internalName,
|
||||
typeRef,
|
||||
this.ensureFunctionType(
|
||||
signature.parameterTypes,
|
||||
signature.returnType,
|
||||
signature.thisType
|
||||
),
|
||||
typesToNativeTypes(startFunctionInstance.additionalLocals),
|
||||
module.createBlock(null, startFunctionBody)
|
||||
);
|
||||
@ -510,8 +519,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
global.set(CommonFlags.MODULE_IMPORT);
|
||||
module.addGlobalImport(
|
||||
global.internalName,
|
||||
global.namespace
|
||||
? global.namespace.simpleName
|
||||
global.parent
|
||||
? global.parent.simpleName
|
||||
: "env",
|
||||
global.simpleName,
|
||||
nativeType
|
||||
@ -609,21 +618,15 @@ export class Compiler extends DiagnosticEmitter {
|
||||
DiagnosticCode.Operation_not_supported,
|
||||
assert(global.declaration).range
|
||||
);
|
||||
global.constantValueKind = ConstantValueKind.INTEGER;
|
||||
global.constantIntegerValue = i64_new(0);
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
global.set(CommonFlags.INLINED); // inline the value from now on
|
||||
if (declaration) {
|
||||
if (declaration.isTopLevel) { // but keep the element as it might be re-exported
|
||||
module.addGlobal(internalName, nativeType, false, initExpr);
|
||||
}
|
||||
if (declaration.range.source.isEntry && declaration.isTopLevelExport) {
|
||||
module.addGlobalExport(global.internalName, declaration.programLevelInternalName);
|
||||
}
|
||||
} else {
|
||||
assert(false); // must have a declaration if constant
|
||||
if (global.is(CommonFlags.MODULE_EXPORT)) {
|
||||
module.addGlobal(internalName, nativeType, false, initExpr);
|
||||
module.addGlobalExport(internalName, mangleExportName(global));
|
||||
} else if (declaration && declaration.isTopLevel) { // might become re-exported
|
||||
module.addGlobal(internalName, nativeType, false, initExpr);
|
||||
}
|
||||
|
||||
} else /* mutable */ {
|
||||
@ -726,9 +729,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
previousValue = <EnumValue>val;
|
||||
|
||||
// export values if the enum is exported
|
||||
if (element.declaration.range.source.isEntry && element.declaration.isTopLevelExport) {
|
||||
if (element.is(CommonFlags.MODULE_EXPORT)) {
|
||||
if (member.is(CommonFlags.INLINED)) {
|
||||
module.addGlobalExport(member.internalName, member.internalName);
|
||||
module.addGlobalExport(member.internalName, mangleExportName(member));
|
||||
} else if (valueDeclaration) {
|
||||
this.warning(
|
||||
DiagnosticCode.Cannot_export_a_mutable_global,
|
||||
@ -781,10 +784,12 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
/** Either reuses or creates the function type matching the specified signature. */
|
||||
private ensureFunctionType(signature: Signature): FunctionTypeRef {
|
||||
var parameters = signature.parameterTypes;
|
||||
var numParameters = parameters.length;
|
||||
var thisType = signature.thisType;
|
||||
private ensureFunctionType(
|
||||
parameterTypes: Type[] | null,
|
||||
returnType: Type,
|
||||
thisType: Type | null = null
|
||||
): FunctionTypeRef {
|
||||
var numParameters = parameterTypes ? parameterTypes.length : 0;
|
||||
var paramTypes: NativeType[];
|
||||
var index = 0;
|
||||
if (thisType) {
|
||||
@ -794,14 +799,17 @@ export class Compiler extends DiagnosticEmitter {
|
||||
} else {
|
||||
paramTypes = new Array(numParameters);
|
||||
}
|
||||
for (let i = 0; i < numParameters; ++i, ++index) {
|
||||
paramTypes[index] = signature.parameterTypes[i].toNativeType();
|
||||
if (parameterTypes) {
|
||||
for (let i = 0; i < numParameters; ++i, ++index) {
|
||||
paramTypes[index] = parameterTypes[i].toNativeType();
|
||||
}
|
||||
}
|
||||
var resultType = signature.returnType.toNativeType();
|
||||
var resultType = returnType.toNativeType();
|
||||
var module = this.module;
|
||||
var typeRef = module.getFunctionTypeBySignature(resultType, paramTypes);
|
||||
if (!typeRef) {
|
||||
typeRef = module.addFunctionType(signature.toSignatureString(), resultType, paramTypes);
|
||||
let name = Signature.makeSignatureString(parameterTypes, returnType, thisType);
|
||||
typeRef = module.addFunctionType(name, resultType, paramTypes);
|
||||
}
|
||||
return typeRef;
|
||||
}
|
||||
@ -832,7 +840,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
var ref: FunctionRef;
|
||||
var typeRef = this.ensureFunctionType(instance.signature);
|
||||
var signature = instance.signature;
|
||||
var typeRef = this.ensureFunctionType(signature.parameterTypes, signature.returnType, signature.thisType);
|
||||
var module = this.module;
|
||||
if (body) {
|
||||
let isConstructor = instance.is(CommonFlags.CONSTRUCTOR);
|
||||
@ -868,7 +877,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// if not all branches are guaranteed to allocate, also append a conditional allocation
|
||||
} else {
|
||||
let parent = assert(instance.memberOf);
|
||||
let parent = assert(instance.parent);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
stmt = module.createBlock(null, [
|
||||
stmt,
|
||||
@ -901,11 +910,11 @@ export class Compiler extends DiagnosticEmitter {
|
||||
instance.set(CommonFlags.MODULE_IMPORT);
|
||||
|
||||
// create the function import
|
||||
let namespace = instance.prototype.namespace;
|
||||
let parent = instance.prototype.parent;
|
||||
ref = module.addFunctionImport(
|
||||
instance.internalName,
|
||||
namespace
|
||||
? namespace.simpleName
|
||||
parent
|
||||
? parent.simpleName
|
||||
: "env",
|
||||
instance.simpleName,
|
||||
typeRef
|
||||
@ -913,8 +922,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
// check module-level export
|
||||
if (declaration.range.source.isEntry && declaration.isTopLevelExport) {
|
||||
module.addFunctionExport(instance.internalName, declaration.name.text);
|
||||
if (instance.is(CommonFlags.MODULE_EXPORT)) {
|
||||
module.addFunctionExport(instance.internalName, mangleExportName(instance));
|
||||
}
|
||||
|
||||
instance.finalize(module, ref);
|
||||
@ -1143,6 +1152,133 @@ export class Compiler extends DiagnosticEmitter {
|
||||
compileClass(instance: Class): bool {
|
||||
if (instance.is(CommonFlags.COMPILED)) return true;
|
||||
instance.set(CommonFlags.COMPILED);
|
||||
var staticMembers = instance.prototype.members;
|
||||
if (staticMembers) {
|
||||
for (let element of staticMembers.values()) {
|
||||
switch (element.kind) {
|
||||
case ElementKind.GLOBAL: {
|
||||
this.compileGlobal(<Global>element);
|
||||
break;
|
||||
}
|
||||
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||
if (
|
||||
!(<FunctionPrototype>element).is(CommonFlags.GENERIC)
|
||||
) {
|
||||
this.compileFunctionUsingTypeArguments(
|
||||
<FunctionPrototype>element,
|
||||
[], null, null,
|
||||
(<FunctionPrototype>element).declaration.name
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ElementKind.PROPERTY: {
|
||||
let getter = (<Property>element).getterPrototype;
|
||||
if (getter) {
|
||||
this.compileFunctionUsingTypeArguments(
|
||||
getter,
|
||||
[], null, null,
|
||||
getter.declaration.name
|
||||
);
|
||||
}
|
||||
let setter = (<Property>element).setterPrototype;
|
||||
if (setter) {
|
||||
this.compileFunctionUsingTypeArguments(
|
||||
setter,
|
||||
[], null, null,
|
||||
setter.declaration.name
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var instanceMembers = instance.members;
|
||||
if (instanceMembers) {
|
||||
for (let element of instanceMembers.values()) {
|
||||
switch (element.kind) {
|
||||
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||
if (
|
||||
!(<FunctionPrototype>element).is(CommonFlags.GENERIC)
|
||||
) {
|
||||
this.compileFunctionUsingTypeArguments(
|
||||
<FunctionPrototype>element,
|
||||
[],
|
||||
instance.contextualTypeArguments,
|
||||
null, // no outer scope
|
||||
(<FunctionPrototype>element).declaration.name
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ElementKind.FIELD: {
|
||||
element.set(CommonFlags.COMPILED);
|
||||
if (!instance.is(CommonFlags.MODULE_EXPORT) || element.is(CommonFlags.PRIVATE)) break;
|
||||
let module = this.module;
|
||||
let name = (<Field>element).simpleName;
|
||||
let type = (<Field>element).type;
|
||||
let nativeType = type.toNativeType();
|
||||
let offset = (<Field>element).memoryOffset;
|
||||
let usizeType = this.options.usizeType;
|
||||
let nativeSizeType = this.options.nativeSizeType;
|
||||
|
||||
// export an implicit getter: get:fieldName(this: usize) -> fieldType
|
||||
let getterName = mangleExportName(element, GETTER_PREFIX + name);
|
||||
module.addFunction(
|
||||
getterName,
|
||||
this.ensureFunctionType(null, type, usizeType),
|
||||
null,
|
||||
module.createLoad(
|
||||
type.byteSize,
|
||||
type.is(TypeFlags.SIGNED),
|
||||
module.createGetLocal(0, nativeSizeType),
|
||||
nativeType,
|
||||
offset
|
||||
)
|
||||
);
|
||||
module.addFunctionExport(getterName, getterName);
|
||||
|
||||
// export an implicit setter: set:fieldName(this: usize, value: fieldType) -> void
|
||||
if (element.is(CommonFlags.READONLY)) break;
|
||||
let setterName = mangleExportName(element, SETTER_PREFIX + name);
|
||||
module.addFunction(
|
||||
setterName,
|
||||
this.ensureFunctionType([ type ], Type.void, usizeType),
|
||||
null,
|
||||
module.createStore(
|
||||
type.byteSize,
|
||||
module.createGetLocal(0, nativeSizeType),
|
||||
module.createGetLocal(1, nativeType),
|
||||
nativeType,
|
||||
offset
|
||||
)
|
||||
);
|
||||
module.addFunctionExport(setterName, setterName);
|
||||
break;
|
||||
}
|
||||
case ElementKind.PROPERTY: {
|
||||
let getter = (<Property>element).getterPrototype;
|
||||
if (getter) {
|
||||
this.compileFunctionUsingTypeArguments(
|
||||
getter,
|
||||
[], instance.contextualTypeArguments, null,
|
||||
getter.declaration.name
|
||||
);
|
||||
}
|
||||
let setter = (<Property>element).setterPrototype;
|
||||
if (setter) {
|
||||
this.compileFunctionUsingTypeArguments(
|
||||
setter,
|
||||
[], instance.contextualTypeArguments, null,
|
||||
setter.declaration.name
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1672,7 +1808,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
flow.set(FlowFlags.RETURNS);
|
||||
|
||||
// TODO: requires exception-handling spec.
|
||||
return compileAbort(this, null, statement);
|
||||
return compileBuiltinAbort(this, null, statement);
|
||||
}
|
||||
|
||||
compileTryStatement(statement: TryStatement): ExpressionRef {
|
||||
@ -4060,9 +4196,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var argumentExpressions: Expression[];
|
||||
var thisArg: ExpressionRef = 0;
|
||||
if (operatorInstance.is(CommonFlags.INSTANCE)) {
|
||||
let classElement = assert(operatorInstance.memberOf);
|
||||
assert(classElement.kind == ElementKind.CLASS);
|
||||
thisArg = this.compileExpression(value, (<Class>classElement).type);
|
||||
let parent = assert(operatorInstance.parent);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
thisArg = this.compileExpression(value, (<Class>parent).type);
|
||||
argumentExpressions = [];
|
||||
} else {
|
||||
argumentExpressions = [ value ];
|
||||
@ -4086,9 +4222,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var argumentExpressions: Expression[];
|
||||
var thisArg: ExpressionRef = 0;
|
||||
if (operatorInstance.is(CommonFlags.INSTANCE)) {
|
||||
let classElement = assert(operatorInstance.memberOf);
|
||||
assert(classElement.kind == ElementKind.CLASS);
|
||||
thisArg = this.compileExpression(left, (<Class>classElement).type);
|
||||
let parent = assert(operatorInstance.parent);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
thisArg = this.compileExpression(left, (<Class>parent).type);
|
||||
argumentExpressions = [ right ];
|
||||
} else {
|
||||
argumentExpressions = [ left, right ];
|
||||
@ -4755,9 +4891,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// here, with their respective locals being blocked. There is no 'makeCallInline'.
|
||||
var body = [];
|
||||
if (thisArg) {
|
||||
let classElement = assert(instance.memberOf);
|
||||
assert(classElement.kind == ElementKind.CLASS);
|
||||
let thisLocal = flow.addScopedLocal((<Class>classElement).type, "this");
|
||||
let parent = assert(instance.parent);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
let thisLocal = flow.addScopedLocal((<Class>parent).type, "this");
|
||||
body.push(
|
||||
module.createSetLocal(thisLocal.index, thisArg)
|
||||
);
|
||||
@ -4879,7 +5015,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
original.prototype,
|
||||
trampolineName,
|
||||
trampolineSignature,
|
||||
original.memberOf,
|
||||
original.parent,
|
||||
original.contextualTypeArguments
|
||||
);
|
||||
trampoline.set(original.flags | CommonFlags.TRAMPOLINE | CommonFlags.COMPILED);
|
||||
@ -4929,8 +5065,14 @@ export class Compiler extends DiagnosticEmitter {
|
||||
this.currentFunction = previousFunction;
|
||||
assert(operandIndex == maxOperands);
|
||||
|
||||
var typeRef = this.ensureFunctionType(trampolineSignature);
|
||||
var funcRef = module.addFunction(trampolineName, typeRef, typesToNativeTypes(trampoline.additionalLocals),
|
||||
var funcRef = module.addFunction(
|
||||
trampolineName,
|
||||
this.ensureFunctionType(
|
||||
trampolineSignature.parameterTypes,
|
||||
trampolineSignature.returnType,
|
||||
trampolineSignature.thisType
|
||||
),
|
||||
typesToNativeTypes(trampoline.additionalLocals),
|
||||
module.createBlock(null, [
|
||||
body,
|
||||
module.createCall(
|
||||
@ -5052,7 +5194,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
assert(numOperands >= minOperands);
|
||||
|
||||
this.ensureFunctionType(signature);
|
||||
this.ensureFunctionType(signature.parameterTypes, signature.returnType, signature.thisType);
|
||||
var module = this.module;
|
||||
|
||||
// fill up omitted arguments with zeroes
|
||||
@ -5200,7 +5342,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
if (currentFunction.is(CommonFlags.INSTANCE)) {
|
||||
let parent = assert(currentFunction.memberOf);
|
||||
let parent = assert(currentFunction.parent);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
let thisType = (<Class>parent).type;
|
||||
if (currentFunction.is(CommonFlags.CONSTRUCTOR)) {
|
||||
@ -5238,7 +5380,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
if (currentFunction.is(CommonFlags.INSTANCE)) {
|
||||
let parent = assert(currentFunction.memberOf);
|
||||
let parent = assert(currentFunction.parent);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
let base = (<Class>parent).base;
|
||||
if (base) {
|
||||
@ -5759,7 +5901,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return module.createGetGlobal((<Global>target).internalName, globalType.toNativeType());
|
||||
}
|
||||
case ElementKind.ENUMVALUE: { // enum value
|
||||
if (!this.compileEnum((<EnumValue>target).enum)) {
|
||||
let parent = (<EnumValue>target).parent;
|
||||
assert(parent !== null && parent.kind == ElementKind.ENUM);
|
||||
if (!this.compileEnum(<Enum>parent)) {
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
this.currentType = Type.i32;
|
||||
@ -5777,7 +5921,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
);
|
||||
this.currentType = (<Field>target).type;
|
||||
return module.createLoad(
|
||||
(<Field>target).type.size >> 3,
|
||||
(<Field>target).type.byteSize,
|
||||
(<Field>target).type.is(TypeFlags.SIGNED | TypeFlags.INTEGER),
|
||||
thisExpr,
|
||||
(<Field>target).type.toNativeType(),
|
||||
@ -5799,7 +5943,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return module.createUnreachable();
|
||||
}
|
||||
if (instance.is(CommonFlags.INSTANCE)) {
|
||||
let parent = assert(instance.memberOf);
|
||||
let parent = assert(instance.parent);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
let thisExpression = assert(program.resolvedThisExpression);
|
||||
let thisExpr = this.compileExpressionRetainType(
|
||||
@ -6420,6 +6564,50 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// helpers
|
||||
|
||||
function mangleExportName(element: Element, explicitSimpleName: string | null = null): string {
|
||||
var simpleName = explicitSimpleName != null
|
||||
? explicitSimpleName
|
||||
: element.simpleName;
|
||||
switch (element.kind) {
|
||||
case ElementKind.FUNCTION: {
|
||||
let parent = (<Function>element).parent || (<Function>element).prototype.parent;
|
||||
return parent
|
||||
? mangleExportName(parent)
|
||||
+ (element.is(CommonFlags.INSTANCE) ? INSTANCE_DELIMITER : STATIC_DELIMITER)
|
||||
+ simpleName
|
||||
: simpleName;
|
||||
}
|
||||
case ElementKind.FIELD: {
|
||||
let parent = assert((<Field>element).parent);
|
||||
return mangleExportName(parent)
|
||||
+ (element.is(CommonFlags.INSTANCE) ? INSTANCE_DELIMITER : STATIC_DELIMITER)
|
||||
+ simpleName;
|
||||
}
|
||||
case ElementKind.ENUMVALUE: {
|
||||
let parent = assert((<EnumValue>element).parent);
|
||||
return mangleExportName(parent)
|
||||
+ (element.is(CommonFlags.INSTANCE) ? INSTANCE_DELIMITER : STATIC_DELIMITER)
|
||||
+ simpleName;
|
||||
}
|
||||
case ElementKind.CLASS: {
|
||||
let parent = (<Class>element).prototype.parent;
|
||||
return parent
|
||||
? mangleExportName(parent)
|
||||
+ STATIC_DELIMITER
|
||||
+ simpleName
|
||||
: simpleName;
|
||||
}
|
||||
default: {
|
||||
let parent = element.parent;
|
||||
return parent
|
||||
? mangleExportName(parent)
|
||||
+ STATIC_DELIMITER
|
||||
+ simpleName
|
||||
: simpleName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds the debug location of the specified expression at the specified range to the source map. */
|
||||
function addDebugLocation(expr: ExpressionRef, range: Range, module: Module, currentFunction: Function): void {
|
||||
var source = range.source;
|
||||
|
@ -11,13 +11,15 @@ import {
|
||||
Global,
|
||||
Enum,
|
||||
EnumValue,
|
||||
Field,
|
||||
Function,
|
||||
Class,
|
||||
Namespace,
|
||||
FunctionPrototype,
|
||||
Class,
|
||||
ClassPrototype,
|
||||
Namespace,
|
||||
ConstantValueKind,
|
||||
Interface
|
||||
Interface,
|
||||
Property
|
||||
} from "./program";
|
||||
|
||||
import {
|
||||
@ -41,51 +43,56 @@ abstract class ExportsWalker {
|
||||
}
|
||||
|
||||
walk(): void {
|
||||
for (let element of this.program.moduleLevelExports.values()) {
|
||||
this.visitElement(element);
|
||||
}
|
||||
for (let element of this.program.moduleLevelExports.values()) this.visitElement(element);
|
||||
}
|
||||
|
||||
visitElement(element: Element): void {
|
||||
switch (element.kind) {
|
||||
case ElementKind.GLOBAL: {
|
||||
if (element.is(CommonFlags.COMPILED)) {
|
||||
this.visitGlobal(<Global>element);
|
||||
}
|
||||
if (element.is(CommonFlags.COMPILED)) this.visitGlobal(<Global>element);
|
||||
break;
|
||||
}
|
||||
case ElementKind.ENUM: {
|
||||
if (element.is(CommonFlags.COMPILED)) {
|
||||
this.visitEnum(<Enum>element);
|
||||
}
|
||||
if (element.is(CommonFlags.COMPILED)) this.visitEnum(<Enum>element);
|
||||
break;
|
||||
}
|
||||
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||
for (let instance of (<FunctionPrototype>element).instances.values()) {
|
||||
if (instance.is(CommonFlags.COMPILED)) {
|
||||
this.visitFunction(<Function>instance);
|
||||
}
|
||||
}
|
||||
this.visitCompiledFunctions(<FunctionPrototype>element);
|
||||
break;
|
||||
}
|
||||
case ElementKind.CLASS_PROTOTYPE: {
|
||||
for (let instance of (<ClassPrototype>element).instances.values()) {
|
||||
if (instance.is(CommonFlags.COMPILED)) {
|
||||
this.visitClass(<Class>instance);
|
||||
}
|
||||
}
|
||||
this.visitCompiledClasses(<ClassPrototype>element);
|
||||
break;
|
||||
}
|
||||
case ElementKind.FIELD: {
|
||||
if ((<Field>element).is(CommonFlags.COMPILED)) this.visitField(<Field>element);
|
||||
break;
|
||||
}
|
||||
case ElementKind.PROPERTY: {
|
||||
let prop = <Property>element;
|
||||
let getter = prop.getterPrototype;
|
||||
if (getter) this.visitCompiledFunctions(getter);
|
||||
let setter = prop.setterPrototype;
|
||||
if (setter) this.visitCompiledFunctions(setter);
|
||||
break;
|
||||
}
|
||||
case ElementKind.NAMESPACE: {
|
||||
if ((<Namespace>element).is(CommonFlags.COMPILED)) {
|
||||
this.visitNamespace(<Namespace>element);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
if (hasCompiledMember(<Namespace>element)) this.visitNamespace(<Namespace>element);
|
||||
break;
|
||||
}
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
visitCompiledFunctions(element: FunctionPrototype): void {
|
||||
for (let instance of element.instances.values()) {
|
||||
if (instance.is(CommonFlags.COMPILED)) this.visitFunction(<Function>instance);
|
||||
}
|
||||
}
|
||||
|
||||
visitCompiledClasses(element: ClassPrototype): void {
|
||||
for (let instance of element.instances.values()) {
|
||||
if (instance.is(CommonFlags.COMPILED)) this.visitClass(<Class>instance);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +101,7 @@ abstract class ExportsWalker {
|
||||
abstract visitFunction(element: Function): void;
|
||||
abstract visitClass(element: Class): void;
|
||||
abstract visitInterface(element: Interface): void;
|
||||
abstract visitField(element: Field): void;
|
||||
abstract visitNamespace(element: Element): void;
|
||||
}
|
||||
|
||||
@ -120,9 +128,7 @@ export class IDLBuilder extends ExportsWalker {
|
||||
var sb = this.sb;
|
||||
var isConst = element.is(CommonFlags.INLINED);
|
||||
indent(sb, this.indentLevel);
|
||||
if (isConst) {
|
||||
sb.push("const ");
|
||||
}
|
||||
if (isConst) sb.push("const ");
|
||||
sb.push(this.typeToString(element.type));
|
||||
sb.push(" ");
|
||||
sb.push(element.simpleName);
|
||||
@ -158,11 +164,8 @@ export class IDLBuilder extends ExportsWalker {
|
||||
if (member.kind == ElementKind.ENUMVALUE) {
|
||||
let isConst = (<EnumValue>member).is(CommonFlags.INLINED);
|
||||
indent(sb, this.indentLevel);
|
||||
if (isConst) {
|
||||
sb.push("const ");
|
||||
} else {
|
||||
sb.push("readonly ");
|
||||
}
|
||||
if (isConst) sb.push("const ");
|
||||
else sb.push("readonly ");
|
||||
sb.push("unsigned long ");
|
||||
sb.push(name);
|
||||
if (isConst) {
|
||||
@ -173,9 +176,7 @@ export class IDLBuilder extends ExportsWalker {
|
||||
}
|
||||
}
|
||||
for (let member of members.values()) {
|
||||
if (member.kind != ElementKind.ENUMVALUE) {
|
||||
this.visitElement(member);
|
||||
}
|
||||
if (member.kind != ElementKind.ENUMVALUE) this.visitElement(member);
|
||||
}
|
||||
}
|
||||
indent(sb, --this.indentLevel);
|
||||
@ -209,9 +210,7 @@ export class IDLBuilder extends ExportsWalker {
|
||||
sb.push("interface ");
|
||||
sb.push(element.simpleName);
|
||||
sb.push(" {\n");
|
||||
for (let member of members.values()) {
|
||||
this.visitElement(member);
|
||||
}
|
||||
for (let member of members.values()) this.visitElement(member);
|
||||
indent(sb, --this.indentLevel);
|
||||
sb.push("}\n");
|
||||
}
|
||||
@ -234,6 +233,10 @@ export class IDLBuilder extends ExportsWalker {
|
||||
this.visitClass(element);
|
||||
}
|
||||
|
||||
visitField(element: Field): void {
|
||||
// TODO
|
||||
}
|
||||
|
||||
visitNamespace(element: Namespace): void {
|
||||
if (this.seen.has(element)) return;
|
||||
this.seen.add(element);
|
||||
@ -244,9 +247,7 @@ export class IDLBuilder extends ExportsWalker {
|
||||
sb.push(" {\n");
|
||||
var members = element.members;
|
||||
if (members) {
|
||||
for (let member of members.values()) {
|
||||
this.visitElement(member);
|
||||
}
|
||||
for (let member of members.values()) this.visitElement(member);
|
||||
}
|
||||
indent(sb, --this.indentLevel);
|
||||
sb.push("}\n");
|
||||
@ -311,8 +312,12 @@ export class TSDBuilder extends ExportsWalker {
|
||||
var sb = this.sb;
|
||||
var isConst = element.is(CommonFlags.INLINED);
|
||||
indent(sb, this.indentLevel);
|
||||
if (isConst) {
|
||||
sb.push("const ");
|
||||
if (element.is(CommonFlags.STATIC)) {
|
||||
if (isConst) sb.push("static readonly ");
|
||||
else assert(false);
|
||||
} else {
|
||||
if (isConst) sb.push("const ");
|
||||
else sb.push("var ");
|
||||
}
|
||||
sb.push(element.simpleName);
|
||||
sb.push(": ");
|
||||
@ -345,9 +350,7 @@ export class TSDBuilder extends ExportsWalker {
|
||||
--numMembers;
|
||||
}
|
||||
}
|
||||
if (numMembers) {
|
||||
this.visitNamespace(element);
|
||||
}
|
||||
if (numMembers) this.visitNamespace(element);
|
||||
}
|
||||
indent(sb, --this.indentLevel);
|
||||
sb.push("}\n");
|
||||
@ -356,11 +359,22 @@ export class TSDBuilder extends ExportsWalker {
|
||||
visitFunction(element: Function): void {
|
||||
if (this.seen.has(element)) return;
|
||||
this.seen.add(element);
|
||||
if (element.is(CommonFlags.PRIVATE)) return;
|
||||
var sb = this.sb;
|
||||
var signature = element.signature;
|
||||
indent(sb, this.indentLevel);
|
||||
sb.push("function ");
|
||||
sb.push(element.simpleName);
|
||||
if (element.is(CommonFlags.PROTECTED)) sb.push("protected ");
|
||||
if (element.is(CommonFlags.STATIC)) sb.push("static ");
|
||||
if (element.is(CommonFlags.GET)) {
|
||||
sb.push("get ");
|
||||
sb.push(element.prototype.declaration.name.text); // 'get:funcName' internally
|
||||
} else if (element.is(CommonFlags.SET)) {
|
||||
sb.push("set ");
|
||||
sb.push(element.prototype.declaration.name.text);
|
||||
} else {
|
||||
if (!element.is(CommonFlags.INSTANCE)) sb.push("function ");
|
||||
sb.push(element.simpleName);
|
||||
}
|
||||
sb.push("(");
|
||||
var parameters = signature.parameterTypes;
|
||||
var numParameters = parameters.length;
|
||||
@ -372,8 +386,12 @@ export class TSDBuilder extends ExportsWalker {
|
||||
sb.push(": ");
|
||||
sb.push(this.typeToString(parameters[i]));
|
||||
}
|
||||
sb.push("): ");
|
||||
sb.push(this.typeToString(signature.returnType));
|
||||
if (element.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.SET)) {
|
||||
sb.push(")");
|
||||
} else {
|
||||
sb.push("): ");
|
||||
sb.push(this.typeToString(signature.returnType));
|
||||
}
|
||||
sb.push(";\n");
|
||||
this.visitNamespace(element);
|
||||
}
|
||||
@ -394,18 +412,22 @@ export class TSDBuilder extends ExportsWalker {
|
||||
}
|
||||
sb.push(element.simpleName);
|
||||
var base = element.base;
|
||||
if (base) {
|
||||
if (base && base.is(CommonFlags.COMPILED | CommonFlags.MODULE_EXPORT)) {
|
||||
sb.push(" extends ");
|
||||
sb.push(base.simpleName); // TODO: fqn
|
||||
}
|
||||
sb.push(" {\n");
|
||||
var members = element.prototype.members; // static
|
||||
if (members) {
|
||||
// TODO
|
||||
for (let member of members.values()) {
|
||||
this.visitElement(member);
|
||||
}
|
||||
}
|
||||
var ctor = element.constructorInstance;
|
||||
if (ctor) this.visitFunction(ctor);
|
||||
members = element.members; // instance
|
||||
if (members) {
|
||||
// TODO
|
||||
for (let member of members.values()) this.visitElement(member);
|
||||
}
|
||||
indent(sb, --this.indentLevel);
|
||||
sb.push("}\n");
|
||||
@ -415,6 +437,40 @@ export class TSDBuilder extends ExportsWalker {
|
||||
this.visitClass(element);
|
||||
}
|
||||
|
||||
visitField(element: Field): void {
|
||||
if (element.is(CommonFlags.PRIVATE)) return;
|
||||
var sb = this.sb;
|
||||
indent(sb, this.indentLevel);
|
||||
if (element.is(CommonFlags.PROTECTED)) sb.push("protected ");
|
||||
if (element.is(CommonFlags.STATIC)) sb.push("static ");
|
||||
if (element.is(CommonFlags.READONLY)) sb.push("readonly ");
|
||||
sb.push(element.simpleName);
|
||||
sb.push(": ");
|
||||
sb.push(this.typeToString(element.type));
|
||||
sb.push(";\n");
|
||||
/* TBD: the compiler implicitly generates setters if the class is exported
|
||||
indent(sb, this.indentLevel);
|
||||
sb.push("get ");
|
||||
sb.push(element.simpleName);
|
||||
sb.push("(): ");
|
||||
sb.push(this.typeToString(element.type));
|
||||
sb.push(";\n");
|
||||
if (!element.is(CommonFlags.READONLY)) {
|
||||
indent(sb, this.indentLevel);
|
||||
if (element.is(CommonFlags.PROTECTED)) sb.push("protected ");
|
||||
if (element.is(CommonFlags.STATIC)) sb.push("static ");
|
||||
if (element.is(CommonFlags.READONLY)) sb.push("readonly ");
|
||||
sb.push("set ");
|
||||
sb.push(element.simpleName);
|
||||
sb.push("(");
|
||||
sb.push(element.simpleName);
|
||||
sb.push(": ");
|
||||
sb.push(this.typeToString(element.type));
|
||||
sb.push(");\n");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
visitNamespace(element: Element): void {
|
||||
var members = element.members;
|
||||
if (members && members.size) {
|
||||
@ -423,9 +479,7 @@ export class TSDBuilder extends ExportsWalker {
|
||||
sb.push("namespace ");
|
||||
sb.push(element.simpleName);
|
||||
sb.push(" {\n");
|
||||
for (let member of members.values()) {
|
||||
this.visitElement(member);
|
||||
}
|
||||
for (let member of members.values()) this.visitElement(member);
|
||||
indent(sb, --this.indentLevel);
|
||||
sb.push("}\n");
|
||||
}
|
||||
@ -477,3 +531,33 @@ export class TSDBuilder extends ExportsWalker {
|
||||
}
|
||||
|
||||
// TODO: C bindings? or is this sufficiently covered by WebIDL and using a 3rd-party tool?
|
||||
|
||||
// helpers
|
||||
|
||||
/** Tests if a namespace-like element has at least one compiled member. */
|
||||
function hasCompiledMember(element: Element): bool {
|
||||
var members = element.members;
|
||||
if (members) {
|
||||
for (let member of members.values()) {
|
||||
switch (member.kind) {
|
||||
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||
for (let instance of (<FunctionPrototype>member).instances.values()) {
|
||||
if (instance.is(CommonFlags.COMPILED)) return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ElementKind.CLASS_PROTOTYPE: {
|
||||
for (let instance of (<ClassPrototype>member).instances.values()) {
|
||||
if (instance.is(CommonFlags.COMPILED)) return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (member.is(CommonFlags.COMPILED) || hasCompiledMember(member)) return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -28,9 +28,8 @@ import {
|
||||
CommonTypeNode,
|
||||
TypeNode,
|
||||
TypeParameterNode,
|
||||
// ParameterNode,
|
||||
// ParameterKind,
|
||||
// SignatureNode,
|
||||
ParameterKind,
|
||||
SignatureNode,
|
||||
DecoratorNode,
|
||||
DecoratorKind,
|
||||
|
||||
@ -59,12 +58,10 @@ import {
|
||||
MethodDeclaration,
|
||||
NamespaceDeclaration,
|
||||
TypeDeclaration,
|
||||
VariableDeclaration,
|
||||
VariableLikeDeclarationStatement,
|
||||
VariableStatement,
|
||||
|
||||
ParameterKind,
|
||||
SignatureNode,
|
||||
VariableDeclaration,
|
||||
stringToDecoratorKind
|
||||
} from "./ast";
|
||||
|
||||
@ -533,7 +530,7 @@ export class Program extends DiagnosticEmitter {
|
||||
)
|
||||
: DecoratorFlags.NONE
|
||||
);
|
||||
prototype.namespace = namespace;
|
||||
prototype.parent = namespace;
|
||||
this.elementsLookup.set(internalName, prototype);
|
||||
|
||||
var implementsTypes = declaration.implementsTypes;
|
||||
@ -573,10 +570,8 @@ export class Program extends DiagnosticEmitter {
|
||||
namespace.members = new Map();
|
||||
}
|
||||
namespace.members.set(simpleName, prototype);
|
||||
if (namespace.is(CommonFlags.MODULE_EXPORT)) {
|
||||
if (prototype.is(CommonFlags.EXPORT)) {
|
||||
prototype.set(CommonFlags.MODULE_EXPORT);
|
||||
}
|
||||
if (namespace.is(CommonFlags.MODULE_EXPORT) && prototype.is(CommonFlags.EXPORT)) {
|
||||
prototype.set(CommonFlags.MODULE_EXPORT);
|
||||
}
|
||||
|
||||
// otherwise add to file-level exports if exported
|
||||
@ -662,8 +657,12 @@ export class Program extends DiagnosticEmitter {
|
||||
Type.void, // resolved later on
|
||||
declaration
|
||||
);
|
||||
staticField.parent = classPrototype;
|
||||
classPrototype.members.set(name, staticField);
|
||||
this.elementsLookup.set(internalName, staticField);
|
||||
if (classPrototype.is(CommonFlags.MODULE_EXPORT)) {
|
||||
staticField.set(CommonFlags.MODULE_EXPORT);
|
||||
}
|
||||
|
||||
// instance fields are remembered until resolved
|
||||
} else {
|
||||
@ -685,6 +684,7 @@ export class Program extends DiagnosticEmitter {
|
||||
declaration
|
||||
);
|
||||
classPrototype.instanceMembers.set(name, instanceField);
|
||||
// TBD: no need to mark as MODULE_EXPORT
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,6 +958,7 @@ export class Program extends DiagnosticEmitter {
|
||||
this.elementsLookup.set(internalPropertyName, propertyElement);
|
||||
if (classPrototype.is(CommonFlags.MODULE_EXPORT)) {
|
||||
propertyElement.set(CommonFlags.MODULE_EXPORT);
|
||||
instancePrototype.set(CommonFlags.MODULE_EXPORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -976,7 +977,7 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
var simpleName = declaration.name.text;
|
||||
var element = new Enum(this, simpleName, internalName, declaration);
|
||||
element.namespace = namespace;
|
||||
element.parent = namespace;
|
||||
this.elementsLookup.set(internalName, element);
|
||||
|
||||
if (namespace) {
|
||||
@ -992,7 +993,7 @@ export class Program extends DiagnosticEmitter {
|
||||
namespace.members = new Map();
|
||||
}
|
||||
namespace.members.set(simpleName, element);
|
||||
if (namespace.is(CommonFlags.MODULE_EXPORT)) {
|
||||
if (namespace.is(CommonFlags.MODULE_EXPORT) && element.is(CommonFlags.EXPORT)) {
|
||||
element.set(CommonFlags.MODULE_EXPORT);
|
||||
}
|
||||
} else if (element.is(CommonFlags.EXPORT)) { // no namespace
|
||||
@ -1031,7 +1032,6 @@ export class Program extends DiagnosticEmitter {
|
||||
): void {
|
||||
var name = declaration.name.text;
|
||||
var internalName = declaration.fileLevelInternalName;
|
||||
var isModuleExport = enm.is(CommonFlags.MODULE_EXPORT);
|
||||
if (enm.members) {
|
||||
if (enm.members.has(name)) {
|
||||
this.error(
|
||||
@ -1045,7 +1045,7 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
var value = new EnumValue(enm, this, name, internalName, declaration);
|
||||
enm.members.set(name, value);
|
||||
if (isModuleExport) {
|
||||
if (enm.is(CommonFlags.MODULE_EXPORT)) {
|
||||
value.set(CommonFlags.MODULE_EXPORT);
|
||||
}
|
||||
}
|
||||
@ -1212,7 +1212,7 @@ export class Program extends DiagnosticEmitter {
|
||||
)
|
||||
: DecoratorFlags.NONE
|
||||
);
|
||||
prototype.namespace = namespace;
|
||||
prototype.parent = namespace;
|
||||
this.elementsLookup.set(internalName, prototype);
|
||||
|
||||
if (namespace) {
|
||||
@ -1229,6 +1229,7 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
namespace.members.set(simpleName, prototype);
|
||||
if (namespace.is(CommonFlags.MODULE_EXPORT) && prototype.is(CommonFlags.EXPORT)) {
|
||||
prototype.parent = namespace;
|
||||
prototype.set(CommonFlags.MODULE_EXPORT);
|
||||
}
|
||||
} else if (prototype.is(CommonFlags.EXPORT)) { // no namespace
|
||||
@ -1358,7 +1359,7 @@ export class Program extends DiagnosticEmitter {
|
||||
? this.filterDecorators(decorators, DecoratorFlags.GLOBAL)
|
||||
: DecoratorFlags.NONE
|
||||
);
|
||||
prototype.namespace = namespace;
|
||||
prototype.parent = namespace;
|
||||
this.elementsLookup.set(internalName, prototype);
|
||||
|
||||
if (namespace) {
|
||||
@ -1436,7 +1437,7 @@ export class Program extends DiagnosticEmitter {
|
||||
var namespace = this.elementsLookup.get(internalName);
|
||||
if (!namespace) {
|
||||
namespace = new Namespace(this, simpleName, internalName, declaration);
|
||||
namespace.namespace = parentNamespace;
|
||||
namespace.parent = parentNamespace;
|
||||
this.elementsLookup.set(internalName, namespace);
|
||||
this.checkGlobalOptions(namespace, declaration);
|
||||
}
|
||||
@ -1563,7 +1564,7 @@ export class Program extends DiagnosticEmitter {
|
||||
Type.void, // resolved later on
|
||||
declaration
|
||||
);
|
||||
global.namespace = namespace;
|
||||
global.parent = namespace;
|
||||
this.elementsLookup.set(internalName, global);
|
||||
|
||||
if (namespace) {
|
||||
@ -1836,14 +1837,14 @@ export class Program extends DiagnosticEmitter {
|
||||
// }
|
||||
|
||||
// search contextual parent namespaces if applicable
|
||||
if (namespace = contextualFunction.prototype.namespace) {
|
||||
if (namespace = contextualFunction.prototype.parent) {
|
||||
do {
|
||||
if (element = this.elementsLookup.get(namespace.internalName + STATIC_DELIMITER + name)) {
|
||||
this.resolvedThisExpression = null;
|
||||
this.resolvedElementExpression = null;
|
||||
return element; // LOCAL
|
||||
}
|
||||
} while (namespace = namespace.namespace);
|
||||
} while (namespace = namespace.parent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2061,7 +2062,7 @@ export class Program extends DiagnosticEmitter {
|
||||
return explicitLocal;
|
||||
}
|
||||
}
|
||||
let parent = contextualFunction.memberOf;
|
||||
let parent = contextualFunction.parent;
|
||||
if (parent) {
|
||||
this.resolvedThisExpression = null;
|
||||
this.resolvedElementExpression = null;
|
||||
@ -2082,7 +2083,7 @@ export class Program extends DiagnosticEmitter {
|
||||
return explicitLocal;
|
||||
}
|
||||
}
|
||||
let parent = contextualFunction.memberOf;
|
||||
let parent = contextualFunction.parent;
|
||||
if (parent && parent.kind == ElementKind.CLASS && (parent = (<Class>parent).base)) {
|
||||
this.resolvedThisExpression = null;
|
||||
this.resolvedElementExpression = null;
|
||||
@ -2308,8 +2309,8 @@ export abstract class Element {
|
||||
decoratorFlags: DecoratorFlags = DecoratorFlags.NONE;
|
||||
/** Namespaced member elements. */
|
||||
members: Map<string,Element> | null = null;
|
||||
/** Parent namespace, if applicable. */
|
||||
namespace: Element | null = null;
|
||||
/** Parent element, if applicable. */
|
||||
parent: Element | null = null;
|
||||
|
||||
/** Constructs a new element, linking it to its containing {@link Program}. */
|
||||
protected constructor(program: Program, simpleName: string, internalName: string) {
|
||||
@ -2378,8 +2379,6 @@ export class EnumValue extends Element {
|
||||
|
||||
/** Declaration reference. */
|
||||
declaration: EnumValueDeclaration;
|
||||
/** Parent enum. */
|
||||
enum: Enum;
|
||||
/** Constant value, if applicable. */
|
||||
constantValue: i32 = 0;
|
||||
|
||||
@ -2391,7 +2390,7 @@ export class EnumValue extends Element {
|
||||
declaration: EnumValueDeclaration
|
||||
) {
|
||||
super(program, simpleName, internalName);
|
||||
this.enum = enm;
|
||||
this.parent = enm;
|
||||
this.declaration = declaration;
|
||||
}
|
||||
}
|
||||
@ -2732,8 +2731,6 @@ export class Function extends Element {
|
||||
prototype: FunctionPrototype;
|
||||
/** Function signature. */
|
||||
signature: Signature;
|
||||
/** If a member of another namespace-like element, the concrete element it is a member of. */
|
||||
memberOf: Element | null;
|
||||
/** Map of locals by name. */
|
||||
locals: Map<string,Local> = new Map();
|
||||
/** List of additional non-parameter locals. */
|
||||
@ -2764,19 +2761,19 @@ export class Function extends Element {
|
||||
prototype: FunctionPrototype,
|
||||
internalName: string,
|
||||
signature: Signature,
|
||||
memberOf: Element | null = null,
|
||||
parent: Element | null = null,
|
||||
contextualTypeArguments: Map<string,Type> | null = null
|
||||
) {
|
||||
super(prototype.program, prototype.simpleName, internalName);
|
||||
this.prototype = prototype;
|
||||
this.signature = signature;
|
||||
this.memberOf = memberOf;
|
||||
this.parent = parent;
|
||||
this.flags = prototype.flags;
|
||||
this.decoratorFlags = prototype.decoratorFlags;
|
||||
this.contextualTypeArguments = contextualTypeArguments;
|
||||
if (!(prototype.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN) || prototype.is(CommonFlags.DECLARE))) {
|
||||
let localIndex = 0;
|
||||
if (memberOf && memberOf.kind == ElementKind.CLASS) {
|
||||
if (parent && parent.kind == ElementKind.CLASS) {
|
||||
assert(this.is(CommonFlags.INSTANCE));
|
||||
this.locals.set(
|
||||
"this",
|
||||
@ -2787,7 +2784,7 @@ export class Function extends Element {
|
||||
assert(signature.thisType)
|
||||
)
|
||||
);
|
||||
let inheritedTypeArguments = (<Class>memberOf).contextualTypeArguments;
|
||||
let inheritedTypeArguments = (<Class>parent).contextualTypeArguments;
|
||||
if (inheritedTypeArguments) {
|
||||
if (!this.contextualTypeArguments) this.contextualTypeArguments = new Map();
|
||||
for (let [inheritedName, inheritedType] of inheritedTypeArguments) {
|
||||
@ -3048,12 +3045,14 @@ export class Field extends VariableLikeElement {
|
||||
prototype: FieldPrototype,
|
||||
internalName: string,
|
||||
type: Type,
|
||||
declaration: FieldDeclaration
|
||||
declaration: FieldDeclaration,
|
||||
parent: Class
|
||||
) {
|
||||
super(prototype.program, prototype.simpleName, internalName, type, declaration);
|
||||
this.prototype = prototype;
|
||||
this.flags = prototype.flags;
|
||||
this.type = type;
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3219,7 +3218,8 @@ export class ClassPrototype extends Element {
|
||||
<FieldPrototype>member,
|
||||
internalName + INSTANCE_DELIMITER + (<FieldPrototype>member).simpleName,
|
||||
fieldType,
|
||||
fieldDeclaration
|
||||
fieldDeclaration,
|
||||
instance
|
||||
);
|
||||
switch (fieldType.byteSize) { // align
|
||||
case 1: break;
|
||||
|
25
src/types.ts
25
src/types.ts
@ -557,19 +557,22 @@ export class Signature {
|
||||
return thisReturnType == targetReturnType || thisReturnType.isAssignableTo(targetReturnType);
|
||||
}
|
||||
|
||||
/** Converts a signature to a function type string. */
|
||||
static makeSignatureString(parameterTypes: Type[] | null, returnType: Type, thisType: Type | null = null): string {
|
||||
var sb = [];
|
||||
if (thisType) sb.push(thisType.toSignatureString());
|
||||
if (parameterTypes) {
|
||||
for (let i = 0, k = parameterTypes.length; i < k; ++i) {
|
||||
sb.push(parameterTypes[i].toSignatureString());
|
||||
}
|
||||
}
|
||||
sb.push(returnType.toSignatureString());
|
||||
return sb.join("");
|
||||
}
|
||||
|
||||
/** Converts this signature to a function type string. */
|
||||
toSignatureString(): string {
|
||||
var sb = [];
|
||||
var thisType = this.thisType;
|
||||
if (thisType) {
|
||||
sb.push(thisType.toSignatureString());
|
||||
}
|
||||
var parameterTypes = this.parameterTypes;
|
||||
for (let i = 0, k = parameterTypes.length; i < k; ++i) {
|
||||
sb.push(parameterTypes[i].toSignatureString());
|
||||
}
|
||||
sb.push(this.returnType.toSignatureString());
|
||||
return sb.join("");
|
||||
return Signature.makeSignatureString(this.parameterTypes, this.returnType, this.thisType);
|
||||
}
|
||||
|
||||
/** Converts this signature to a string. */
|
||||
|
@ -18,20 +18,20 @@
|
||||
(global $enum/SelfReference.ZERO i32 (i32.const 0))
|
||||
(global $enum/SelfReference.ONE i32 (i32.const 1))
|
||||
(memory $0 1)
|
||||
(export "enum/Implicit.ZERO" (global $enum/Implicit.ZERO))
|
||||
(export "enum/Implicit.ONE" (global $enum/Implicit.ONE))
|
||||
(export "enum/Implicit.TWO" (global $enum/Implicit.TWO))
|
||||
(export "enum/Implicit.THREE" (global $enum/Implicit.THREE))
|
||||
(export "enum/Explicit.ZERO" (global $enum/Explicit.ZERO))
|
||||
(export "enum/Explicit.ONE" (global $enum/Explicit.ONE))
|
||||
(export "enum/Explicit.TWO" (global $enum/Explicit.TWO))
|
||||
(export "enum/Explicit.THREE" (global $enum/Explicit.THREE))
|
||||
(export "enum/Mixed.ZERO" (global $enum/Mixed.ZERO))
|
||||
(export "enum/Mixed.ONE" (global $enum/Mixed.ONE))
|
||||
(export "enum/Mixed.THREE" (global $enum/Mixed.THREE))
|
||||
(export "enum/Mixed.FOUR" (global $enum/Mixed.FOUR))
|
||||
(export "enum/SelfReference.ZERO" (global $enum/SelfReference.ZERO))
|
||||
(export "enum/SelfReference.ONE" (global $enum/SelfReference.ONE))
|
||||
(export "Implicit.ZERO" (global $enum/Implicit.ZERO))
|
||||
(export "Implicit.ONE" (global $enum/Implicit.ONE))
|
||||
(export "Implicit.TWO" (global $enum/Implicit.TWO))
|
||||
(export "Implicit.THREE" (global $enum/Implicit.THREE))
|
||||
(export "Explicit.ZERO" (global $enum/Explicit.ZERO))
|
||||
(export "Explicit.ONE" (global $enum/Explicit.ONE))
|
||||
(export "Explicit.TWO" (global $enum/Explicit.TWO))
|
||||
(export "Explicit.THREE" (global $enum/Explicit.THREE))
|
||||
(export "Mixed.ZERO" (global $enum/Mixed.ZERO))
|
||||
(export "Mixed.ONE" (global $enum/Mixed.ONE))
|
||||
(export "Mixed.THREE" (global $enum/Mixed.THREE))
|
||||
(export "Mixed.FOUR" (global $enum/Mixed.FOUR))
|
||||
(export "SelfReference.ZERO" (global $enum/SelfReference.ZERO))
|
||||
(export "SelfReference.ONE" (global $enum/SelfReference.ONE))
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $enum/getZero (; 0 ;) (type $i) (result i32)
|
||||
|
@ -19,20 +19,20 @@
|
||||
(global $enum/SelfReference.ONE i32 (i32.const 1))
|
||||
(global $HEAP_BASE i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(export "enum/Implicit.ZERO" (global $enum/Implicit.ZERO))
|
||||
(export "enum/Implicit.ONE" (global $enum/Implicit.ONE))
|
||||
(export "enum/Implicit.TWO" (global $enum/Implicit.TWO))
|
||||
(export "enum/Implicit.THREE" (global $enum/Implicit.THREE))
|
||||
(export "enum/Explicit.ZERO" (global $enum/Explicit.ZERO))
|
||||
(export "enum/Explicit.ONE" (global $enum/Explicit.ONE))
|
||||
(export "enum/Explicit.TWO" (global $enum/Explicit.TWO))
|
||||
(export "enum/Explicit.THREE" (global $enum/Explicit.THREE))
|
||||
(export "enum/Mixed.ZERO" (global $enum/Mixed.ZERO))
|
||||
(export "enum/Mixed.ONE" (global $enum/Mixed.ONE))
|
||||
(export "enum/Mixed.THREE" (global $enum/Mixed.THREE))
|
||||
(export "enum/Mixed.FOUR" (global $enum/Mixed.FOUR))
|
||||
(export "enum/SelfReference.ZERO" (global $enum/SelfReference.ZERO))
|
||||
(export "enum/SelfReference.ONE" (global $enum/SelfReference.ONE))
|
||||
(export "Implicit.ZERO" (global $enum/Implicit.ZERO))
|
||||
(export "Implicit.ONE" (global $enum/Implicit.ONE))
|
||||
(export "Implicit.TWO" (global $enum/Implicit.TWO))
|
||||
(export "Implicit.THREE" (global $enum/Implicit.THREE))
|
||||
(export "Explicit.ZERO" (global $enum/Explicit.ZERO))
|
||||
(export "Explicit.ONE" (global $enum/Explicit.ONE))
|
||||
(export "Explicit.TWO" (global $enum/Explicit.TWO))
|
||||
(export "Explicit.THREE" (global $enum/Explicit.THREE))
|
||||
(export "Mixed.ZERO" (global $enum/Mixed.ZERO))
|
||||
(export "Mixed.ONE" (global $enum/Mixed.ONE))
|
||||
(export "Mixed.THREE" (global $enum/Mixed.THREE))
|
||||
(export "Mixed.FOUR" (global $enum/Mixed.FOUR))
|
||||
(export "SelfReference.ZERO" (global $enum/SelfReference.ZERO))
|
||||
(export "SelfReference.ONE" (global $enum/SelfReference.ONE))
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $enum/getZero (; 0 ;) (type $i) (result i32)
|
||||
|
@ -11,7 +11,7 @@
|
||||
(export "a" (global $export/a))
|
||||
(export "b" (global $export/b))
|
||||
(export "renamed_c" (global $export/c))
|
||||
(export "two" (func $export/ns.two))
|
||||
(export "ns.two" (func $export/ns.two))
|
||||
(export "memory" (memory $0))
|
||||
(func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(i32.add
|
||||
|
@ -12,7 +12,7 @@
|
||||
(export "a" (global $export/a))
|
||||
(export "b" (global $export/b))
|
||||
(export "renamed_c" (global $export/c))
|
||||
(export "two" (func $export/ns.two))
|
||||
(export "ns.two" (func $export/ns.two))
|
||||
(export "memory" (memory $0))
|
||||
(func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(return
|
||||
|
66
tests/compiler/exports.optimized.wat
Normal file
66
tests/compiler/exports.optimized.wat
Normal file
@ -0,0 +1,66 @@
|
||||
(module
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(type $i (func (result i32)))
|
||||
(type $ii (func (param i32) (result i32)))
|
||||
(type $iiv (func (param i32 i32)))
|
||||
(type $iv (func (param i32)))
|
||||
(global $exports/Animal.CAT i32 (i32.const 0))
|
||||
(global $exports/Animal.DOG i32 (i32.const 1))
|
||||
(global $exports/animals.Animal.CAT i32 (i32.const 0))
|
||||
(global $exports/animals.Animal.DOG i32 (i32.const 1))
|
||||
(global $exports/Car.TIRES i32 (i32.const 4))
|
||||
(global $exports/vehicles.Car.TIRES i32 (i32.const 4))
|
||||
(global $exports/outer.inner.a i32 (i32.const 42))
|
||||
(memory $0 1)
|
||||
(export "add" (func $exports/add))
|
||||
(export "math.sub" (func $exports/math.sub))
|
||||
(export "Animal.CAT" (global $exports/Animal.CAT))
|
||||
(export "Animal.DOG" (global $exports/Animal.DOG))
|
||||
(export "animals.Animal.CAT" (global $exports/animals.Animal.CAT))
|
||||
(export "animals.Animal.DOG" (global $exports/animals.Animal.DOG))
|
||||
(export "Car.TIRES" (global $exports/Car.TIRES))
|
||||
(export "Car.getNumTires" (func $exports/Car.getNumTires))
|
||||
(export "Car#get:doors" (func $Car#get:doors))
|
||||
(export "Car#set:doors" (func $Car#set:doors))
|
||||
(export "Car#get:numDoors" (func $Car#get:doors))
|
||||
(export "Car#set:numDoors" (func $Car#set:doors))
|
||||
(export "Car#openDoors" (func $exports/Car#openDoors))
|
||||
(export "vehicles.Car.TIRES" (global $exports/vehicles.Car.TIRES))
|
||||
(export "vehicles.Car.getNumTires" (func $exports/Car.getNumTires))
|
||||
(export "vehicles.Car#get:doors" (func $Car#get:doors))
|
||||
(export "vehicles.Car#set:doors" (func $Car#set:doors))
|
||||
(export "vehicles.Car#get:numDoors" (func $Car#get:doors))
|
||||
(export "vehicles.Car#set:numDoors" (func $Car#set:doors))
|
||||
(export "vehicles.Car#openDoors" (func $exports/Car#openDoors))
|
||||
(export "outer.inner.a" (global $exports/outer.inner.a))
|
||||
(export "memory" (memory $0))
|
||||
(func $exports/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(func $exports/math.sub (; 1 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(i32.sub
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(func $exports/Car.getNumTires (; 2 ;) (type $i) (result i32)
|
||||
(i32.const 4)
|
||||
)
|
||||
(func $Car#get:doors (; 3 ;) (type $ii) (param $0 i32) (result i32)
|
||||
(i32.load
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(func $Car#set:doors (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32)
|
||||
(i32.store
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(func $exports/Car#openDoors (; 5 ;) (type $iv) (param $0 i32)
|
||||
(nop)
|
||||
)
|
||||
)
|
54
tests/compiler/exports.ts
Normal file
54
tests/compiler/exports.ts
Normal file
@ -0,0 +1,54 @@
|
||||
// top-level function
|
||||
export function add(a: i32, b: i32): i32 {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
// namespaced function
|
||||
export namespace math {
|
||||
export function sub(a: i32, b: i32): i32 {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
|
||||
// top-level enum
|
||||
export enum Animal {
|
||||
CAT,
|
||||
DOG
|
||||
}
|
||||
|
||||
// namespaced enum
|
||||
export namespace animals {
|
||||
export enum Animal {
|
||||
CAT,
|
||||
DOG
|
||||
}
|
||||
}
|
||||
|
||||
// top-level class
|
||||
export class Car {
|
||||
static readonly TIRES: i32 = 4;
|
||||
static getNumTires(): i32 { return this.TIRES; }
|
||||
constructor(public doors: i32 = 2) { this.doors = doors; }
|
||||
get numDoors(): i32 { return this.doors; }
|
||||
set numDoors(doors: i32) { this.doors = doors; }
|
||||
openDoors(): void {}
|
||||
}
|
||||
|
||||
// namespaced class
|
||||
export namespace vehicles {
|
||||
export class Car {
|
||||
static readonly TIRES: i32 = 4;
|
||||
static getNumTires(): i32 { return this.TIRES; }
|
||||
constructor(public doors: i32 = 2) { this.doors = doors; }
|
||||
get numDoors(): i32 { return this.doors; }
|
||||
set numDoors(doors: i32) { this.doors = doors; }
|
||||
openDoors(): void {}
|
||||
}
|
||||
}
|
||||
|
||||
// namespaced namespace
|
||||
export namespace outer {
|
||||
export namespace inner {
|
||||
export const a = 42;
|
||||
}
|
||||
}
|
116
tests/compiler/exports.untouched.wat
Normal file
116
tests/compiler/exports.untouched.wat
Normal file
@ -0,0 +1,116 @@
|
||||
(module
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(type $i (func (result i32)))
|
||||
(type $ii (func (param i32) (result i32)))
|
||||
(type $iiv (func (param i32 i32)))
|
||||
(type $iv (func (param i32)))
|
||||
(global $exports/Animal.CAT i32 (i32.const 0))
|
||||
(global $exports/Animal.DOG i32 (i32.const 1))
|
||||
(global $exports/animals.Animal.CAT i32 (i32.const 0))
|
||||
(global $exports/animals.Animal.DOG i32 (i32.const 1))
|
||||
(global $exports/Car.TIRES i32 (i32.const 4))
|
||||
(global $exports/vehicles.Car.TIRES i32 (i32.const 4))
|
||||
(global $exports/outer.inner.a i32 (i32.const 42))
|
||||
(global $HEAP_BASE i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(export "add" (func $exports/add))
|
||||
(export "math.sub" (func $exports/math.sub))
|
||||
(export "Animal.CAT" (global $exports/Animal.CAT))
|
||||
(export "Animal.DOG" (global $exports/Animal.DOG))
|
||||
(export "animals.Animal.CAT" (global $exports/animals.Animal.CAT))
|
||||
(export "animals.Animal.DOG" (global $exports/animals.Animal.DOG))
|
||||
(export "Car.TIRES" (global $exports/Car.TIRES))
|
||||
(export "Car.getNumTires" (func $exports/Car.getNumTires))
|
||||
(export "Car#get:doors" (func $Car#get:doors))
|
||||
(export "Car#set:doors" (func $Car#set:doors))
|
||||
(export "Car#get:numDoors" (func $exports/Car#get:numDoors))
|
||||
(export "Car#set:numDoors" (func $exports/Car#set:numDoors))
|
||||
(export "Car#openDoors" (func $exports/Car#openDoors))
|
||||
(export "vehicles.Car.TIRES" (global $exports/vehicles.Car.TIRES))
|
||||
(export "vehicles.Car.getNumTires" (func $exports/vehicles.Car.getNumTires))
|
||||
(export "vehicles.Car#get:doors" (func $vehicles.Car#get:doors))
|
||||
(export "vehicles.Car#set:doors" (func $vehicles.Car#set:doors))
|
||||
(export "vehicles.Car#get:numDoors" (func $exports/vehicles.Car#get:numDoors))
|
||||
(export "vehicles.Car#set:numDoors" (func $exports/vehicles.Car#set:numDoors))
|
||||
(export "vehicles.Car#openDoors" (func $exports/vehicles.Car#openDoors))
|
||||
(export "outer.inner.a" (global $exports/outer.inner.a))
|
||||
(export "memory" (memory $0))
|
||||
(func $exports/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(return
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $exports/math.sub (; 1 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(return
|
||||
(i32.sub
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $exports/Car.getNumTires (; 2 ;) (type $i) (result i32)
|
||||
(return
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(func $Car#get:doors (; 3 ;) (type $ii) (param $0 i32) (result i32)
|
||||
(i32.load
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(func $Car#set:doors (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32)
|
||||
(i32.store
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(func $exports/Car#get:numDoors (; 5 ;) (type $ii) (param $0 i32) (result i32)
|
||||
(return
|
||||
(i32.load
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $exports/Car#set:numDoors (; 6 ;) (type $iiv) (param $0 i32) (param $1 i32)
|
||||
(i32.store
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(func $exports/Car#openDoors (; 7 ;) (type $iv) (param $0 i32)
|
||||
)
|
||||
(func $exports/vehicles.Car.getNumTires (; 8 ;) (type $i) (result i32)
|
||||
(return
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(func $vehicles.Car#get:doors (; 9 ;) (type $ii) (param $0 i32) (result i32)
|
||||
(i32.load
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(func $vehicles.Car#set:doors (; 10 ;) (type $iiv) (param $0 i32) (param $1 i32)
|
||||
(i32.store
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(func $exports/vehicles.Car#get:numDoors (; 11 ;) (type $ii) (param $0 i32) (result i32)
|
||||
(return
|
||||
(i32.load
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $exports/vehicles.Car#set:numDoors (; 12 ;) (type $iiv) (param $0 i32) (param $1 i32)
|
||||
(i32.store
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(func $exports/vehicles.Car#openDoors (; 13 ;) (type $iv) (param $0 i32)
|
||||
)
|
||||
)
|
@ -54,10 +54,10 @@
|
||||
(export "anExportedConstantGlobal" (global $showcase/anExportedConstantGlobal))
|
||||
(export "aConstantGlobal" (global $showcase/aConstantGlobal))
|
||||
(export "anAliasedConstantGlobal" (global $showcase/anExportedConstantGlobal))
|
||||
(export "showcase/AnEnum.ONE" (global $showcase/AnEnum.ONE))
|
||||
(export "showcase/AnEnum.TWO" (global $showcase/AnEnum.TWO))
|
||||
(export "showcase/AnEnum.FOUR" (global $showcase/AnEnum.FOUR))
|
||||
(export "showcase/AnEnum.FIVE" (global $showcase/AnEnum.FIVE))
|
||||
(export "AnEnum.ONE" (global $showcase/AnEnum.ONE))
|
||||
(export "AnEnum.TWO" (global $showcase/AnEnum.TWO))
|
||||
(export "AnEnum.FOUR" (global $showcase/AnEnum.FOUR))
|
||||
(export "AnEnum.FIVE" (global $showcase/AnEnum.FIVE))
|
||||
(export "anExportedFunction" (func $showcase/anExportedFunction))
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
|
@ -64,10 +64,10 @@
|
||||
(export "anExportedConstantGlobal" (global $showcase/anExportedConstantGlobal))
|
||||
(export "aConstantGlobal" (global $showcase/aConstantGlobal))
|
||||
(export "anAliasedConstantGlobal" (global $showcase/anExportedConstantGlobal))
|
||||
(export "showcase/AnEnum.ONE" (global $showcase/AnEnum.ONE))
|
||||
(export "showcase/AnEnum.TWO" (global $showcase/AnEnum.TWO))
|
||||
(export "showcase/AnEnum.FOUR" (global $showcase/AnEnum.FOUR))
|
||||
(export "showcase/AnEnum.FIVE" (global $showcase/AnEnum.FIVE))
|
||||
(export "AnEnum.ONE" (global $showcase/AnEnum.ONE))
|
||||
(export "AnEnum.TWO" (global $showcase/AnEnum.TWO))
|
||||
(export "AnEnum.FOUR" (global $showcase/AnEnum.FOUR))
|
||||
(export "AnEnum.FIVE" (global $showcase/AnEnum.FIVE))
|
||||
(export "anExportedFunction" (func $showcase/anExportedFunction))
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
|
Loading…
x
Reference in New Issue
Block a user