mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-05-05 11:52:27 +00:00
Namespaces
This commit is contained in:
parent
7d85b0cc7f
commit
99b0fdf7a8
@ -5,7 +5,7 @@ AssemblyScript NEXT
|
||||
|
||||
**AssemblyScript** is a new compiler targeting [WebAssembly](http://webassembly.org) while utilizing [TypeScript](http://www.typescriptlang.org)'s syntax and [node](https://nodejs.org)'s vibrant ecosystem. Instead of requiring complex toolchains to set up, you can simply `npm install` it - or run it in a browser.
|
||||
|
||||
By compiling syntactially but not necessarily semantically valid TypeScript to [Binaryen](https://github.com/WebAssembly/binaryen) IR, the resulting module can be validated, optimized, emitted in WebAssembly text or binary format and converted to [asm.js](http://asmjs.org) as a polyfill.
|
||||
By compiling syntactially (not necessarily semantically) valid TypeScript to [Binaryen](https://github.com/WebAssembly/binaryen) IR, the resulting module can be validated, optimized, emitted in WebAssembly text or binary format and converted to [asm.js](http://asmjs.org) as a polyfill.
|
||||
|
||||
The compiler itself utilizes "portable definitions" so it can be compiled to both JavaScript using `tsc` and, eventually, to WebAssembly using `asc`.
|
||||
|
||||
|
@ -130,7 +130,8 @@ args._.forEach(filename => {
|
||||
var options = assemblyscript.createOptions();
|
||||
assemblyscript.setTarget(options, 0);
|
||||
assemblyscript.setNoTreeShaking(options, args.noTreeShaking);
|
||||
assemblyscript.setNoDebug(options, args.noDebug);
|
||||
assemblyscript.setNoAssert(options, args.noAssert);
|
||||
// TODO: noDebug binaryen feature, removing names the debug section
|
||||
|
||||
var module = assemblyscript.compile(parser, options);
|
||||
checkDiagnostics(parser);
|
||||
|
@ -43,7 +43,7 @@
|
||||
"desc": "Disables tree-shaking.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"noDebug": {
|
||||
"noAssert": {
|
||||
"desc": "Disables assertions.",
|
||||
"type": "boolean"
|
||||
},
|
||||
|
14
src/ast.ts
14
src/ast.ts
@ -1809,12 +1809,16 @@ export function mangleInternalName(declaration: DeclarationStatement): string {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!declaration.parent)
|
||||
let parent: Node | null = declaration.parent;
|
||||
if (!parent)
|
||||
return name;
|
||||
if (declaration.parent.kind == NodeKind.CLASS)
|
||||
return (<ClassDeclaration>declaration.parent).internalName + (hasModifier(ModifierKind.STATIC, declaration.modifiers) ? STATIC_DELIMITER : INSTANCE_DELIMITER) + name;
|
||||
if (declaration.parent.kind == NodeKind.NAMESPACE || declaration.parent.kind == NodeKind.ENUM)
|
||||
return (<DeclarationStatement>declaration.parent).internalName + STATIC_DELIMITER + name;
|
||||
if (declaration.kind == NodeKind.VARIABLEDECLARATION && parent.kind == NodeKind.VARIABLE) // skip over
|
||||
if (!(parent = parent.parent))
|
||||
return name;
|
||||
if (parent.kind == NodeKind.CLASS)
|
||||
return (<ClassDeclaration>parent).internalName + (hasModifier(ModifierKind.STATIC, declaration.modifiers) ? STATIC_DELIMITER : INSTANCE_DELIMITER) + name;
|
||||
if (parent.kind == NodeKind.NAMESPACE || parent.kind == NodeKind.ENUM)
|
||||
return (<DeclarationStatement>parent).internalName + STATIC_DELIMITER + name;
|
||||
return declaration.range.source.internalPath + PATH_DELIMITER + name;
|
||||
}
|
||||
|
||||
|
@ -494,7 +494,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
return module.createUnreachable();
|
||||
arg0 = compiler.compileExpression(operands[0], Type.i32); // reports
|
||||
compiler.currentType = Type.void;
|
||||
return compiler.options.noDebug
|
||||
return compiler.options.noAssert
|
||||
? module.createNop()
|
||||
: module.createIf(
|
||||
module.createUnary(UnaryOp.EqzI32, arg0),
|
||||
|
138
src/compiler.ts
138
src/compiler.ts
@ -119,7 +119,7 @@ export class Options {
|
||||
/** If true, compiles everything instead of just reachable code. */
|
||||
noTreeShaking: bool = false;
|
||||
/** If true, replaces assertions with nops. */
|
||||
noDebug: bool = false;
|
||||
noAssert: bool = false;
|
||||
}
|
||||
|
||||
const enum ConversionKind {
|
||||
@ -306,7 +306,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
throw new Error("unexpected missing global");
|
||||
if (!this.compileGlobal(<Global>element))
|
||||
return null;
|
||||
if (declaration.range.source.isEntry && (<VariableStatement>declaration.parent).parent == declaration.range.source && hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
||||
if (isModuleExport(element, declaration)) {
|
||||
if ((<Global>element).hasConstantValue)
|
||||
this.module.addGlobalExport(element.internalName, declaration.identifier.name);
|
||||
else
|
||||
@ -470,7 +470,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
const instance: Function | null = this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, typeArguments, contextualTypeArguments, alternativeReportNode);
|
||||
if (!instance)
|
||||
return;
|
||||
if (declaration.range.source.isEntry && declaration.parent == declaration.range.source && hasModifier(ModifierKind.EXPORT, declaration.modifiers))
|
||||
if (isModuleExport(instance, declaration))
|
||||
this.module.addFunctionExport(instance.internalName, declaration.identifier.name);
|
||||
}
|
||||
|
||||
@ -527,7 +527,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// create the function
|
||||
const internalName: string = instance.internalName;
|
||||
if (instance.isDeclared) {
|
||||
if (instance.isDeclared) { // TODO: use parent namespace as externalModuleName, if applicable
|
||||
this.module.addFunctionImport(internalName, "env", declaration.identifier.name, typeRef);
|
||||
} else {
|
||||
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, <ExpressionRef[]>stmts, NativeType.None));
|
||||
@ -573,7 +573,6 @@ export class Compiler extends DiagnosticEmitter {
|
||||
throw new Error("unexpected namespace member");
|
||||
}
|
||||
}
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
compileNamespace(ns: Namespace): void {
|
||||
@ -1834,7 +1833,115 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.compileExpression(expression.expression, contextualType, ConversionKind.NONE);
|
||||
}
|
||||
|
||||
compilePropertyAccessExpression(expression: PropertyAccessExpression, contextualType: Type): ExpressionRef {
|
||||
compilePropertyAccessExpression(propertyAccess: PropertyAccessExpression, contextualType: Type): ExpressionRef {
|
||||
const expression: Expression = propertyAccess.expression;
|
||||
const propertyName: string = propertyAccess.property.name;
|
||||
|
||||
// the lhs expression is either 'this', 'super', an identifier or another property access
|
||||
let target: Element | null;
|
||||
switch (expression.kind) {
|
||||
|
||||
default:
|
||||
throw new Error("unexpected expression kind");
|
||||
|
||||
case NodeKind.THIS:
|
||||
if (!this.currentFunction.instanceMethodOf) {
|
||||
this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range);
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
target = this.currentFunction.instanceMethodOf;
|
||||
break;
|
||||
|
||||
case NodeKind.SUPER:
|
||||
if (!(this.currentFunction.instanceMethodOf && this.currentFunction.instanceMethodOf.base)) {
|
||||
this.error(DiagnosticCode._super_can_only_be_referenced_in_a_derived_class, expression.range);
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
target = this.currentFunction.instanceMethodOf.base;
|
||||
break;
|
||||
|
||||
case NodeKind.IDENTIFIER:
|
||||
target = this.program.resolveIdentifier(<IdentifierExpression>expression, this.currentFunction); // reports
|
||||
break;
|
||||
|
||||
case NodeKind.PROPERTYACCESS:
|
||||
target = this.program.resolvePropertyAccess(<PropertyAccessExpression>expression, this.currentFunction); // reports
|
||||
break;
|
||||
}
|
||||
if (!target)
|
||||
return this.module.createUnreachable();
|
||||
|
||||
// look up the property within the target to obtain the actual element
|
||||
let element: Element | null;
|
||||
let expr: ExpressionRef;
|
||||
switch (target.kind) {
|
||||
|
||||
// handle enum value right away
|
||||
|
||||
case ElementKind.ENUM:
|
||||
element = (<Enum>target).members.get(propertyName);
|
||||
if (!element) {
|
||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName);
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
this.currentType = Type.i32;
|
||||
return (<EnumValue>element).hasConstantValue
|
||||
? this.module.createI32((<EnumValue>element).constantValue)
|
||||
: this.module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
||||
|
||||
// postpone everything else
|
||||
|
||||
case ElementKind.LOCAL:
|
||||
element = (<Local>target).type.classType;
|
||||
if (!element) {
|
||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName, (<Local>target).type.toString());
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
target = element;
|
||||
break;
|
||||
|
||||
case ElementKind.GLOBAL:
|
||||
if (!this.compileGlobal(<Global>target))
|
||||
return this.module.createUnreachable();
|
||||
element = (<Type>(<Global>target).type).classType;
|
||||
if (!element) {
|
||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName, (<Local>target).type.toString());
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
target = element;
|
||||
break;
|
||||
|
||||
case ElementKind.NAMESPACE:
|
||||
element = (<Namespace>target).members.get(propertyName);
|
||||
if (!(element && element.isExported)) {
|
||||
this.error(DiagnosticCode.Namespace_0_has_no_exported_member_1, propertyAccess.property.range, (<Namespace>target).internalName, propertyName);
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
target = element;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("unexpected target kind");
|
||||
}
|
||||
|
||||
// handle the element
|
||||
switch (element.kind) {
|
||||
|
||||
case ElementKind.LOCAL:
|
||||
return this.module.createGetLocal((<Local>element).index, typeToNativeType(this.currentType = (<Local>element).type));
|
||||
|
||||
case ElementKind.GLOBAL:
|
||||
this.compileGlobal(<Global>element);
|
||||
return this.module.createGetGlobal((<Global>element).internalName, typeToNativeType(this.currentType = <Type>(<Global>element).type));
|
||||
|
||||
case ElementKind.FUNCTION: // getter
|
||||
if (!(<Function>element).prototype.isGetter) {
|
||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName, element.internalName);
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
return this.compileCall(<Function>element, [], propertyAccess);
|
||||
}
|
||||
this.error(DiagnosticCode.Operation_not_supported, propertyAccess.range);
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
@ -2031,3 +2138,22 @@ function typesToSignatureName(paramTypes: Type[], returnType: Type): string {
|
||||
sb.push(typeToSignatureNamePart(returnType));
|
||||
return sb.join("");
|
||||
}
|
||||
|
||||
function isModuleExport(element: Element, declaration: DeclarationStatement): bool {
|
||||
if (!element.isExported)
|
||||
return false;
|
||||
if (declaration.range.source.isEntry)
|
||||
return true;
|
||||
let parentNode: Node | null = declaration.parent;
|
||||
if (!parentNode)
|
||||
return false;
|
||||
if (parentNode.kind == NodeKind.VARIABLE)
|
||||
if (!(parentNode = parentNode.parent))
|
||||
return false;
|
||||
if (parentNode.kind != NodeKind.NAMESPACE && parentNode.kind != NodeKind.CLASS)
|
||||
return false;
|
||||
let parent: Element | null = element.program.elements.get((<DeclarationStatement>parentNode).internalName);
|
||||
if (!parent)
|
||||
return false;
|
||||
return isModuleExport(parent, <DeclarationStatement>parentNode);
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ export enum DiagnosticCode {
|
||||
Type_0_is_not_generic = 2315,
|
||||
Type_0_is_not_assignable_to_type_1 = 2322,
|
||||
_this_cannot_be_referenced_in_current_location = 2332,
|
||||
_super_can_only_be_referenced_in_a_derived_class = 2335,
|
||||
Property_0_does_not_exist_on_type_1 = 2339,
|
||||
Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures = 2349,
|
||||
The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access = 2357,
|
||||
@ -69,6 +70,7 @@ export enum DiagnosticCode {
|
||||
Expected_0_arguments_but_got_1 = 2554,
|
||||
Expected_at_least_0_arguments_but_got_1 = 2555,
|
||||
Expected_0_type_arguments_but_got_1 = 2558,
|
||||
Namespace_0_has_no_exported_member_1 = 2694,
|
||||
File_0_not_found = 6054
|
||||
}
|
||||
|
||||
@ -130,6 +132,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 2315: return "Type '{0}' is not generic.";
|
||||
case 2322: return "Type '{0}' is not assignable to type '{1}'.";
|
||||
case 2332: return "'this' cannot be referenced in current location.";
|
||||
case 2335: return "'super' can only be referenced in a derived class.";
|
||||
case 2339: return "Property '{0}' does not exist on type '{1}'.";
|
||||
case 2349: return "Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures.";
|
||||
case 2357: return "The operand of an increment or decrement operator must be a variable or a property access.";
|
||||
@ -142,6 +145,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 2554: return "Expected {0} arguments, but got {1}.";
|
||||
case 2555: return "Expected at least {0} arguments, but got {1}.";
|
||||
case 2558: return "Expected {0} type arguments, but got {1}.";
|
||||
case 2694: return "Namespace '{0}' has no exported member '{1}'.";
|
||||
case 6054: return "File '{0}' not found.";
|
||||
default: return "";
|
||||
}
|
||||
|
@ -57,6 +57,7 @@
|
||||
"Type '{0}' is not generic.": 2315,
|
||||
"Type '{0}' is not assignable to type '{1}'.": 2322,
|
||||
"'this' cannot be referenced in current location.": 2332,
|
||||
"'super' can only be referenced in a derived class.": 2335,
|
||||
"Property '{0}' does not exist on type '{1}'.": 2339,
|
||||
"Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures.": 2349,
|
||||
"The operand of an increment or decrement operator must be a variable or a property access.": 2357,
|
||||
@ -69,6 +70,7 @@
|
||||
"Expected {0} arguments, but got {1}.": 2554,
|
||||
"Expected at least {0} arguments, but got {1}.": 2555,
|
||||
"Expected {0} type arguments, but got {1}.": 2558,
|
||||
"Namespace '{0}' has no exported member '{1}'.": 2694,
|
||||
|
||||
"File '{0}' not found.": 6054
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ export abstract class DiagnosticEmitter {
|
||||
const message: DiagnosticMessage = DiagnosticMessage.create(code, category, arg0, arg1).withRange(range);
|
||||
this.diagnostics.push(message);
|
||||
console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
|
||||
// console.log(new Error().stack);
|
||||
console.log(<string>new Error("stack").stack);
|
||||
}
|
||||
|
||||
error(code: DiagnosticCode, range: Range, arg0: string | null = null, arg1: string | null = null): void {
|
||||
|
@ -84,9 +84,9 @@ export function setNoTreeShaking(options: Options, noTreeShaking: bool): void {
|
||||
options.noTreeShaking = noTreeShaking;
|
||||
}
|
||||
|
||||
/** Sets the `noDebug` option. */
|
||||
export function setNoDebug(options: Options, noDebug: bool): void {
|
||||
options.noDebug = noDebug;
|
||||
/** Sets the `noAssert` option. */
|
||||
export function setNoAssert(options: Options, noAssert: bool): void {
|
||||
options.noAssert = noAssert;
|
||||
}
|
||||
|
||||
/** Compiles the sources computed by the parser to a module. */
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
|
||||
// expressions
|
||||
AssertionKind,
|
||||
CallExpression,
|
||||
Expression,
|
||||
IdentifierExpression,
|
||||
StringLiteralExpression,
|
||||
@ -31,6 +32,7 @@ import {
|
||||
BreakStatement,
|
||||
ClassDeclaration,
|
||||
ContinueStatement,
|
||||
DeclarationStatement,
|
||||
Decorator,
|
||||
DoStatement,
|
||||
EnumDeclaration,
|
||||
@ -39,6 +41,7 @@ import {
|
||||
ExportMember,
|
||||
ExportStatement,
|
||||
ExpressionStatement,
|
||||
FieldDeclaration,
|
||||
ForStatement,
|
||||
FunctionDeclaration,
|
||||
IfStatement,
|
||||
@ -47,9 +50,8 @@ import {
|
||||
MethodDeclaration,
|
||||
Modifier,
|
||||
ModifierKind,
|
||||
DeclarationStatement,
|
||||
NamespaceDeclaration,
|
||||
Parameter,
|
||||
FieldDeclaration,
|
||||
ReturnStatement,
|
||||
Statement,
|
||||
SwitchCase,
|
||||
@ -61,8 +63,7 @@ import {
|
||||
VariableDeclaration,
|
||||
WhileStatement,
|
||||
|
||||
hasModifier,
|
||||
NamespaceDeclaration
|
||||
hasModifier
|
||||
|
||||
} from "./ast";
|
||||
|
||||
@ -1514,6 +1515,13 @@ export class Parser extends DiagnosticEmitter {
|
||||
if (token == Token.DOT) {
|
||||
if (next.kind == NodeKind.IDENTIFIER) {
|
||||
expr = Expression.createPropertyAccess(<Expression>expr, <IdentifierExpression>next, tn.range(startPos, tn.pos));
|
||||
} else if (next.kind == NodeKind.CALL) { // amend
|
||||
let propertyCall: CallExpression = <CallExpression>next;
|
||||
if (propertyCall.expression.kind == NodeKind.IDENTIFIER) {
|
||||
propertyCall.expression = Expression.createPropertyAccess(<Expression>expr, <IdentifierExpression>propertyCall.expression, tn.range(startPos, tn.pos));
|
||||
} else
|
||||
throw new Error("unexpected expression kind");
|
||||
expr = propertyCall;
|
||||
} else {
|
||||
this.error(DiagnosticCode.Identifier_expected, next.range);
|
||||
return null;
|
||||
|
245
src/program.ts
245
src/program.ts
@ -210,8 +210,9 @@ export class Program extends DiagnosticEmitter {
|
||||
} while (true);
|
||||
}
|
||||
|
||||
private initializeClass(declaration: ClassDeclaration): void {
|
||||
const internalName: string = declaration.internalName;
|
||||
private initializeClass(declaration: ClassDeclaration, namespace: Namespace | null = null): void {
|
||||
throw new Error("not implemented");
|
||||
/* const internalName: string = declaration.internalName;
|
||||
if (this.elements.has(internalName)) {
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
return;
|
||||
@ -233,11 +234,12 @@ export class Program extends DiagnosticEmitter {
|
||||
this.initializeMethod(<MethodDeclaration>memberDeclaration, prototype);
|
||||
else
|
||||
throw new Error("unexpected class member");
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
private initializeField(declaration: FieldDeclaration, classPrototype: ClassPrototype): void {
|
||||
const name: string = declaration.identifier.name;
|
||||
throw new Error("not implemented");
|
||||
/* const name: string = declaration.identifier.name;
|
||||
if (classPrototype.members.has(name)) {
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
||||
return;
|
||||
@ -249,11 +251,12 @@ export class Program extends DiagnosticEmitter {
|
||||
} else {
|
||||
const field: FieldPrototype = new FieldPrototype(classPrototype, internalName, declaration);
|
||||
classPrototype.members.set(name, field);
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
private initializeMethod(declaration: MethodDeclaration, classPrototype: ClassPrototype): void {
|
||||
let name: string = declaration.identifier.name;
|
||||
throw new Error("not implemented");
|
||||
/* let name: string = declaration.identifier.name;
|
||||
const internalName: string = declaration.internalName;
|
||||
if (classPrototype.members.has(name)) {
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
@ -273,23 +276,30 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
}
|
||||
classPrototype.members.set(name, func);
|
||||
classPrototype.members.set(name, func); */
|
||||
}
|
||||
|
||||
private initializeEnum(declaration: EnumDeclaration): void {
|
||||
private initializeEnum(declaration: EnumDeclaration, namespace: Namespace | null = null): void {
|
||||
const internalName: string = declaration.internalName;
|
||||
if (this.elements.has(internalName)) {
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
return;
|
||||
}
|
||||
const enm: Enum = new Enum(this, internalName, declaration);
|
||||
this.elements.set(internalName, enm);
|
||||
if (enm.isExported) {
|
||||
|
||||
if (this.elements.has(internalName))
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
this.elements.set(internalName, enm);
|
||||
|
||||
if (namespace) {
|
||||
if (namespace.members.has(declaration.identifier.name)) {
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
} else
|
||||
namespace.members.set(declaration.identifier.name, enm);
|
||||
} else if (enm.isExported) {
|
||||
if (this.exports.has(internalName))
|
||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
this.exports.set(internalName, enm);
|
||||
}
|
||||
|
||||
const values: EnumValueDeclaration[] = declaration.members;
|
||||
for (let i: i32 = 0, k: i32 = values.length; i < k; ++i)
|
||||
this.initializeEnumValue(values[i], enm);
|
||||
@ -386,15 +396,22 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
private initializeFunction(declaration: FunctionDeclaration): void {
|
||||
private initializeFunction(declaration: FunctionDeclaration, namespace: Namespace | null = null): void {
|
||||
const internalName: string = declaration.internalName;
|
||||
const prototype: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, null);
|
||||
|
||||
if (this.elements.has(internalName)) {
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
return;
|
||||
}
|
||||
this.elements.set(internalName, prototype);
|
||||
if (prototype.isExported) {
|
||||
|
||||
if (namespace) {
|
||||
if (namespace.members.has(declaration.identifier.name))
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
namespace.members.set(declaration.identifier.name, prototype);
|
||||
} else if (prototype.isExported) {
|
||||
if (this.exports.has(internalName))
|
||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
@ -455,20 +472,27 @@ export class Program extends DiagnosticEmitter {
|
||||
queuedImports.push(queuedImport);
|
||||
}
|
||||
|
||||
private initializeInterface(declaration: InterfaceDeclaration): void {
|
||||
private initializeInterface(declaration: InterfaceDeclaration, namespace: Namespace | null = null): void {
|
||||
const internalName: string = declaration.internalName;
|
||||
const prototype: InterfacePrototype = new InterfacePrototype(this, internalName, declaration);
|
||||
|
||||
if (this.elements.has(internalName))
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
this.elements.set(internalName, prototype);
|
||||
|
||||
if (prototype.isExported) {
|
||||
if (namespace) {
|
||||
if (namespace.members.has(prototype.internalName))
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
namespace.members.set(prototype.internalName, prototype);
|
||||
} else if (prototype.isExported) {
|
||||
if (this.exports.has(internalName))
|
||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
this.exports.set(internalName, prototype);
|
||||
}
|
||||
|
||||
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
||||
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
||||
const memberDeclaration: DeclarationStatement = memberDeclarations[j];
|
||||
@ -488,48 +512,54 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
private initializeNamespace(declaration: NamespaceDeclaration): void {
|
||||
private initializeNamespace(declaration: NamespaceDeclaration, parentNamespace: Namespace | null = null): void {
|
||||
const internalName: string = declaration.internalName;
|
||||
const namespace: Namespace = new Namespace(this, internalName, declaration);
|
||||
|
||||
if (this.elements.has(internalName))
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
else {
|
||||
else
|
||||
this.elements.set(internalName, namespace);
|
||||
if (namespace.isExported) {
|
||||
|
||||
if (parentNamespace) {
|
||||
if (parentNamespace.members.has(declaration.identifier.name))
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
parentNamespace.members.set(declaration.identifier.name, namespace);
|
||||
} else if (namespace.isExported) {
|
||||
if (this.exports.has(internalName))
|
||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
this.exports.set(internalName, namespace);
|
||||
}
|
||||
}
|
||||
|
||||
const members: Statement[] = declaration.members;
|
||||
for (let i: i32 = 0, k: i32 = members.length; i < k; ++i) {
|
||||
const statement: Statement = members[i];
|
||||
switch (statement.kind) {
|
||||
|
||||
case NodeKind.CLASS:
|
||||
this.initializeClass(<ClassDeclaration>statement);
|
||||
this.initializeClass(<ClassDeclaration>statement, namespace);
|
||||
break;
|
||||
|
||||
case NodeKind.ENUM:
|
||||
this.initializeEnum(<EnumDeclaration>statement);
|
||||
this.initializeEnum(<EnumDeclaration>statement, namespace);
|
||||
break;
|
||||
|
||||
case NodeKind.FUNCTION:
|
||||
this.initializeFunction(<FunctionDeclaration>statement);
|
||||
this.initializeFunction(<FunctionDeclaration>statement, namespace);
|
||||
break;
|
||||
|
||||
case NodeKind.INTERFACE:
|
||||
this.initializeInterface(<InterfaceDeclaration>statement);
|
||||
this.initializeInterface(<InterfaceDeclaration>statement, namespace);
|
||||
break;
|
||||
|
||||
case NodeKind.NAMESPACE:
|
||||
this.initializeNamespace(<NamespaceDeclaration>statement);
|
||||
this.initializeNamespace(<NamespaceDeclaration>statement, namespace);
|
||||
break;
|
||||
|
||||
case NodeKind.VARIABLE:
|
||||
this.initializeVariables(<VariableStatement>statement, true);
|
||||
this.initializeVariables(<VariableStatement>statement, namespace);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -538,17 +568,24 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
private initializeVariables(statement: VariableStatement, isNamespaceMember: bool = false): void {
|
||||
private initializeVariables(statement: VariableStatement, namespace: Namespace | null = null): void {
|
||||
const declarations: VariableDeclaration[] = statement.declarations;
|
||||
for (let i: i32 = 0, k: i32 = declarations.length; i < k; ++i) {
|
||||
const declaration: VariableDeclaration = declarations[i];
|
||||
const internalName: string = declaration.internalName;
|
||||
const global: Global = new Global(this, internalName, declaration, null);
|
||||
|
||||
if (this.elements.has(internalName))
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
else {
|
||||
this.elements.set(internalName, global);
|
||||
if (global.isExported) {
|
||||
|
||||
if (namespace) {
|
||||
if (namespace.members.has(declaration.identifier.name))
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
namespace.members.set(declaration.identifier.name, global);
|
||||
} else if (global.isExported) {
|
||||
if (this.exports.has(internalName))
|
||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||
else
|
||||
@ -596,7 +633,7 @@ export class Program extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Resolves {@link TypeParameter}s to concrete {@link Type}s. */
|
||||
/** Resolves an array of type parameters to concrete types. */
|
||||
resolveTypeArguments(typeParameters: TypeParameter[], typeArgumentNodes: TypeNode[] | null, contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): Type[] | null {
|
||||
const parameterCount: i32 = typeParameters.length;
|
||||
const argumentCount: i32 = typeArgumentNodes ? typeArgumentNodes.length : 0;
|
||||
@ -618,6 +655,49 @@ export class Program extends DiagnosticEmitter {
|
||||
return typeArguments;
|
||||
}
|
||||
|
||||
/** Resolves an identifier to the element is refers to. */
|
||||
resolveIdentifier(identifier: IdentifierExpression, contextualFunction: Function): Element | null {
|
||||
const name: string = identifier.name;
|
||||
const local: Local | null = <Local | null>contextualFunction.locals.get(name);
|
||||
if (local)
|
||||
return local;
|
||||
let element: Element | null;
|
||||
if (element = this.elements.get(identifier.range.source.internalPath + PATH_DELIMITER + name))
|
||||
return element;
|
||||
if (element = this.elements.get(name))
|
||||
return element;
|
||||
this.error(DiagnosticCode.Cannot_find_name_0, identifier.range, name);
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Resolves a property access the element it refers to. */
|
||||
resolvePropertyAccess(propertyAccess: PropertyAccessExpression, contextualFunction: Function): Element | null {
|
||||
const expression: Expression = propertyAccess.expression;
|
||||
let target: Element | null = null;
|
||||
if (expression.kind == NodeKind.IDENTIFIER) {
|
||||
target = this.resolveIdentifier(<IdentifierExpression>expression, contextualFunction);
|
||||
} else if (expression.kind == NodeKind.PROPERTYACCESS) {
|
||||
target = this.resolvePropertyAccess(<PropertyAccessExpression>expression, contextualFunction);
|
||||
} else
|
||||
throw new Error("unexpected target kind");
|
||||
if (!target)
|
||||
return null;
|
||||
const propertyName: string = propertyAccess.property.name;
|
||||
let member: Element | null = null;
|
||||
if (target.kind == ElementKind.ENUM)
|
||||
member = (<Enum>target).members.get(propertyName);
|
||||
else if (target.kind == ElementKind.NAMESPACE)
|
||||
member = (<Namespace>target).members.get(propertyName);
|
||||
// else if (target.kind == ElementKind.CLASS_PROTOTYPE)
|
||||
// member = <Element | null>(<ClassPrototype>target).members.get(propertyName);
|
||||
// else if (target.kind == ElementKind.CLASS)
|
||||
// member = <Element | null>(<Class>target).members.get(propertyName);
|
||||
if (member)
|
||||
return member;
|
||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, expression.range, (<PropertyAccessExpression>expression).property.name, target.internalName);
|
||||
return null;
|
||||
}
|
||||
|
||||
resolveElement(expression: Expression, contextualFunction: Function): Element | null {
|
||||
|
||||
// this -> Class
|
||||
@ -630,38 +710,11 @@ export class Program extends DiagnosticEmitter {
|
||||
|
||||
// local or global name
|
||||
if (expression.kind == NodeKind.IDENTIFIER) {
|
||||
const name: string = (<IdentifierExpression>expression).name;
|
||||
const local: Local | null = <Local | null>contextualFunction.locals.get(name);
|
||||
if (local)
|
||||
return local;
|
||||
const fileGlobalElement: Element | null = <Element | null>this.elements.get(expression.range.source.internalPath + PATH_DELIMITER + name);
|
||||
if (fileGlobalElement)
|
||||
return fileGlobalElement;
|
||||
const programGlobalElement: Element | null = <Element | null>this.elements.get(name);
|
||||
if (programGlobalElement)
|
||||
return programGlobalElement;
|
||||
this.error(DiagnosticCode.Cannot_find_name_0, expression.range, name);
|
||||
return null;
|
||||
return this.resolveIdentifier(<IdentifierExpression>expression, contextualFunction);
|
||||
|
||||
// static or instance property (incl. enum values) or method
|
||||
} else if (expression.kind == NodeKind.PROPERTYACCESS) {
|
||||
const target: Element | null = this.resolveElement((<PropertyAccessExpression>expression).expression, contextualFunction); // reports
|
||||
if (!target)
|
||||
return null;
|
||||
const propertyName: string = (<PropertyAccessExpression>expression).property.name;
|
||||
let member: Element | null = null;
|
||||
if (target.kind == ElementKind.ENUM)
|
||||
member = <EnumValue | null>(<Enum>target).members.get(propertyName);
|
||||
else if (target.kind == ElementKind.CLASS_PROTOTYPE)
|
||||
member = <Element | null>(<ClassPrototype>target).members.get(propertyName);
|
||||
else if (target.kind == ElementKind.CLASS)
|
||||
member = <Element | null>(<Class>target).members.get(propertyName);
|
||||
else if (target.kind == ElementKind.NAMESPACE)
|
||||
member = <Element | null>(<Namespace>target).members.get(propertyName);
|
||||
if (member)
|
||||
return member;
|
||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, expression.range, (<PropertyAccessExpression>expression).property.name, target.internalName);
|
||||
return null;
|
||||
return this.resolvePropertyAccess(<PropertyAccessExpression>expression, contextualFunction);
|
||||
}
|
||||
|
||||
throw new Error("not implemented: " + expression.kind);
|
||||
@ -1130,13 +1183,14 @@ export class Function extends Element {
|
||||
return local;
|
||||
}
|
||||
|
||||
private tempI32s: Local[] = [];
|
||||
private tempI64s: Local[] = [];
|
||||
private tempF32s: Local[] = [];
|
||||
private tempF64s: Local[] = [];
|
||||
private tempI32s: Local[] | null = null;
|
||||
private tempI64s: Local[] | null = null;
|
||||
private tempF32s: Local[] | null = null;
|
||||
private tempF64s: Local[] | null = null;
|
||||
|
||||
/** Gets a free temporary local of the specified type. */
|
||||
getTempLocal(type: Type): Local {
|
||||
let temps: Local[];
|
||||
let temps: Local[] | null;
|
||||
switch (typeToNativeType(type)) {
|
||||
case NativeType.I32: temps = this.tempI32s; break;
|
||||
case NativeType.I64: temps = this.tempI64s; break;
|
||||
@ -1144,30 +1198,32 @@ export class Function extends Element {
|
||||
case NativeType.F64: temps = this.tempF64s; break;
|
||||
default: throw new Error("unexpected type");
|
||||
}
|
||||
if (temps.length > 0)
|
||||
if (temps && temps.length > 0)
|
||||
return temps.pop();
|
||||
return this.addLocal(type);
|
||||
}
|
||||
|
||||
/** Frees the temporary local for reuse. */
|
||||
freeTempLocal(local: Local): void {
|
||||
let temps: Local[];
|
||||
switch (typeToNativeType(local.type)) {
|
||||
case NativeType.I32: temps = this.tempI32s; break;
|
||||
case NativeType.I64: temps = this.tempI64s; break;
|
||||
case NativeType.F32: temps = this.tempF32s; break;
|
||||
case NativeType.F64: temps = this.tempF64s; break;
|
||||
case NativeType.I32: temps = this.tempI32s || (this.tempI32s = []); break;
|
||||
case NativeType.I64: temps = this.tempI64s || (this.tempI64s = []); break;
|
||||
case NativeType.F32: temps = this.tempF32s || (this.tempF32s = []); break;
|
||||
case NativeType.F64: temps = this.tempF64s || (this.tempF64s = []); break;
|
||||
default: throw new Error("unexpected type");
|
||||
}
|
||||
temps.push(local);
|
||||
}
|
||||
|
||||
/** Gets and immediately frees a temporary local of the specified type. */
|
||||
getAndFreeTempLocal(type: Type): Local {
|
||||
let temps: Local[];
|
||||
switch (typeToNativeType(type)) {
|
||||
case NativeType.I32: temps = this.tempI32s; break;
|
||||
case NativeType.I64: temps = this.tempI64s; break;
|
||||
case NativeType.F32: temps = this.tempF32s; break;
|
||||
case NativeType.F64: temps = this.tempF64s; break;
|
||||
case NativeType.I32: temps = this.tempI32s || (this.tempI32s = []); break;
|
||||
case NativeType.I64: temps = this.tempI64s || (this.tempI64s = []); break;
|
||||
case NativeType.F32: temps = this.tempF32s || (this.tempF32s = []); break;
|
||||
case NativeType.F64: temps = this.tempF64s || (this.tempF64s = []); break;
|
||||
default: throw new Error("unexpected type");
|
||||
}
|
||||
if (temps.length > 0)
|
||||
@ -1250,17 +1306,25 @@ export class Field extends Element {
|
||||
}
|
||||
|
||||
/** A yet unresolved class prototype. */
|
||||
export class ClassPrototype extends Namespace {
|
||||
export class ClassPrototype extends Element {
|
||||
|
||||
kind = ElementKind.CLASS_PROTOTYPE;
|
||||
|
||||
/** Declaration reference. */
|
||||
declaration: ClassDeclaration | null;
|
||||
/** Resolved instances. */
|
||||
instances: Map<string,Class>;
|
||||
instances: Map<string,Class> = new Map();
|
||||
/** Static fields. */
|
||||
staticFields: Map<string,Global> | null = null;
|
||||
/** Static methods. */
|
||||
staticMethods: Map<string,Function> | null = null;
|
||||
/** Static getters. */
|
||||
staticGetters: Map<string,Function> | null = null;
|
||||
/** Static setters. */
|
||||
staticSetters: Map<string,Function> | null = null;
|
||||
|
||||
constructor(program: Program, internalName: string, declaration: ClassDeclaration | null = null) {
|
||||
super(program, internalName, null);
|
||||
super(program, internalName);
|
||||
if (this.declaration = declaration) {
|
||||
if (this.declaration.modifiers) {
|
||||
for (let i: i32 = 0, k: i32 = this.declaration.modifiers.length; i < k; ++i) {
|
||||
@ -1275,7 +1339,6 @@ export class ClassPrototype extends Namespace {
|
||||
if (this.declaration.typeParameters.length)
|
||||
this.isGeneric = true;
|
||||
}
|
||||
this.instances = new Map();
|
||||
}
|
||||
|
||||
resolve(typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null): Class {
|
||||
@ -1305,7 +1368,7 @@ export class ClassPrototype extends Namespace {
|
||||
}
|
||||
|
||||
/** A resolved class. */
|
||||
export class Class extends Namespace {
|
||||
export class Class extends Element {
|
||||
|
||||
kind = ElementKind.CLASS;
|
||||
|
||||
@ -1317,19 +1380,27 @@ export class Class extends Namespace {
|
||||
type: Type;
|
||||
/** Base class, if applicable. */
|
||||
base: Class | null;
|
||||
|
||||
/** Contextual type argumentsfor fields and methods. */
|
||||
contextualTypeArguments: Map<string,Type> = new Map();
|
||||
/** Instance fields. */
|
||||
instanceFields: Map<string,Field> | null = null;
|
||||
/** Instance methods. */
|
||||
instanceMethods: Map<string,Function> | null = null;
|
||||
/** Instance getters. */
|
||||
instanceGetters: Map<string,Function> | null = null;
|
||||
/** Instance setters. */
|
||||
instanceSetters: Map<string,Function> | null = null;
|
||||
|
||||
/** Constructs a new class. */
|
||||
constructor(prototype: ClassPrototype, internalName: string, typeArguments: Type[] = [], base: Class | null = null) {
|
||||
super(prototype.program, internalName, prototype.declaration);
|
||||
super(prototype.program, internalName);
|
||||
this.prototype = prototype;
|
||||
this.flags = prototype.flags;
|
||||
this.typeArguments = typeArguments;
|
||||
this.base = base;
|
||||
this.type = (prototype.program.target == Target.WASM64 ? Type.usize64 : Type.usize32).asClass(this);
|
||||
this.base = base;
|
||||
|
||||
// inherit base class contextual type arguments
|
||||
// inherit contextual type arguments from base class
|
||||
if (base)
|
||||
for (let [name, type] of base.contextualTypeArguments)
|
||||
this.contextualTypeArguments.set(name, type);
|
||||
@ -1350,13 +1421,13 @@ export class Class extends Namespace {
|
||||
}
|
||||
}
|
||||
|
||||
/** A yet unresvoled interface. */
|
||||
/** A yet unresolved interface. */
|
||||
export class InterfacePrototype extends ClassPrototype {
|
||||
|
||||
kind = ElementKind.INTERFACE_PROTOTYPE;
|
||||
|
||||
/** Declaration reference. */
|
||||
declaration: InterfaceDeclaration | null;
|
||||
declaration: InterfaceDeclaration | null; // more specific
|
||||
|
||||
/** Constructs a new interface prototype. */
|
||||
constructor(program: Program, internalName: string, declaration: InterfaceDeclaration | null = null) {
|
||||
@ -1370,9 +1441,9 @@ export class Interface extends Class {
|
||||
kind = ElementKind.INTERFACE;
|
||||
|
||||
/** Prototype reference. */
|
||||
prototype: InterfacePrototype;
|
||||
prototype: InterfacePrototype; // more specific
|
||||
/** Base interface, if applcable. */
|
||||
base: Interface | null;
|
||||
base: Interface | null; // more specific
|
||||
|
||||
/** Constructs a new interface. */
|
||||
constructor(prototype: InterfacePrototype, internalName: string, typeArguments: Type[] = [], base: Interface | null = null) {
|
||||
|
24
std/portable.d.ts
vendored
24
std/portable.d.ts
vendored
@ -87,30 +87,31 @@ declare class String {
|
||||
static fromCodePoint(cp: i32): string;
|
||||
static fromCodePoints(arr: i32[]): string;
|
||||
readonly length: i32;
|
||||
private constructor();
|
||||
indexOf(subject: string): i32;
|
||||
lastIndexOf(subject: string): i32;
|
||||
charCodeAt(index: i32): i32;
|
||||
substring(from: i32, to?: i32): string;
|
||||
startsWith(subject: string): bool;
|
||||
endsWith(subject: string): bool;
|
||||
replace(search: string, replacement: string): string;
|
||||
toString(): string;
|
||||
}
|
||||
|
||||
declare class Boolean {}
|
||||
interface Boolean {}
|
||||
|
||||
declare class Number {
|
||||
toString(radix: i32): string;
|
||||
private constructor();
|
||||
toString(radix?: i32): string;
|
||||
}
|
||||
|
||||
declare class Object {}
|
||||
interface Object {}
|
||||
|
||||
declare class Function {
|
||||
/** @deprecated */
|
||||
apply(subject: any): any;
|
||||
}
|
||||
interface Function {}
|
||||
|
||||
declare class RegExp {}
|
||||
interface RegExp {}
|
||||
|
||||
declare interface IArguments {}
|
||||
interface IArguments {}
|
||||
|
||||
declare class Error {
|
||||
constructor(message: string);
|
||||
@ -119,7 +120,8 @@ declare class Error {
|
||||
}
|
||||
|
||||
declare class Symbol {
|
||||
static iterator: symbol;
|
||||
private constructor();
|
||||
static readonly iterator: symbol;
|
||||
}
|
||||
|
||||
declare class Set<T> {
|
||||
@ -139,7 +141,7 @@ declare class Map<K,V> {
|
||||
[Symbol.iterator](): Iterator<[K, V]>;
|
||||
}
|
||||
|
||||
declare interface Iterator<T> {}
|
||||
interface Iterator<T> {}
|
||||
|
||||
declare namespace JSON {
|
||||
/** @deprecated */
|
||||
|
@ -1,5 +1,6 @@
|
||||
(module
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(type $v (func))
|
||||
(global $export/a i32 (i32.const 1))
|
||||
(global $export/b i32 (i32.const 2))
|
||||
(memory $0 1)
|
||||
@ -7,6 +8,7 @@
|
||||
(export "renamed_sub" (func $export/sub))
|
||||
(export "a" (global $export/a))
|
||||
(export "renamed_b" (global $export/b))
|
||||
(export "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
|
||||
@ -20,4 +22,7 @@
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(func $export/ns.two (; 2 ;) (type $v)
|
||||
(nop)
|
||||
)
|
||||
)
|
||||
|
@ -14,7 +14,7 @@ const b: i32 = 2;
|
||||
|
||||
export { b as renamed_b };
|
||||
|
||||
/* export namespace ns {
|
||||
export namespace ns {
|
||||
function one(): void {}
|
||||
export function two(): void {}
|
||||
} */
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
(module
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(type $v (func))
|
||||
(global $export/a i32 (i32.const 1))
|
||||
(global $export/b i32 (i32.const 2))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
@ -8,6 +9,7 @@
|
||||
(export "renamed_sub" (func $export/sub))
|
||||
(export "a" (global $export/a))
|
||||
(export "renamed_b" (global $export/b))
|
||||
(export "two" (func $export/ns.two))
|
||||
(export "memory" (memory $0))
|
||||
(func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(return
|
||||
@ -25,6 +27,8 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $export/ns.two (; 2 ;) (type $v)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
@ -60,9 +64,13 @@
|
||||
export/sub
|
||||
export/a
|
||||
export/b
|
||||
export/ns
|
||||
export/ns.one
|
||||
export/ns.two
|
||||
[program.exports]
|
||||
export/add
|
||||
export/renamed_sub
|
||||
export/a
|
||||
export/renamed_b
|
||||
export/ns
|
||||
;)
|
||||
|
@ -41,5 +41,10 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(block $__inlined_func$export/ns.two
|
||||
(nop)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -16,7 +16,10 @@
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(func $start (; 2 ;) (type $v)
|
||||
(func $export/ns.two (; 2 ;) (type $v)
|
||||
(nop)
|
||||
)
|
||||
(func $start (; 3 ;) (type $v)
|
||||
(drop
|
||||
(i32.add
|
||||
(call $export/add
|
||||
@ -29,5 +32,6 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(call $export/ns.two)
|
||||
)
|
||||
)
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { add, renamed_sub as sub, a, renamed_b as b } from "./export";
|
||||
import { add, renamed_sub as sub, a, renamed_b as b, ns as renamed_ns } from "./export";
|
||||
|
||||
add(a, b) + sub(b, a);
|
||||
|
||||
renamed_ns.two();
|
||||
|
@ -23,7 +23,9 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $start (; 2 ;) (type $v)
|
||||
(func $export/ns.two (; 2 ;) (type $v)
|
||||
)
|
||||
(func $start (; 3 ;) (type $v)
|
||||
(drop
|
||||
(i32.add
|
||||
(call $export/add
|
||||
@ -36,6 +38,7 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(call $export/ns.two)
|
||||
)
|
||||
)
|
||||
(;
|
||||
@ -72,13 +75,18 @@
|
||||
export/sub
|
||||
export/a
|
||||
export/b
|
||||
export/ns
|
||||
export/ns.one
|
||||
export/ns.two
|
||||
import/add
|
||||
import/sub
|
||||
import/a
|
||||
import/b
|
||||
import/renamed_ns
|
||||
[program.exports]
|
||||
export/add
|
||||
export/renamed_sub
|
||||
export/a
|
||||
export/renamed_b
|
||||
export/ns
|
||||
;)
|
||||
|
11
tests/compiler/namespace.optimized-inlined.wast
Normal file
11
tests/compiler/namespace.optimized-inlined.wast
Normal file
@ -0,0 +1,11 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(memory $0 1)
|
||||
(export "test" (func $namespace/test))
|
||||
(export "memory" (memory $0))
|
||||
(func $namespace/test (; 0 ;) (type $v)
|
||||
(block $__inlined_func$namespace/Outer.Inner.aFunc
|
||||
(nop)
|
||||
)
|
||||
)
|
||||
)
|
12
tests/compiler/namespace.optimized.wast
Normal file
12
tests/compiler/namespace.optimized.wast
Normal file
@ -0,0 +1,12 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(memory $0 1)
|
||||
(export "test" (func $namespace/test))
|
||||
(export "memory" (memory $0))
|
||||
(func $namespace/Outer.Inner.aFunc (; 0 ;) (type $v)
|
||||
(nop)
|
||||
)
|
||||
(func $namespace/test (; 1 ;) (type $v)
|
||||
(call $namespace/Outer.Inner.aFunc)
|
||||
)
|
||||
)
|
13
tests/compiler/namespace.ts
Normal file
13
tests/compiler/namespace.ts
Normal file
@ -0,0 +1,13 @@
|
||||
namespace Outer {
|
||||
export namespace Inner {
|
||||
export let aVar: i32;
|
||||
export function aFunc(): void {}
|
||||
export enum anEnum { ONE = 1 }
|
||||
}
|
||||
}
|
||||
|
||||
export function test(): void {
|
||||
Outer.Inner.aVar;
|
||||
Outer.Inner.aFunc();
|
||||
Outer.Inner.anEnum.ONE;
|
||||
}
|
58
tests/compiler/namespace.wast
Normal file
58
tests/compiler/namespace.wast
Normal file
@ -0,0 +1,58 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(global $namespace/Outer.Inner.aVar (mut i32) (i32.const 0))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(export "test" (func $namespace/test))
|
||||
(export "memory" (memory $0))
|
||||
(func $namespace/Outer.Inner.aFunc (; 0 ;) (type $v)
|
||||
)
|
||||
(func $namespace/test (; 1 ;) (type $v)
|
||||
(drop
|
||||
(get_global $namespace/Outer.Inner.aVar)
|
||||
)
|
||||
(call $namespace/Outer.Inner.aFunc)
|
||||
(drop
|
||||
(get_global $namespace/Outer.Inner.anEnum.ONE)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
clz
|
||||
ctz
|
||||
popcnt
|
||||
rotl
|
||||
rotr
|
||||
abs
|
||||
ceil
|
||||
copysign
|
||||
floor
|
||||
max
|
||||
min
|
||||
nearest
|
||||
sqrt
|
||||
trunc
|
||||
current_memory
|
||||
grow_memory
|
||||
unreachable
|
||||
load
|
||||
store
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
parseInt
|
||||
parseFloat
|
||||
namespace/Outer
|
||||
namespace/Outer.Inner
|
||||
namespace/Outer.Inner.aVar
|
||||
namespace/Outer.Inner.aFunc
|
||||
namespace/Outer.Inner.anEnum
|
||||
namespace/test
|
||||
[program.exports]
|
||||
namespace/test
|
||||
;)
|
@ -1,7 +1,9 @@
|
||||
export { add, renamed_sub, a as renamed_a, renamed_b as rerenamed_b } from "./export";
|
||||
|
||||
import { add as imported_add, renamed_sub as imported_sub } from "./export";
|
||||
import { add as imported_add, renamed_sub as imported_sub, ns as imported_ns } from "./export";
|
||||
|
||||
export { imported_add as renamed_add, imported_sub as rerenamed_sub };
|
||||
|
||||
imported_add(1, 2) + imported_sub(3, 4);
|
||||
|
||||
export { ns as renamed_ns } from "./export";
|
||||
|
@ -29,7 +29,9 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $start (; 2 ;) (type $v)
|
||||
(func $export/ns.two (; 2 ;) (type $v)
|
||||
)
|
||||
(func $start (; 3 ;) (type $v)
|
||||
(drop
|
||||
(i32.add
|
||||
(call $export/add
|
||||
@ -78,17 +80,23 @@
|
||||
export/sub
|
||||
export/a
|
||||
export/b
|
||||
export/ns
|
||||
export/ns.one
|
||||
export/ns.two
|
||||
reexport/imported_add
|
||||
reexport/imported_sub
|
||||
reexport/imported_ns
|
||||
[program.exports]
|
||||
export/add
|
||||
export/renamed_sub
|
||||
export/a
|
||||
export/renamed_b
|
||||
export/ns
|
||||
reexport/add
|
||||
reexport/renamed_sub
|
||||
reexport/renamed_a
|
||||
reexport/rerenamed_b
|
||||
reexport/renamed_add
|
||||
reexport/rerenamed_sub
|
||||
reexport/renamed_ns
|
||||
;)
|
||||
|
11
tests/parser/namespace.ts
Normal file
11
tests/parser/namespace.ts
Normal file
@ -0,0 +1,11 @@
|
||||
declare namespace A {
|
||||
namespace B {
|
||||
export namespace C {
|
||||
let aVar: i32;
|
||||
const aConst: i32;
|
||||
function aFunc(): void {}
|
||||
enum AnEnum {}
|
||||
class AClass {}
|
||||
}
|
||||
}
|
||||
}
|
15
tests/parser/namespace.ts.fixture.ts
Normal file
15
tests/parser/namespace.ts.fixture.ts
Normal file
@ -0,0 +1,15 @@
|
||||
declare namespace A {
|
||||
namespace B {
|
||||
export namespace C {
|
||||
let aVar: i32;
|
||||
const aConst: i32;
|
||||
function aFunc(): void {
|
||||
}
|
||||
enum AnEnum {
|
||||
|
||||
}
|
||||
class AClass {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
tests/parser/var.ts
Normal file
3
tests/parser/var.ts
Normal file
@ -0,0 +1,3 @@
|
||||
var a: i32;
|
||||
let b: i32;
|
||||
const c: i32;
|
3
tests/parser/var.ts.fixture.ts
Normal file
3
tests/parser/var.ts.fixture.ts
Normal file
@ -0,0 +1,3 @@
|
||||
let a: i32;
|
||||
let b: i32;
|
||||
const c: i32;
|
Loading…
x
Reference in New Issue
Block a user