Rename memory instructions; Rework constant handling

This commit is contained in:
dcodeIO
2018-07-18 23:49:32 +02:00
parent 34e8facfdc
commit a1b75b69b7
170 changed files with 26392 additions and 5185 deletions

View File

@ -32,7 +32,6 @@ import {
getConstValueI64High,
getConstValueF32,
getConstValueF64,
getFunctionBody,
getGetLocalIndex,
getBlockChildCount,
getBlockChild,
@ -404,9 +403,172 @@ export class Compiler extends DiagnosticEmitter {
if (!functionTableExported) module.addTableExport("0", "table");
}
// set up module exports
for (let [name, moduleExport] of program.moduleLevelExports) {
this.makeModuleExport(name, moduleExport.element);
}
return module;
}
/** Applies the respective module export(s) for the specified element. */
private makeModuleExport(name: string, element: Element, prefix: string = ""): void {
// traverse members
var members = element.members;
if (members) {
let subPrefix = prefix + name + (element.kind == ElementKind.CLASS
? INSTANCE_DELIMITER
: STATIC_DELIMITER
);
if (element.kind == ElementKind.NAMESPACE) {
for (let member of members.values()) {
if (!member.is(CommonFlags.EXPORT)) continue;
this.makeModuleExport(member.simpleName, member, subPrefix);
}
} else {
for (let member of members.values()) {
if (member.is(CommonFlags.PRIVATE)) continue;
this.makeModuleExport(member.simpleName, member, subPrefix);
}
}
}
switch (element.kind) {
// export global
case ElementKind.GLOBAL: {
let isConst = element.is(CommonFlags.CONST) || element.is(CommonFlags.STATIC | CommonFlags.READONLY);
if (!isConst && !this.options.hasFeature(Feature.MUTABLE_GLOBAL)) {
let declaration = (<Global>element).declaration;
if (declaration) {
this.error(
DiagnosticCode.Cannot_export_a_mutable_global,
declaration.name.range
);
}
} else {
this.module.addGlobalExport(element.internalName, prefix + name);
}
break;
}
case ElementKind.ENUMVALUE: {
if (!assert(element.parent).is(CommonFlags.CONST) && !this.options.hasFeature(Feature.MUTABLE_GLOBAL)) {
let declaration = (<EnumValue>element).declaration;
if (declaration) {
this.error(
DiagnosticCode.Cannot_export_a_mutable_global,
declaration.name.range
);
}
} else {
this.module.addGlobalExport(element.internalName, prefix + name);
}
break;
}
// export function
case ElementKind.FUNCTION: {
let instance = <Function>element;
let signature = instance.signature;
if (signature.requiredParameters < signature.parameterTypes.length) {
// utilize trampoline to fill in omitted arguments
instance = this.ensureTrampoline(instance);
this.ensureArgcSet();
}
if (instance.is(CommonFlags.COMPILED)) this.module.addFunctionExport(instance.internalName, prefix + name);
break;
}
// export getter and setter
case ElementKind.PROPERTY: {
let getter = assert((<Property>element).getterPrototype);
this.makeModuleExport(GETTER_PREFIX + name, getter, prefix);
let setter = (<Property>element).setterPrototype;
if (setter) this.makeModuleExport(SETTER_PREFIX + name, setter, prefix);
break;
}
// export a getter and a setter
case ElementKind.FIELD: {
let module = this.module;
let type = (<Field>element).type;
let nativeType = type.toNativeType();
let offset = (<Field>element).memoryOffset;
let usizeType = this.options.usizeType;
let nativeSizeType = this.options.nativeSizeType;
// make a getter
let getterName = prefix + 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);
// make a setter
if (!element.is(CommonFlags.READONLY)) {
let setterName = prefix + 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;
}
// skip prototype and export instances
case ElementKind.FUNCTION_PROTOTYPE: {
for (let instance of (<FunctionPrototype>element).instances.values()) {
let instanceName = name;
if (instance.is(CommonFlags.GENERIC)) {
let fullName = instance.internalName;
instanceName += fullName.substring(fullName.lastIndexOf("<"));
}
this.makeModuleExport(instanceName, instance, prefix);
}
break;
}
case ElementKind.CLASS_PROTOTYPE: {
for (let instance of (<ClassPrototype>element).instances.values()) {
let instanceName = name;
if (instance.is(CommonFlags.GENERIC)) {
let fullName = instance.internalName;
instanceName += fullName.substring(fullName.lastIndexOf("<"));
}
let ctor = instance.constructorInstance;
if (ctor) this.makeModuleExport(instanceName + INSTANCE_DELIMITER + ctor.simpleName, ctor, prefix);
this.makeModuleExport(instanceName, instance, prefix);
}
break;
}
// all possible members already handled above
case ElementKind.ENUM:
case ElementKind.CLASS:
case ElementKind.NAMESPACE: break;
default: assert(false);
}
}
// sources
/** Compiles a source by looking it up by path first. */
@ -568,13 +730,13 @@ export class Compiler extends DiagnosticEmitter {
if (global.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) return true;
var nativeType = global.type.toNativeType();
var isConstant = global.isAny(CommonFlags.CONST) || global.is(CommonFlags.STATIC | CommonFlags.READONLY);
var isDeclaredConstant = global.is(CommonFlags.CONST) || global.is(CommonFlags.STATIC | CommonFlags.READONLY);
// handle imports
if (global.is(CommonFlags.AMBIENT)) {
// constant global
if (isConstant || this.options.hasFeature(Feature.MUTABLE_GLOBAL)) {
if (isDeclaredConstant || this.options.hasFeature(Feature.MUTABLE_GLOBAL)) {
global.set(CommonFlags.MODULE_IMPORT);
if (declaration) {
mangleImportName(global, declaration, global.parent);
@ -601,49 +763,77 @@ export class Compiler extends DiagnosticEmitter {
return false;
}
// the MVP does not yet support initializer expressions other than constant values (and
// the MVP does not yet support initializer expressions other than constant values (and constant
// get_globals), hence such initializations must be performed in the start function for now.
var initializeInStart = false;
// inlined constant can be compiled as-is
if (global.is(CommonFlags.INLINED)) {
initExpr = this.compileInlineConstant(global, global.type, true);
// evaluate initializer if present
if (declaration !== null && declaration.initializer !== null) {
if (!initExpr) {
initExpr = this.compileExpression(
declaration.initializer,
global.type,
ConversionKind.IMPLICIT,
WrapMode.WRAP
);
}
} else {
// evaluate initializer if present
if (declaration && declaration.initializer) {
if (!initExpr) {
initExpr = this.compileExpression(
declaration.initializer,
global.type,
ConversionKind.IMPLICIT,
WrapMode.WRAP
);
}
// check if the initializer is constant
if (getExpressionId(initExpr) != ExpressionId.Const) {
// if a constant global, check if the initializer becomes constant after precompute
if (isConstant) {
initExpr = this.precomputeExpressionRef(initExpr);
if (getExpressionId(initExpr) != ExpressionId.Const) {
this.warning(
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
declaration.range
);
initializeInStart = true;
}
} else {
if (getExpressionId(initExpr) != ExpressionId.Const) {
if (isDeclaredConstant) {
initExpr = module.precomputeExpression(initExpr);
if (getExpressionId(initExpr) != ExpressionId.Const) {
this.warning(
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
declaration.range
);
initializeInStart = true;
}
} else {
initializeInStart = true;
}
// initialize to zero if there's no initializer
} else {
initExpr = global.type.toNativeZero(module);
}
// explicitly inline if annotated
if (global.hasDecorator(DecoratorFlags.INLINE)) {
if (!initializeInStart) { // reported above
assert(getExpressionId(initExpr) == ExpressionId.Const);
let exprType = getExpressionType(initExpr);
switch (exprType) {
case NativeType.I32: {
global.constantValueKind = ConstantValueKind.INTEGER;
global.constantIntegerValue = i64_new(getConstValueI32(initExpr), 0);
break;
}
case NativeType.I64: {
global.constantValueKind = ConstantValueKind.INTEGER;
global.constantIntegerValue = i64_new(
getConstValueI64Low(initExpr),
getConstValueI64High(initExpr)
);
break;
}
case NativeType.F32: {
global.constantValueKind = ConstantValueKind.FLOAT;
global.constantFloatValue = getConstValueF32(initExpr);
break;
}
case NativeType.F64: {
global.constantValueKind = ConstantValueKind.FLOAT;
global.constantFloatValue = getConstValueF64(initExpr);
break;
}
default: {
assert(false);
return false;
}
}
global.set(CommonFlags.INLINED); // inline the value from now on
}
}
// initialize to zero if there's no initializer
} else {
initExpr = global.type.toNativeZero(module);
}
var internalName = global.internalName;
@ -652,50 +842,8 @@ export class Compiler extends DiagnosticEmitter {
module.addGlobal(internalName, nativeType, true, global.type.toNativeZero(module));
this.startFunctionBody.push(module.createSetGlobal(internalName, initExpr));
} else { // compile as-is
if (isConstant) {
let exprType = getExpressionType(initExpr);
switch (exprType) {
case NativeType.I32: {
global.constantValueKind = ConstantValueKind.INTEGER;
global.constantIntegerValue = i64_new(getConstValueI32(initExpr), 0);
break;
}
case NativeType.I64: {
global.constantValueKind = ConstantValueKind.INTEGER;
global.constantIntegerValue = i64_new(
getConstValueI64Low(initExpr),
getConstValueI64High(initExpr)
);
break;
}
case NativeType.F32: {
global.constantValueKind = ConstantValueKind.FLOAT;
global.constantFloatValue = getConstValueF32(initExpr);
break;
}
case NativeType.F64: {
global.constantValueKind = ConstantValueKind.FLOAT;
global.constantFloatValue = getConstValueF64(initExpr);
break;
}
default: {
assert(false);
return false;
}
}
global.set(CommonFlags.INLINED); // inline the value from now on
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 */ {
module.addGlobal(internalName, nativeType, !isConstant, initExpr);
}
} else { // compile normally
module.addGlobal(internalName, nativeType, !isDeclaredConstant, initExpr);
}
return true;
}
@ -716,6 +864,7 @@ export class Compiler extends DiagnosticEmitter {
var module = this.module;
this.currentEnum = element;
var previousValue: EnumValue | null = null;
var previousValueIsMut = false;
if (element.members) {
for (let member of element.members.values()) {
@ -724,86 +873,61 @@ export class Compiler extends DiagnosticEmitter {
let val = <EnumValue>member;
let valueDeclaration = val.declaration;
val.set(CommonFlags.COMPILED);
if (val.is(CommonFlags.INLINED)) {
if (element.declaration.isTopLevelExport) {
module.addGlobal(
val.internalName,
NativeType.I32,
false, // constant
module.createI32(val.constantValue)
);
}
} else {
let initExpr: ExpressionRef;
if (valueDeclaration.value) {
initExpr = this.compileExpression(
<Expression>valueDeclaration.value,
Type.i32,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
if (getExpressionId(initExpr) != ExpressionId.Const) {
initExpr = this.precomputeExpressionRef(initExpr);
let initExpr: ExpressionRef;
if (valueDeclaration.value) {
initExpr = this.compileExpression(
<Expression>valueDeclaration.value,
Type.i32,
ConversionKind.IMPLICIT,
WrapMode.NONE
);
if (getExpressionId(initExpr) != ExpressionId.Const) {
if (element.is(CommonFlags.CONST)) {
initExpr = module.precomputeExpression(initExpr);
if (getExpressionId(initExpr) != ExpressionId.Const) {
if (element.is(CommonFlags.CONST)) {
this.warning(
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
valueDeclaration.range
);
}
this.error(
DiagnosticCode.In_const_enum_declarations_member_initializer_must_be_constant_expression,
valueDeclaration.value.range
);
initInStart = true;
}
} else {
initInStart = true;
}
} else if (previousValue == null) {
initExpr = module.createI32(0);
} else if (previousValue.is(CommonFlags.INLINED)) {
initExpr = module.createI32(previousValue.constantValue + 1);
} else {
// in TypeScript this errors with TS1061, but actually we can do:
initExpr = module.createBinary(BinaryOp.AddI32,
module.createGetGlobal(previousValue.internalName, NativeType.I32),
module.createI32(1)
}
} else if (previousValue == null) {
initExpr = module.createI32(0);
} else {
if (previousValueIsMut) {
this.error(
DiagnosticCode.Enum_member_must_have_initializer,
valueDeclaration.range
);
}
initExpr = module.createBinary(BinaryOp.AddI32,
module.createGetGlobal(previousValue.internalName, NativeType.I32),
module.createI32(1)
);
initExpr = module.precomputeExpression(initExpr);
if (getExpressionId(initExpr) != ExpressionId.Const) {
if (element.is(CommonFlags.CONST)) {
this.warning(
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
this.error(
DiagnosticCode.In_const_enum_declarations_member_initializer_must_be_constant_expression,
valueDeclaration.range
);
}
initInStart = true;
}
if (initInStart) {
module.addGlobal(
val.internalName,
NativeType.I32,
true, // mutable
module.createI32(0)
);
this.startFunctionBody.push(module.createSetGlobal(val.internalName, initExpr));
} else {
module.addGlobal(val.internalName, NativeType.I32, false, initExpr);
if (getExpressionType(initExpr) == NativeType.I32) {
val.constantValue = getConstValueI32(initExpr);
val.set(CommonFlags.INLINED);
} else {
assert(false);
val.constantValue = 0;
}
}
}
if (initInStart) {
module.addGlobal(val.internalName, NativeType.I32, true, module.createI32(0));
this.startFunctionBody.push(module.createSetGlobal(val.internalName, initExpr));
previousValueIsMut = true;
} else {
module.addGlobal(val.internalName, NativeType.I32, !element.is(CommonFlags.CONST), initExpr);
previousValueIsMut = false;
}
previousValue = <EnumValue>val;
// export values if the enum is exported
if (element.is(CommonFlags.MODULE_EXPORT)) {
if (member.is(CommonFlags.INLINED) || this.options.hasFeature(Feature.MUTABLE_GLOBAL)) {
module.addGlobalExport(member.internalName, mangleExportName(member));
} else if (valueDeclaration) {
this.warning(
DiagnosticCode.Cannot_export_a_mutable_global,
valueDeclaration.range
);
}
}
}
}
this.currentEnum = null;
@ -1015,16 +1139,6 @@ export class Compiler extends DiagnosticEmitter {
);
}
// check module-level export
if (instance.is(CommonFlags.MODULE_EXPORT)) {
if (signature.requiredParameters < signature.parameterTypes.length) {
// export the trampoline if the function takes optional parameters
instance = this.ensureTrampoline(instance);
this.ensureArgcSet();
}
module.addFunctionExport(instance.internalName, mangleExportName(instance));
}
instance.finalize(module, ref);
return true;
}
@ -1140,18 +1254,14 @@ export class Compiler extends DiagnosticEmitter {
// exports
compileExportStatement(statement: ExportStatement): void {
var module = this.module;
var fileLevelExports = this.program.fileLevelExports;
var members = statement.members;
if (!members) return; // filespace
for (let i = 0, k = members.length; i < k; ++i) {
let member = members[i];
let internalExportName = (
statement.range.source.internalPath +
PATH_DELIMITER +
member.externalName.text
let element = fileLevelExports.get(
statement.range.source.internalPath + PATH_DELIMITER + member.externalName.text
);
let element = fileLevelExports.get(internalExportName);
if (!element) continue; // reported in Program#initialize
switch (element.kind) {
case ElementKind.CLASS_PROTOTYPE: {
@ -1169,36 +1279,18 @@ export class Compiler extends DiagnosticEmitter {
!(<FunctionPrototype>element).is(CommonFlags.GENERIC) &&
statement.range.source.isEntry
) {
let functionInstance = this.compileFunctionUsingTypeArguments(
this.compileFunctionUsingTypeArguments(
<FunctionPrototype>element,
[],
null, // no contextual type arguments
null, // no outer scope
(<FunctionPrototype>element).declaration.name
);
if (functionInstance) {
let functionDeclaration = functionInstance.prototype.declaration;
if (functionDeclaration && functionDeclaration.needsExplicitExport(member)) {
module.addFunctionExport(functionInstance.internalName, member.externalName.text);
}
}
}
break;
}
case ElementKind.GLOBAL: {
if (this.compileGlobal(<Global>element) && statement.range.source.isEntry) {
let globalDeclaration = (<Global>element).declaration;
if (globalDeclaration && globalDeclaration.needsExplicitExport(member)) {
if ((<Global>element).is(CommonFlags.INLINED)) {
module.addGlobalExport(element.internalName, member.externalName.text);
} else {
this.warning(
DiagnosticCode.Cannot_export_a_mutable_global,
member.range
);
}
}
}
this.compileGlobal(<Global>element);
break;
}
case ElementKind.NAMESPACE: {
@ -1310,47 +1402,6 @@ export class Compiler extends DiagnosticEmitter {
}
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: {
@ -1676,7 +1727,7 @@ export class Compiler extends DiagnosticEmitter {
this.currentType
);
// check if the condition is always true
let condPre = this.precomputeExpressionRef(condExpr);
let condPre = module.precomputeExpression(condExpr);
if (getExpressionId(condPre) == ExpressionId.Const) {
assert(getExpressionType(condPre) == NativeType.I32);
if (getConstValueI32(condPre) != 0) alwaysTrue = true;
@ -1766,7 +1817,7 @@ export class Compiler extends DiagnosticEmitter {
this.currentFunction.isAny(CommonFlags.GENERIC | CommonFlags.GENERIC_CONTEXT)
) {
// Try to eliminate unnecesssary branches if the condition is constant
let condExprPrecomp = this.precomputeExpressionRef(condExpr);
let condExprPrecomp = module.precomputeExpression(condExpr);
if (
getExpressionId(condExprPrecomp) == ExpressionId.Const &&
getExpressionType(condExprPrecomp) == NativeType.I32
@ -2057,7 +2108,7 @@ export class Compiler extends DiagnosticEmitter {
let isInlined = false;
if (declaration.is(CommonFlags.CONST)) {
if (initExpr) {
initExpr = this.precomputeExpressionRef(initExpr);
initExpr = this.module.precomputeExpression(initExpr);
if (getExpressionId(initExpr) == ExpressionId.Const) {
let local = new Local(program, name, -1, type);
switch (getExpressionType(initExpr)) {
@ -2162,7 +2213,7 @@ export class Compiler extends DiagnosticEmitter {
this.currentFunction.isAny(CommonFlags.GENERIC | CommonFlags.GENERIC_CONTEXT)
) {
// Try to eliminate unnecesssary loops if the condition is constant
let condExprPrecomp = this.precomputeExpressionRef(condExpr);
let condExprPrecomp = module.precomputeExpression(condExpr);
if (
getExpressionId(condExprPrecomp) == ExpressionId.Const &&
getExpressionType(condExprPrecomp) == NativeType.I32
@ -2432,22 +2483,11 @@ export class Compiler extends DiagnosticEmitter {
conversionKind: ConversionKind,
wrapMode: WrapMode
): ExpressionRef {
return this.precomputeExpressionRef(
return this.module.precomputeExpression(
this.compileExpression(expression, contextualType, conversionKind, wrapMode)
);
}
precomputeExpressionRef(expr: ExpressionRef): ExpressionRef {
var module = this.module;
var type = this.currentType;
var nativeType = type.toNativeType();
var funcRef = module.addTemporaryFunction(nativeType, null, expr);
module.runPasses([ "precompute" ], funcRef);
var ret = getFunctionBody(funcRef);
module.removeTemporaryFunction();
return ret;
}
convertExpression(
expr: ExpressionRef,
fromType: Type,
@ -5497,8 +5537,8 @@ export class Compiler extends DiagnosticEmitter {
names[i] = label;
}
var body = module.createBlock(names[0], [
module.createBlock("oob", [
module.createSwitch(names, "oob",
module.createBlock("outOfRange", [
module.createSwitch(names, "outOfRange",
// condition is number of provided optional arguments, so subtract required arguments
minArguments
? module.createBinary(
@ -5946,10 +5986,11 @@ export class Compiler extends DiagnosticEmitter {
switch (target.kind) {
case ElementKind.LOCAL: {
let localType = (<Local>target).type;
assert(localType != Type.void);
if ((<Local>target).is(CommonFlags.INLINED)) {
return this.compileInlineConstant(<Local>target, contextualType, retainConstantType);
}
let localType = (<Local>target).type;
let localIndex = (<Local>target).index;
assert(localIndex >= 0);
this.currentType = localType;
@ -6252,7 +6293,7 @@ export class Compiler extends DiagnosticEmitter {
? this.compileExpression(<Expression>expressions[i], elementType, ConversionKind.IMPLICIT, WrapMode.NONE)
: elementType.toNativeZero(module);
if (isStatic) {
expr = this.precomputeExpressionRef(exprs[i]);
expr = module.precomputeExpression(exprs[i]);
if (getExpressionId(expr) == ExpressionId.Const) {
assert(getExpressionType(expr) == nativeElementType);
switch (nativeElementType) {
@ -6601,6 +6642,7 @@ export class Compiler extends DiagnosticEmitter {
let parent = (<EnumValue>target).parent;
assert(parent !== null && parent.kind == ElementKind.ENUM);
if (!this.compileEnum(<Enum>parent)) {
this.currentType = Type.i32;
return this.module.createUnreachable();
}
this.currentType = Type.i32;
@ -6688,7 +6730,7 @@ export class Compiler extends DiagnosticEmitter {
this.currentFunction.isAny(CommonFlags.GENERIC | CommonFlags.GENERIC_CONTEXT)
) {
// Try to eliminate unnecesssary branches if the condition is constant
let condExprPrecomp = this.precomputeExpressionRef(condExpr);
let condExprPrecomp = this.module.precomputeExpression(condExpr);
if (
getExpressionId(condExprPrecomp) == ExpressionId.Const &&
getExpressionType(condExprPrecomp) == NativeType.I32
@ -7536,47 +7578,6 @@ export class Compiler extends DiagnosticEmitter {
// helpers
function mangleExportName(element: Element, simpleName: string = element.simpleName): string {
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;
}
}
}
function mangleImportName(
element: Element,
declaration: DeclarationStatement,