Initial support for default imports/exports, see #98

Does not implement combinations like 'import theDefault, *' yet
This commit is contained in:
dcode 2019-06-04 08:55:22 +02:00
parent 27e54ed07b
commit fa667386d9
20 changed files with 336 additions and 73 deletions

View File

@ -39,9 +39,6 @@
"no-debugger": {
"severity": "error"
},
"no-default-export": {
"severity": "error"
},
"no-duplicate-super": {
"severity": "error"
},

View File

@ -67,6 +67,7 @@ export enum NodeKind {
DO,
EMPTY,
EXPORT,
EXPORTDEFAULT,
EXPORTIMPORT,
EXPRESSION,
FOR,
@ -701,6 +702,16 @@ export abstract class Node {
return stmt;
}
static createExportDefaultStatement(
declaration: DeclarationStatement,
range: Range
): ExportDefaultStatement {
var stmt = new ExportDefaultStatement();
stmt.declaration = declaration;
stmt.range = range;
return stmt;
}
static createExportImportStatement(
name: IdentifierExpression,
externalName: IdentifierExpression,
@ -1775,6 +1786,14 @@ export class ExportStatement extends Statement {
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. */
export class ExpressionStatement extends Statement {
kind = NodeKind.EXPRESSION;

View File

@ -156,7 +156,8 @@ import {
nodeIsConstantValue,
findDecorator,
isTypeOmitted
isTypeOmitted,
ExportDefaultStatement
} from "./ast";
import {
@ -1619,6 +1620,9 @@ export class Compiler extends DiagnosticEmitter {
// === Statements ===============================================================================
compileTopLevelStatement(statement: Statement, body: ExpressionRef[]): void {
if (statement.kind == NodeKind.EXPORTDEFAULT) {
statement = (<ExportDefaultStatement>statement).declaration;
}
switch (statement.kind) {
case NodeKind.CLASSDECLARATION: {
let memberStatements = (<ClassDeclaration>statement).members;

View File

@ -66,6 +66,7 @@ export enum DiagnosticCode {
Type_expected = 1110,
A_default_clause_cannot_appear_more_than_once_in_a_switch_statement = 1113,
Duplicate_label_0 = 1114,
An_export_assignment_cannot_have_modifiers = 1120,
Octal_literals_are_not_allowed_in_strict_mode = 1121,
Digit_expected = 1124,
Hexadecimal_digit_expected = 1125,
@ -204,6 +205,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 1110: return "Type expected.";
case 1113: return "A 'default' clause cannot appear more than once in a 'switch' statement.";
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 1124: return "Digit expected.";
case 1125: return "Hexadecimal digit expected.";

View File

@ -59,6 +59,7 @@
"Type expected.": 1110,
"A 'default' clause cannot appear more than once in a 'switch' statement.": 1113,
"Duplicate label '{0}'.": 1114,
"An export assignment cannot have modifiers.": 1120,
"Octal literals are not allowed in strict mode.": 1121,
"Digit expected.": 1124,
"Hexadecimal digit expected.": 1125,

View File

@ -52,6 +52,7 @@ import {
EmptyStatement,
ExportImportStatement,
ExportStatement,
ExportDefaultStatement,
ExpressionStatement,
ForStatement,
IfStatement,
@ -230,6 +231,10 @@ export class ASTBuilder {
this.visitExportStatement(<ExportStatement>node);
break;
}
case NodeKind.EXPORTDEFAULT: {
this.visitExportDefaultStatement(<ExportDefaultStatement>node);
break;
}
case NodeKind.EXPORTIMPORT: {
this.visitExportImportStatement(<ExportImportStatement>node);
break;
@ -851,15 +856,19 @@ export class ASTBuilder {
}
}
visitClassDeclaration(node: ClassDeclaration): void {
visitClassDeclaration(node: ClassDeclaration, isDefault: bool = false): void {
var decorators = node.decorators;
if (decorators) {
for (let i = 0, k = decorators.length; i < k; ++i) {
this.serializeDecorator(decorators[i]);
}
}
this.serializeExternalModifiers(node);
var sb = this.sb;
if (isDefault) {
sb.push("export default ");
} else {
this.serializeExternalModifiers(node);
}
if (node.is(CommonFlags.ABSTRACT)) sb.push("abstract ");
if (node.name.text.length) {
sb.push("class ");
@ -931,9 +940,13 @@ export class ASTBuilder {
visitEmptyStatement(node: EmptyStatement): void {
}
visitEnumDeclaration(node: EnumDeclaration): void {
visitEnumDeclaration(node: EnumDeclaration, isDefault: bool = false): void {
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 ");
sb.push("enum ");
this.visitIdentifierExpression(node.name);
@ -1011,6 +1024,33 @@ export class ASTBuilder {
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 {
this.visitNode(node.expression);
}
@ -1065,7 +1105,7 @@ export class ASTBuilder {
this.visitNode(node.statement);
}
visitFunctionDeclaration(node: FunctionDeclaration): void {
visitFunctionDeclaration(node: FunctionDeclaration, isDefault: bool = false): void {
var sb = this.sb;
var decorators = node.decorators;
if (decorators) {
@ -1073,8 +1113,12 @@ export class ASTBuilder {
this.serializeDecorator(decorators[i]);
}
}
this.serializeExternalModifiers(node);
this.serializeAccessModifiers(node);
if (isDefault) {
sb.push("export default ");
} else {
this.serializeExternalModifiers(node);
this.serializeAccessModifiers(node);
}
if (node.name.text.length) {
sb.push("function ");
} else {
@ -1230,15 +1274,19 @@ export class ASTBuilder {
this.visitTypeNode(node.valueType);
}
visitInterfaceDeclaration(node: InterfaceDeclaration): void {
visitInterfaceDeclaration(node: InterfaceDeclaration, isDefault: bool = false): void {
var decorators = node.decorators;
if (decorators) {
for (let i = 0, k = decorators.length; i < k; ++i) {
this.serializeDecorator(decorators[i]);
}
}
this.serializeExternalModifiers(node);
var sb = this.sb;
if (isDefault) {
sb.push("export default ");
} else {
this.serializeExternalModifiers(node);
}
sb.push("interface ");
this.visitIdentifierExpression(node.name);
var typeParameters = node.typeParameters;
@ -1284,15 +1332,19 @@ export class ASTBuilder {
this.visitFunctionCommon(node);
}
visitNamespaceDeclaration(node: NamespaceDeclaration): void {
visitNamespaceDeclaration(node: NamespaceDeclaration, isDefault: bool = false): void {
var decorators = node.decorators;
if (decorators) {
for (let i = 0, k = decorators.length; i < k; ++i) {
this.serializeDecorator(decorators[i]);
}
}
this.serializeExternalModifiers(node);
var sb = this.sb;
if (isDefault) {
sb.push("export default ");
} else {
this.serializeExternalModifiers(node);
}
sb.push("namespace ");
this.visitIdentifierExpression(node.name);
var members = node.members;

View File

@ -171,31 +171,34 @@ export class Parser extends DiagnosticEmitter {
// check modifiers
var exportStart: i32 = 0;
var exportEnd: i32 = 0;
var defaultStart: i32 = 0;
var defaultEnd: i32 = 0;
if (tn.skip(Token.EXPORT)) {
if (tn.skip(Token.DEFAULT)) {
this.error(
DiagnosticCode.Operation_not_supported,
tn.range()
);
}
if (startPos < 0) startPos = tn.tokenPos;
flags |= CommonFlags.EXPORT;
exportStart = tn.tokenPos;
exportEnd = tn.pos;
if (tn.skip(Token.DEFAULT)) {
defaultStart = tn.tokenPos;
defaultEnd = tn.pos;
}
}
var declareStart: i32 = 0;
var declareEnd: i32 = 0;
var contextIsAmbient = namespace != null && namespace.is(CommonFlags.AMBIENT);
if (tn.skip(Token.DECLARE)) {
if (startPos < 0) startPos = tn.tokenPos;
if (contextIsAmbient) {
this.error(
DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context,
tn.range()
); // 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) {
flags |= CommonFlags.AMBIENT;
}
@ -297,7 +300,18 @@ export class Parser extends DiagnosticEmitter {
// handle plain exports
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
} 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;
}
@ -2318,6 +2351,28 @@ export class Parser extends DiagnosticEmitter {
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(
tn: Tokenizer
): ImportStatement | null {
@ -2330,7 +2385,7 @@ export class Parser extends DiagnosticEmitter {
var members: ImportDeclaration[] | null = null;
var namespaceName: IdentifierExpression | null = null;
var skipFrom = false;
if (tn.skip(Token.OPENBRACE)) {
if (tn.skip(Token.OPENBRACE)) { // import { ... } from "file"
members = new Array();
while (!tn.skip(Token.CLOSEBRACE)) {
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.skipIdentifier()) {
namespaceName = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
@ -2366,7 +2421,25 @@ export class Parser extends DiagnosticEmitter {
);
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;
}

View File

@ -75,7 +75,8 @@ import {
VariableStatement,
decoratorNameToKind,
findDecorator
findDecorator,
ExportDefaultStatement
} from "./ast";
import {
@ -100,10 +101,6 @@ import {
Flow
} from "./flow";
import {
BuiltinSymbols
} from "./builtins";
/** Represents a yet unresolved `import`. */
class QueuedImport {
constructor(
@ -616,6 +613,10 @@ export class Program extends DiagnosticEmitter {
this.initializeExports(<ExportStatement>statement, file, queuedExports, queuedExportsStar);
break;
}
case NodeKind.EXPORTDEFAULT: {
this.initializeExportDefault(<ExportDefaultStatement>statement, file, queuedExtends, queuedImplements);
break;
}
case NodeKind.IMPORT: {
this.initializeImports(<ImportStatement>statement, file, queuedImports, queuedExports);
break;
@ -1117,7 +1118,7 @@ export class Program extends DiagnosticEmitter {
queuedExtends: ClassPrototype[],
/** So far queued `implements` clauses. */
queuedImplements: ClassPrototype[]
): void {
): ClassPrototype | null {
var name = declaration.name.text;
var element = new ClassPrototype(
name,
@ -1129,7 +1130,7 @@ export class Program extends DiagnosticEmitter {
DecoratorFlags.UNMANAGED
)
);
if (!parent.add(name, element)) return;
if (!parent.add(name, element)) return null;
var implementsTypes = declaration.implementsTypes;
if (implementsTypes) {
@ -1180,6 +1181,7 @@ export class Program extends DiagnosticEmitter {
default: assert(false); // class member expected
}
}
return element;
}
/** Initializes a field of a class or interface. */
@ -1396,7 +1398,7 @@ export class Program extends DiagnosticEmitter {
declaration: EnumDeclaration,
/** Parent element, usually a file or namespace. */
parent: Element
): void {
): Enum | null {
var name = declaration.name.text;
var element = new Enum(
name,
@ -1408,11 +1410,12 @@ export class Program extends DiagnosticEmitter {
DecoratorFlags.LAZY
)
);
if (!parent.add(name, element)) return;
if (!parent.add(name, element)) return null;
var values = declaration.values;
for (let i = 0, k = values.length; i < k; ++i) {
this.initializeEnumValue(values[i], element);
}
return element;
}
/** 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. */
private initializeImports(
/** The statement to initialize. */
@ -1531,7 +1583,7 @@ export class Program extends DiagnosticEmitter {
parent: File,
/** So far queued `import`s. */
queuedImports: QueuedImport[],
/** SO far queued `export`s. */
/** So far queued `export`s. */
queuedExports: Map<File,Map<string,QueuedExport>>
): void {
var declarations = statement.declarations;
@ -1598,7 +1650,7 @@ export class Program extends DiagnosticEmitter {
declaration: FunctionDeclaration,
/** Parent element, usually a file or namespace. */
parent: Element
): void {
): FunctionPrototype | null {
var name = declaration.name.text;
var validDecorators = DecoratorFlags.UNSAFE | DecoratorFlags.BUILTIN;
if (declaration.is(CommonFlags.AMBIENT)) {
@ -1622,7 +1674,7 @@ export class Program extends DiagnosticEmitter {
declaration,
this.checkDecorators(declaration.decorators, validDecorators)
);
if (!parent.add(name, element)) return;
if (!parent.add(name, element)) return null;
if (element.hasDecorator(DecoratorFlags.START)) {
if (this.explicitStartFunction) {
this.error(
@ -1631,6 +1683,7 @@ export class Program extends DiagnosticEmitter {
);
} else this.explicitStartFunction = element;
}
return element;
}
/** Initializes an interface. */
@ -1639,7 +1692,7 @@ export class Program extends DiagnosticEmitter {
declaration: InterfaceDeclaration,
/** Parent element, usually a file or namespace. */
parent: Element
): void {
): InterfacePrototype | null {
var name = declaration.name.text;
var element = new InterfacePrototype(
name,
@ -1649,7 +1702,7 @@ export class Program extends DiagnosticEmitter {
DecoratorFlags.GLOBAL
)
);
if (!parent.add(name, element)) return;
if (!parent.add(name, element)) return null;
var memberDeclarations = declaration.members;
for (let i = 0, k = memberDeclarations.length; i < k; ++i) {
let memberDeclaration = memberDeclarations[i];
@ -1669,6 +1722,7 @@ export class Program extends DiagnosticEmitter {
default: assert(false); // interface member expected
}
}
return element;
}
/** Initializes a namespace. */
@ -1681,7 +1735,7 @@ export class Program extends DiagnosticEmitter {
queuedExtends: ClassPrototype[],
/** So far queued `implements` clauses. */
queuedImplements: ClassPrototype[]
): void {
): Namespace | null {
var name = declaration.name.text;
var original = new Namespace(
name,
@ -1689,7 +1743,7 @@ export class Program extends DiagnosticEmitter {
declaration,
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 members = declaration.members;
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
return element;
}
/** Initializes a `type` definition. */

View File

@ -1,6 +1,6 @@
{
"asc_flags": [
"--runtime none",
"--runtime half",
"--use ASC_RTRACE=1"
]
}

View File

@ -0,0 +1,5 @@
{
"asc_flags": [
"--runtime none"
]
}

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

View File

@ -0,0 +1 @@
export default function theDefault(): void {}

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

View File

@ -13,6 +13,7 @@
(export "b" (global $export/b))
(export "renamed_c" (global $export/c))
(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)
local.get $0
local.get $1

View File

@ -28,3 +28,5 @@ export namespace ns {
function one(): void {}
export function two(): void {}
}
export default ns;

View File

@ -15,6 +15,7 @@
(export "b" (global $export/b))
(export "renamed_c" (global $export/c))
(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)
local.get $0
local.get $1

View File

@ -21,3 +21,11 @@ other.sub(other.b, other.renamed_c) +
other.renamed_mul(other.renamed_c, other.a);
other.ns.two();
import theDefault from "./export";
theDefault.two();
import theOtherDefault from "./export-default";
theOtherDefault();

View File

@ -27,37 +27,42 @@
(func $export/ns.two (; 3 ;) (type $FUNCSIG$v)
nop
)
(func $start:import (; 4 ;) (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
(func $export-default/theDefault (; 4 ;) (type $FUNCSIG$v)
nop
)
(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
)
(func $null (; 6 ;) (type $FUNCSIG$v)
(func $null (; 7 ;) (type $FUNCSIG$v)
)
)

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

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