Fix external names of class exports and similar; Support a few more kinds in TSDBuilder, see #74

This commit is contained in:
dcodeIO 2018-04-15 00:34:19 +02:00
parent 78a679759a
commit 81223977d0
15 changed files with 713 additions and 202 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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. */

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View 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
View 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;
}
}

View 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)
)
)

View File

@ -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)

View File

@ -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)