mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-28 16:32:15 +00:00
Initial support for default imports/exports, see #98
Does not implement combinations like 'import theDefault, *' yet
This commit is contained in:
parent
27e54ed07b
commit
fa667386d9
@ -39,9 +39,6 @@
|
|||||||
"no-debugger": {
|
"no-debugger": {
|
||||||
"severity": "error"
|
"severity": "error"
|
||||||
},
|
},
|
||||||
"no-default-export": {
|
|
||||||
"severity": "error"
|
|
||||||
},
|
|
||||||
"no-duplicate-super": {
|
"no-duplicate-super": {
|
||||||
"severity": "error"
|
"severity": "error"
|
||||||
},
|
},
|
||||||
|
19
src/ast.ts
19
src/ast.ts
@ -67,6 +67,7 @@ export enum NodeKind {
|
|||||||
DO,
|
DO,
|
||||||
EMPTY,
|
EMPTY,
|
||||||
EXPORT,
|
EXPORT,
|
||||||
|
EXPORTDEFAULT,
|
||||||
EXPORTIMPORT,
|
EXPORTIMPORT,
|
||||||
EXPRESSION,
|
EXPRESSION,
|
||||||
FOR,
|
FOR,
|
||||||
@ -701,6 +702,16 @@ export abstract class Node {
|
|||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static createExportDefaultStatement(
|
||||||
|
declaration: DeclarationStatement,
|
||||||
|
range: Range
|
||||||
|
): ExportDefaultStatement {
|
||||||
|
var stmt = new ExportDefaultStatement();
|
||||||
|
stmt.declaration = declaration;
|
||||||
|
stmt.range = range;
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
|
||||||
static createExportImportStatement(
|
static createExportImportStatement(
|
||||||
name: IdentifierExpression,
|
name: IdentifierExpression,
|
||||||
externalName: IdentifierExpression,
|
externalName: IdentifierExpression,
|
||||||
@ -1775,6 +1786,14 @@ export class ExportStatement extends Statement {
|
|||||||
isDeclare: bool;
|
isDeclare: bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Represents an `export default` statement. */
|
||||||
|
export class ExportDefaultStatement extends Statement {
|
||||||
|
kind = NodeKind.EXPORTDEFAULT;
|
||||||
|
|
||||||
|
/** Declaration being exported as default. */
|
||||||
|
declaration: DeclarationStatement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Represents an expression that is used as a statement. */
|
/** Represents an expression that is used as a statement. */
|
||||||
export class ExpressionStatement extends Statement {
|
export class ExpressionStatement extends Statement {
|
||||||
kind = NodeKind.EXPRESSION;
|
kind = NodeKind.EXPRESSION;
|
||||||
|
@ -156,7 +156,8 @@ import {
|
|||||||
|
|
||||||
nodeIsConstantValue,
|
nodeIsConstantValue,
|
||||||
findDecorator,
|
findDecorator,
|
||||||
isTypeOmitted
|
isTypeOmitted,
|
||||||
|
ExportDefaultStatement
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -1619,6 +1620,9 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// === Statements ===============================================================================
|
// === Statements ===============================================================================
|
||||||
|
|
||||||
compileTopLevelStatement(statement: Statement, body: ExpressionRef[]): void {
|
compileTopLevelStatement(statement: Statement, body: ExpressionRef[]): void {
|
||||||
|
if (statement.kind == NodeKind.EXPORTDEFAULT) {
|
||||||
|
statement = (<ExportDefaultStatement>statement).declaration;
|
||||||
|
}
|
||||||
switch (statement.kind) {
|
switch (statement.kind) {
|
||||||
case NodeKind.CLASSDECLARATION: {
|
case NodeKind.CLASSDECLARATION: {
|
||||||
let memberStatements = (<ClassDeclaration>statement).members;
|
let memberStatements = (<ClassDeclaration>statement).members;
|
||||||
|
@ -66,6 +66,7 @@ export enum DiagnosticCode {
|
|||||||
Type_expected = 1110,
|
Type_expected = 1110,
|
||||||
A_default_clause_cannot_appear_more_than_once_in_a_switch_statement = 1113,
|
A_default_clause_cannot_appear_more_than_once_in_a_switch_statement = 1113,
|
||||||
Duplicate_label_0 = 1114,
|
Duplicate_label_0 = 1114,
|
||||||
|
An_export_assignment_cannot_have_modifiers = 1120,
|
||||||
Octal_literals_are_not_allowed_in_strict_mode = 1121,
|
Octal_literals_are_not_allowed_in_strict_mode = 1121,
|
||||||
Digit_expected = 1124,
|
Digit_expected = 1124,
|
||||||
Hexadecimal_digit_expected = 1125,
|
Hexadecimal_digit_expected = 1125,
|
||||||
@ -204,6 +205,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
|||||||
case 1110: return "Type expected.";
|
case 1110: return "Type expected.";
|
||||||
case 1113: return "A 'default' clause cannot appear more than once in a 'switch' statement.";
|
case 1113: return "A 'default' clause cannot appear more than once in a 'switch' statement.";
|
||||||
case 1114: return "Duplicate label '{0}'.";
|
case 1114: return "Duplicate label '{0}'.";
|
||||||
|
case 1120: return "An export assignment cannot have modifiers.";
|
||||||
case 1121: return "Octal literals are not allowed in strict mode.";
|
case 1121: return "Octal literals are not allowed in strict mode.";
|
||||||
case 1124: return "Digit expected.";
|
case 1124: return "Digit expected.";
|
||||||
case 1125: return "Hexadecimal digit expected.";
|
case 1125: return "Hexadecimal digit expected.";
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
"Type expected.": 1110,
|
"Type expected.": 1110,
|
||||||
"A 'default' clause cannot appear more than once in a 'switch' statement.": 1113,
|
"A 'default' clause cannot appear more than once in a 'switch' statement.": 1113,
|
||||||
"Duplicate label '{0}'.": 1114,
|
"Duplicate label '{0}'.": 1114,
|
||||||
|
"An export assignment cannot have modifiers.": 1120,
|
||||||
"Octal literals are not allowed in strict mode.": 1121,
|
"Octal literals are not allowed in strict mode.": 1121,
|
||||||
"Digit expected.": 1124,
|
"Digit expected.": 1124,
|
||||||
"Hexadecimal digit expected.": 1125,
|
"Hexadecimal digit expected.": 1125,
|
||||||
|
@ -52,6 +52,7 @@ import {
|
|||||||
EmptyStatement,
|
EmptyStatement,
|
||||||
ExportImportStatement,
|
ExportImportStatement,
|
||||||
ExportStatement,
|
ExportStatement,
|
||||||
|
ExportDefaultStatement,
|
||||||
ExpressionStatement,
|
ExpressionStatement,
|
||||||
ForStatement,
|
ForStatement,
|
||||||
IfStatement,
|
IfStatement,
|
||||||
@ -230,6 +231,10 @@ export class ASTBuilder {
|
|||||||
this.visitExportStatement(<ExportStatement>node);
|
this.visitExportStatement(<ExportStatement>node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NodeKind.EXPORTDEFAULT: {
|
||||||
|
this.visitExportDefaultStatement(<ExportDefaultStatement>node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NodeKind.EXPORTIMPORT: {
|
case NodeKind.EXPORTIMPORT: {
|
||||||
this.visitExportImportStatement(<ExportImportStatement>node);
|
this.visitExportImportStatement(<ExportImportStatement>node);
|
||||||
break;
|
break;
|
||||||
@ -851,15 +856,19 @@ export class ASTBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visitClassDeclaration(node: ClassDeclaration): void {
|
visitClassDeclaration(node: ClassDeclaration, isDefault: bool = false): void {
|
||||||
var decorators = node.decorators;
|
var decorators = node.decorators;
|
||||||
if (decorators) {
|
if (decorators) {
|
||||||
for (let i = 0, k = decorators.length; i < k; ++i) {
|
for (let i = 0, k = decorators.length; i < k; ++i) {
|
||||||
this.serializeDecorator(decorators[i]);
|
this.serializeDecorator(decorators[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.serializeExternalModifiers(node);
|
|
||||||
var sb = this.sb;
|
var sb = this.sb;
|
||||||
|
if (isDefault) {
|
||||||
|
sb.push("export default ");
|
||||||
|
} else {
|
||||||
|
this.serializeExternalModifiers(node);
|
||||||
|
}
|
||||||
if (node.is(CommonFlags.ABSTRACT)) sb.push("abstract ");
|
if (node.is(CommonFlags.ABSTRACT)) sb.push("abstract ");
|
||||||
if (node.name.text.length) {
|
if (node.name.text.length) {
|
||||||
sb.push("class ");
|
sb.push("class ");
|
||||||
@ -931,9 +940,13 @@ export class ASTBuilder {
|
|||||||
visitEmptyStatement(node: EmptyStatement): void {
|
visitEmptyStatement(node: EmptyStatement): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
visitEnumDeclaration(node: EnumDeclaration): void {
|
visitEnumDeclaration(node: EnumDeclaration, isDefault: bool = false): void {
|
||||||
var sb = this.sb;
|
var sb = this.sb;
|
||||||
this.serializeExternalModifiers(node);
|
if (isDefault) {
|
||||||
|
sb.push("export default ");
|
||||||
|
} else {
|
||||||
|
this.serializeExternalModifiers(node);
|
||||||
|
}
|
||||||
if (node.is(CommonFlags.CONST)) sb.push("const ");
|
if (node.is(CommonFlags.CONST)) sb.push("const ");
|
||||||
sb.push("enum ");
|
sb.push("enum ");
|
||||||
this.visitIdentifierExpression(node.name);
|
this.visitIdentifierExpression(node.name);
|
||||||
@ -1011,6 +1024,33 @@ export class ASTBuilder {
|
|||||||
sb.push(";");
|
sb.push(";");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
visitExportDefaultStatement(node: ExportDefaultStatement): void {
|
||||||
|
var declaration = node.declaration;
|
||||||
|
switch (declaration.kind) {
|
||||||
|
case NodeKind.ENUMDECLARATION: {
|
||||||
|
this.visitEnumDeclaration(<EnumDeclaration>declaration, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeKind.FUNCTIONDECLARATION: {
|
||||||
|
this.visitFunctionDeclaration(<FunctionDeclaration>declaration, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeKind.CLASSDECLARATION: {
|
||||||
|
this.visitClassDeclaration(<ClassDeclaration>declaration, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeKind.INTERFACEDECLARATION: {
|
||||||
|
this.visitInterfaceDeclaration(<InterfaceDeclaration>declaration, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeKind.NAMESPACEDECLARATION: {
|
||||||
|
this.visitNamespaceDeclaration(<NamespaceDeclaration>declaration, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
visitExpressionStatement(node: ExpressionStatement): void {
|
visitExpressionStatement(node: ExpressionStatement): void {
|
||||||
this.visitNode(node.expression);
|
this.visitNode(node.expression);
|
||||||
}
|
}
|
||||||
@ -1065,7 +1105,7 @@ export class ASTBuilder {
|
|||||||
this.visitNode(node.statement);
|
this.visitNode(node.statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitFunctionDeclaration(node: FunctionDeclaration): void {
|
visitFunctionDeclaration(node: FunctionDeclaration, isDefault: bool = false): void {
|
||||||
var sb = this.sb;
|
var sb = this.sb;
|
||||||
var decorators = node.decorators;
|
var decorators = node.decorators;
|
||||||
if (decorators) {
|
if (decorators) {
|
||||||
@ -1073,8 +1113,12 @@ export class ASTBuilder {
|
|||||||
this.serializeDecorator(decorators[i]);
|
this.serializeDecorator(decorators[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.serializeExternalModifiers(node);
|
if (isDefault) {
|
||||||
this.serializeAccessModifiers(node);
|
sb.push("export default ");
|
||||||
|
} else {
|
||||||
|
this.serializeExternalModifiers(node);
|
||||||
|
this.serializeAccessModifiers(node);
|
||||||
|
}
|
||||||
if (node.name.text.length) {
|
if (node.name.text.length) {
|
||||||
sb.push("function ");
|
sb.push("function ");
|
||||||
} else {
|
} else {
|
||||||
@ -1230,15 +1274,19 @@ export class ASTBuilder {
|
|||||||
this.visitTypeNode(node.valueType);
|
this.visitTypeNode(node.valueType);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitInterfaceDeclaration(node: InterfaceDeclaration): void {
|
visitInterfaceDeclaration(node: InterfaceDeclaration, isDefault: bool = false): void {
|
||||||
var decorators = node.decorators;
|
var decorators = node.decorators;
|
||||||
if (decorators) {
|
if (decorators) {
|
||||||
for (let i = 0, k = decorators.length; i < k; ++i) {
|
for (let i = 0, k = decorators.length; i < k; ++i) {
|
||||||
this.serializeDecorator(decorators[i]);
|
this.serializeDecorator(decorators[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.serializeExternalModifiers(node);
|
|
||||||
var sb = this.sb;
|
var sb = this.sb;
|
||||||
|
if (isDefault) {
|
||||||
|
sb.push("export default ");
|
||||||
|
} else {
|
||||||
|
this.serializeExternalModifiers(node);
|
||||||
|
}
|
||||||
sb.push("interface ");
|
sb.push("interface ");
|
||||||
this.visitIdentifierExpression(node.name);
|
this.visitIdentifierExpression(node.name);
|
||||||
var typeParameters = node.typeParameters;
|
var typeParameters = node.typeParameters;
|
||||||
@ -1284,15 +1332,19 @@ export class ASTBuilder {
|
|||||||
this.visitFunctionCommon(node);
|
this.visitFunctionCommon(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitNamespaceDeclaration(node: NamespaceDeclaration): void {
|
visitNamespaceDeclaration(node: NamespaceDeclaration, isDefault: bool = false): void {
|
||||||
var decorators = node.decorators;
|
var decorators = node.decorators;
|
||||||
if (decorators) {
|
if (decorators) {
|
||||||
for (let i = 0, k = decorators.length; i < k; ++i) {
|
for (let i = 0, k = decorators.length; i < k; ++i) {
|
||||||
this.serializeDecorator(decorators[i]);
|
this.serializeDecorator(decorators[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.serializeExternalModifiers(node);
|
|
||||||
var sb = this.sb;
|
var sb = this.sb;
|
||||||
|
if (isDefault) {
|
||||||
|
sb.push("export default ");
|
||||||
|
} else {
|
||||||
|
this.serializeExternalModifiers(node);
|
||||||
|
}
|
||||||
sb.push("namespace ");
|
sb.push("namespace ");
|
||||||
this.visitIdentifierExpression(node.name);
|
this.visitIdentifierExpression(node.name);
|
||||||
var members = node.members;
|
var members = node.members;
|
||||||
|
@ -171,31 +171,34 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
// check modifiers
|
// check modifiers
|
||||||
var exportStart: i32 = 0;
|
var exportStart: i32 = 0;
|
||||||
var exportEnd: i32 = 0;
|
var exportEnd: i32 = 0;
|
||||||
|
var defaultStart: i32 = 0;
|
||||||
|
var defaultEnd: i32 = 0;
|
||||||
if (tn.skip(Token.EXPORT)) {
|
if (tn.skip(Token.EXPORT)) {
|
||||||
if (tn.skip(Token.DEFAULT)) {
|
|
||||||
this.error(
|
|
||||||
DiagnosticCode.Operation_not_supported,
|
|
||||||
tn.range()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (startPos < 0) startPos = tn.tokenPos;
|
if (startPos < 0) startPos = tn.tokenPos;
|
||||||
flags |= CommonFlags.EXPORT;
|
flags |= CommonFlags.EXPORT;
|
||||||
exportStart = tn.tokenPos;
|
exportStart = tn.tokenPos;
|
||||||
exportEnd = tn.pos;
|
exportEnd = tn.pos;
|
||||||
|
if (tn.skip(Token.DEFAULT)) {
|
||||||
|
defaultStart = tn.tokenPos;
|
||||||
|
defaultEnd = tn.pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var declareStart: i32 = 0;
|
var declareStart: i32 = 0;
|
||||||
var declareEnd: i32 = 0;
|
var declareEnd: i32 = 0;
|
||||||
var contextIsAmbient = namespace != null && namespace.is(CommonFlags.AMBIENT);
|
var contextIsAmbient = namespace != null && namespace.is(CommonFlags.AMBIENT);
|
||||||
if (tn.skip(Token.DECLARE)) {
|
if (tn.skip(Token.DECLARE)) {
|
||||||
if (startPos < 0) startPos = tn.tokenPos;
|
|
||||||
if (contextIsAmbient) {
|
if (contextIsAmbient) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context,
|
DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context,
|
||||||
tn.range()
|
tn.range()
|
||||||
); // recoverable
|
); // recoverable
|
||||||
|
} else {
|
||||||
|
if (startPos < 0) startPos = tn.tokenPos;
|
||||||
|
declareStart = startPos;
|
||||||
|
declareEnd = tn.pos;
|
||||||
|
flags |= CommonFlags.DECLARE | CommonFlags.AMBIENT;
|
||||||
}
|
}
|
||||||
flags |= CommonFlags.DECLARE | CommonFlags.AMBIENT;
|
|
||||||
} else if (contextIsAmbient) {
|
} else if (contextIsAmbient) {
|
||||||
flags |= CommonFlags.AMBIENT;
|
flags |= CommonFlags.AMBIENT;
|
||||||
}
|
}
|
||||||
@ -297,7 +300,18 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// handle plain exports
|
// handle plain exports
|
||||||
if (flags & CommonFlags.EXPORT) {
|
if (flags & CommonFlags.EXPORT) {
|
||||||
statement = this.parseExport(tn, startPos, (flags & CommonFlags.DECLARE) != 0);
|
if (defaultEnd && tn.skipIdentifier(IdentifierHandling.PREFER)) {
|
||||||
|
if (declareEnd) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode.An_export_assignment_cannot_have_modifiers,
|
||||||
|
tn.range(declareStart, declareEnd)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
statement = this.parseExportDefaultAlias(tn, startPos, defaultStart, defaultEnd);
|
||||||
|
defaultStart = defaultEnd = 0; // consume
|
||||||
|
} else {
|
||||||
|
statement = this.parseExport(tn, startPos, (flags & CommonFlags.DECLARE) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
// handle non-declaration statements
|
// handle non-declaration statements
|
||||||
} else {
|
} else {
|
||||||
@ -330,6 +344,25 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if this an `export default` declaration
|
||||||
|
if (defaultEnd && statement !== null) {
|
||||||
|
switch (statement.kind) {
|
||||||
|
case NodeKind.ENUMDECLARATION:
|
||||||
|
case NodeKind.FUNCTIONDECLARATION:
|
||||||
|
case NodeKind.CLASSDECLARATION:
|
||||||
|
case NodeKind.INTERFACEDECLARATION:
|
||||||
|
case NodeKind.NAMESPACEDECLARATION: {
|
||||||
|
return Node.createExportDefaultStatement(<DeclarationStatement>statement, tn.range(startPos, tn.pos));
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
|
tn.range(defaultStart, defaultEnd), "default"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2318,6 +2351,28 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseExportDefaultAlias(
|
||||||
|
tn: Tokenizer,
|
||||||
|
startPos: i32,
|
||||||
|
defaultStart: i32,
|
||||||
|
defaultEnd: i32
|
||||||
|
): ExportStatement {
|
||||||
|
|
||||||
|
// at 'export' 'default': [Known-To-Be-]Identifier
|
||||||
|
|
||||||
|
var name = tn.readIdentifier();
|
||||||
|
var range = tn.range();
|
||||||
|
var ret = Node.createExportStatement([
|
||||||
|
Node.createExportMember(
|
||||||
|
Node.createIdentifierExpression(name, range),
|
||||||
|
Node.createIdentifierExpression("default", tn.range(defaultStart, defaultEnd)),
|
||||||
|
range
|
||||||
|
)
|
||||||
|
], null, false, tn.range(startPos, tn.pos));
|
||||||
|
tn.skip(Token.SEMICOLON);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
parseImport(
|
parseImport(
|
||||||
tn: Tokenizer
|
tn: Tokenizer
|
||||||
): ImportStatement | null {
|
): ImportStatement | null {
|
||||||
@ -2330,7 +2385,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
var members: ImportDeclaration[] | null = null;
|
var members: ImportDeclaration[] | null = null;
|
||||||
var namespaceName: IdentifierExpression | null = null;
|
var namespaceName: IdentifierExpression | null = null;
|
||||||
var skipFrom = false;
|
var skipFrom = false;
|
||||||
if (tn.skip(Token.OPENBRACE)) {
|
if (tn.skip(Token.OPENBRACE)) { // import { ... } from "file"
|
||||||
members = new Array();
|
members = new Array();
|
||||||
while (!tn.skip(Token.CLOSEBRACE)) {
|
while (!tn.skip(Token.CLOSEBRACE)) {
|
||||||
let member = this.parseImportDeclaration(tn);
|
let member = this.parseImportDeclaration(tn);
|
||||||
@ -2348,7 +2403,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (tn.skip(Token.ASTERISK)) {
|
} else if (tn.skip(Token.ASTERISK)) { // import * from "file"
|
||||||
if (tn.skip(Token.AS)) {
|
if (tn.skip(Token.AS)) {
|
||||||
if (tn.skipIdentifier()) {
|
if (tn.skipIdentifier()) {
|
||||||
namespaceName = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
namespaceName = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
||||||
@ -2366,7 +2421,25 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (tn.skip(Token.IDENTIFIER, IdentifierHandling.PREFER)) { // import Name from "file"
|
||||||
|
let name = tn.readIdentifier();
|
||||||
|
let range = tn.range();
|
||||||
|
members = [
|
||||||
|
Node.createImportDeclaration(
|
||||||
|
Node.createIdentifierExpression("default", range),
|
||||||
|
Node.createIdentifierExpression(name, range),
|
||||||
|
range
|
||||||
|
)
|
||||||
|
];
|
||||||
|
if (tn.skip(Token.COMMA)) {
|
||||||
|
// TODO: default + star, default + members
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode.Operation_not_supported,
|
||||||
|
tn.range()
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else { // import "file"
|
||||||
skipFrom = true;
|
skipFrom = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,8 @@ import {
|
|||||||
VariableStatement,
|
VariableStatement,
|
||||||
|
|
||||||
decoratorNameToKind,
|
decoratorNameToKind,
|
||||||
findDecorator
|
findDecorator,
|
||||||
|
ExportDefaultStatement
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -100,10 +101,6 @@ import {
|
|||||||
Flow
|
Flow
|
||||||
} from "./flow";
|
} from "./flow";
|
||||||
|
|
||||||
import {
|
|
||||||
BuiltinSymbols
|
|
||||||
} from "./builtins";
|
|
||||||
|
|
||||||
/** Represents a yet unresolved `import`. */
|
/** Represents a yet unresolved `import`. */
|
||||||
class QueuedImport {
|
class QueuedImport {
|
||||||
constructor(
|
constructor(
|
||||||
@ -616,6 +613,10 @@ export class Program extends DiagnosticEmitter {
|
|||||||
this.initializeExports(<ExportStatement>statement, file, queuedExports, queuedExportsStar);
|
this.initializeExports(<ExportStatement>statement, file, queuedExports, queuedExportsStar);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NodeKind.EXPORTDEFAULT: {
|
||||||
|
this.initializeExportDefault(<ExportDefaultStatement>statement, file, queuedExtends, queuedImplements);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NodeKind.IMPORT: {
|
case NodeKind.IMPORT: {
|
||||||
this.initializeImports(<ImportStatement>statement, file, queuedImports, queuedExports);
|
this.initializeImports(<ImportStatement>statement, file, queuedImports, queuedExports);
|
||||||
break;
|
break;
|
||||||
@ -1117,7 +1118,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
queuedExtends: ClassPrototype[],
|
queuedExtends: ClassPrototype[],
|
||||||
/** So far queued `implements` clauses. */
|
/** So far queued `implements` clauses. */
|
||||||
queuedImplements: ClassPrototype[]
|
queuedImplements: ClassPrototype[]
|
||||||
): void {
|
): ClassPrototype | null {
|
||||||
var name = declaration.name.text;
|
var name = declaration.name.text;
|
||||||
var element = new ClassPrototype(
|
var element = new ClassPrototype(
|
||||||
name,
|
name,
|
||||||
@ -1129,7 +1130,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
DecoratorFlags.UNMANAGED
|
DecoratorFlags.UNMANAGED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (!parent.add(name, element)) return;
|
if (!parent.add(name, element)) return null;
|
||||||
|
|
||||||
var implementsTypes = declaration.implementsTypes;
|
var implementsTypes = declaration.implementsTypes;
|
||||||
if (implementsTypes) {
|
if (implementsTypes) {
|
||||||
@ -1180,6 +1181,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
default: assert(false); // class member expected
|
default: assert(false); // class member expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initializes a field of a class or interface. */
|
/** Initializes a field of a class or interface. */
|
||||||
@ -1396,7 +1398,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
declaration: EnumDeclaration,
|
declaration: EnumDeclaration,
|
||||||
/** Parent element, usually a file or namespace. */
|
/** Parent element, usually a file or namespace. */
|
||||||
parent: Element
|
parent: Element
|
||||||
): void {
|
): Enum | null {
|
||||||
var name = declaration.name.text;
|
var name = declaration.name.text;
|
||||||
var element = new Enum(
|
var element = new Enum(
|
||||||
name,
|
name,
|
||||||
@ -1408,11 +1410,12 @@ export class Program extends DiagnosticEmitter {
|
|||||||
DecoratorFlags.LAZY
|
DecoratorFlags.LAZY
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (!parent.add(name, element)) return;
|
if (!parent.add(name, element)) return null;
|
||||||
var values = declaration.values;
|
var values = declaration.values;
|
||||||
for (let i = 0, k = values.length; i < k; ++i) {
|
for (let i = 0, k = values.length; i < k; ++i) {
|
||||||
this.initializeEnumValue(values[i], element);
|
this.initializeEnumValue(values[i], element);
|
||||||
}
|
}
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initializes an enum value. */
|
/** Initializes an enum value. */
|
||||||
@ -1523,6 +1526,55 @@ export class Program extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initializeExportDefault(
|
||||||
|
/** The statement to initialize. */
|
||||||
|
statement: ExportDefaultStatement,
|
||||||
|
/** Parent file. */
|
||||||
|
parent: File,
|
||||||
|
/** So far queued `extends` clauses. */
|
||||||
|
queuedExtends: Array<ClassPrototype>,
|
||||||
|
/** So far queued `implements` clauses. */
|
||||||
|
queuedImplements: ClassPrototype[]
|
||||||
|
): void {
|
||||||
|
var declaration = statement.declaration;
|
||||||
|
var element: DeclaredElement | null = null;
|
||||||
|
switch (declaration.kind) {
|
||||||
|
case NodeKind.ENUMDECLARATION: {
|
||||||
|
element = this.initializeEnum(<EnumDeclaration>declaration, parent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeKind.FUNCTIONDECLARATION: {
|
||||||
|
element = this.initializeFunction(<FunctionDeclaration>declaration, parent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeKind.CLASSDECLARATION: {
|
||||||
|
element = this.initializeClass(<ClassDeclaration>declaration, parent, queuedExtends, queuedImplements);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeKind.INTERFACEDECLARATION: {
|
||||||
|
element = this.initializeInterface(<InterfaceDeclaration>declaration, parent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NodeKind.NAMESPACEDECLARATION: {
|
||||||
|
element = this.initializeNamespace(<NamespaceDeclaration>declaration, parent, queuedExtends, queuedImplements);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
if (element) {
|
||||||
|
let exports = parent.exports;
|
||||||
|
if (!exports) parent.exports = exports = new Map();
|
||||||
|
else if (exports.has("default")) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode.Duplicate_identifier_0,
|
||||||
|
declaration.name.range, "default"
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
exports.set("default", element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Initializes an `import` statement. */
|
/** Initializes an `import` statement. */
|
||||||
private initializeImports(
|
private initializeImports(
|
||||||
/** The statement to initialize. */
|
/** The statement to initialize. */
|
||||||
@ -1531,7 +1583,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
parent: File,
|
parent: File,
|
||||||
/** So far queued `import`s. */
|
/** So far queued `import`s. */
|
||||||
queuedImports: QueuedImport[],
|
queuedImports: QueuedImport[],
|
||||||
/** SO far queued `export`s. */
|
/** So far queued `export`s. */
|
||||||
queuedExports: Map<File,Map<string,QueuedExport>>
|
queuedExports: Map<File,Map<string,QueuedExport>>
|
||||||
): void {
|
): void {
|
||||||
var declarations = statement.declarations;
|
var declarations = statement.declarations;
|
||||||
@ -1598,7 +1650,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
declaration: FunctionDeclaration,
|
declaration: FunctionDeclaration,
|
||||||
/** Parent element, usually a file or namespace. */
|
/** Parent element, usually a file or namespace. */
|
||||||
parent: Element
|
parent: Element
|
||||||
): void {
|
): FunctionPrototype | null {
|
||||||
var name = declaration.name.text;
|
var name = declaration.name.text;
|
||||||
var validDecorators = DecoratorFlags.UNSAFE | DecoratorFlags.BUILTIN;
|
var validDecorators = DecoratorFlags.UNSAFE | DecoratorFlags.BUILTIN;
|
||||||
if (declaration.is(CommonFlags.AMBIENT)) {
|
if (declaration.is(CommonFlags.AMBIENT)) {
|
||||||
@ -1622,7 +1674,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
declaration,
|
declaration,
|
||||||
this.checkDecorators(declaration.decorators, validDecorators)
|
this.checkDecorators(declaration.decorators, validDecorators)
|
||||||
);
|
);
|
||||||
if (!parent.add(name, element)) return;
|
if (!parent.add(name, element)) return null;
|
||||||
if (element.hasDecorator(DecoratorFlags.START)) {
|
if (element.hasDecorator(DecoratorFlags.START)) {
|
||||||
if (this.explicitStartFunction) {
|
if (this.explicitStartFunction) {
|
||||||
this.error(
|
this.error(
|
||||||
@ -1631,6 +1683,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
} else this.explicitStartFunction = element;
|
} else this.explicitStartFunction = element;
|
||||||
}
|
}
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initializes an interface. */
|
/** Initializes an interface. */
|
||||||
@ -1639,7 +1692,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
declaration: InterfaceDeclaration,
|
declaration: InterfaceDeclaration,
|
||||||
/** Parent element, usually a file or namespace. */
|
/** Parent element, usually a file or namespace. */
|
||||||
parent: Element
|
parent: Element
|
||||||
): void {
|
): InterfacePrototype | null {
|
||||||
var name = declaration.name.text;
|
var name = declaration.name.text;
|
||||||
var element = new InterfacePrototype(
|
var element = new InterfacePrototype(
|
||||||
name,
|
name,
|
||||||
@ -1649,7 +1702,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
DecoratorFlags.GLOBAL
|
DecoratorFlags.GLOBAL
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (!parent.add(name, element)) return;
|
if (!parent.add(name, element)) return null;
|
||||||
var memberDeclarations = declaration.members;
|
var memberDeclarations = declaration.members;
|
||||||
for (let i = 0, k = memberDeclarations.length; i < k; ++i) {
|
for (let i = 0, k = memberDeclarations.length; i < k; ++i) {
|
||||||
let memberDeclaration = memberDeclarations[i];
|
let memberDeclaration = memberDeclarations[i];
|
||||||
@ -1669,6 +1722,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
default: assert(false); // interface member expected
|
default: assert(false); // interface member expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initializes a namespace. */
|
/** Initializes a namespace. */
|
||||||
@ -1681,7 +1735,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
queuedExtends: ClassPrototype[],
|
queuedExtends: ClassPrototype[],
|
||||||
/** So far queued `implements` clauses. */
|
/** So far queued `implements` clauses. */
|
||||||
queuedImplements: ClassPrototype[]
|
queuedImplements: ClassPrototype[]
|
||||||
): void {
|
): Namespace | null {
|
||||||
var name = declaration.name.text;
|
var name = declaration.name.text;
|
||||||
var original = new Namespace(
|
var original = new Namespace(
|
||||||
name,
|
name,
|
||||||
@ -1689,7 +1743,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
declaration,
|
declaration,
|
||||||
this.checkDecorators(declaration.decorators, DecoratorFlags.GLOBAL)
|
this.checkDecorators(declaration.decorators, DecoratorFlags.GLOBAL)
|
||||||
);
|
);
|
||||||
if (!parent.add(name, original)) return;
|
if (!parent.add(name, original)) return null;
|
||||||
var element = assert(parent.lookupInSelf(name)); // possibly merged
|
var element = assert(parent.lookupInSelf(name)); // possibly merged
|
||||||
var members = declaration.members;
|
var members = declaration.members;
|
||||||
for (let i = 0, k = members.length; i < k; ++i) {
|
for (let i = 0, k = members.length; i < k; ++i) {
|
||||||
@ -1727,6 +1781,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (original != element) copyMembers(original, element); // retain original parent
|
if (original != element) copyMembers(original, element); // retain original parent
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initializes a `type` definition. */
|
/** Initializes a `type` definition. */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"asc_flags": [
|
"asc_flags": [
|
||||||
"--runtime none",
|
"--runtime half",
|
||||||
"--use ASC_RTRACE=1"
|
"--use ASC_RTRACE=1"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
5
tests/compiler/export-default.json
Normal file
5
tests/compiler/export-default.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"asc_flags": [
|
||||||
|
"--runtime none"
|
||||||
|
]
|
||||||
|
}
|
10
tests/compiler/export-default.optimized.wat
Normal file
10
tests/compiler/export-default.optimized.wat
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(module
|
||||||
|
(type $FUNCSIG$v (func))
|
||||||
|
(memory $0 0)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(export "theDefault" (func $export-default/theDefault))
|
||||||
|
(export "default" (func $export-default/theDefault))
|
||||||
|
(func $export-default/theDefault (; 0 ;) (type $FUNCSIG$v)
|
||||||
|
nop
|
||||||
|
)
|
||||||
|
)
|
1
tests/compiler/export-default.ts
Normal file
1
tests/compiler/export-default.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default function theDefault(): void {}
|
14
tests/compiler/export-default.untouched.wat
Normal file
14
tests/compiler/export-default.untouched.wat
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
(module
|
||||||
|
(type $FUNCSIG$v (func))
|
||||||
|
(memory $0 0)
|
||||||
|
(table $0 1 funcref)
|
||||||
|
(elem (i32.const 0) $null)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(export "theDefault" (func $export-default/theDefault))
|
||||||
|
(export "default" (func $export-default/theDefault))
|
||||||
|
(func $export-default/theDefault (; 0 ;) (type $FUNCSIG$v)
|
||||||
|
nop
|
||||||
|
)
|
||||||
|
(func $null (; 1 ;) (type $FUNCSIG$v)
|
||||||
|
)
|
||||||
|
)
|
@ -13,6 +13,7 @@
|
|||||||
(export "b" (global $export/b))
|
(export "b" (global $export/b))
|
||||||
(export "renamed_c" (global $export/c))
|
(export "renamed_c" (global $export/c))
|
||||||
(export "ns.two" (func $export/ns.one))
|
(export "ns.two" (func $export/ns.one))
|
||||||
|
(export "default.two" (func $export/ns.one))
|
||||||
(func $export/add (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
|
(func $export/add (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
local.get $0
|
local.get $0
|
||||||
local.get $1
|
local.get $1
|
||||||
|
@ -28,3 +28,5 @@ export namespace ns {
|
|||||||
function one(): void {}
|
function one(): void {}
|
||||||
export function two(): void {}
|
export function two(): void {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default ns;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
(export "b" (global $export/b))
|
(export "b" (global $export/b))
|
||||||
(export "renamed_c" (global $export/c))
|
(export "renamed_c" (global $export/c))
|
||||||
(export "ns.two" (func $export/ns.two))
|
(export "ns.two" (func $export/ns.two))
|
||||||
|
(export "default.two" (func $export/ns.two))
|
||||||
(func $export/add (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
|
(func $export/add (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
local.get $0
|
local.get $0
|
||||||
local.get $1
|
local.get $1
|
||||||
|
@ -21,3 +21,11 @@ other.sub(other.b, other.renamed_c) +
|
|||||||
other.renamed_mul(other.renamed_c, other.a);
|
other.renamed_mul(other.renamed_c, other.a);
|
||||||
|
|
||||||
other.ns.two();
|
other.ns.two();
|
||||||
|
|
||||||
|
import theDefault from "./export";
|
||||||
|
|
||||||
|
theDefault.two();
|
||||||
|
|
||||||
|
import theOtherDefault from "./export-default";
|
||||||
|
|
||||||
|
theOtherDefault();
|
||||||
|
@ -27,37 +27,42 @@
|
|||||||
(func $export/ns.two (; 3 ;) (type $FUNCSIG$v)
|
(func $export/ns.two (; 3 ;) (type $FUNCSIG$v)
|
||||||
nop
|
nop
|
||||||
)
|
)
|
||||||
(func $start:import (; 4 ;) (type $FUNCSIG$v)
|
(func $export-default/theDefault (; 4 ;) (type $FUNCSIG$v)
|
||||||
global.get $export/a
|
nop
|
||||||
global.get $export/b
|
|
||||||
call $export/add
|
|
||||||
global.get $export/b
|
|
||||||
global.get $export/c
|
|
||||||
call $export/sub
|
|
||||||
i32.add
|
|
||||||
global.get $export/c
|
|
||||||
global.get $export/a
|
|
||||||
call $export/mul
|
|
||||||
i32.add
|
|
||||||
drop
|
|
||||||
call $export/ns.two
|
|
||||||
global.get $export/a
|
|
||||||
global.get $export/b
|
|
||||||
call $export/add
|
|
||||||
global.get $export/b
|
|
||||||
global.get $export/c
|
|
||||||
call $export/sub
|
|
||||||
i32.add
|
|
||||||
global.get $export/c
|
|
||||||
global.get $export/a
|
|
||||||
call $export/mul
|
|
||||||
i32.add
|
|
||||||
drop
|
|
||||||
call $export/ns.two
|
|
||||||
)
|
)
|
||||||
(func $start (; 5 ;) (type $FUNCSIG$v)
|
(func $start:import (; 5 ;) (type $FUNCSIG$v)
|
||||||
|
global.get $export/a
|
||||||
|
global.get $export/b
|
||||||
|
call $export/add
|
||||||
|
global.get $export/b
|
||||||
|
global.get $export/c
|
||||||
|
call $export/sub
|
||||||
|
i32.add
|
||||||
|
global.get $export/c
|
||||||
|
global.get $export/a
|
||||||
|
call $export/mul
|
||||||
|
i32.add
|
||||||
|
drop
|
||||||
|
call $export/ns.two
|
||||||
|
global.get $export/a
|
||||||
|
global.get $export/b
|
||||||
|
call $export/add
|
||||||
|
global.get $export/b
|
||||||
|
global.get $export/c
|
||||||
|
call $export/sub
|
||||||
|
i32.add
|
||||||
|
global.get $export/c
|
||||||
|
global.get $export/a
|
||||||
|
call $export/mul
|
||||||
|
i32.add
|
||||||
|
drop
|
||||||
|
call $export/ns.two
|
||||||
|
call $export/ns.two
|
||||||
|
call $export-default/theDefault
|
||||||
|
)
|
||||||
|
(func $start (; 6 ;) (type $FUNCSIG$v)
|
||||||
call $start:import
|
call $start:import
|
||||||
)
|
)
|
||||||
(func $null (; 6 ;) (type $FUNCSIG$v)
|
(func $null (; 7 ;) (type $FUNCSIG$v)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
6
tests/parser/export-default.ts
Normal file
6
tests/parser/export-default.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export default function theFunction(): void {}
|
||||||
|
export default class TheClass {}
|
||||||
|
// not so ts-y:
|
||||||
|
export default enum TheEnum {}
|
||||||
|
export default namespace theNamespace {}
|
||||||
|
export default something;
|
7
tests/parser/export-default.ts.fixture.ts
Normal file
7
tests/parser/export-default.ts.fixture.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export default function theFunction(): void {}
|
||||||
|
export default class TheClass {}
|
||||||
|
export default enum TheEnum {}
|
||||||
|
export default namespace theNamespace {}
|
||||||
|
export {
|
||||||
|
something as default
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user