mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-05-19 02:31:25 +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.
|
**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`.
|
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();
|
var options = assemblyscript.createOptions();
|
||||||
assemblyscript.setTarget(options, 0);
|
assemblyscript.setTarget(options, 0);
|
||||||
assemblyscript.setNoTreeShaking(options, args.noTreeShaking);
|
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);
|
var module = assemblyscript.compile(parser, options);
|
||||||
checkDiagnostics(parser);
|
checkDiagnostics(parser);
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
"desc": "Disables tree-shaking.",
|
"desc": "Disables tree-shaking.",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"noDebug": {
|
"noAssert": {
|
||||||
"desc": "Disables assertions.",
|
"desc": "Disables assertions.",
|
||||||
"type": "boolean"
|
"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;
|
return name;
|
||||||
if (declaration.parent.kind == NodeKind.CLASS)
|
if (declaration.kind == NodeKind.VARIABLEDECLARATION && parent.kind == NodeKind.VARIABLE) // skip over
|
||||||
return (<ClassDeclaration>declaration.parent).internalName + (hasModifier(ModifierKind.STATIC, declaration.modifiers) ? STATIC_DELIMITER : INSTANCE_DELIMITER) + name;
|
if (!(parent = parent.parent))
|
||||||
if (declaration.parent.kind == NodeKind.NAMESPACE || declaration.parent.kind == NodeKind.ENUM)
|
return name;
|
||||||
return (<DeclarationStatement>declaration.parent).internalName + STATIC_DELIMITER + 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;
|
return declaration.range.source.internalPath + PATH_DELIMITER + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,7 +494,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
arg0 = compiler.compileExpression(operands[0], Type.i32); // reports
|
arg0 = compiler.compileExpression(operands[0], Type.i32); // reports
|
||||||
compiler.currentType = Type.void;
|
compiler.currentType = Type.void;
|
||||||
return compiler.options.noDebug
|
return compiler.options.noAssert
|
||||||
? module.createNop()
|
? module.createNop()
|
||||||
: module.createIf(
|
: module.createIf(
|
||||||
module.createUnary(UnaryOp.EqzI32, arg0),
|
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. */
|
/** If true, compiles everything instead of just reachable code. */
|
||||||
noTreeShaking: bool = false;
|
noTreeShaking: bool = false;
|
||||||
/** If true, replaces assertions with nops. */
|
/** If true, replaces assertions with nops. */
|
||||||
noDebug: bool = false;
|
noAssert: bool = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const enum ConversionKind {
|
const enum ConversionKind {
|
||||||
@ -306,7 +306,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
throw new Error("unexpected missing global");
|
throw new Error("unexpected missing global");
|
||||||
if (!this.compileGlobal(<Global>element))
|
if (!this.compileGlobal(<Global>element))
|
||||||
return null;
|
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)
|
if ((<Global>element).hasConstantValue)
|
||||||
this.module.addGlobalExport(element.internalName, declaration.identifier.name);
|
this.module.addGlobalExport(element.internalName, declaration.identifier.name);
|
||||||
else
|
else
|
||||||
@ -470,7 +470,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
const instance: Function | null = this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, typeArguments, contextualTypeArguments, alternativeReportNode);
|
const instance: Function | null = this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, typeArguments, contextualTypeArguments, alternativeReportNode);
|
||||||
if (!instance)
|
if (!instance)
|
||||||
return;
|
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);
|
this.module.addFunctionExport(instance.internalName, declaration.identifier.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +527,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// create the function
|
// create the function
|
||||||
const internalName: string = instance.internalName;
|
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);
|
this.module.addFunctionImport(internalName, "env", declaration.identifier.name, typeRef);
|
||||||
} else {
|
} else {
|
||||||
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, <ExpressionRef[]>stmts, NativeType.None));
|
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("unexpected namespace member");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error("not implemented");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileNamespace(ns: Namespace): void {
|
compileNamespace(ns: Namespace): void {
|
||||||
@ -1834,7 +1833,115 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.compileExpression(expression.expression, contextualType, ConversionKind.NONE);
|
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");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2031,3 +2138,22 @@ function typesToSignatureName(paramTypes: Type[], returnType: Type): string {
|
|||||||
sb.push(typeToSignatureNamePart(returnType));
|
sb.push(typeToSignatureNamePart(returnType));
|
||||||
return sb.join("");
|
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_generic = 2315,
|
||||||
Type_0_is_not_assignable_to_type_1 = 2322,
|
Type_0_is_not_assignable_to_type_1 = 2322,
|
||||||
_this_cannot_be_referenced_in_current_location = 2332,
|
_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,
|
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,
|
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,
|
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_0_arguments_but_got_1 = 2554,
|
||||||
Expected_at_least_0_arguments_but_got_1 = 2555,
|
Expected_at_least_0_arguments_but_got_1 = 2555,
|
||||||
Expected_0_type_arguments_but_got_1 = 2558,
|
Expected_0_type_arguments_but_got_1 = 2558,
|
||||||
|
Namespace_0_has_no_exported_member_1 = 2694,
|
||||||
File_0_not_found = 6054
|
File_0_not_found = 6054
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +132,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
|||||||
case 2315: return "Type '{0}' is not generic.";
|
case 2315: return "Type '{0}' is not generic.";
|
||||||
case 2322: return "Type '{0}' is not assignable to type '{1}'.";
|
case 2322: return "Type '{0}' is not assignable to type '{1}'.";
|
||||||
case 2332: return "'this' cannot be referenced in current location.";
|
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 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 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.";
|
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 2554: return "Expected {0} arguments, but got {1}.";
|
||||||
case 2555: return "Expected at least {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 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.";
|
case 6054: return "File '{0}' not found.";
|
||||||
default: return "";
|
default: return "";
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
"Type '{0}' is not generic.": 2315,
|
"Type '{0}' is not generic.": 2315,
|
||||||
"Type '{0}' is not assignable to type '{1}'.": 2322,
|
"Type '{0}' is not assignable to type '{1}'.": 2322,
|
||||||
"'this' cannot be referenced in current location.": 2332,
|
"'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,
|
"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,
|
"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,
|
"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 {0} arguments, but got {1}.": 2554,
|
||||||
"Expected at least {0} arguments, but got {1}.": 2555,
|
"Expected at least {0} arguments, but got {1}.": 2555,
|
||||||
"Expected {0} type arguments, but got {1}.": 2558,
|
"Expected {0} type arguments, but got {1}.": 2558,
|
||||||
|
"Namespace '{0}' has no exported member '{1}'.": 2694,
|
||||||
|
|
||||||
"File '{0}' not found.": 6054
|
"File '{0}' not found.": 6054
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ export abstract class DiagnosticEmitter {
|
|||||||
const message: DiagnosticMessage = DiagnosticMessage.create(code, category, arg0, arg1).withRange(range);
|
const message: DiagnosticMessage = DiagnosticMessage.create(code, category, arg0, arg1).withRange(range);
|
||||||
this.diagnostics.push(message);
|
this.diagnostics.push(message);
|
||||||
console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
|
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 {
|
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;
|
options.noTreeShaking = noTreeShaking;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the `noDebug` option. */
|
/** Sets the `noAssert` option. */
|
||||||
export function setNoDebug(options: Options, noDebug: bool): void {
|
export function setNoAssert(options: Options, noAssert: bool): void {
|
||||||
options.noDebug = noDebug;
|
options.noAssert = noAssert;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compiles the sources computed by the parser to a module. */
|
/** Compiles the sources computed by the parser to a module. */
|
||||||
|
@ -22,6 +22,7 @@ import {
|
|||||||
|
|
||||||
// expressions
|
// expressions
|
||||||
AssertionKind,
|
AssertionKind,
|
||||||
|
CallExpression,
|
||||||
Expression,
|
Expression,
|
||||||
IdentifierExpression,
|
IdentifierExpression,
|
||||||
StringLiteralExpression,
|
StringLiteralExpression,
|
||||||
@ -31,6 +32,7 @@ import {
|
|||||||
BreakStatement,
|
BreakStatement,
|
||||||
ClassDeclaration,
|
ClassDeclaration,
|
||||||
ContinueStatement,
|
ContinueStatement,
|
||||||
|
DeclarationStatement,
|
||||||
Decorator,
|
Decorator,
|
||||||
DoStatement,
|
DoStatement,
|
||||||
EnumDeclaration,
|
EnumDeclaration,
|
||||||
@ -39,6 +41,7 @@ import {
|
|||||||
ExportMember,
|
ExportMember,
|
||||||
ExportStatement,
|
ExportStatement,
|
||||||
ExpressionStatement,
|
ExpressionStatement,
|
||||||
|
FieldDeclaration,
|
||||||
ForStatement,
|
ForStatement,
|
||||||
FunctionDeclaration,
|
FunctionDeclaration,
|
||||||
IfStatement,
|
IfStatement,
|
||||||
@ -47,9 +50,8 @@ import {
|
|||||||
MethodDeclaration,
|
MethodDeclaration,
|
||||||
Modifier,
|
Modifier,
|
||||||
ModifierKind,
|
ModifierKind,
|
||||||
DeclarationStatement,
|
NamespaceDeclaration,
|
||||||
Parameter,
|
Parameter,
|
||||||
FieldDeclaration,
|
|
||||||
ReturnStatement,
|
ReturnStatement,
|
||||||
Statement,
|
Statement,
|
||||||
SwitchCase,
|
SwitchCase,
|
||||||
@ -61,8 +63,7 @@ import {
|
|||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
WhileStatement,
|
WhileStatement,
|
||||||
|
|
||||||
hasModifier,
|
hasModifier
|
||||||
NamespaceDeclaration
|
|
||||||
|
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
|
|
||||||
@ -1514,6 +1515,13 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
if (token == Token.DOT) {
|
if (token == Token.DOT) {
|
||||||
if (next.kind == NodeKind.IDENTIFIER) {
|
if (next.kind == NodeKind.IDENTIFIER) {
|
||||||
expr = Expression.createPropertyAccess(<Expression>expr, <IdentifierExpression>next, tn.range(startPos, tn.pos));
|
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 {
|
} else {
|
||||||
this.error(DiagnosticCode.Identifier_expected, next.range);
|
this.error(DiagnosticCode.Identifier_expected, next.range);
|
||||||
return null;
|
return null;
|
||||||
|
243
src/program.ts
243
src/program.ts
@ -210,8 +210,9 @@ export class Program extends DiagnosticEmitter {
|
|||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeClass(declaration: ClassDeclaration): void {
|
private initializeClass(declaration: ClassDeclaration, namespace: Namespace | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
throw new Error("not implemented");
|
||||||
|
/* const internalName: string = declaration.internalName;
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
return;
|
return;
|
||||||
@ -233,11 +234,12 @@ export class Program extends DiagnosticEmitter {
|
|||||||
this.initializeMethod(<MethodDeclaration>memberDeclaration, prototype);
|
this.initializeMethod(<MethodDeclaration>memberDeclaration, prototype);
|
||||||
else
|
else
|
||||||
throw new Error("unexpected class member");
|
throw new Error("unexpected class member");
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeField(declaration: FieldDeclaration, classPrototype: ClassPrototype): void {
|
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)) {
|
if (classPrototype.members.has(name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
||||||
return;
|
return;
|
||||||
@ -249,11 +251,12 @@ export class Program extends DiagnosticEmitter {
|
|||||||
} else {
|
} else {
|
||||||
const field: FieldPrototype = new FieldPrototype(classPrototype, internalName, declaration);
|
const field: FieldPrototype = new FieldPrototype(classPrototype, internalName, declaration);
|
||||||
classPrototype.members.set(name, field);
|
classPrototype.members.set(name, field);
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeMethod(declaration: MethodDeclaration, classPrototype: ClassPrototype): void {
|
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;
|
const internalName: string = declaration.internalName;
|
||||||
if (classPrototype.members.has(name)) {
|
if (classPrototype.members.has(name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
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;
|
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);
|
const enm: Enum = new Enum(this, internalName, declaration);
|
||||||
|
|
||||||
|
if (this.elements.has(internalName))
|
||||||
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
|
else
|
||||||
this.elements.set(internalName, enm);
|
this.elements.set(internalName, enm);
|
||||||
if (enm.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, enm);
|
||||||
|
} else if (enm.isExported) {
|
||||||
if (this.exports.has(internalName))
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
this.exports.set(internalName, enm);
|
this.exports.set(internalName, enm);
|
||||||
}
|
}
|
||||||
|
|
||||||
const values: EnumValueDeclaration[] = declaration.members;
|
const values: EnumValueDeclaration[] = declaration.members;
|
||||||
for (let i: i32 = 0, k: i32 = values.length; i < k; ++i)
|
for (let i: i32 = 0, k: i32 = values.length; i < k; ++i)
|
||||||
this.initializeEnumValue(values[i], enm);
|
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 internalName: string = declaration.internalName;
|
||||||
const prototype: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, null);
|
const prototype: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, null);
|
||||||
|
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.elements.set(internalName, prototype);
|
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))
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
@ -455,20 +472,27 @@ export class Program extends DiagnosticEmitter {
|
|||||||
queuedImports.push(queuedImport);
|
queuedImports.push(queuedImport);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeInterface(declaration: InterfaceDeclaration): void {
|
private initializeInterface(declaration: InterfaceDeclaration, namespace: Namespace | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const prototype: InterfacePrototype = new InterfacePrototype(this, internalName, declaration);
|
const prototype: InterfacePrototype = new InterfacePrototype(this, internalName, declaration);
|
||||||
|
|
||||||
if (this.elements.has(internalName))
|
if (this.elements.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
this.elements.set(internalName, prototype);
|
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))
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
this.exports.set(internalName, prototype);
|
this.exports.set(internalName, prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
||||||
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
||||||
const memberDeclaration: DeclarationStatement = memberDeclarations[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 internalName: string = declaration.internalName;
|
||||||
const namespace: Namespace = new Namespace(this, internalName, declaration);
|
const namespace: Namespace = new Namespace(this, internalName, declaration);
|
||||||
|
|
||||||
if (this.elements.has(internalName))
|
if (this.elements.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else {
|
else
|
||||||
this.elements.set(internalName, namespace);
|
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))
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
this.exports.set(internalName, namespace);
|
this.exports.set(internalName, namespace);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const members: Statement[] = declaration.members;
|
const members: Statement[] = declaration.members;
|
||||||
for (let i: i32 = 0, k: i32 = members.length; i < k; ++i) {
|
for (let i: i32 = 0, k: i32 = members.length; i < k; ++i) {
|
||||||
const statement: Statement = members[i];
|
const statement: Statement = members[i];
|
||||||
switch (statement.kind) {
|
switch (statement.kind) {
|
||||||
|
|
||||||
case NodeKind.CLASS:
|
case NodeKind.CLASS:
|
||||||
this.initializeClass(<ClassDeclaration>statement);
|
this.initializeClass(<ClassDeclaration>statement, namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.ENUM:
|
case NodeKind.ENUM:
|
||||||
this.initializeEnum(<EnumDeclaration>statement);
|
this.initializeEnum(<EnumDeclaration>statement, namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.FUNCTION:
|
case NodeKind.FUNCTION:
|
||||||
this.initializeFunction(<FunctionDeclaration>statement);
|
this.initializeFunction(<FunctionDeclaration>statement, namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.INTERFACE:
|
case NodeKind.INTERFACE:
|
||||||
this.initializeInterface(<InterfaceDeclaration>statement);
|
this.initializeInterface(<InterfaceDeclaration>statement, namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.NAMESPACE:
|
case NodeKind.NAMESPACE:
|
||||||
this.initializeNamespace(<NamespaceDeclaration>statement);
|
this.initializeNamespace(<NamespaceDeclaration>statement, namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.VARIABLE:
|
case NodeKind.VARIABLE:
|
||||||
this.initializeVariables(<VariableStatement>statement, true);
|
this.initializeVariables(<VariableStatement>statement, namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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;
|
const declarations: VariableDeclaration[] = statement.declarations;
|
||||||
for (let i: i32 = 0, k: i32 = declarations.length; i < k; ++i) {
|
for (let i: i32 = 0, k: i32 = declarations.length; i < k; ++i) {
|
||||||
const declaration: VariableDeclaration = declarations[i];
|
const declaration: VariableDeclaration = declarations[i];
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const global: Global = new Global(this, internalName, declaration, null);
|
const global: Global = new Global(this, internalName, declaration, null);
|
||||||
|
|
||||||
if (this.elements.has(internalName))
|
if (this.elements.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else {
|
else {
|
||||||
this.elements.set(internalName, global);
|
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))
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
@ -596,7 +633,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
return null;
|
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 {
|
resolveTypeArguments(typeParameters: TypeParameter[], typeArgumentNodes: TypeNode[] | null, contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): Type[] | null {
|
||||||
const parameterCount: i32 = typeParameters.length;
|
const parameterCount: i32 = typeParameters.length;
|
||||||
const argumentCount: i32 = typeArgumentNodes ? typeArgumentNodes.length : 0;
|
const argumentCount: i32 = typeArgumentNodes ? typeArgumentNodes.length : 0;
|
||||||
@ -618,6 +655,49 @@ export class Program extends DiagnosticEmitter {
|
|||||||
return typeArguments;
|
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 {
|
resolveElement(expression: Expression, contextualFunction: Function): Element | null {
|
||||||
|
|
||||||
// this -> Class
|
// this -> Class
|
||||||
@ -630,38 +710,11 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// local or global name
|
// local or global name
|
||||||
if (expression.kind == NodeKind.IDENTIFIER) {
|
if (expression.kind == NodeKind.IDENTIFIER) {
|
||||||
const name: string = (<IdentifierExpression>expression).name;
|
return this.resolveIdentifier(<IdentifierExpression>expression, contextualFunction);
|
||||||
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;
|
|
||||||
|
|
||||||
// static or instance property (incl. enum values) or method
|
// static or instance property (incl. enum values) or method
|
||||||
} else if (expression.kind == NodeKind.PROPERTYACCESS) {
|
} else if (expression.kind == NodeKind.PROPERTYACCESS) {
|
||||||
const target: Element | null = this.resolveElement((<PropertyAccessExpression>expression).expression, contextualFunction); // reports
|
return this.resolvePropertyAccess(<PropertyAccessExpression>expression, contextualFunction);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("not implemented: " + expression.kind);
|
throw new Error("not implemented: " + expression.kind);
|
||||||
@ -1130,13 +1183,14 @@ export class Function extends Element {
|
|||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
private tempI32s: Local[] = [];
|
private tempI32s: Local[] | null = null;
|
||||||
private tempI64s: Local[] = [];
|
private tempI64s: Local[] | null = null;
|
||||||
private tempF32s: Local[] = [];
|
private tempF32s: Local[] | null = null;
|
||||||
private tempF64s: Local[] = [];
|
private tempF64s: Local[] | null = null;
|
||||||
|
|
||||||
|
/** Gets a free temporary local of the specified type. */
|
||||||
getTempLocal(type: Type): Local {
|
getTempLocal(type: Type): Local {
|
||||||
let temps: Local[];
|
let temps: Local[] | null;
|
||||||
switch (typeToNativeType(type)) {
|
switch (typeToNativeType(type)) {
|
||||||
case NativeType.I32: temps = this.tempI32s; break;
|
case NativeType.I32: temps = this.tempI32s; break;
|
||||||
case NativeType.I64: temps = this.tempI64s; break;
|
case NativeType.I64: temps = this.tempI64s; break;
|
||||||
@ -1144,30 +1198,32 @@ export class Function extends Element {
|
|||||||
case NativeType.F64: temps = this.tempF64s; break;
|
case NativeType.F64: temps = this.tempF64s; break;
|
||||||
default: throw new Error("unexpected type");
|
default: throw new Error("unexpected type");
|
||||||
}
|
}
|
||||||
if (temps.length > 0)
|
if (temps && temps.length > 0)
|
||||||
return temps.pop();
|
return temps.pop();
|
||||||
return this.addLocal(type);
|
return this.addLocal(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Frees the temporary local for reuse. */
|
||||||
freeTempLocal(local: Local): void {
|
freeTempLocal(local: Local): void {
|
||||||
let temps: Local[];
|
let temps: Local[];
|
||||||
switch (typeToNativeType(local.type)) {
|
switch (typeToNativeType(local.type)) {
|
||||||
case NativeType.I32: temps = this.tempI32s; break;
|
case NativeType.I32: temps = this.tempI32s || (this.tempI32s = []); break;
|
||||||
case NativeType.I64: temps = this.tempI64s; break;
|
case NativeType.I64: temps = this.tempI64s || (this.tempI64s = []); break;
|
||||||
case NativeType.F32: temps = this.tempF32s; break;
|
case NativeType.F32: temps = this.tempF32s || (this.tempF32s = []); break;
|
||||||
case NativeType.F64: temps = this.tempF64s; break;
|
case NativeType.F64: temps = this.tempF64s || (this.tempF64s = []); break;
|
||||||
default: throw new Error("unexpected type");
|
default: throw new Error("unexpected type");
|
||||||
}
|
}
|
||||||
temps.push(local);
|
temps.push(local);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gets and immediately frees a temporary local of the specified type. */
|
||||||
getAndFreeTempLocal(type: Type): Local {
|
getAndFreeTempLocal(type: Type): Local {
|
||||||
let temps: Local[];
|
let temps: Local[];
|
||||||
switch (typeToNativeType(type)) {
|
switch (typeToNativeType(type)) {
|
||||||
case NativeType.I32: temps = this.tempI32s; break;
|
case NativeType.I32: temps = this.tempI32s || (this.tempI32s = []); break;
|
||||||
case NativeType.I64: temps = this.tempI64s; break;
|
case NativeType.I64: temps = this.tempI64s || (this.tempI64s = []); break;
|
||||||
case NativeType.F32: temps = this.tempF32s; break;
|
case NativeType.F32: temps = this.tempF32s || (this.tempF32s = []); break;
|
||||||
case NativeType.F64: temps = this.tempF64s; break;
|
case NativeType.F64: temps = this.tempF64s || (this.tempF64s = []); break;
|
||||||
default: throw new Error("unexpected type");
|
default: throw new Error("unexpected type");
|
||||||
}
|
}
|
||||||
if (temps.length > 0)
|
if (temps.length > 0)
|
||||||
@ -1250,17 +1306,25 @@ export class Field extends Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A yet unresolved class prototype. */
|
/** A yet unresolved class prototype. */
|
||||||
export class ClassPrototype extends Namespace {
|
export class ClassPrototype extends Element {
|
||||||
|
|
||||||
kind = ElementKind.CLASS_PROTOTYPE;
|
kind = ElementKind.CLASS_PROTOTYPE;
|
||||||
|
|
||||||
/** Declaration reference. */
|
/** Declaration reference. */
|
||||||
declaration: ClassDeclaration | null;
|
declaration: ClassDeclaration | null;
|
||||||
/** Resolved instances. */
|
/** 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) {
|
constructor(program: Program, internalName: string, declaration: ClassDeclaration | null = null) {
|
||||||
super(program, internalName, null);
|
super(program, internalName);
|
||||||
if (this.declaration = declaration) {
|
if (this.declaration = declaration) {
|
||||||
if (this.declaration.modifiers) {
|
if (this.declaration.modifiers) {
|
||||||
for (let i: i32 = 0, k: i32 = this.declaration.modifiers.length; i < k; ++i) {
|
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)
|
if (this.declaration.typeParameters.length)
|
||||||
this.isGeneric = true;
|
this.isGeneric = true;
|
||||||
}
|
}
|
||||||
this.instances = new Map();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null): Class {
|
resolve(typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null): Class {
|
||||||
@ -1305,7 +1368,7 @@ export class ClassPrototype extends Namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A resolved class. */
|
/** A resolved class. */
|
||||||
export class Class extends Namespace {
|
export class Class extends Element {
|
||||||
|
|
||||||
kind = ElementKind.CLASS;
|
kind = ElementKind.CLASS;
|
||||||
|
|
||||||
@ -1317,19 +1380,27 @@ export class Class extends Namespace {
|
|||||||
type: Type;
|
type: Type;
|
||||||
/** Base class, if applicable. */
|
/** Base class, if applicable. */
|
||||||
base: Class | null;
|
base: Class | null;
|
||||||
|
/** Contextual type argumentsfor fields and methods. */
|
||||||
contextualTypeArguments: Map<string,Type> = new Map();
|
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. */
|
/** Constructs a new class. */
|
||||||
constructor(prototype: ClassPrototype, internalName: string, typeArguments: Type[] = [], base: Class | null = null) {
|
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.prototype = prototype;
|
||||||
this.flags = prototype.flags;
|
this.flags = prototype.flags;
|
||||||
this.typeArguments = typeArguments;
|
this.typeArguments = typeArguments;
|
||||||
this.base = base;
|
|
||||||
this.type = (prototype.program.target == Target.WASM64 ? Type.usize64 : Type.usize32).asClass(this);
|
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)
|
if (base)
|
||||||
for (let [name, type] of base.contextualTypeArguments)
|
for (let [name, type] of base.contextualTypeArguments)
|
||||||
this.contextualTypeArguments.set(name, type);
|
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 {
|
export class InterfacePrototype extends ClassPrototype {
|
||||||
|
|
||||||
kind = ElementKind.INTERFACE_PROTOTYPE;
|
kind = ElementKind.INTERFACE_PROTOTYPE;
|
||||||
|
|
||||||
/** Declaration reference. */
|
/** Declaration reference. */
|
||||||
declaration: InterfaceDeclaration | null;
|
declaration: InterfaceDeclaration | null; // more specific
|
||||||
|
|
||||||
/** Constructs a new interface prototype. */
|
/** Constructs a new interface prototype. */
|
||||||
constructor(program: Program, internalName: string, declaration: InterfaceDeclaration | null = null) {
|
constructor(program: Program, internalName: string, declaration: InterfaceDeclaration | null = null) {
|
||||||
@ -1370,9 +1441,9 @@ export class Interface extends Class {
|
|||||||
kind = ElementKind.INTERFACE;
|
kind = ElementKind.INTERFACE;
|
||||||
|
|
||||||
/** Prototype reference. */
|
/** Prototype reference. */
|
||||||
prototype: InterfacePrototype;
|
prototype: InterfacePrototype; // more specific
|
||||||
/** Base interface, if applcable. */
|
/** Base interface, if applcable. */
|
||||||
base: Interface | null;
|
base: Interface | null; // more specific
|
||||||
|
|
||||||
/** Constructs a new interface. */
|
/** Constructs a new interface. */
|
||||||
constructor(prototype: InterfacePrototype, internalName: string, typeArguments: Type[] = [], base: Interface | null = null) {
|
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 fromCodePoint(cp: i32): string;
|
||||||
static fromCodePoints(arr: i32[]): string;
|
static fromCodePoints(arr: i32[]): string;
|
||||||
readonly length: i32;
|
readonly length: i32;
|
||||||
|
private constructor();
|
||||||
indexOf(subject: string): i32;
|
indexOf(subject: string): i32;
|
||||||
|
lastIndexOf(subject: string): i32;
|
||||||
charCodeAt(index: i32): i32;
|
charCodeAt(index: i32): i32;
|
||||||
substring(from: i32, to?: i32): string;
|
substring(from: i32, to?: i32): string;
|
||||||
startsWith(subject: string): bool;
|
startsWith(subject: string): bool;
|
||||||
endsWith(subject: string): bool;
|
endsWith(subject: string): bool;
|
||||||
replace(search: string, replacement: string): string;
|
replace(search: string, replacement: string): string;
|
||||||
|
toString(): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare class Boolean {}
|
interface Boolean {}
|
||||||
|
|
||||||
declare class Number {
|
declare class Number {
|
||||||
toString(radix: i32): string;
|
private constructor();
|
||||||
|
toString(radix?: i32): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare class Object {}
|
interface Object {}
|
||||||
|
|
||||||
declare class Function {
|
interface Function {}
|
||||||
/** @deprecated */
|
|
||||||
apply(subject: any): any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare class RegExp {}
|
interface RegExp {}
|
||||||
|
|
||||||
declare interface IArguments {}
|
interface IArguments {}
|
||||||
|
|
||||||
declare class Error {
|
declare class Error {
|
||||||
constructor(message: string);
|
constructor(message: string);
|
||||||
@ -119,7 +120,8 @@ declare class Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare class Symbol {
|
declare class Symbol {
|
||||||
static iterator: symbol;
|
private constructor();
|
||||||
|
static readonly iterator: symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare class Set<T> {
|
declare class Set<T> {
|
||||||
@ -139,7 +141,7 @@ declare class Map<K,V> {
|
|||||||
[Symbol.iterator](): Iterator<[K, V]>;
|
[Symbol.iterator](): Iterator<[K, V]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface Iterator<T> {}
|
interface Iterator<T> {}
|
||||||
|
|
||||||
declare namespace JSON {
|
declare namespace JSON {
|
||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
(module
|
(module
|
||||||
(type $iii (func (param i32 i32) (result i32)))
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
|
(type $v (func))
|
||||||
(global $export/a i32 (i32.const 1))
|
(global $export/a i32 (i32.const 1))
|
||||||
(global $export/b i32 (i32.const 2))
|
(global $export/b i32 (i32.const 2))
|
||||||
(memory $0 1)
|
(memory $0 1)
|
||||||
@ -7,6 +8,7 @@
|
|||||||
(export "renamed_sub" (func $export/sub))
|
(export "renamed_sub" (func $export/sub))
|
||||||
(export "a" (global $export/a))
|
(export "a" (global $export/a))
|
||||||
(export "renamed_b" (global $export/b))
|
(export "renamed_b" (global $export/b))
|
||||||
|
(export "two" (func $export/ns.two))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
(func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
(i32.add
|
(i32.add
|
||||||
@ -20,4 +22,7 @@
|
|||||||
(get_local $1)
|
(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 { b as renamed_b };
|
||||||
|
|
||||||
/* export namespace ns {
|
export namespace ns {
|
||||||
function one(): void {}
|
function one(): void {}
|
||||||
export function two(): void {}
|
export function two(): void {}
|
||||||
} */
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
(module
|
(module
|
||||||
(type $iii (func (param i32 i32) (result i32)))
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
|
(type $v (func))
|
||||||
(global $export/a i32 (i32.const 1))
|
(global $export/a i32 (i32.const 1))
|
||||||
(global $export/b i32 (i32.const 2))
|
(global $export/b i32 (i32.const 2))
|
||||||
(global $HEAP_START i32 (i32.const 4))
|
(global $HEAP_START i32 (i32.const 4))
|
||||||
@ -8,6 +9,7 @@
|
|||||||
(export "renamed_sub" (func $export/sub))
|
(export "renamed_sub" (func $export/sub))
|
||||||
(export "a" (global $export/a))
|
(export "a" (global $export/a))
|
||||||
(export "renamed_b" (global $export/b))
|
(export "renamed_b" (global $export/b))
|
||||||
|
(export "two" (func $export/ns.two))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
(func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
(return
|
(return
|
||||||
@ -25,6 +27,8 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(func $export/ns.two (; 2 ;) (type $v)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
(;
|
(;
|
||||||
[program.elements]
|
[program.elements]
|
||||||
@ -60,9 +64,13 @@
|
|||||||
export/sub
|
export/sub
|
||||||
export/a
|
export/a
|
||||||
export/b
|
export/b
|
||||||
|
export/ns
|
||||||
|
export/ns.one
|
||||||
|
export/ns.two
|
||||||
[program.exports]
|
[program.exports]
|
||||||
export/add
|
export/add
|
||||||
export/renamed_sub
|
export/renamed_sub
|
||||||
export/a
|
export/a
|
||||||
export/renamed_b
|
export/renamed_b
|
||||||
|
export/ns
|
||||||
;)
|
;)
|
||||||
|
@ -41,5 +41,10 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(block
|
||||||
|
(block $__inlined_func$export/ns.two
|
||||||
|
(nop)
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -16,7 +16,10 @@
|
|||||||
(get_local $1)
|
(get_local $1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(func $start (; 2 ;) (type $v)
|
(func $export/ns.two (; 2 ;) (type $v)
|
||||||
|
(nop)
|
||||||
|
)
|
||||||
|
(func $start (; 3 ;) (type $v)
|
||||||
(drop
|
(drop
|
||||||
(i32.add
|
(i32.add
|
||||||
(call $export/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);
|
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
|
(drop
|
||||||
(i32.add
|
(i32.add
|
||||||
(call $export/add
|
(call $export/add
|
||||||
@ -36,6 +38,7 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(call $export/ns.two)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(;
|
(;
|
||||||
@ -72,13 +75,18 @@
|
|||||||
export/sub
|
export/sub
|
||||||
export/a
|
export/a
|
||||||
export/b
|
export/b
|
||||||
|
export/ns
|
||||||
|
export/ns.one
|
||||||
|
export/ns.two
|
||||||
import/add
|
import/add
|
||||||
import/sub
|
import/sub
|
||||||
import/a
|
import/a
|
||||||
import/b
|
import/b
|
||||||
|
import/renamed_ns
|
||||||
[program.exports]
|
[program.exports]
|
||||||
export/add
|
export/add
|
||||||
export/renamed_sub
|
export/renamed_sub
|
||||||
export/a
|
export/a
|
||||||
export/renamed_b
|
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";
|
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 };
|
export { imported_add as renamed_add, imported_sub as rerenamed_sub };
|
||||||
|
|
||||||
imported_add(1, 2) + imported_sub(3, 4);
|
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
|
(drop
|
||||||
(i32.add
|
(i32.add
|
||||||
(call $export/add
|
(call $export/add
|
||||||
@ -78,17 +80,23 @@
|
|||||||
export/sub
|
export/sub
|
||||||
export/a
|
export/a
|
||||||
export/b
|
export/b
|
||||||
|
export/ns
|
||||||
|
export/ns.one
|
||||||
|
export/ns.two
|
||||||
reexport/imported_add
|
reexport/imported_add
|
||||||
reexport/imported_sub
|
reexport/imported_sub
|
||||||
|
reexport/imported_ns
|
||||||
[program.exports]
|
[program.exports]
|
||||||
export/add
|
export/add
|
||||||
export/renamed_sub
|
export/renamed_sub
|
||||||
export/a
|
export/a
|
||||||
export/renamed_b
|
export/renamed_b
|
||||||
|
export/ns
|
||||||
reexport/add
|
reexport/add
|
||||||
reexport/renamed_sub
|
reexport/renamed_sub
|
||||||
reexport/renamed_a
|
reexport/renamed_a
|
||||||
reexport/rerenamed_b
|
reexport/rerenamed_b
|
||||||
reexport/renamed_add
|
reexport/renamed_add
|
||||||
reexport/rerenamed_sub
|
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