mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-29 00:42:16 +00:00
AST cleanup; Definition generators scaffolding
This commit is contained in:
parent
eef923d124
commit
faac3c31eb
97
bin/asc.js
97
bin/asc.js
@ -286,6 +286,9 @@ exports.main = function main(argv, options, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finish parsing
|
||||||
|
const program = assemblyscript.finishParsing(parser);
|
||||||
|
|
||||||
// Begin compilation
|
// Begin compilation
|
||||||
const compilerOptions = assemblyscript.createOptions();
|
const compilerOptions = assemblyscript.createOptions();
|
||||||
assemblyscript.setTarget(compilerOptions, 0);
|
assemblyscript.setTarget(compilerOptions, 0);
|
||||||
@ -301,7 +304,7 @@ exports.main = function main(argv, options, callback) {
|
|||||||
(() => {
|
(() => {
|
||||||
try {
|
try {
|
||||||
stats.compileTime += measure(() => {
|
stats.compileTime += measure(() => {
|
||||||
module = assemblyscript.compile(parser, compilerOptions);
|
module = assemblyscript.compileProgram(program, compilerOptions);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return callback(e);
|
return callback(e);
|
||||||
@ -434,23 +437,23 @@ exports.main = function main(argv, options, callback) {
|
|||||||
: path.basename(args.binaryFile) + ".map"
|
: path.basename(args.binaryFile) + ".map"
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
let binary;
|
let wasm;
|
||||||
stats.emitCount++;
|
stats.emitCount++;
|
||||||
stats.emitTime += measure(() => {
|
stats.emitTime += measure(() => {
|
||||||
binary = module.toBinary(sourceMapURL)
|
wasm = module.toBinary(sourceMapURL)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (args.binaryFile.length) {
|
if (args.binaryFile.length) {
|
||||||
writeFile(path.join(baseDir, args.binaryFile), binary.output);
|
writeFile(path.join(baseDir, args.binaryFile), wasm.output);
|
||||||
} else {
|
} else {
|
||||||
writeStdout(binary.output);
|
writeStdout(wasm.output);
|
||||||
hasStdout = true;
|
hasStdout = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post-process source map
|
// Post-process source map
|
||||||
if (binary.sourceMap != null) {
|
if (wasm.sourceMap != null) {
|
||||||
if (args.binaryFile.length) {
|
if (args.binaryFile.length) {
|
||||||
let sourceMap = JSON.parse(binary.sourceMap);
|
let sourceMap = JSON.parse(wasm.sourceMap);
|
||||||
sourceMap.sourceRoot = exports.sourceMapRoot;
|
sourceMap.sourceRoot = exports.sourceMapRoot;
|
||||||
sourceMap.sources.forEach((name, index) => {
|
sourceMap.sources.forEach((name, index) => {
|
||||||
let text = null;
|
let text = null;
|
||||||
@ -482,30 +485,6 @@ exports.main = function main(argv, options, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write text
|
|
||||||
if (
|
|
||||||
args.textFile != null || (
|
|
||||||
args.binaryFile == null &&
|
|
||||||
args.asmjsFile == null
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
let text;
|
|
||||||
if (args.textFile && args.textFile.length) {
|
|
||||||
stats.emitCount++;
|
|
||||||
stats.emitTime += measure(() => {
|
|
||||||
text = module.toText();
|
|
||||||
});
|
|
||||||
writeFile(path.join(baseDir, args.textFile), text);
|
|
||||||
} else if (!hasStdout) {
|
|
||||||
stats.emitCount++;
|
|
||||||
stats.emitTime += measure(() => {
|
|
||||||
text = module.toText()
|
|
||||||
});
|
|
||||||
writeStdout(text);
|
|
||||||
hasStdout = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write asm.js
|
// Write asm.js
|
||||||
if (args.asmjsFile != null) {
|
if (args.asmjsFile != null) {
|
||||||
let asm;
|
let asm;
|
||||||
@ -524,6 +503,62 @@ exports.main = function main(argv, options, callback) {
|
|||||||
hasStdout = true;
|
hasStdout = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write WebIDL
|
||||||
|
if (args.idlFile != null) {
|
||||||
|
let idl;
|
||||||
|
if (args.idlFile.length) {
|
||||||
|
stats.emitCount++;
|
||||||
|
stats.emitTime += measure(() => {
|
||||||
|
idl = assemblyscript.buildIDL(program);
|
||||||
|
});
|
||||||
|
writeFile(path.join(baseDir, args.idlFile), idl);
|
||||||
|
} else if (!hasStdout) {
|
||||||
|
stats.emitCount++;
|
||||||
|
stats.emitTime += measure(() => {
|
||||||
|
idl = assemblyscript.buildIDL(program);
|
||||||
|
});
|
||||||
|
writeStdout(idl);
|
||||||
|
hasStdout = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write TypeScript definition
|
||||||
|
if (args.tsdFile != null) {
|
||||||
|
let tsd;
|
||||||
|
if (args.tsdFile.length) {
|
||||||
|
stats.emitCount++;
|
||||||
|
stats.emitTime += measure(() => {
|
||||||
|
tsd = assemblyscript.buildTSD(program);
|
||||||
|
});
|
||||||
|
writeFile(path.join(baseDir, args.tsdFile), tsd);
|
||||||
|
} else if (!hasStdout) {
|
||||||
|
stats.emitCount++;
|
||||||
|
stats.emitTime += measure(() => {
|
||||||
|
tsd = assemblyscript.buildTSD(program);
|
||||||
|
});
|
||||||
|
writeStdout(tsd);
|
||||||
|
hasStdout = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write text (must be last)
|
||||||
|
if (args.textFile != null) {
|
||||||
|
let wat;
|
||||||
|
if (args.textFile && args.textFile.length) {
|
||||||
|
stats.emitCount++;
|
||||||
|
stats.emitTime += measure(() => {
|
||||||
|
wat = module.toText();
|
||||||
|
});
|
||||||
|
writeFile(path.join(baseDir, args.textFile), wat);
|
||||||
|
} else if (!hasStdout) {
|
||||||
|
stats.emitCount++;
|
||||||
|
stats.emitTime += measure(() => {
|
||||||
|
wat = module.toText()
|
||||||
|
});
|
||||||
|
writeStdout(wat);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.dispose();
|
module.dispose();
|
||||||
|
10
bin/asc.json
10
bin/asc.json
@ -62,6 +62,16 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"aliases": [ "a" ]
|
"aliases": [ "a" ]
|
||||||
},
|
},
|
||||||
|
"idlFile": {
|
||||||
|
"desc": "Specifies the WebIDL output file (.idl).",
|
||||||
|
"type": "string",
|
||||||
|
"aliases": [ "i" ]
|
||||||
|
},
|
||||||
|
"tsdFile": {
|
||||||
|
"desc": "Specifies the TypeScript definition output file (.d.ts).",
|
||||||
|
"type": "string",
|
||||||
|
"aliases": [ "d" ]
|
||||||
|
},
|
||||||
"sourceMap": {
|
"sourceMap": {
|
||||||
"desc": [
|
"desc": [
|
||||||
"Enables source map generation. Optionally takes the URL",
|
"Enables source map generation. Optionally takes the URL",
|
||||||
|
2
dist/asc.js
vendored
2
dist/asc.js
vendored
File diff suppressed because one or more lines are too long
2
dist/asc.js.map
vendored
2
dist/asc.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/assemblyscript.js
vendored
2
dist/assemblyscript.js
vendored
File diff suppressed because one or more lines are too long
2
dist/assemblyscript.js.map
vendored
2
dist/assemblyscript.js.map
vendored
File diff suppressed because one or more lines are too long
19
lib/demangle/index.js
Normal file
19
lib/demangle/index.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* @file AssemblyScript demangler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = demangle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demangles module exports to a friendly object structure compatible with WebIDL and TypeScript
|
||||||
|
* definitions.
|
||||||
|
*/
|
||||||
|
function demangle(exports) {
|
||||||
|
var root = {};
|
||||||
|
for (let i in exports) {
|
||||||
|
if (exports.hasOwnProperty(i)) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
@ -47,7 +47,8 @@
|
|||||||
"test:parser": "node tests/parser",
|
"test:parser": "node tests/parser",
|
||||||
"test:compiler": "node tests/compiler",
|
"test:compiler": "node tests/compiler",
|
||||||
"test": "npm run test:config --scripts-prepend-node-path && npm run test:parser --scripts-prepend-node-path && npm run test:compiler --scripts-prepend-node-path",
|
"test": "npm run test:config --scripts-prepend-node-path && npm run test:parser --scripts-prepend-node-path && npm run test:compiler --scripts-prepend-node-path",
|
||||||
"test:pr": "npm run clean && npm test && npm run build && npm test && npm run clean"
|
"test:pr": "npm run clean && npm test && npm run build && npm test && npm run clean",
|
||||||
|
"all": "npm run lint && npm run clean && npm test && npm run build && npm test"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"bin/",
|
"bin/",
|
||||||
|
178
src/ast.ts
178
src/ast.ts
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
CommonFlags,
|
||||||
PATH_DELIMITER,
|
PATH_DELIMITER,
|
||||||
STATIC_DELIMITER,
|
STATIC_DELIMITER,
|
||||||
INSTANCE_DELIMITER
|
INSTANCE_DELIMITER
|
||||||
@ -37,7 +38,6 @@ export enum NodeKind {
|
|||||||
ELEMENTACCESS,
|
ELEMENTACCESS,
|
||||||
FALSE,
|
FALSE,
|
||||||
FUNCTION,
|
FUNCTION,
|
||||||
FUNCTIONARROW,
|
|
||||||
LITERAL,
|
LITERAL,
|
||||||
NEW,
|
NEW,
|
||||||
NULL,
|
NULL,
|
||||||
@ -86,7 +86,6 @@ export enum NodeKind {
|
|||||||
|
|
||||||
// special
|
// special
|
||||||
DECORATOR,
|
DECORATOR,
|
||||||
MODIFIER,
|
|
||||||
EXPORTMEMBER,
|
EXPORTMEMBER,
|
||||||
SWITCHCASE
|
SWITCHCASE
|
||||||
}
|
}
|
||||||
@ -100,6 +99,15 @@ export abstract class Node {
|
|||||||
range: Range;
|
range: Range;
|
||||||
/** Parent node. */
|
/** Parent node. */
|
||||||
parent: Node | null = null;
|
parent: Node | null = null;
|
||||||
|
/** Common flags indicating specific traits. */
|
||||||
|
flags: CommonFlags = CommonFlags.NONE;
|
||||||
|
|
||||||
|
/** Tests if this node has a specific flag or flags. */
|
||||||
|
is(flag: CommonFlags): bool { return (this.flags & flag) == flag; }
|
||||||
|
/** Tests if this node has one of the specified flags. */
|
||||||
|
isAny(flag: CommonFlags): bool { return (this.flags & flag) != 0; }
|
||||||
|
/** Sets a specific flag or flags. */
|
||||||
|
set(flag: CommonFlags): void { this.flags |= flag; }
|
||||||
|
|
||||||
// types
|
// types
|
||||||
|
|
||||||
@ -212,13 +220,6 @@ export abstract class Node {
|
|||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static createModifier(kind: ModifierKind, range: Range): ModifierNode {
|
|
||||||
var elem = new ModifierNode();
|
|
||||||
elem.range = range;
|
|
||||||
elem.modifierKind = kind;
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
// expressions
|
// expressions
|
||||||
|
|
||||||
static createIdentifierExpression(
|
static createIdentifierExpression(
|
||||||
@ -341,12 +342,10 @@ export abstract class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static createFunctionExpression(
|
static createFunctionExpression(
|
||||||
declaration: FunctionDeclaration,
|
declaration: FunctionDeclaration
|
||||||
isArrow: bool = false
|
|
||||||
): FunctionExpression {
|
): FunctionExpression {
|
||||||
var expr = isArrow
|
var expr = new FunctionExpression();
|
||||||
? new FunctionArrowExpression()
|
expr.flags = declaration.flags & CommonFlags.ARROW;
|
||||||
: new FunctionExpression();
|
|
||||||
expr.range = declaration.range;
|
expr.range = declaration.range;
|
||||||
expr.declaration = declaration;
|
expr.declaration = declaration;
|
||||||
return expr;
|
return expr;
|
||||||
@ -518,18 +517,18 @@ export abstract class Node {
|
|||||||
extendsType: TypeNode | null, // can't be a function
|
extendsType: TypeNode | null, // can't be a function
|
||||||
implementsTypes: TypeNode[], // can't be a function
|
implementsTypes: TypeNode[], // can't be a function
|
||||||
members: DeclarationStatement[],
|
members: DeclarationStatement[],
|
||||||
modifiers: ModifierNode[] | null,
|
|
||||||
decorators: DecoratorNode[] | null,
|
decorators: DecoratorNode[] | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): ClassDeclaration {
|
): ClassDeclaration {
|
||||||
var stmt = new ClassDeclaration();
|
var stmt = new ClassDeclaration();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.name = identifier; identifier.parent = stmt;
|
stmt.name = identifier; identifier.parent = stmt;
|
||||||
stmt.typeParameters = typeParameters; setParent(typeParameters, stmt);
|
stmt.typeParameters = typeParameters; setParent(typeParameters, stmt);
|
||||||
stmt.extendsType = extendsType; if (extendsType) extendsType.parent = stmt;
|
stmt.extendsType = extendsType; if (extendsType) extendsType.parent = stmt;
|
||||||
stmt.implementsTypes = implementsTypes; setParent(implementsTypes, stmt);
|
stmt.implementsTypes = implementsTypes; setParent(implementsTypes, stmt);
|
||||||
stmt.members = members; setParent(members, stmt);
|
stmt.members = members; setParent(members, stmt);
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@ -567,15 +566,15 @@ export abstract class Node {
|
|||||||
static createEnumDeclaration(
|
static createEnumDeclaration(
|
||||||
name: IdentifierExpression,
|
name: IdentifierExpression,
|
||||||
members: EnumValueDeclaration[],
|
members: EnumValueDeclaration[],
|
||||||
modifiers: ModifierNode[] | null,
|
|
||||||
decorators: DecoratorNode[] | null,
|
decorators: DecoratorNode[] | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): EnumDeclaration {
|
): EnumDeclaration {
|
||||||
var stmt = new EnumDeclaration();
|
var stmt = new EnumDeclaration();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.name = name; name.parent = stmt;
|
stmt.name = name; name.parent = stmt;
|
||||||
stmt.values = members; setParent(members, stmt);
|
stmt.values = members; setParent(members, stmt);
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@ -583,10 +582,12 @@ export abstract class Node {
|
|||||||
static createEnumValueDeclaration(
|
static createEnumValueDeclaration(
|
||||||
name: IdentifierExpression,
|
name: IdentifierExpression,
|
||||||
value: Expression | null,
|
value: Expression | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): EnumValueDeclaration {
|
): EnumValueDeclaration {
|
||||||
var stmt = new EnumValueDeclaration();
|
var stmt = new EnumValueDeclaration();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.name = name; name.parent = stmt;
|
stmt.name = name; name.parent = stmt;
|
||||||
stmt.value = value; if (value) value.parent = stmt;
|
stmt.value = value; if (value) value.parent = stmt;
|
||||||
return stmt;
|
return stmt;
|
||||||
@ -595,11 +596,12 @@ export abstract class Node {
|
|||||||
static createExportStatement(
|
static createExportStatement(
|
||||||
members: ExportMember[],
|
members: ExportMember[],
|
||||||
path: StringLiteralExpression | null,
|
path: StringLiteralExpression | null,
|
||||||
modifiers: ModifierNode[] | null,
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): ExportStatement {
|
): ExportStatement {
|
||||||
var stmt = new ExportStatement();
|
var stmt = new ExportStatement();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.members = members; setParent(members, stmt);
|
stmt.members = members; setParent(members, stmt);
|
||||||
stmt.path = path;
|
stmt.path = path;
|
||||||
if (path) {
|
if (path) {
|
||||||
@ -617,7 +619,6 @@ export abstract class Node {
|
|||||||
stmt.normalizedPath = null;
|
stmt.normalizedPath = null;
|
||||||
stmt.internalPath = null;
|
stmt.internalPath = null;
|
||||||
}
|
}
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,15 +736,15 @@ export abstract class Node {
|
|||||||
name: IdentifierExpression,
|
name: IdentifierExpression,
|
||||||
extendsType: TypeNode | null, // can't be a function
|
extendsType: TypeNode | null, // can't be a function
|
||||||
members: DeclarationStatement[],
|
members: DeclarationStatement[],
|
||||||
modifiers: ModifierNode[] | null,
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): InterfaceDeclaration {
|
): InterfaceDeclaration {
|
||||||
var stmt = new InterfaceDeclaration();
|
var stmt = new InterfaceDeclaration();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.name = name; name.parent = stmt;
|
stmt.name = name; name.parent = stmt;
|
||||||
stmt.extendsType = extendsType; if (extendsType) extendsType.parent = stmt;
|
stmt.extendsType = extendsType; if (extendsType) extendsType.parent = stmt;
|
||||||
stmt.members = members; setParent(members, stmt);
|
stmt.members = members; setParent(members, stmt);
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,16 +752,16 @@ export abstract class Node {
|
|||||||
name: IdentifierExpression,
|
name: IdentifierExpression,
|
||||||
type: CommonTypeNode | null,
|
type: CommonTypeNode | null,
|
||||||
initializer: Expression | null,
|
initializer: Expression | null,
|
||||||
modifiers: ModifierNode[] | null,
|
|
||||||
decorators: DecoratorNode[] | null,
|
decorators: DecoratorNode[] | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): FieldDeclaration {
|
): FieldDeclaration {
|
||||||
var stmt = new FieldDeclaration();
|
var stmt = new FieldDeclaration();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.name = name; name.parent = stmt;
|
stmt.name = name; name.parent = stmt;
|
||||||
stmt.type = type; if (type) type.parent = stmt;
|
stmt.type = type; if (type) type.parent = stmt;
|
||||||
stmt.initializer = initializer; if (initializer) initializer.parent = stmt;
|
stmt.initializer = initializer; if (initializer) initializer.parent = stmt;
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@ -786,17 +787,17 @@ export abstract class Node {
|
|||||||
typeParameters: TypeParameterNode[] | null,
|
typeParameters: TypeParameterNode[] | null,
|
||||||
signature: SignatureNode,
|
signature: SignatureNode,
|
||||||
body: Statement | null,
|
body: Statement | null,
|
||||||
modifiers: ModifierNode[] | null,
|
|
||||||
decorators: DecoratorNode[] | null,
|
decorators: DecoratorNode[] | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): FunctionDeclaration {
|
): FunctionDeclaration {
|
||||||
var stmt = new FunctionDeclaration();
|
var stmt = new FunctionDeclaration();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.name = name; name.parent = stmt;
|
stmt.name = name; name.parent = stmt;
|
||||||
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
||||||
stmt.signature = signature; signature.parent = stmt;
|
stmt.signature = signature; signature.parent = stmt;
|
||||||
stmt.body = body; if (body) body.parent = stmt;
|
stmt.body = body; if (body) body.parent = stmt;
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@ -806,17 +807,17 @@ export abstract class Node {
|
|||||||
typeParameters: TypeParameterNode[] | null,
|
typeParameters: TypeParameterNode[] | null,
|
||||||
signature: SignatureNode,
|
signature: SignatureNode,
|
||||||
body: Statement | null,
|
body: Statement | null,
|
||||||
modifiers: ModifierNode[] | null,
|
|
||||||
decorators: DecoratorNode[] | null,
|
decorators: DecoratorNode[] | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): MethodDeclaration {
|
): MethodDeclaration {
|
||||||
var stmt = new MethodDeclaration();
|
var stmt = new MethodDeclaration();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.name = name; name.parent = stmt;
|
stmt.name = name; name.parent = stmt;
|
||||||
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
||||||
stmt.signature = signature; signature.parent = stmt;
|
stmt.signature = signature; signature.parent = stmt;
|
||||||
stmt.body = body; if (body) body.parent = stmt;
|
stmt.body = body; if (body) body.parent = stmt;
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@ -824,15 +825,15 @@ export abstract class Node {
|
|||||||
static createNamespaceDeclaration(
|
static createNamespaceDeclaration(
|
||||||
name: IdentifierExpression,
|
name: IdentifierExpression,
|
||||||
members: Statement[],
|
members: Statement[],
|
||||||
modifiers: ModifierNode[] | null,
|
|
||||||
decorators: DecoratorNode[] | null,
|
decorators: DecoratorNode[] | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): NamespaceDeclaration {
|
): NamespaceDeclaration {
|
||||||
var stmt = new NamespaceDeclaration();
|
var stmt = new NamespaceDeclaration();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.name = name; name.parent = stmt;
|
stmt.name = name; name.parent = stmt;
|
||||||
stmt.members = members; setParent(members, stmt);
|
stmt.members = members; setParent(members, stmt);
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@ -904,30 +905,30 @@ export abstract class Node {
|
|||||||
name: IdentifierExpression,
|
name: IdentifierExpression,
|
||||||
typeParameters: TypeParameterNode[] | null,
|
typeParameters: TypeParameterNode[] | null,
|
||||||
alias: CommonTypeNode,
|
alias: CommonTypeNode,
|
||||||
modifiers: ModifierNode[] | null,
|
|
||||||
decorators: DecoratorNode[] | null,
|
decorators: DecoratorNode[] | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): TypeDeclaration {
|
): TypeDeclaration {
|
||||||
var stmt = new TypeDeclaration();
|
var stmt = new TypeDeclaration();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.name = name; name.parent = stmt;
|
stmt.name = name; name.parent = stmt;
|
||||||
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
||||||
stmt.type = alias; alias.parent = stmt;
|
stmt.type = alias; alias.parent = stmt;
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static createVariableStatement(
|
static createVariableStatement(
|
||||||
declarations: VariableDeclaration[],
|
declarations: VariableDeclaration[],
|
||||||
modifiers: ModifierNode[] | null,
|
|
||||||
decorators: DecoratorNode[] | null,
|
decorators: DecoratorNode[] | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): VariableStatement {
|
): VariableStatement {
|
||||||
var stmt = new VariableStatement();
|
var stmt = new VariableStatement();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
|
stmt.flags = flags;
|
||||||
stmt.declarations = declarations; setParent(declarations, stmt);
|
stmt.declarations = declarations; setParent(declarations, stmt);
|
||||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
|
||||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@ -936,16 +937,16 @@ export abstract class Node {
|
|||||||
name: IdentifierExpression,
|
name: IdentifierExpression,
|
||||||
type: CommonTypeNode | null,
|
type: CommonTypeNode | null,
|
||||||
initializer: Expression | null,
|
initializer: Expression | null,
|
||||||
modifiers: ModifierNode[] | null,
|
|
||||||
decorators: DecoratorNode[] | null,
|
decorators: DecoratorNode[] | null,
|
||||||
|
flags: CommonFlags,
|
||||||
range: Range
|
range: Range
|
||||||
): VariableDeclaration {
|
): VariableDeclaration {
|
||||||
var elem = new VariableDeclaration();
|
var elem = new VariableDeclaration();
|
||||||
elem.range = range;
|
elem.range = range;
|
||||||
|
elem.flags = flags;
|
||||||
elem.name = name; name.parent = elem;
|
elem.name = name; name.parent = elem;
|
||||||
elem.type = type; if (type) type.parent = elem;
|
elem.type = type; if (type) type.parent = elem;
|
||||||
elem.initializer = initializer; if (initializer) initializer.parent = elem;
|
elem.initializer = initializer; if (initializer) initializer.parent = elem;
|
||||||
elem.modifiers = modifiers; // inherited from parent VariableStatement
|
|
||||||
elem.decorators = decorators; // inherited
|
elem.decorators = decorators; // inherited
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
@ -1061,32 +1062,6 @@ export class DecoratorNode extends Node {
|
|||||||
arguments: Expression[] | null;
|
arguments: Expression[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Indicates the specific kind of a modifier. */
|
|
||||||
export enum ModifierKind {
|
|
||||||
ASYNC,
|
|
||||||
CONST,
|
|
||||||
LET,
|
|
||||||
DECLARE,
|
|
||||||
EXPORT,
|
|
||||||
IMPORT,
|
|
||||||
STATIC,
|
|
||||||
ABSTRACT,
|
|
||||||
PUBLIC,
|
|
||||||
PRIVATE,
|
|
||||||
PROTECTED,
|
|
||||||
READONLY,
|
|
||||||
GET,
|
|
||||||
SET,
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Represents a single modifier. */
|
|
||||||
export class ModifierNode extends Node {
|
|
||||||
kind = NodeKind.MODIFIER;
|
|
||||||
|
|
||||||
/** Specific modifier kind. */
|
|
||||||
modifierKind: ModifierKind;
|
|
||||||
}
|
|
||||||
|
|
||||||
// expressions
|
// expressions
|
||||||
|
|
||||||
/** Base class of all expression nodes. */
|
/** Base class of all expression nodes. */
|
||||||
@ -1208,11 +1183,6 @@ export class FunctionExpression extends Expression {
|
|||||||
declaration: FunctionDeclaration;
|
declaration: FunctionDeclaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents an arrow function expression. */
|
|
||||||
export class FunctionArrowExpression extends FunctionExpression {
|
|
||||||
kind = NodeKind.FUNCTIONARROW;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Represents an integer literal expression. */
|
/** Represents an integer literal expression. */
|
||||||
export class IntegerLiteralExpression extends LiteralExpression {
|
export class IntegerLiteralExpression extends LiteralExpression {
|
||||||
literalKind = LiteralKind.INTEGER;
|
literalKind = LiteralKind.INTEGER;
|
||||||
@ -1380,8 +1350,6 @@ export abstract class DeclarationStatement extends Statement {
|
|||||||
|
|
||||||
/** Simple name being declared. */
|
/** Simple name being declared. */
|
||||||
name: IdentifierExpression;
|
name: IdentifierExpression;
|
||||||
/** Array of modifiers. */
|
|
||||||
modifiers: ModifierNode[] | null;
|
|
||||||
/** Array of decorators. */
|
/** Array of decorators. */
|
||||||
decorators: DecoratorNode[] | null = null;
|
decorators: DecoratorNode[] | null = null;
|
||||||
|
|
||||||
@ -1423,21 +1391,12 @@ export abstract class DeclarationStatement extends Statement {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (parent.kind == NodeKind.NAMESPACEDECLARATION) {
|
if (parent.kind == NodeKind.NAMESPACEDECLARATION) {
|
||||||
return (
|
return this.is(CommonFlags.EXPORT) && (<NamespaceDeclaration>parent).isTopLevelExport;
|
||||||
hasModifier(ModifierKind.EXPORT, this.modifiers) &&
|
|
||||||
(<NamespaceDeclaration>parent).isTopLevelExport
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (parent.kind == NodeKind.CLASSDECLARATION) {
|
if (parent.kind == NodeKind.CLASSDECLARATION) {
|
||||||
return (
|
return this.is(CommonFlags.STATIC) && (<ClassDeclaration>parent).isTopLevelExport;
|
||||||
hasModifier(ModifierKind.STATIC, this.modifiers) &&
|
|
||||||
(<ClassDeclaration>parent).isTopLevelExport
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return (
|
return parent.kind == NodeKind.SOURCE && this.is(CommonFlags.EXPORT);
|
||||||
parent.kind == NodeKind.SOURCE &&
|
|
||||||
hasModifier(ModifierKind.EXPORT, this.modifiers)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Tests if this declaration needs an explicit export. */
|
/** Tests if this declaration needs an explicit export. */
|
||||||
@ -1531,7 +1490,6 @@ export class EnumDeclaration extends DeclarationStatement {
|
|||||||
/** Represents a value of an `enum` declaration. */
|
/** Represents a value of an `enum` declaration. */
|
||||||
export class EnumValueDeclaration extends DeclarationStatement {
|
export class EnumValueDeclaration extends DeclarationStatement {
|
||||||
kind = NodeKind.ENUMVALUEDECLARATION;
|
kind = NodeKind.ENUMVALUEDECLARATION;
|
||||||
modifiers = null;
|
|
||||||
// name is inherited
|
// name is inherited
|
||||||
|
|
||||||
/** Value expression. */
|
/** Value expression. */
|
||||||
@ -1562,8 +1520,6 @@ export class ExportMember extends Node {
|
|||||||
export class ExportStatement extends Statement {
|
export class ExportStatement extends Statement {
|
||||||
kind = NodeKind.EXPORT;
|
kind = NodeKind.EXPORT;
|
||||||
|
|
||||||
/** Array of modifiers. */
|
|
||||||
modifiers: ModifierNode[] | null;
|
|
||||||
/** Array of members. */
|
/** Array of members. */
|
||||||
members: ExportMember[];
|
members: ExportMember[];
|
||||||
/** Path being exported from, if applicable. */
|
/** Path being exported from, if applicable. */
|
||||||
@ -1636,7 +1592,6 @@ export class IfStatement extends Statement {
|
|||||||
/** Represents an `import` declaration part of an {@link ImportStatement}. */
|
/** Represents an `import` declaration part of an {@link ImportStatement}. */
|
||||||
export class ImportDeclaration extends DeclarationStatement {
|
export class ImportDeclaration extends DeclarationStatement {
|
||||||
kind = NodeKind.IMPORTDECLARATION;
|
kind = NodeKind.IMPORTDECLARATION;
|
||||||
modifiers = null;
|
|
||||||
|
|
||||||
/** Identifier being imported. */
|
/** Identifier being imported. */
|
||||||
externalName: IdentifierExpression;
|
externalName: IdentifierExpression;
|
||||||
@ -1739,17 +1694,12 @@ export class TypeDeclaration extends DeclarationStatement {
|
|||||||
/** Represents a variable declaration part of a {@link VariableStatement}. */
|
/** Represents a variable declaration part of a {@link VariableStatement}. */
|
||||||
export class VariableDeclaration extends VariableLikeDeclarationStatement {
|
export class VariableDeclaration extends VariableLikeDeclarationStatement {
|
||||||
kind = NodeKind.VARIABLEDECLARATION;
|
kind = NodeKind.VARIABLEDECLARATION;
|
||||||
|
|
||||||
/** Array of modifiers. */
|
|
||||||
modifiers: ModifierNode[] | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents a variable statement wrapping {@link VariableDeclaration}s. */
|
/** Represents a variable statement wrapping {@link VariableDeclaration}s. */
|
||||||
export class VariableStatement extends Statement {
|
export class VariableStatement extends Statement {
|
||||||
kind = NodeKind.VARIABLE;
|
kind = NodeKind.VARIABLE;
|
||||||
|
|
||||||
/** Array of modifiers. */
|
|
||||||
modifiers: ModifierNode[] | null;
|
|
||||||
/** Array of decorators. */
|
/** Array of decorators. */
|
||||||
decorators: DecoratorNode[] | null;
|
decorators: DecoratorNode[] | null;
|
||||||
/** Array of member declarations. */
|
/** Array of member declarations. */
|
||||||
@ -1774,52 +1724,6 @@ export class WhileStatement extends Statement {
|
|||||||
statement: Statement;
|
statement: Statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Cached unused modifiers for reuse. */
|
|
||||||
var reusableModifiers: ModifierNode[] | null = null;
|
|
||||||
|
|
||||||
export function setReusableModifiers(modifiers: ModifierNode[]): void {
|
|
||||||
reusableModifiers = modifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Creates a new modifiers array. */
|
|
||||||
export function createModifiers(): ModifierNode[] {
|
|
||||||
var ret: ModifierNode[];
|
|
||||||
if (reusableModifiers != null) {
|
|
||||||
ret = reusableModifiers;
|
|
||||||
reusableModifiers = null;
|
|
||||||
} else {
|
|
||||||
ret = [];
|
|
||||||
}
|
|
||||||
ret.length = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility
|
|
||||||
|
|
||||||
/** Adds a modifier to a set of modifiers. Creates a new set if `null`. */
|
|
||||||
export function addModifier(modifier: ModifierNode, modifiers: ModifierNode[] | null): ModifierNode[] {
|
|
||||||
if (modifiers == null) modifiers = createModifiers();
|
|
||||||
modifiers.push(modifier);
|
|
||||||
return modifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a specific modifier from the specified set of modifiers. */
|
|
||||||
export function getModifier(kind: ModifierKind, modifiers: ModifierNode[] | null): ModifierNode | null {
|
|
||||||
if (modifiers) {
|
|
||||||
for (let i = 0, k = modifiers.length; i < k; ++i) {
|
|
||||||
if (modifiers[i].modifierKind == kind) {
|
|
||||||
return modifiers[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Tests whether a modifier exists in the specified set of modifiers. */
|
|
||||||
export function hasModifier(kind: ModifierKind, modifiers: ModifierNode[] | null): bool {
|
|
||||||
return getModifier(kind, modifiers) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the first decorator by name within at set of decorators, if present. */
|
/** Gets the first decorator by name within at set of decorators, if present. */
|
||||||
export function getFirstDecorator(name: string, decorators: DecoratorNode[] | null): DecoratorNode | null {
|
export function getFirstDecorator(name: string, decorators: DecoratorNode[] | null): DecoratorNode | null {
|
||||||
if (decorators) {
|
if (decorators) {
|
||||||
@ -1852,7 +1756,7 @@ export function mangleInternalName(declaration: DeclarationStatement, asGlobal:
|
|||||||
}
|
}
|
||||||
if (parent.kind == NodeKind.CLASSDECLARATION) {
|
if (parent.kind == NodeKind.CLASSDECLARATION) {
|
||||||
return mangleInternalName(<ClassDeclaration>parent, asGlobal) + (
|
return mangleInternalName(<ClassDeclaration>parent, asGlobal) + (
|
||||||
hasModifier(ModifierKind.STATIC, declaration.modifiers)
|
declaration.is(CommonFlags.STATIC)
|
||||||
? STATIC_DELIMITER
|
? STATIC_DELIMITER
|
||||||
: INSTANCE_DELIMITER
|
: INSTANCE_DELIMITER
|
||||||
) + name;
|
) + name;
|
||||||
|
@ -2338,7 +2338,7 @@ export function compileAllocate(
|
|||||||
var module = compiler.module;
|
var module = compiler.module;
|
||||||
var options = compiler.options;
|
var options = compiler.options;
|
||||||
|
|
||||||
var prototype = program.elements.get(options.allocateImpl);
|
var prototype = program.elementsLookup.get(options.allocateImpl);
|
||||||
if (!prototype) {
|
if (!prototype) {
|
||||||
program.error(
|
program.error(
|
||||||
DiagnosticCode.Cannot_find_name_0,
|
DiagnosticCode.Cannot_find_name_0,
|
||||||
@ -2377,10 +2377,10 @@ export function compileAbort(
|
|||||||
var program = compiler.program;
|
var program = compiler.program;
|
||||||
var module = compiler.module;
|
var module = compiler.module;
|
||||||
|
|
||||||
var stringType = program.types.get("string"); // might be intended
|
var stringType = program.typesLookup.get("string"); // might be intended
|
||||||
if (!stringType) return module.createUnreachable();
|
if (!stringType) return module.createUnreachable();
|
||||||
|
|
||||||
var abortPrototype = program.elements.get("abort"); // might be intended
|
var abortPrototype = program.elementsLookup.get("abort"); // might be intended
|
||||||
if (!abortPrototype || abortPrototype.kind != ElementKind.FUNCTION_PROTOTYPE) return module.createUnreachable();
|
if (!abortPrototype || abortPrototype.kind != ElementKind.FUNCTION_PROTOTYPE) return module.createUnreachable();
|
||||||
|
|
||||||
var abortInstance = (<FunctionPrototype>abortPrototype).resolve(); // reports
|
var abortInstance = (<FunctionPrototype>abortPrototype).resolve(); // reports
|
||||||
|
214
src/compiler.ts
214
src/compiler.ts
@ -39,7 +39,7 @@ import {
|
|||||||
Property,
|
Property,
|
||||||
VariableLikeElement,
|
VariableLikeElement,
|
||||||
FlowFlags,
|
FlowFlags,
|
||||||
ElementFlags,
|
CommonFlags,
|
||||||
ConstantValueKind,
|
ConstantValueKind,
|
||||||
|
|
||||||
PATH_DELIMITER,
|
PATH_DELIMITER,
|
||||||
@ -47,7 +47,8 @@ import {
|
|||||||
} from "./program";
|
} from "./program";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Token
|
Token,
|
||||||
|
operatorTokenToString
|
||||||
} from "./tokenizer";
|
} from "./tokenizer";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -72,7 +73,6 @@ import {
|
|||||||
IfStatement,
|
IfStatement,
|
||||||
ImportStatement,
|
ImportStatement,
|
||||||
InterfaceDeclaration,
|
InterfaceDeclaration,
|
||||||
ModifierKind,
|
|
||||||
NamespaceDeclaration,
|
NamespaceDeclaration,
|
||||||
ReturnStatement,
|
ReturnStatement,
|
||||||
SwitchStatement,
|
SwitchStatement,
|
||||||
@ -102,9 +102,7 @@ import {
|
|||||||
ArrayLiteralExpression,
|
ArrayLiteralExpression,
|
||||||
StringLiteralExpression,
|
StringLiteralExpression,
|
||||||
UnaryPostfixExpression,
|
UnaryPostfixExpression,
|
||||||
UnaryPrefixExpression,
|
UnaryPrefixExpression
|
||||||
|
|
||||||
hasModifier
|
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -239,14 +237,13 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
program.initialize(options);
|
program.initialize(options);
|
||||||
|
|
||||||
// set up the start function wrapping top-level statements, of all files.
|
// set up the start function wrapping top-level statements, of all files.
|
||||||
var startFunctionPrototype = assert(program.elements.get("start"));
|
var startFunctionPrototype = assert(program.elementsLookup.get("start"));
|
||||||
assert(startFunctionPrototype.kind == ElementKind.FUNCTION_PROTOTYPE);
|
assert(startFunctionPrototype.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||||
var startFunctionInstance = new Function(
|
var startFunctionInstance = new Function(
|
||||||
<FunctionPrototype>startFunctionPrototype,
|
<FunctionPrototype>startFunctionPrototype,
|
||||||
startFunctionPrototype.internalName,
|
startFunctionPrototype.internalName,
|
||||||
new Signature([], Type.void)
|
new Signature([], Type.void)
|
||||||
);
|
);
|
||||||
startFunctionInstance.set(ElementFlags.START);
|
|
||||||
this.startFunction = startFunctionInstance;
|
this.startFunction = startFunctionInstance;
|
||||||
this.currentFunction = startFunctionInstance;
|
this.currentFunction = startFunctionInstance;
|
||||||
|
|
||||||
@ -383,10 +380,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
switch (statement.kind) {
|
switch (statement.kind) {
|
||||||
case NodeKind.CLASSDECLARATION: {
|
case NodeKind.CLASSDECLARATION: {
|
||||||
if (
|
if (
|
||||||
(
|
(noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) &&
|
||||||
noTreeShaking ||
|
|
||||||
(isEntry && hasModifier(ModifierKind.EXPORT, (<ClassDeclaration>statement).modifiers))
|
|
||||||
) &&
|
|
||||||
!(<ClassDeclaration>statement).isGeneric
|
!(<ClassDeclaration>statement).isGeneric
|
||||||
) {
|
) {
|
||||||
this.compileClassDeclaration(<ClassDeclaration>statement, []);
|
this.compileClassDeclaration(<ClassDeclaration>statement, []);
|
||||||
@ -394,20 +388,14 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.ENUMDECLARATION: {
|
case NodeKind.ENUMDECLARATION: {
|
||||||
if (
|
if (noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) {
|
||||||
noTreeShaking ||
|
|
||||||
(isEntry && hasModifier(ModifierKind.EXPORT, (<EnumDeclaration>statement).modifiers))
|
|
||||||
) {
|
|
||||||
this.compileEnumDeclaration(<EnumDeclaration>statement);
|
this.compileEnumDeclaration(<EnumDeclaration>statement);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.FUNCTIONDECLARATION: {
|
case NodeKind.FUNCTIONDECLARATION: {
|
||||||
if (
|
if (
|
||||||
(
|
(noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) &&
|
||||||
noTreeShaking ||
|
|
||||||
(isEntry && hasModifier(ModifierKind.EXPORT, (<FunctionDeclaration>statement).modifiers))
|
|
||||||
) &&
|
|
||||||
!(<FunctionDeclaration>statement).isGeneric
|
!(<FunctionDeclaration>statement).isGeneric
|
||||||
) {
|
) {
|
||||||
this.compileFunctionDeclaration(<FunctionDeclaration>statement, []);
|
this.compileFunctionDeclaration(<FunctionDeclaration>statement, []);
|
||||||
@ -422,10 +410,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.NAMESPACEDECLARATION: {
|
case NodeKind.NAMESPACEDECLARATION: {
|
||||||
if (
|
if (noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) {
|
||||||
noTreeShaking ||
|
|
||||||
(isEntry && hasModifier(ModifierKind.EXPORT, (<NamespaceDeclaration>statement).modifiers))
|
|
||||||
) {
|
|
||||||
this.compileNamespaceDeclaration(<NamespaceDeclaration>statement);
|
this.compileNamespaceDeclaration(<NamespaceDeclaration>statement);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -462,15 +447,15 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
compileGlobalDeclaration(declaration: VariableDeclaration): Global | null {
|
compileGlobalDeclaration(declaration: VariableDeclaration): Global | null {
|
||||||
// look up the initialized program element
|
// look up the initialized program element
|
||||||
var element = assert(this.program.elements.get(declaration.fileLevelInternalName));
|
var element = assert(this.program.elementsLookup.get(declaration.fileLevelInternalName));
|
||||||
assert(element.kind == ElementKind.GLOBAL);
|
assert(element.kind == ElementKind.GLOBAL);
|
||||||
if (!this.compileGlobal(<Global>element)) return null; // reports
|
if (!this.compileGlobal(<Global>element)) return null; // reports
|
||||||
return <Global>element;
|
return <Global>element;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileGlobal(global: Global): bool {
|
compileGlobal(global: Global): bool {
|
||||||
if (global.is(ElementFlags.COMPILED) || global.is(ElementFlags.BUILTIN)) return true;
|
if (global.is(CommonFlags.COMPILED) || global.is(CommonFlags.BUILTIN)) return true;
|
||||||
global.set(ElementFlags.COMPILED); // ^ built-ins are compiled on use
|
global.set(CommonFlags.COMPILED); // ^ built-ins are compiled on use
|
||||||
|
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
var declaration = global.declaration;
|
var declaration = global.declaration;
|
||||||
@ -520,10 +505,11 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var nativeType = global.type.toNativeType();
|
var nativeType = global.type.toNativeType();
|
||||||
|
|
||||||
// handle imports
|
// handle imports
|
||||||
if (global.is(ElementFlags.DECLARED)) {
|
if (global.is(CommonFlags.DECLARE)) {
|
||||||
|
|
||||||
// constant global
|
// constant global
|
||||||
if (global.is(ElementFlags.CONSTANT)) {
|
if (global.is(CommonFlags.CONST)) {
|
||||||
|
global.set(CommonFlags.MODULE_IMPORT);
|
||||||
module.addGlobalImport(
|
module.addGlobalImport(
|
||||||
global.internalName,
|
global.internalName,
|
||||||
global.namespace
|
global.namespace
|
||||||
@ -532,7 +518,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
global.simpleName,
|
global.simpleName,
|
||||||
nativeType
|
nativeType
|
||||||
);
|
);
|
||||||
global.set(ElementFlags.COMPILED);
|
global.set(CommonFlags.COMPILED);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// importing mutable globals is not supported in the MVP
|
// importing mutable globals is not supported in the MVP
|
||||||
@ -550,7 +536,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var initializeInStart = false;
|
var initializeInStart = false;
|
||||||
|
|
||||||
// inlined constant can be compiled as-is
|
// inlined constant can be compiled as-is
|
||||||
if (global.is(ElementFlags.INLINED)) {
|
if (global.is(CommonFlags.INLINED)) {
|
||||||
initExpr = this.compileInlineConstant(global, global.type, true);
|
initExpr = this.compileInlineConstant(global, global.type, true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -565,7 +551,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
||||||
|
|
||||||
// if a constant global, check if the initializer becomes constant after precompute
|
// if a constant global, check if the initializer becomes constant after precompute
|
||||||
if (global.is(ElementFlags.CONSTANT)) {
|
if (global.is(CommonFlags.CONST)) {
|
||||||
initExpr = this.precomputeExpressionRef(initExpr);
|
initExpr = this.precomputeExpressionRef(initExpr);
|
||||||
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
||||||
this.warning(
|
this.warning(
|
||||||
@ -593,7 +579,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
} else { // compile as-is
|
} else { // compile as-is
|
||||||
|
|
||||||
if (global.is(ElementFlags.CONSTANT)) {
|
if (global.is(CommonFlags.CONST)) {
|
||||||
let exprType = _BinaryenExpressionGetType(initExpr);
|
let exprType = _BinaryenExpressionGetType(initExpr);
|
||||||
switch (exprType) {
|
switch (exprType) {
|
||||||
case NativeType.I32: {
|
case NativeType.I32: {
|
||||||
@ -630,7 +616,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
global.set(ElementFlags.INLINED); // inline the value from now on
|
global.set(CommonFlags.INLINED); // inline the value from now on
|
||||||
if (declaration.isTopLevel) { // but keep the element if it might be re-exported
|
if (declaration.isTopLevel) { // but keep the element if it might be re-exported
|
||||||
module.addGlobal(internalName, nativeType, false, initExpr);
|
module.addGlobal(internalName, nativeType, false, initExpr);
|
||||||
}
|
}
|
||||||
@ -639,7 +625,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else /* mutable */ {
|
} else /* mutable */ {
|
||||||
module.addGlobal(internalName, nativeType, !global.is(ElementFlags.CONSTANT), initExpr);
|
module.addGlobal(internalName, nativeType, !global.is(CommonFlags.CONST), initExpr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -648,15 +634,15 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// enums
|
// enums
|
||||||
|
|
||||||
compileEnumDeclaration(declaration: EnumDeclaration): Enum | null {
|
compileEnumDeclaration(declaration: EnumDeclaration): Enum | null {
|
||||||
var element = assert(this.program.elements.get(declaration.fileLevelInternalName));
|
var element = assert(this.program.elementsLookup.get(declaration.fileLevelInternalName));
|
||||||
assert(element.kind == ElementKind.ENUM);
|
assert(element.kind == ElementKind.ENUM);
|
||||||
if (!this.compileEnum(<Enum>element)) return null;
|
if (!this.compileEnum(<Enum>element)) return null;
|
||||||
return <Enum>element;
|
return <Enum>element;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileEnum(element: Enum): bool {
|
compileEnum(element: Enum): bool {
|
||||||
if (element.is(ElementFlags.COMPILED)) return true;
|
if (element.is(CommonFlags.COMPILED)) return true;
|
||||||
element.set(ElementFlags.COMPILED);
|
element.set(CommonFlags.COMPILED);
|
||||||
|
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
this.currentEnum = element;
|
this.currentEnum = element;
|
||||||
@ -668,8 +654,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let initInStart = false;
|
let initInStart = false;
|
||||||
let val = <EnumValue>member;
|
let val = <EnumValue>member;
|
||||||
let valueDeclaration = val.declaration;
|
let valueDeclaration = val.declaration;
|
||||||
val.set(ElementFlags.COMPILED);
|
val.set(CommonFlags.COMPILED);
|
||||||
if (val.is(ElementFlags.INLINED)) {
|
if (val.is(CommonFlags.INLINED)) {
|
||||||
if (element.declaration.isTopLevelExport) {
|
if (element.declaration.isTopLevelExport) {
|
||||||
module.addGlobal(
|
module.addGlobal(
|
||||||
val.internalName,
|
val.internalName,
|
||||||
@ -685,7 +671,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
||||||
initExpr = this.precomputeExpressionRef(initExpr);
|
initExpr = this.precomputeExpressionRef(initExpr);
|
||||||
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
||||||
if (element.is(ElementFlags.CONSTANT)) {
|
if (element.is(CommonFlags.CONST)) {
|
||||||
this.warning(
|
this.warning(
|
||||||
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
|
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
|
||||||
valueDeclaration.range
|
valueDeclaration.range
|
||||||
@ -696,7 +682,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
} else if (previousValue == null) {
|
} else if (previousValue == null) {
|
||||||
initExpr = module.createI32(0);
|
initExpr = module.createI32(0);
|
||||||
} else if (previousValue.is(ElementFlags.INLINED)) {
|
} else if (previousValue.is(CommonFlags.INLINED)) {
|
||||||
initExpr = module.createI32(previousValue.constantValue + 1);
|
initExpr = module.createI32(previousValue.constantValue + 1);
|
||||||
} else {
|
} else {
|
||||||
// in TypeScript this errors with TS1061, but actually we can do:
|
// in TypeScript this errors with TS1061, but actually we can do:
|
||||||
@ -704,7 +690,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
module.createGetGlobal(previousValue.internalName, NativeType.I32),
|
module.createGetGlobal(previousValue.internalName, NativeType.I32),
|
||||||
module.createI32(1)
|
module.createI32(1)
|
||||||
);
|
);
|
||||||
if (element.is(ElementFlags.CONSTANT)) {
|
if (element.is(CommonFlags.CONST)) {
|
||||||
this.warning(
|
this.warning(
|
||||||
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
|
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
|
||||||
valueDeclaration.range
|
valueDeclaration.range
|
||||||
@ -724,7 +710,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
module.addGlobal(val.internalName, NativeType.I32, false, initExpr);
|
module.addGlobal(val.internalName, NativeType.I32, false, initExpr);
|
||||||
if (_BinaryenExpressionGetType(initExpr) == NativeType.I32) {
|
if (_BinaryenExpressionGetType(initExpr) == NativeType.I32) {
|
||||||
val.constantValue = _BinaryenConstGetValueI32(initExpr);
|
val.constantValue = _BinaryenConstGetValueI32(initExpr);
|
||||||
val.set(ElementFlags.INLINED);
|
val.set(CommonFlags.INLINED);
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
this.error(
|
this.error(
|
||||||
@ -739,7 +725,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// export values if the enum is exported
|
// export values if the enum is exported
|
||||||
if (element.declaration.range.source.isEntry && element.declaration.isTopLevelExport) {
|
if (element.declaration.range.source.isEntry && element.declaration.isTopLevelExport) {
|
||||||
if (member.is(ElementFlags.INLINED)) {
|
if (member.is(CommonFlags.INLINED)) {
|
||||||
module.addGlobalExport(member.internalName, member.internalName);
|
module.addGlobalExport(member.internalName, member.internalName);
|
||||||
} else if (valueDeclaration) {
|
} else if (valueDeclaration) {
|
||||||
this.warning(
|
this.warning(
|
||||||
@ -762,7 +748,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
typeArguments: TypeNode[],
|
typeArguments: TypeNode[],
|
||||||
contextualTypeArguments: Map<string,Type> | null = null
|
contextualTypeArguments: Map<string,Type> | null = null
|
||||||
): Function | null {
|
): Function | null {
|
||||||
var element = assert(this.program.elements.get(declaration.fileLevelInternalName));
|
var element = assert(this.program.elementsLookup.get(declaration.fileLevelInternalName));
|
||||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||||
return this.compileFunctionUsingTypeArguments( // reports
|
return this.compileFunctionUsingTypeArguments( // reports
|
||||||
<FunctionPrototype>element,
|
<FunctionPrototype>element,
|
||||||
@ -816,22 +802,22 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
/** Compiles a readily resolved function instance. */
|
/** Compiles a readily resolved function instance. */
|
||||||
compileFunction(instance: Function): bool {
|
compileFunction(instance: Function): bool {
|
||||||
if (instance.is(ElementFlags.COMPILED)) return true;
|
if (instance.is(CommonFlags.COMPILED)) return true;
|
||||||
assert(!instance.is(ElementFlags.BUILTIN) || instance.simpleName == "abort");
|
assert(!instance.is(CommonFlags.BUILTIN) || instance.simpleName == "abort");
|
||||||
instance.set(ElementFlags.COMPILED);
|
instance.set(CommonFlags.COMPILED);
|
||||||
|
|
||||||
// check that modifiers are matching but still compile as-is
|
// check that modifiers are matching but still compile as-is
|
||||||
var declaration = instance.prototype.declaration;
|
var declaration = instance.prototype.declaration;
|
||||||
var body = declaration.body;
|
var body = declaration.body;
|
||||||
if (body) {
|
if (body) {
|
||||||
if (instance.is(ElementFlags.DECLARED)) {
|
if (instance.is(CommonFlags.DECLARE)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts,
|
DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts,
|
||||||
declaration.name.range
|
declaration.name.range
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!instance.is(ElementFlags.DECLARED)) {
|
if (!instance.is(CommonFlags.DECLARE)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
|
DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
|
||||||
declaration.name.range
|
declaration.name.range
|
||||||
@ -869,7 +855,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
instance.set(ElementFlags.IMPORTED);
|
instance.set(CommonFlags.MODULE_IMPORT);
|
||||||
|
|
||||||
// create the function import
|
// create the function import
|
||||||
let namespace = instance.prototype.namespace;
|
let namespace = instance.prototype.namespace;
|
||||||
@ -902,10 +888,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
switch (member.kind) {
|
switch (member.kind) {
|
||||||
case NodeKind.CLASSDECLARATION: {
|
case NodeKind.CLASSDECLARATION: {
|
||||||
if (
|
if (
|
||||||
(
|
(noTreeShaking || member.is(CommonFlags.EXPORT)) &&
|
||||||
noTreeShaking ||
|
!(<ClassDeclaration>member).isGeneric
|
||||||
hasModifier(ModifierKind.EXPORT, (<ClassDeclaration>member).modifiers)
|
|
||||||
) && !(<ClassDeclaration>member).isGeneric
|
|
||||||
) {
|
) {
|
||||||
this.compileClassDeclaration(<ClassDeclaration>member, []);
|
this.compileClassDeclaration(<ClassDeclaration>member, []);
|
||||||
}
|
}
|
||||||
@ -913,30 +897,22 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case NodeKind.INTERFACEDECLARATION: {
|
case NodeKind.INTERFACEDECLARATION: {
|
||||||
if (
|
if (
|
||||||
(
|
(noTreeShaking || member.is(CommonFlags.EXPORT)) &&
|
||||||
noTreeShaking ||
|
!(<InterfaceDeclaration>member).isGeneric
|
||||||
hasModifier(ModifierKind.EXPORT, (<InterfaceDeclaration>member).modifiers)
|
|
||||||
) && !(<InterfaceDeclaration>member).isGeneric
|
|
||||||
) {
|
) {
|
||||||
this.compileInterfaceDeclaration(<InterfaceDeclaration>member, []);
|
this.compileInterfaceDeclaration(<InterfaceDeclaration>member, []);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.ENUMDECLARATION: {
|
case NodeKind.ENUMDECLARATION: {
|
||||||
if (
|
if (noTreeShaking || member.is(CommonFlags.EXPORT)) {
|
||||||
noTreeShaking ||
|
|
||||||
hasModifier(ModifierKind.EXPORT, (<EnumDeclaration>member).modifiers)
|
|
||||||
) {
|
|
||||||
this.compileEnumDeclaration(<EnumDeclaration>member);
|
this.compileEnumDeclaration(<EnumDeclaration>member);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.FUNCTIONDECLARATION: {
|
case NodeKind.FUNCTIONDECLARATION: {
|
||||||
if (
|
if (
|
||||||
(
|
(noTreeShaking || member.is(CommonFlags.EXPORT)) &&
|
||||||
noTreeShaking ||
|
|
||||||
hasModifier(ModifierKind.EXPORT, (<FunctionDeclaration>member).modifiers)
|
|
||||||
) &&
|
|
||||||
!(<FunctionDeclaration>member).isGeneric
|
!(<FunctionDeclaration>member).isGeneric
|
||||||
) {
|
) {
|
||||||
this.compileFunctionDeclaration(<FunctionDeclaration>member, []);
|
this.compileFunctionDeclaration(<FunctionDeclaration>member, []);
|
||||||
@ -944,19 +920,13 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.NAMESPACEDECLARATION: {
|
case NodeKind.NAMESPACEDECLARATION: {
|
||||||
if (
|
if (noTreeShaking || member.is(CommonFlags.EXPORT)) {
|
||||||
noTreeShaking ||
|
|
||||||
hasModifier(ModifierKind.EXPORT, (<NamespaceDeclaration>member).modifiers)
|
|
||||||
) {
|
|
||||||
this.compileNamespaceDeclaration(<NamespaceDeclaration>member);
|
this.compileNamespaceDeclaration(<NamespaceDeclaration>member);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.VARIABLE: {
|
case NodeKind.VARIABLE: {
|
||||||
if (
|
if (noTreeShaking || member.is(CommonFlags.EXPORT)) {
|
||||||
noTreeShaking ||
|
|
||||||
hasModifier(ModifierKind.EXPORT, (<VariableStatement>member).modifiers)
|
|
||||||
) {
|
|
||||||
let variableInit = this.compileVariableStatement(<VariableStatement>member, true);
|
let variableInit = this.compileVariableStatement(<VariableStatement>member, true);
|
||||||
if (variableInit) this.startFunctionBody.push(variableInit);
|
if (variableInit) this.startFunctionBody.push(variableInit);
|
||||||
}
|
}
|
||||||
@ -984,8 +954,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
noTreeShaking ||
|
noTreeShaking ||
|
||||||
(<ClassPrototype>element).is(ElementFlags.EXPORTED)
|
(<ClassPrototype>element).is(CommonFlags.EXPORT)
|
||||||
) && !(<ClassPrototype>element).is(ElementFlags.GENERIC)
|
) && !(<ClassPrototype>element).is(CommonFlags.GENERIC)
|
||||||
) {
|
) {
|
||||||
this.compileClassUsingTypeArguments(<ClassPrototype>element, []);
|
this.compileClassUsingTypeArguments(<ClassPrototype>element, []);
|
||||||
}
|
}
|
||||||
@ -998,8 +968,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
case ElementKind.FUNCTION_PROTOTYPE: {
|
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
noTreeShaking || (<FunctionPrototype>element).is(ElementFlags.EXPORTED)
|
noTreeShaking || (<FunctionPrototype>element).is(CommonFlags.EXPORT)
|
||||||
) && !(<FunctionPrototype>element).is(ElementFlags.GENERIC)
|
) && !(<FunctionPrototype>element).is(CommonFlags.GENERIC)
|
||||||
) {
|
) {
|
||||||
this.compileFunctionUsingTypeArguments(
|
this.compileFunctionUsingTypeArguments(
|
||||||
<FunctionPrototype>element,
|
<FunctionPrototype>element,
|
||||||
@ -1026,7 +996,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
compileExportStatement(statement: ExportStatement): void {
|
compileExportStatement(statement: ExportStatement): void {
|
||||||
var module = this.module;
|
var module = this.module;
|
||||||
var exports = this.program.exports;
|
var exports = this.program.fileLevelExports;
|
||||||
var members = statement.members;
|
var members = statement.members;
|
||||||
for (let i = 0, k = members.length; i < k; ++i) {
|
for (let i = 0, k = members.length; i < k; ++i) {
|
||||||
let member = members[i];
|
let member = members[i];
|
||||||
@ -1039,7 +1009,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (!element) continue; // reported in Program#initialize
|
if (!element) continue; // reported in Program#initialize
|
||||||
switch (element.kind) {
|
switch (element.kind) {
|
||||||
case ElementKind.CLASS_PROTOTYPE: {
|
case ElementKind.CLASS_PROTOTYPE: {
|
||||||
if (!(<ClassPrototype>element).is(ElementFlags.GENERIC)) {
|
if (!(<ClassPrototype>element).is(CommonFlags.GENERIC)) {
|
||||||
this.compileClassUsingTypeArguments(<ClassPrototype>element, []);
|
this.compileClassUsingTypeArguments(<ClassPrototype>element, []);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1050,7 +1020,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case ElementKind.FUNCTION_PROTOTYPE: {
|
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||||
if (
|
if (
|
||||||
!(<FunctionPrototype>element).is(ElementFlags.GENERIC) &&
|
!(<FunctionPrototype>element).is(CommonFlags.GENERIC) &&
|
||||||
statement.range.source.isEntry
|
statement.range.source.isEntry
|
||||||
) {
|
) {
|
||||||
let functionInstance = this.compileFunctionUsingTypeArguments(
|
let functionInstance = this.compileFunctionUsingTypeArguments(
|
||||||
@ -1072,7 +1042,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (this.compileGlobal(<Global>element) && statement.range.source.isEntry) {
|
if (this.compileGlobal(<Global>element) && statement.range.source.isEntry) {
|
||||||
let globalDeclaration = (<Global>element).declaration;
|
let globalDeclaration = (<Global>element).declaration;
|
||||||
if (globalDeclaration && globalDeclaration.needsExplicitExport(member)) {
|
if (globalDeclaration && globalDeclaration.needsExplicitExport(member)) {
|
||||||
if ((<Global>element).is(ElementFlags.INLINED)) {
|
if ((<Global>element).is(CommonFlags.INLINED)) {
|
||||||
module.addGlobalExport(element.internalName, member.externalName.text);
|
module.addGlobalExport(element.internalName, member.externalName.text);
|
||||||
} else {
|
} else {
|
||||||
this.warning(
|
this.warning(
|
||||||
@ -1100,7 +1070,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
contextualTypeArguments: Map<string,Type> | null = null,
|
contextualTypeArguments: Map<string,Type> | null = null,
|
||||||
alternativeReportNode: Node | null = null
|
alternativeReportNode: Node | null = null
|
||||||
): void {
|
): void {
|
||||||
var element = assert(this.program.elements.get(declaration.fileLevelInternalName));
|
var element = assert(this.program.elementsLookup.get(declaration.fileLevelInternalName));
|
||||||
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
|
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
|
||||||
this.compileClassUsingTypeArguments(
|
this.compileClassUsingTypeArguments(
|
||||||
<ClassPrototype>element,
|
<ClassPrototype>element,
|
||||||
@ -1126,8 +1096,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileClass(instance: Class): bool {
|
compileClass(instance: Class): bool {
|
||||||
if (instance.is(ElementFlags.COMPILED)) return true;
|
if (instance.is(CommonFlags.COMPILED)) return true;
|
||||||
instance.set(ElementFlags.COMPILED);
|
instance.set(CommonFlags.COMPILED);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1159,7 +1129,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
/** Ensures that a table entry exists for the specified function and returns its index. */
|
/** Ensures that a table entry exists for the specified function and returns its index. */
|
||||||
ensureFunctionTableEntry(func: Function): i32 {
|
ensureFunctionTableEntry(func: Function): i32 {
|
||||||
assert(func.is(ElementFlags.COMPILED));
|
assert(func.is(CommonFlags.COMPILED));
|
||||||
if (func.functionTableIndex >= 0) {
|
if (func.functionTableIndex >= 0) {
|
||||||
return func.functionTableIndex;
|
return func.functionTableIndex;
|
||||||
}
|
}
|
||||||
@ -1671,7 +1641,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (hasModifier(ModifierKind.CONST, declaration.modifiers)) {
|
if (declaration.is(CommonFlags.CONST)) {
|
||||||
if (init) {
|
if (init) {
|
||||||
init = this.precomputeExpressionRef(init);
|
init = this.precomputeExpressionRef(init);
|
||||||
if (_BinaryenExpressionGetId(init) == ExpressionId.Const) {
|
if (_BinaryenExpressionGetId(init) == ExpressionId.Const) {
|
||||||
@ -1730,7 +1700,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasModifier(ModifierKind.LET, declaration.modifiers)) { // here: not top-level
|
if (declaration.is(CommonFlags.LET)) { // here: not top-level
|
||||||
currentFunction.flow.addScopedLocal(name, type, declaration.name); // reports
|
currentFunction.flow.addScopedLocal(name, type, declaration.name); // reports
|
||||||
} else {
|
} else {
|
||||||
currentFunction.addLocal(type, name); // reports
|
currentFunction.addLocal(type, name); // reports
|
||||||
@ -1809,7 +1779,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
contextualType: Type,
|
contextualType: Type,
|
||||||
retainType: bool
|
retainType: bool
|
||||||
): ExpressionRef {
|
): ExpressionRef {
|
||||||
assert(element.is(ElementFlags.INLINED));
|
assert(element.is(CommonFlags.INLINED));
|
||||||
var type = element.type;
|
var type = element.type;
|
||||||
switch (
|
switch (
|
||||||
!retainType &&
|
!retainType &&
|
||||||
@ -1913,8 +1883,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
expr = this.compileElementAccessExpression(<ElementAccessExpression>expression, contextualType);
|
expr = this.compileElementAccessExpression(<ElementAccessExpression>expression, contextualType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind.FUNCTION:
|
case NodeKind.FUNCTION: {
|
||||||
case NodeKind.FUNCTIONARROW: {
|
|
||||||
expr = this.compileFunctionExpression(<FunctionExpression>expression, contextualType);
|
expr = this.compileFunctionExpression(<FunctionExpression>expression, contextualType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2582,7 +2551,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
} else {
|
} else {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Operator_0_cannot_be_applied_to_types_1_and_2,
|
DiagnosticCode.Operator_0_cannot_be_applied_to_types_1_and_2,
|
||||||
expression.range, Token.operatorToString(expression.operator), leftType.toString(), rightType.toString()
|
expression.range, operatorTokenToString(expression.operator), leftType.toString(), rightType.toString()
|
||||||
);
|
);
|
||||||
this.currentType = contextualType;
|
this.currentType = contextualType;
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
@ -2648,7 +2617,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
} else {
|
} else {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Operator_0_cannot_be_applied_to_types_1_and_2,
|
DiagnosticCode.Operator_0_cannot_be_applied_to_types_1_and_2,
|
||||||
expression.range, Token.operatorToString(expression.operator), leftType.toString(), rightType.toString()
|
expression.range, operatorTokenToString(expression.operator), leftType.toString(), rightType.toString()
|
||||||
);
|
);
|
||||||
this.currentType = contextualType;
|
this.currentType = contextualType;
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
@ -3183,7 +3152,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
case TypeKind.F64: {
|
case TypeKind.F64: {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
|
DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
|
||||||
expression.range, Token.operatorToString(expression.operator), this.currentType.toString()
|
expression.range, operatorTokenToString(expression.operator), this.currentType.toString()
|
||||||
);
|
);
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
}
|
}
|
||||||
@ -3257,7 +3226,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
case TypeKind.F64: {
|
case TypeKind.F64: {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
|
DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
|
||||||
expression.range, Token.operatorToString(expression.operator), this.currentType.toString()
|
expression.range, operatorTokenToString(expression.operator), this.currentType.toString()
|
||||||
);
|
);
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
}
|
}
|
||||||
@ -3739,7 +3708,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
switch (element.kind) {
|
switch (element.kind) {
|
||||||
case ElementKind.LOCAL: {
|
case ElementKind.LOCAL: {
|
||||||
this.currentType = tee ? (<Local>element).type : Type.void;
|
this.currentType = tee ? (<Local>element).type : Type.void;
|
||||||
if ((<Local>element).is(ElementFlags.CONSTANT)) {
|
if ((<Local>element).is(CommonFlags.CONST)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
|
DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
|
||||||
expression.range, (<Local>element).internalName
|
expression.range, (<Local>element).internalName
|
||||||
@ -3755,7 +3724,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let type = (<Global>element).type;
|
let type = (<Global>element).type;
|
||||||
assert(type != Type.void);
|
assert(type != Type.void);
|
||||||
this.currentType = tee ? type : Type.void;
|
this.currentType = tee ? type : Type.void;
|
||||||
if ((<Local>element).is(ElementFlags.CONSTANT)) {
|
if ((<Local>element).is(CommonFlags.CONST)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
|
DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
|
||||||
expression.range,
|
expression.range,
|
||||||
@ -3775,7 +3744,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ElementKind.FIELD: {
|
case ElementKind.FIELD: {
|
||||||
if ((<Field>element).prototype.isReadonly) {
|
if ((<Field>element).is(CommonFlags.READONLY)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
|
DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
|
||||||
expression.range, (<Field>element).internalName
|
expression.range, (<Field>element).internalName
|
||||||
@ -3823,7 +3792,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// call just the setter if the return value isn't of interest
|
// call just the setter if the return value isn't of interest
|
||||||
if (!tee) {
|
if (!tee) {
|
||||||
if (setterInstance.is(ElementFlags.INSTANCE)) {
|
if (setterInstance.is(CommonFlags.INSTANCE)) {
|
||||||
assert(resolved.isInstanceTarget);
|
assert(resolved.isInstanceTarget);
|
||||||
let thisArg = this.compileExpression(
|
let thisArg = this.compileExpression(
|
||||||
<Expression>resolved.targetExpression,
|
<Expression>resolved.targetExpression,
|
||||||
@ -3842,7 +3811,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (!getterInstance) return module.createUnreachable();
|
if (!getterInstance) return module.createUnreachable();
|
||||||
let returnType = getterInstance.signature.returnType;
|
let returnType = getterInstance.signature.returnType;
|
||||||
let nativeReturnType = returnType.toNativeType();
|
let nativeReturnType = returnType.toNativeType();
|
||||||
if (setterInstance.is(ElementFlags.INSTANCE)) {
|
if (setterInstance.is(CommonFlags.INSTANCE)) {
|
||||||
assert(resolved.isInstanceTarget);
|
assert(resolved.isInstanceTarget);
|
||||||
let thisArg = this.compileExpression(
|
let thisArg = this.compileExpression(
|
||||||
<Expression>resolved.targetExpression,
|
<Expression>resolved.targetExpression,
|
||||||
@ -3956,7 +3925,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let prototype = <FunctionPrototype>element;
|
let prototype = <FunctionPrototype>element;
|
||||||
|
|
||||||
// builtins are compiled on the fly
|
// builtins are compiled on the fly
|
||||||
if (prototype.is(ElementFlags.BUILTIN)) {
|
if (prototype.is(CommonFlags.BUILTIN)) {
|
||||||
let expr = compileBuiltinCall( // reports
|
let expr = compileBuiltinCall( // reports
|
||||||
this,
|
this,
|
||||||
prototype,
|
prototype,
|
||||||
@ -3986,7 +3955,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
if (!instance) return module.createUnreachable();
|
if (!instance) return module.createUnreachable();
|
||||||
let thisArg: ExpressionRef = 0;
|
let thisArg: ExpressionRef = 0;
|
||||||
if (instance.is(ElementFlags.INSTANCE)) {
|
if (instance.is(CommonFlags.INSTANCE)) {
|
||||||
assert(resolved.isInstanceTarget);
|
assert(resolved.isInstanceTarget);
|
||||||
thisArg = this.compileExpression(
|
thisArg = this.compileExpression(
|
||||||
<Expression>resolved.targetExpression,
|
<Expression>resolved.targetExpression,
|
||||||
@ -4174,7 +4143,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var originalParameterDeclarations = original.prototype.declaration.signature.parameterTypes;
|
var originalParameterDeclarations = original.prototype.declaration.signature.parameterTypes;
|
||||||
var commonReturnType = originalSignature.returnType;
|
var commonReturnType = originalSignature.returnType;
|
||||||
var commonThisType = originalSignature.thisType;
|
var commonThisType = originalSignature.thisType;
|
||||||
var isInstance = original.is(ElementFlags.INSTANCE);
|
var isInstance = original.is(CommonFlags.INSTANCE);
|
||||||
|
|
||||||
// arguments excl. `this`, operands incl. `this`
|
// arguments excl. `this`, operands incl. `this`
|
||||||
var minArguments = originalSignature.requiredParameters;
|
var minArguments = originalSignature.requiredParameters;
|
||||||
@ -4216,7 +4185,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var trampolineName = originalName + "|trampoline";
|
var trampolineName = originalName + "|trampoline";
|
||||||
trampolineSignature.requiredParameters = maxArguments + 1;
|
trampolineSignature.requiredParameters = maxArguments + 1;
|
||||||
trampoline = new Function(original.prototype, trampolineName, trampolineSignature, original.instanceMethodOf);
|
trampoline = new Function(original.prototype, trampolineName, trampolineSignature, original.instanceMethodOf);
|
||||||
trampoline.flags = original.flags | ElementFlags.COMPILED;
|
trampoline.flags = original.flags;
|
||||||
|
trampoline.set(CommonFlags.COMPILED);
|
||||||
original.trampoline = trampoline;
|
original.trampoline = trampoline;
|
||||||
|
|
||||||
// compile initializers of omitted arguments in scope of the trampoline function
|
// compile initializers of omitted arguments in scope of the trampoline function
|
||||||
@ -4278,7 +4248,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var minOperands = minArguments;
|
var minOperands = minArguments;
|
||||||
var maxArguments = instance.signature.parameterTypes.length;
|
var maxArguments = instance.signature.parameterTypes.length;
|
||||||
var maxOperands = maxArguments;
|
var maxOperands = maxArguments;
|
||||||
if (instance.is(ElementFlags.INSTANCE)) {
|
if (instance.is(CommonFlags.INSTANCE)) {
|
||||||
++minOperands;
|
++minOperands;
|
||||||
++maxOperands;
|
++maxOperands;
|
||||||
--numArguments;
|
--numArguments;
|
||||||
@ -4300,7 +4270,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
var returnType = instance.signature.returnType;
|
var returnType = instance.signature.returnType;
|
||||||
this.currentType = returnType;
|
this.currentType = returnType;
|
||||||
if (instance.is(ElementFlags.IMPORTED)) {
|
if (instance.is(CommonFlags.MODULE_IMPORT)) {
|
||||||
return module.createCallImport(instance.internalName, operands, returnType.toNativeType());
|
return module.createCallImport(instance.internalName, operands, returnType.toNativeType());
|
||||||
} else {
|
} else {
|
||||||
return module.createCall(instance.internalName, operands, returnType.toNativeType());
|
return module.createCall(instance.internalName, operands, returnType.toNativeType());
|
||||||
@ -4445,7 +4415,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case NodeKind.THIS: {
|
case NodeKind.THIS: {
|
||||||
let currentFunction = this.currentFunction;
|
let currentFunction = this.currentFunction;
|
||||||
if (currentFunction.is(ElementFlags.INSTANCE)) {
|
if (currentFunction.is(CommonFlags.INSTANCE)) {
|
||||||
let thisType = assert(currentFunction.instanceMethodOf).type;
|
let thisType = assert(currentFunction.instanceMethodOf).type;
|
||||||
this.currentType = thisType;
|
this.currentType = thisType;
|
||||||
return module.createGetLocal(0, thisType.toNativeType());
|
return module.createGetLocal(0, thisType.toNativeType());
|
||||||
@ -4459,7 +4429,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
case NodeKind.SUPER: {
|
case NodeKind.SUPER: {
|
||||||
let currentFunction = this.currentFunction;
|
let currentFunction = this.currentFunction;
|
||||||
if (currentFunction.is(ElementFlags.INSTANCE)) {
|
if (currentFunction.is(CommonFlags.INSTANCE)) {
|
||||||
let base = assert(currentFunction.instanceMethodOf).base;
|
let base = assert(currentFunction.instanceMethodOf).base;
|
||||||
if (base) {
|
if (base) {
|
||||||
let superType = base.type;
|
let superType = base.type;
|
||||||
@ -4487,7 +4457,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var element = resolved.element;
|
var element = resolved.element;
|
||||||
switch (element.kind) {
|
switch (element.kind) {
|
||||||
case ElementKind.LOCAL: {
|
case ElementKind.LOCAL: {
|
||||||
if ((<Local>element).is(ElementFlags.INLINED)) {
|
if ((<Local>element).is(CommonFlags.INLINED)) {
|
||||||
return this.compileInlineConstant(<Local>element, contextualType, retainConstantType);
|
return this.compileInlineConstant(<Local>element, contextualType, retainConstantType);
|
||||||
}
|
}
|
||||||
let localType = (<Local>element).type;
|
let localType = (<Local>element).type;
|
||||||
@ -4497,7 +4467,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createGetLocal(localIndex, localType.toNativeType());
|
return this.module.createGetLocal(localIndex, localType.toNativeType());
|
||||||
}
|
}
|
||||||
case ElementKind.GLOBAL: {
|
case ElementKind.GLOBAL: {
|
||||||
if (element.is(ElementFlags.BUILTIN)) {
|
if (element.is(CommonFlags.BUILTIN)) {
|
||||||
return compileBuiltinGetConstant(this, <Global>element, expression);
|
return compileBuiltinGetConstant(this, <Global>element, expression);
|
||||||
}
|
}
|
||||||
if (!this.compileGlobal(<Global>element)) { // reports; not yet compiled if a static field
|
if (!this.compileGlobal(<Global>element)) { // reports; not yet compiled if a static field
|
||||||
@ -4505,14 +4475,14 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
let globalType = (<Global>element).type;
|
let globalType = (<Global>element).type;
|
||||||
assert(globalType != Type.void);
|
assert(globalType != Type.void);
|
||||||
if ((<Global>element).is(ElementFlags.INLINED)) {
|
if ((<Global>element).is(CommonFlags.INLINED)) {
|
||||||
return this.compileInlineConstant(<Global>element, contextualType, retainConstantType);
|
return this.compileInlineConstant(<Global>element, contextualType, retainConstantType);
|
||||||
}
|
}
|
||||||
this.currentType = globalType;
|
this.currentType = globalType;
|
||||||
return this.module.createGetGlobal((<Global>element).internalName, globalType.toNativeType());
|
return this.module.createGetGlobal((<Global>element).internalName, globalType.toNativeType());
|
||||||
}
|
}
|
||||||
case ElementKind.ENUMVALUE: { // here: if referenced from within the same enum
|
case ElementKind.ENUMVALUE: { // here: if referenced from within the same enum
|
||||||
if (!element.is(ElementFlags.COMPILED)) {
|
if (!element.is(CommonFlags.COMPILED)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums,
|
DiagnosticCode.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums,
|
||||||
expression.range
|
expression.range
|
||||||
@ -4521,7 +4491,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
this.currentType = Type.i32;
|
this.currentType = Type.i32;
|
||||||
if ((<EnumValue>element).is(ElementFlags.INLINED)) {
|
if ((<EnumValue>element).is(CommonFlags.INLINED)) {
|
||||||
return this.module.createI32((<EnumValue>element).constantValue);
|
return this.module.createI32((<EnumValue>element).constantValue);
|
||||||
}
|
}
|
||||||
return this.module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
return this.module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
||||||
@ -4547,7 +4517,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let classType = contextualType.classType;
|
let classType = contextualType.classType;
|
||||||
if (
|
if (
|
||||||
classType &&
|
classType &&
|
||||||
classType == this.program.elements.get("Array") &&
|
classType == this.program.elementsLookup.get("Array") &&
|
||||||
classType.typeArguments && classType.typeArguments.length == 1
|
classType.typeArguments && classType.typeArguments.length == 1
|
||||||
) {
|
) {
|
||||||
return this.compileStaticArray(
|
return this.compileStaticArray(
|
||||||
@ -4698,7 +4668,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
stringSegments.set(stringValue, stringSegment);
|
stringSegments.set(stringValue, stringSegment);
|
||||||
}
|
}
|
||||||
var stringOffset = stringSegment.offset;
|
var stringOffset = stringSegment.offset;
|
||||||
var stringType = this.program.types.get("string");
|
var stringType = this.program.typesLookup.get("string");
|
||||||
this.currentType = stringType ? stringType : options.usizeType;
|
this.currentType = stringType ? stringType : options.usizeType;
|
||||||
if (options.isWasm64) {
|
if (options.isWasm64) {
|
||||||
return module.createI64(i64_low(stringOffset), i64_high(stringOffset));
|
return module.createI64(i64_low(stringOffset), i64_high(stringOffset));
|
||||||
@ -4825,7 +4795,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (member.kind == ElementKind.FIELD) {
|
if (member.kind == ElementKind.FIELD) {
|
||||||
let field = <Field>member;
|
let field = <Field>member;
|
||||||
let fieldDeclaration = field.prototype.declaration;
|
let fieldDeclaration = field.prototype.declaration;
|
||||||
if (field.is(ElementFlags.CONSTANT)) {
|
if (field.is(CommonFlags.CONST)) {
|
||||||
assert(false); // there are no built-in fields currently
|
assert(false); // there are no built-in fields currently
|
||||||
} else if (fieldDeclaration && fieldDeclaration.initializer) {
|
} else if (fieldDeclaration && fieldDeclaration.initializer) {
|
||||||
initializers.push(module.createStore(field.type.byteSize,
|
initializers.push(module.createStore(field.type.byteSize,
|
||||||
@ -4899,7 +4869,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var targetExpr: ExpressionRef;
|
var targetExpr: ExpressionRef;
|
||||||
switch (element.kind) {
|
switch (element.kind) {
|
||||||
case ElementKind.GLOBAL: { // static property
|
case ElementKind.GLOBAL: { // static property
|
||||||
if (element.is(ElementFlags.BUILTIN)) {
|
if (element.is(CommonFlags.BUILTIN)) {
|
||||||
return compileBuiltinGetConstant(this, <Global>element, propertyAccess);
|
return compileBuiltinGetConstant(this, <Global>element, propertyAccess);
|
||||||
}
|
}
|
||||||
if (!this.compileGlobal(<Global>element)) { // reports; not yet compiled if a static field
|
if (!this.compileGlobal(<Global>element)) { // reports; not yet compiled if a static field
|
||||||
@ -4907,7 +4877,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
let globalType = (<Global>element).type;
|
let globalType = (<Global>element).type;
|
||||||
assert(globalType != Type.void);
|
assert(globalType != Type.void);
|
||||||
if ((<Global>element).is(ElementFlags.INLINED)) {
|
if ((<Global>element).is(CommonFlags.INLINED)) {
|
||||||
return this.compileInlineConstant(<Global>element, contextualType, retainConstantType);
|
return this.compileInlineConstant(<Global>element, contextualType, retainConstantType);
|
||||||
}
|
}
|
||||||
this.currentType = globalType;
|
this.currentType = globalType;
|
||||||
@ -4918,7 +4888,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
this.currentType = Type.i32;
|
this.currentType = Type.i32;
|
||||||
if ((<EnumValue>element).is(ElementFlags.INLINED)) {
|
if ((<EnumValue>element).is(CommonFlags.INLINED)) {
|
||||||
return module.createI32((<EnumValue>element).constantValue);
|
return module.createI32((<EnumValue>element).constantValue);
|
||||||
}
|
}
|
||||||
return module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
return module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
||||||
@ -4949,7 +4919,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (!this.checkCallSignature( // reports
|
if (!this.checkCallSignature( // reports
|
||||||
signature,
|
signature,
|
||||||
0,
|
0,
|
||||||
instance.is(ElementFlags.INSTANCE),
|
instance.is(CommonFlags.INSTANCE),
|
||||||
propertyAccess
|
propertyAccess
|
||||||
)) {
|
)) {
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
|
478
src/definitions.ts
Normal file
478
src/definitions.ts
Normal file
@ -0,0 +1,478 @@
|
|||||||
|
/**
|
||||||
|
* @file Definition builders for WebIDL and TypeScript.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Program,
|
||||||
|
Element,
|
||||||
|
CommonFlags,
|
||||||
|
ElementKind,
|
||||||
|
Global,
|
||||||
|
Enum,
|
||||||
|
EnumValue,
|
||||||
|
Function,
|
||||||
|
Class,
|
||||||
|
Namespace,
|
||||||
|
FunctionPrototype,
|
||||||
|
ClassPrototype,
|
||||||
|
ConstantValueKind,
|
||||||
|
Interface
|
||||||
|
} from "./program";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
TypeKind
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
|
import {
|
||||||
|
indent
|
||||||
|
} from "./util/text";
|
||||||
|
|
||||||
|
/** Walker base class. */
|
||||||
|
abstract class ExportsWalker {
|
||||||
|
|
||||||
|
/** Program reference. */
|
||||||
|
program: Program;
|
||||||
|
|
||||||
|
/** Constructs a new Element walker. */
|
||||||
|
constructor(program: Program) {
|
||||||
|
this.program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
walk(): void {
|
||||||
|
for (let element of this.program.moduleLevelExports.values()) {
|
||||||
|
this.visitElement(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visitElement(element: Element): void {
|
||||||
|
switch (element.kind) {
|
||||||
|
case ElementKind.GLOBAL: {
|
||||||
|
if (element.is(CommonFlags.COMPILED)) {
|
||||||
|
this.visitGlobal(<Global>element);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ElementKind.ENUM: {
|
||||||
|
if (element.is(CommonFlags.COMPILED)) {
|
||||||
|
this.visitEnum(<Enum>element);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||||
|
for (let instance of (<FunctionPrototype>element).instances.values()) {
|
||||||
|
if (instance.is(CommonFlags.COMPILED)) {
|
||||||
|
this.visitFunction(<Function>instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ElementKind.CLASS_PROTOTYPE: {
|
||||||
|
for (let instance of (<ClassPrototype>element).instances.values()) {
|
||||||
|
if (instance.is(CommonFlags.COMPILED)) {
|
||||||
|
this.visitClass(<Class>instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ElementKind.NAMESPACE: {
|
||||||
|
if ((<Namespace>element).is(CommonFlags.COMPILED)) {
|
||||||
|
this.visitNamespace(<Namespace>element);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract visitGlobal(element: Global): void;
|
||||||
|
abstract visitEnum(element: Enum): void;
|
||||||
|
abstract visitFunction(element: Function): void;
|
||||||
|
abstract visitClass(element: Class): void;
|
||||||
|
abstract visitInterface(element: Interface): void;
|
||||||
|
abstract visitNamespace(element: Element): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A WebIDL definitions builder. */
|
||||||
|
export class IDLBuilder extends ExportsWalker {
|
||||||
|
|
||||||
|
/** Builds WebIDL definitions for the specified program. */
|
||||||
|
static build(program: Program): string {
|
||||||
|
return new IDLBuilder(program).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private sb: string[] = [];
|
||||||
|
private seen: Set<Element> = new Set();
|
||||||
|
private indentLevel: i32 = 0;
|
||||||
|
|
||||||
|
/** Constructs a new WebIDL builder. */
|
||||||
|
constructor(program: Program) {
|
||||||
|
super(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitGlobal(element: Global): void {
|
||||||
|
if (this.seen.has(element)) return;
|
||||||
|
this.seen.add(element);
|
||||||
|
var sb = this.sb;
|
||||||
|
var isConst = element.is(CommonFlags.INLINED);
|
||||||
|
indent(sb, this.indentLevel);
|
||||||
|
if (isConst) {
|
||||||
|
sb.push("const ");
|
||||||
|
}
|
||||||
|
sb.push(this.typeToString(element.type));
|
||||||
|
sb.push(" ");
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
if (isConst) {
|
||||||
|
switch (element.constantValueKind) {
|
||||||
|
case ConstantValueKind.INTEGER: {
|
||||||
|
sb.push(" = ");
|
||||||
|
sb.push(i64_to_string(element.constantIntegerValue));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConstantValueKind.FLOAT: {
|
||||||
|
sb.push(" = ");
|
||||||
|
sb.push(element.constantFloatValue.toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.push(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
visitEnum(element: Enum): void {
|
||||||
|
if (this.seen.has(element)) return;
|
||||||
|
this.seen.add(element);
|
||||||
|
var sb = this.sb;
|
||||||
|
indent(sb, this.indentLevel++);
|
||||||
|
sb.push("interface ");
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
sb.push(" {\n");
|
||||||
|
var members = element.members;
|
||||||
|
if (members) {
|
||||||
|
for (let [name, member] of members) {
|
||||||
|
if (member.kind == ElementKind.ENUMVALUE) {
|
||||||
|
let isConst = (<EnumValue>member).is(CommonFlags.INLINED);
|
||||||
|
indent(sb, this.indentLevel);
|
||||||
|
if (isConst) {
|
||||||
|
sb.push("const ");
|
||||||
|
} else {
|
||||||
|
sb.push("readonly ");
|
||||||
|
}
|
||||||
|
sb.push("unsigned long ");
|
||||||
|
sb.push(name);
|
||||||
|
if (isConst) {
|
||||||
|
sb.push(" = ");
|
||||||
|
sb.push((<EnumValue>member).constantValue.toString(10));
|
||||||
|
}
|
||||||
|
sb.push(";\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let member of members.values()) {
|
||||||
|
if (member.kind != ElementKind.ENUMVALUE) {
|
||||||
|
this.visitElement(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indent(sb, --this.indentLevel);
|
||||||
|
sb.push("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
visitFunction(element: Function): void {
|
||||||
|
if (this.seen.has(element)) return;
|
||||||
|
this.seen.add(element);
|
||||||
|
var sb = this.sb;
|
||||||
|
var signature = element.signature;
|
||||||
|
indent(sb, this.indentLevel);
|
||||||
|
sb.push(this.typeToString(signature.returnType));
|
||||||
|
sb.push(" ");
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
sb.push("(");
|
||||||
|
var parameters = signature.parameterTypes;
|
||||||
|
var numParameters = parameters.length;
|
||||||
|
// var requiredParameters = signature.requiredParameters;
|
||||||
|
for (let i = 0; i < numParameters; ++i) {
|
||||||
|
if (i) sb.push(", ");
|
||||||
|
// if (i >= requiredParameters) sb.push("optional ");
|
||||||
|
sb.push(this.typeToString(parameters[i]));
|
||||||
|
sb.push(" ");
|
||||||
|
sb.push(signature.getParameterName(i));
|
||||||
|
}
|
||||||
|
sb.push(");\n");
|
||||||
|
var members = element.members;
|
||||||
|
if (members && members.size) {
|
||||||
|
indent(sb, this.indentLevel);
|
||||||
|
sb.push("interface ");
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
sb.push(" {\n");
|
||||||
|
for (let member of members.values()) {
|
||||||
|
this.visitElement(member);
|
||||||
|
}
|
||||||
|
indent(sb, --this.indentLevel);
|
||||||
|
sb.push("}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visitClass(element: Class): void {
|
||||||
|
if (this.seen.has(element)) return;
|
||||||
|
this.seen.add(element);
|
||||||
|
var sb = this.sb;
|
||||||
|
indent(sb, this.indentLevel++);
|
||||||
|
sb.push("interface ");
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
sb.push(" {\n");
|
||||||
|
// TODO
|
||||||
|
indent(sb, --this.indentLevel);
|
||||||
|
sb.push("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
visitInterface(element: Interface): void {
|
||||||
|
this.visitClass(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitNamespace(element: Namespace): void {
|
||||||
|
if (this.seen.has(element)) return;
|
||||||
|
this.seen.add(element);
|
||||||
|
var sb = this.sb;
|
||||||
|
indent(sb, this.indentLevel++);
|
||||||
|
sb.push("interface ");
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
sb.push(" {\n");
|
||||||
|
var members = element.members;
|
||||||
|
if (members) {
|
||||||
|
for (let member of members.values()) {
|
||||||
|
this.visitElement(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indent(sb, --this.indentLevel);
|
||||||
|
sb.push("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
typeToString(type: Type): string {
|
||||||
|
switch (type.kind) {
|
||||||
|
case TypeKind.I8: return "byte";
|
||||||
|
case TypeKind.I16: return "short";
|
||||||
|
case TypeKind.I32: return "long";
|
||||||
|
case TypeKind.I64: return "long long";
|
||||||
|
case TypeKind.ISIZE: return this.program.options.isWasm64 ? "long long" : "long";
|
||||||
|
case TypeKind.U8: return "octet";
|
||||||
|
case TypeKind.U16: return "unsigned short";
|
||||||
|
case TypeKind.U32: return "unsigned long";
|
||||||
|
// ^ TODO: function types
|
||||||
|
case TypeKind.U64: return "unsigned long long";
|
||||||
|
case TypeKind.USIZE: return this.program.options.isWasm64 ? "unsigned long long" : "unsigned long";
|
||||||
|
// ^ TODO: class types
|
||||||
|
case TypeKind.BOOL: return "boolean";
|
||||||
|
case TypeKind.F32: return "unrestricted float";
|
||||||
|
case TypeKind.F64: return "unrestricted double";
|
||||||
|
case TypeKind.VOID: return "void";
|
||||||
|
default: {
|
||||||
|
assert(false);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build(): string {
|
||||||
|
var sb = this.sb;
|
||||||
|
sb.push("interface ASModule {\n");
|
||||||
|
++this.indentLevel;
|
||||||
|
this.walk();
|
||||||
|
--this.indentLevel;
|
||||||
|
sb.push("}\n");
|
||||||
|
return sb.join("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A TypeScript definitions builder. */
|
||||||
|
export class TSDBuilder extends ExportsWalker {
|
||||||
|
|
||||||
|
/** Builds TypeScript definitions for the specified program. */
|
||||||
|
static build(program: Program): string {
|
||||||
|
return new TSDBuilder(program).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private sb: string[] = [];
|
||||||
|
private seen: Set<Element> = new Set();
|
||||||
|
private indentLevel: i32 = 0;
|
||||||
|
|
||||||
|
/** Constructs a new WebIDL builder. */
|
||||||
|
constructor(program: Program) {
|
||||||
|
super(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitGlobal(element: Global): void {
|
||||||
|
if (this.seen.has(element)) return;
|
||||||
|
this.seen.add(element);
|
||||||
|
var sb = this.sb;
|
||||||
|
var isConst = element.is(CommonFlags.INLINED);
|
||||||
|
indent(sb, this.indentLevel);
|
||||||
|
if (isConst) {
|
||||||
|
sb.push("const ");
|
||||||
|
}
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
sb.push(": ");
|
||||||
|
sb.push(this.typeToString(element.type));
|
||||||
|
sb.push(";\n");
|
||||||
|
this.visitNamespace(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitEnum(element: Enum): void {
|
||||||
|
if (this.seen.has(element)) return;
|
||||||
|
this.seen.add(element);
|
||||||
|
var sb = this.sb;
|
||||||
|
indent(sb, this.indentLevel++);
|
||||||
|
sb.push("enum ");
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
sb.push(" {\n");
|
||||||
|
var members = element.members;
|
||||||
|
if (members) {
|
||||||
|
let numMembers = members.size;
|
||||||
|
for (let [name, member] of members) {
|
||||||
|
if (member.kind == ElementKind.ENUMVALUE) {
|
||||||
|
this.seen.add(member);
|
||||||
|
indent(sb, this.indentLevel);
|
||||||
|
sb.push(name);
|
||||||
|
if (member.is(CommonFlags.INLINED)) {
|
||||||
|
sb.push(" = ");
|
||||||
|
sb.push((<EnumValue>member).constantValue.toString(10));
|
||||||
|
}
|
||||||
|
sb.push(",\n");
|
||||||
|
--numMembers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numMembers) {
|
||||||
|
this.visitNamespace(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indent(sb, --this.indentLevel);
|
||||||
|
sb.push("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
visitFunction(element: Function): void {
|
||||||
|
if (this.seen.has(element)) return;
|
||||||
|
this.seen.add(element);
|
||||||
|
var sb = this.sb;
|
||||||
|
var signature = element.signature;
|
||||||
|
indent(sb, this.indentLevel);
|
||||||
|
sb.push("function ");
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
sb.push("(");
|
||||||
|
var parameters = signature.parameterTypes;
|
||||||
|
var numParameters = parameters.length;
|
||||||
|
// var requiredParameters = signature.requiredParameters;
|
||||||
|
for (let i = 0; i < numParameters; ++i) {
|
||||||
|
if (i) sb.push(", ");
|
||||||
|
// if (i >= requiredParameters) sb.push("optional ");
|
||||||
|
sb.push(signature.getParameterName(i));
|
||||||
|
sb.push(": ");
|
||||||
|
sb.push(this.typeToString(parameters[i]));
|
||||||
|
}
|
||||||
|
sb.push("): ");
|
||||||
|
sb.push(this.typeToString(signature.returnType));
|
||||||
|
sb.push(";\n");
|
||||||
|
this.visitNamespace(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitClass(element: Class): void {
|
||||||
|
if (this.seen.has(element)) return;
|
||||||
|
this.seen.add(element);
|
||||||
|
var sb = this.sb;
|
||||||
|
var isInterface = element.kind == ElementKind.INTERFACE;
|
||||||
|
indent(sb, this.indentLevel++);
|
||||||
|
if (isInterface) {
|
||||||
|
sb.push("interface ");
|
||||||
|
} else {
|
||||||
|
if (element.is(CommonFlags.ABSTRACT)) {
|
||||||
|
sb.push("abstract ");
|
||||||
|
}
|
||||||
|
sb.push("class ");
|
||||||
|
}
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
var base = element.base;
|
||||||
|
if (base) {
|
||||||
|
sb.push(" extends ");
|
||||||
|
sb.push(base.simpleName); // TODO: fqn
|
||||||
|
}
|
||||||
|
sb.push(" {\n");
|
||||||
|
var members = element.prototype.members; // static
|
||||||
|
if (members) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
members = element.members; // instance
|
||||||
|
if (members) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
indent(sb, --this.indentLevel);
|
||||||
|
sb.push("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
visitInterface(element: Interface): void {
|
||||||
|
this.visitClass(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitNamespace(element: Element): void {
|
||||||
|
var members = element.members;
|
||||||
|
if (members && members.size) {
|
||||||
|
let sb = this.sb;
|
||||||
|
indent(sb, this.indentLevel++);
|
||||||
|
sb.push("namespace ");
|
||||||
|
sb.push(element.simpleName);
|
||||||
|
sb.push(" {\n");
|
||||||
|
for (let member of members.values()) {
|
||||||
|
this.visitElement(member);
|
||||||
|
}
|
||||||
|
indent(sb, --this.indentLevel);
|
||||||
|
sb.push("}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeToString(type: Type): string {
|
||||||
|
switch (type.kind) {
|
||||||
|
case TypeKind.I8: return "i8";
|
||||||
|
case TypeKind.I16: return "i16";
|
||||||
|
case TypeKind.I32: return "i32";
|
||||||
|
case TypeKind.I64: return "I64";
|
||||||
|
case TypeKind.ISIZE: return this.program.options.isWasm64 ? "I64" : "i32";
|
||||||
|
case TypeKind.U8: return "u8";
|
||||||
|
case TypeKind.U16: return "u16";
|
||||||
|
case TypeKind.U32: return "u32";
|
||||||
|
// ^ TODO: function types
|
||||||
|
case TypeKind.U64: return "U64";
|
||||||
|
case TypeKind.USIZE: return this.program.options.isWasm64 ? "U64" : "u32";
|
||||||
|
// ^ TODO: class types
|
||||||
|
case TypeKind.BOOL: return "bool";
|
||||||
|
case TypeKind.F32: return "f32";
|
||||||
|
case TypeKind.F64: return "f64";
|
||||||
|
case TypeKind.VOID: return "void";
|
||||||
|
default: {
|
||||||
|
assert(false);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build(): string {
|
||||||
|
var sb = this.sb;
|
||||||
|
sb.push("declare module ASModule {\n");
|
||||||
|
sb.push(" type i8 = number;\n");
|
||||||
|
sb.push(" type i16 = number;\n");
|
||||||
|
sb.push(" type i32 = number;\n");
|
||||||
|
sb.push(" type u8 = number;\n");
|
||||||
|
sb.push(" type u16 = number;\n");
|
||||||
|
sb.push(" type u32 = number;\n");
|
||||||
|
sb.push(" type f32 = number;\n");
|
||||||
|
sb.push(" type f64 = number;\n");
|
||||||
|
sb.push(" type bool = any;\n");
|
||||||
|
++this.indentLevel;
|
||||||
|
this.walk();
|
||||||
|
--this.indentLevel;
|
||||||
|
sb.push("}\n");
|
||||||
|
return this.sb.join("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: C bindings? or is this sufficiently covered by WebIDL and using a 3rd-party tool?
|
@ -51,6 +51,7 @@ export enum DiagnosticCode {
|
|||||||
Unexpected_end_of_text = 1126,
|
Unexpected_end_of_text = 1126,
|
||||||
Invalid_character = 1127,
|
Invalid_character = 1127,
|
||||||
_case_or_default_expected = 1130,
|
_case_or_default_expected = 1130,
|
||||||
|
A_declare_modifier_cannot_be_used_in_an_already_ambient_context = 1038,
|
||||||
Type_argument_expected = 1140,
|
Type_argument_expected = 1140,
|
||||||
String_literal_expected = 1141,
|
String_literal_expected = 1141,
|
||||||
Line_break_not_permitted_here = 1142,
|
Line_break_not_permitted_here = 1142,
|
||||||
@ -150,6 +151,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
|||||||
case 1126: return "Unexpected end of text.";
|
case 1126: return "Unexpected end of text.";
|
||||||
case 1127: return "Invalid character.";
|
case 1127: return "Invalid character.";
|
||||||
case 1130: return "'case' or 'default' expected.";
|
case 1130: return "'case' or 'default' expected.";
|
||||||
|
case 1038: return "A 'declare' modifier cannot be used in an already ambient context.";
|
||||||
case 1140: return "Type argument expected.";
|
case 1140: return "Type argument expected.";
|
||||||
case 1141: return "String literal expected.";
|
case 1141: return "String literal expected.";
|
||||||
case 1142: return "Line break not permitted here.";
|
case 1142: return "Line break not permitted here.";
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
"Unexpected end of text.": 1126,
|
"Unexpected end of text.": 1126,
|
||||||
"Invalid character.": 1127,
|
"Invalid character.": 1127,
|
||||||
"'case' or 'default' expected.": 1130,
|
"'case' or 'default' expected.": 1130,
|
||||||
|
"A 'declare' modifier cannot be used in an already ambient context.": 1038,
|
||||||
"Type argument expected.": 1140,
|
"Type argument expected.": 1140,
|
||||||
"String literal expected.": 1141,
|
"String literal expected.": 1141,
|
||||||
"Line break not permitted here.": 1142,
|
"Line break not permitted here.": 1142,
|
||||||
|
@ -111,10 +111,10 @@ export class DiagnosticMessage {
|
|||||||
this.message +
|
this.message +
|
||||||
"\" in " +
|
"\" in " +
|
||||||
this.range.source.normalizedPath +
|
this.range.source.normalizedPath +
|
||||||
" @ " +
|
":" +
|
||||||
this.range.start.toString(10) +
|
this.range.line.toString(10) +
|
||||||
"," +
|
":" +
|
||||||
this.range.end.toString(10)
|
this.range.column.toString(10)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
1140
src/extra/ast.ts
1140
src/extra/ast.ts
File diff suppressed because it is too large
Load Diff
35
src/index.ts
35
src/index.ts
@ -10,6 +10,11 @@ import {
|
|||||||
Decompiler
|
Decompiler
|
||||||
} from "./decompiler";
|
} from "./decompiler";
|
||||||
|
|
||||||
|
import {
|
||||||
|
IDLBuilder,
|
||||||
|
TSDBuilder
|
||||||
|
} from "./definitions";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DiagnosticMessage,
|
DiagnosticMessage,
|
||||||
DiagnosticCategory,
|
DiagnosticCategory,
|
||||||
@ -24,6 +29,11 @@ import {
|
|||||||
Parser
|
Parser
|
||||||
} from "./parser";
|
} from "./parser";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Program,
|
||||||
|
LIBRARY_PREFIX
|
||||||
|
} from "./program";
|
||||||
|
|
||||||
/** Parses a source file. If `parser` has been omitted a new one is created. */
|
/** Parses a source file. If `parser` has been omitted a new one is created. */
|
||||||
export function parseFile(text: string, path: string, isEntry: bool = false,
|
export function parseFile(text: string, path: string, isEntry: bool = false,
|
||||||
parser: Parser | null = null
|
parser: Parser | null = null
|
||||||
@ -107,19 +117,32 @@ export function setMemoryBase(options: Options, memoryBase: u32): void {
|
|||||||
options.memoryBase = memoryBase;
|
options.memoryBase = memoryBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Finishes parsing. */
|
||||||
|
export function finishParsing(parser: Parser): Program {
|
||||||
|
return parser.finish();
|
||||||
|
}
|
||||||
|
|
||||||
/** Compiles the sources computed by the parser to a module. */
|
/** Compiles the sources computed by the parser to a module. */
|
||||||
export function compile(parser: Parser, options: Options | null = null): Module {
|
export function compileProgram(program: Program, options: Options | null = null): Module {
|
||||||
var program = parser.finish();
|
return new Compiler(program, options).compile();
|
||||||
var compiler = new Compiler(program, options);
|
|
||||||
return compiler.compile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Decompiles a module to its (low level) source. */
|
/** Decompiles a module to its (low level) source. */
|
||||||
export function decompile(module: Module): string {
|
export function decompileModule(module: Module): string {
|
||||||
var decompiler = new Decompiler();
|
var decompiler = new Decompiler();
|
||||||
decompiler.decompile(module);
|
decompiler.decompile(module);
|
||||||
return decompiler.finish();
|
return decompiler.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Builds WebIDL definitions for the specified program. */
|
||||||
|
export function buildIDL(program: Program): string {
|
||||||
|
return IDLBuilder.build(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Builds TypeScript definitions for the specified program. */
|
||||||
|
export function buildTSD(program: Program): string {
|
||||||
|
return TSDBuilder.build(program);
|
||||||
|
}
|
||||||
|
|
||||||
/** Prefix indicating a library file. */
|
/** Prefix indicating a library file. */
|
||||||
export { LIBRARY_PREFIX } from "./program";
|
export { LIBRARY_PREFIX };
|
||||||
|
457
src/parser.ts
457
src/parser.ts
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Program,
|
Program,
|
||||||
|
CommonFlags,
|
||||||
LIBRARY_PREFIX,
|
LIBRARY_PREFIX,
|
||||||
PATH_DELIMITER
|
PATH_DELIMITER
|
||||||
} from "./program";
|
} from "./program";
|
||||||
@ -63,8 +64,6 @@ import {
|
|||||||
IfStatement,
|
IfStatement,
|
||||||
ImportDeclaration,
|
ImportDeclaration,
|
||||||
ImportStatement,
|
ImportStatement,
|
||||||
ModifierNode,
|
|
||||||
ModifierKind,
|
|
||||||
NamespaceDeclaration,
|
NamespaceDeclaration,
|
||||||
ParameterNode,
|
ParameterNode,
|
||||||
ParameterKind,
|
ParameterKind,
|
||||||
@ -78,13 +77,7 @@ import {
|
|||||||
VariableStatement,
|
VariableStatement,
|
||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
VoidStatement,
|
VoidStatement,
|
||||||
WhileStatement,
|
WhileStatement
|
||||||
|
|
||||||
addModifier,
|
|
||||||
getModifier,
|
|
||||||
hasModifier,
|
|
||||||
setReusableModifiers
|
|
||||||
|
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
|
|
||||||
/** Parser interface. */
|
/** Parser interface. */
|
||||||
@ -97,6 +90,9 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
/** Log of source file names already processed. */
|
/** Log of source file names already processed. */
|
||||||
seenlog: Set<string> = new Set();
|
seenlog: Set<string> = new Set();
|
||||||
|
|
||||||
|
currentDeclareStart: i32 = 0;
|
||||||
|
currentDeclareEnd: i32 = 0;
|
||||||
|
|
||||||
/** Constructs a new parser. */
|
/** Constructs a new parser. */
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -149,74 +145,95 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
isNamespaceMember: bool = false
|
isNamespaceMember: bool = false
|
||||||
): Statement | null {
|
): Statement | null {
|
||||||
|
var flags = CommonFlags.NONE;
|
||||||
|
var startPos: i32 = -1;
|
||||||
|
|
||||||
// check decorators
|
// check decorators
|
||||||
var decorators: DecoratorNode[] | null = null;
|
var decorators: DecoratorNode[] | null = null;
|
||||||
while (tn.skip(Token.AT)) {
|
while (tn.skip(Token.AT)) {
|
||||||
|
if (startPos < 0) startPos = tn.tokenPos;
|
||||||
let decorator = this.parseDecorator(tn);
|
let decorator = this.parseDecorator(tn);
|
||||||
if (!decorator) break;
|
if (!decorator) break;
|
||||||
|
let name = decorator.name;
|
||||||
|
if (name.kind == NodeKind.IDENTIFIER) {
|
||||||
|
let text = (<IdentifierExpression>name).text;
|
||||||
|
if (text == "global") {
|
||||||
|
flags |= CommonFlags.GLOBAL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (text == "builtin") {
|
||||||
|
flags |= CommonFlags.BUILTIN;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (text == "unmananged") {
|
||||||
|
flags |= CommonFlags.UNMANAGED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!decorators) decorators = [];
|
if (!decorators) decorators = [];
|
||||||
decorators.push(decorator);
|
decorators.push(decorator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check modifiers
|
// check modifiers
|
||||||
var modifiers: ModifierNode[] | null = null;
|
var exportStart: i32 = 0;
|
||||||
|
var exportEnd: i32 = 0;
|
||||||
if (tn.skip(Token.EXPORT)) {
|
if (tn.skip(Token.EXPORT)) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.EXPORT, tn.range()), modifiers);
|
if (startPos < 0) startPos = tn.tokenPos;
|
||||||
|
flags |= CommonFlags.EXPORT;
|
||||||
|
exportStart = tn.tokenPos;
|
||||||
|
exportEnd = tn.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var declareStart: i32 = 0;
|
||||||
|
var declareEnd: i32 = 0;
|
||||||
if (tn.skip(Token.DECLARE)) {
|
if (tn.skip(Token.DECLARE)) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.DECLARE, tn.range()), modifiers);
|
if (startPos < 0) startPos = tn.tokenPos;
|
||||||
tn.peek(true);
|
flags |= CommonFlags.DECLARE;
|
||||||
if (tn.nextTokenOnNewLine) {
|
this.currentDeclareStart = declareStart = tn.tokenPos;
|
||||||
this.error(
|
this.currentDeclareEnd = declareEnd = tn.pos;
|
||||||
DiagnosticCode.Line_break_not_permitted_here,
|
|
||||||
tn.range(tn.pos)
|
|
||||||
); // recoverable, compatibility
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the statement
|
// parse the statement
|
||||||
var statement: Statement | null = null;
|
var statement: Statement | null = null;
|
||||||
var modifier: ModifierNode | null;
|
|
||||||
|
|
||||||
// handle declarations
|
// handle declarations
|
||||||
switch (tn.peek()) {
|
var first = tn.peek();
|
||||||
|
if (startPos < 0) startPos = tn.nextTokenPos;
|
||||||
|
switch (first) {
|
||||||
case Token.CONST: {
|
case Token.CONST: {
|
||||||
tn.next();
|
tn.next();
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.CONST, tn.range()), modifiers);
|
flags |= CommonFlags.CONST;
|
||||||
if (tn.skip(Token.ENUM)) {
|
if (tn.skip(Token.ENUM)) {
|
||||||
statement = this.parseEnum(tn, modifiers, decorators);
|
statement = this.parseEnum(tn, flags, decorators, startPos);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
statement = this.parseVariable(tn, modifiers, decorators);
|
statement = this.parseVariable(tn, flags, decorators, startPos);
|
||||||
decorators = null;
|
decorators = null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.LET: {
|
case Token.LET: flags |= CommonFlags.LET;
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.LET, tn.range()), modifiers);
|
|
||||||
// fall-through
|
|
||||||
}
|
|
||||||
case Token.VAR: {
|
case Token.VAR: {
|
||||||
tn.next();
|
tn.next();
|
||||||
statement = this.parseVariable(tn, modifiers, decorators);
|
statement = this.parseVariable(tn, flags, decorators, startPos);
|
||||||
decorators = null;
|
decorators = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.ENUM: {
|
case Token.ENUM: {
|
||||||
tn.next();
|
tn.next();
|
||||||
statement = this.parseEnum(tn, modifiers, decorators);
|
statement = this.parseEnum(tn, flags, decorators, startPos);
|
||||||
decorators = null;
|
decorators = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.FUNCTION: {
|
case Token.FUNCTION: {
|
||||||
tn.next();
|
tn.next();
|
||||||
statement = this.parseFunction(tn, modifiers, decorators);
|
statement = this.parseFunction(tn, flags, decorators, startPos);
|
||||||
decorators = null;
|
decorators = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.ABSTRACT: {
|
case Token.ABSTRACT: {
|
||||||
tn.next();
|
tn.next();
|
||||||
|
flags |= CommonFlags.ABSTRACT;
|
||||||
if (!tn.skip(Token.CLASS)) {
|
if (!tn.skip(Token.CLASS)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode._0_expected,
|
DiagnosticCode._0_expected,
|
||||||
@ -224,55 +241,55 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
modifiers = addModifier(
|
|
||||||
Node.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers
|
|
||||||
);
|
|
||||||
// fall through
|
// fall through
|
||||||
}
|
}
|
||||||
case Token.CLASS: {
|
case Token.CLASS: {
|
||||||
tn.next();
|
tn.next();
|
||||||
statement = this.parseClass(tn, modifiers, decorators);
|
statement = this.parseClass(tn, flags, decorators, startPos);
|
||||||
decorators = null;
|
decorators = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.NAMESPACE: {
|
case Token.NAMESPACE: {
|
||||||
tn.next();
|
tn.next();
|
||||||
statement = this.parseNamespace(tn, modifiers, decorators);
|
statement = this.parseNamespace(tn, flags, decorators, startPos);
|
||||||
decorators = null;
|
decorators = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.IMPORT: {
|
case Token.IMPORT: {
|
||||||
tn.next();
|
tn.next();
|
||||||
if (modifier = getModifier(ModifierKind.EXPORT, modifiers)) {
|
flags |= CommonFlags.IMPORT;
|
||||||
statement = this.parseExportImport(tn, modifier.range);
|
if (flags & CommonFlags.EXPORT) {
|
||||||
|
statement = this.parseExportImport(tn, startPos);
|
||||||
} else {
|
} else {
|
||||||
statement = this.parseImport(tn);
|
statement = this.parseImport(tn);
|
||||||
}
|
}
|
||||||
if (modifiers) setReusableModifiers(modifiers);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.TYPE: {
|
case Token.TYPE: {
|
||||||
tn.next();
|
tn.next();
|
||||||
statement = this.parseTypeDeclaration(tn, modifiers, decorators);
|
statement = this.parseTypeDeclaration(tn, flags, decorators, startPos);
|
||||||
decorators = null;
|
decorators = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|
||||||
// handle plain exports
|
// handle plain exports
|
||||||
if (hasModifier(ModifierKind.EXPORT, modifiers)) {
|
if (flags & CommonFlags.EXPORT) {
|
||||||
statement = this.parseExport(tn, modifiers); // TODO: why exactly does this have modifiers again? 'declare'?
|
statement = this.parseExport(tn, flags, startPos);
|
||||||
|
|
||||||
// handle non-declaration statements
|
// handle non-declaration statements
|
||||||
} else {
|
} else {
|
||||||
if (modifiers) {
|
if (exportEnd) {
|
||||||
if (modifier = getModifier(ModifierKind.DECLARE, modifiers)) {
|
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode._0_modifier_cannot_be_used_here,
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
modifier.range, "declare"
|
tn.range(exportStart, exportEnd), "export"
|
||||||
); // recoverable
|
); // recoverable
|
||||||
}
|
}
|
||||||
setReusableModifiers(modifiers);
|
if (declareEnd) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
|
tn.range(declareStart, declareEnd), "declare"
|
||||||
|
); // recoverable
|
||||||
}
|
}
|
||||||
if (!isNamespaceMember) {
|
if (!isNamespaceMember) {
|
||||||
statement = this.parseStatement(tn, true);
|
statement = this.parseStatement(tn, true);
|
||||||
@ -688,30 +705,28 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
parseVariable(
|
parseVariable(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
modifiers: ModifierNode[] | null,
|
flags: CommonFlags,
|
||||||
decorators: DecoratorNode[] | null
|
decorators: DecoratorNode[] | null,
|
||||||
|
startPos: i32
|
||||||
): VariableStatement | null {
|
): VariableStatement | null {
|
||||||
|
|
||||||
// at ('const' | 'let' | 'var'): VariableDeclaration (',' VariableDeclaration)* ';'?
|
// at ('const' | 'let' | 'var'): VariableDeclaration (',' VariableDeclaration)* ';'?
|
||||||
|
|
||||||
var startPos = modifiers && modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
|
||||||
var members = new Array<VariableDeclaration>();
|
var members = new Array<VariableDeclaration>();
|
||||||
var isDeclare = hasModifier(ModifierKind.DECLARE, modifiers);
|
|
||||||
do {
|
do {
|
||||||
let member = this.parseVariableDeclaration(tn, isDeclare, modifiers, decorators);
|
let member = this.parseVariableDeclaration(tn, flags, decorators);
|
||||||
if (!member) return null;
|
if (!member) return null;
|
||||||
members.push(<VariableDeclaration>member);
|
members.push(<VariableDeclaration>member);
|
||||||
} while (tn.skip(Token.COMMA));
|
} while (tn.skip(Token.COMMA));
|
||||||
|
|
||||||
var ret = Node.createVariableStatement(members, modifiers, decorators, tn.range(startPos, tn.pos));
|
var ret = Node.createVariableStatement(members, decorators, flags, tn.range(startPos, tn.pos));
|
||||||
tn.skip(Token.SEMICOLON);
|
tn.skip(Token.SEMICOLON);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
parseVariableDeclaration(
|
parseVariableDeclaration(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
isDeclare: bool = false,
|
parentFlags: CommonFlags,
|
||||||
parentModifiers: ModifierNode[] | null,
|
|
||||||
parentDecorators: DecoratorNode[] | null
|
parentDecorators: DecoratorNode[] | null
|
||||||
): VariableDeclaration | null {
|
): VariableDeclaration | null {
|
||||||
|
|
||||||
@ -725,6 +740,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
var identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
||||||
|
var flags = parentFlags;
|
||||||
|
|
||||||
var type: CommonTypeNode | null = null;
|
var type: CommonTypeNode | null = null;
|
||||||
if (tn.skip(Token.COLON)) {
|
if (tn.skip(Token.COLON)) {
|
||||||
@ -733,7 +749,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
var initializer: Expression | null = null;
|
var initializer: Expression | null = null;
|
||||||
if (tn.skip(Token.EQUALS)) {
|
if (tn.skip(Token.EQUALS)) {
|
||||||
if (isDeclare) {
|
if (flags & CommonFlags.AMBIENT) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Initializers_are_not_allowed_in_ambient_contexts,
|
DiagnosticCode.Initializers_are_not_allowed_in_ambient_contexts,
|
||||||
tn.range()
|
tn.range()
|
||||||
@ -742,12 +758,12 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
initializer = this.parseExpression(tn, Precedence.COMMA + 1);
|
initializer = this.parseExpression(tn, Precedence.COMMA + 1);
|
||||||
if (!initializer) return null;
|
if (!initializer) return null;
|
||||||
} else {
|
} else {
|
||||||
if (hasModifier(ModifierKind.CONST, parentModifiers)) {
|
if (flags & CommonFlags.CONST) {
|
||||||
if (!hasModifier(ModifierKind.DECLARE, parentModifiers)) {
|
if (!(flags & CommonFlags.DECLARE)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode._const_declarations_must_be_initialized,
|
DiagnosticCode._const_declarations_must_be_initialized,
|
||||||
identifier.range
|
identifier.range
|
||||||
);
|
); // recoverable
|
||||||
}
|
}
|
||||||
} else if (!type) { // neither type nor initializer
|
} else if (!type) { // neither type nor initializer
|
||||||
this.error(
|
this.error(
|
||||||
@ -760,21 +776,21 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
identifier,
|
identifier,
|
||||||
type,
|
type,
|
||||||
initializer,
|
initializer,
|
||||||
parentModifiers,
|
|
||||||
parentDecorators,
|
parentDecorators,
|
||||||
|
flags,
|
||||||
Range.join(identifier.range, tn.range())
|
Range.join(identifier.range, tn.range())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseEnum(
|
parseEnum(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
modifiers: ModifierNode[] | null,
|
flags: CommonFlags,
|
||||||
decorators: DecoratorNode[] | null
|
decorators: DecoratorNode[] | null,
|
||||||
|
startPos: i32
|
||||||
): EnumDeclaration | null {
|
): EnumDeclaration | null {
|
||||||
|
|
||||||
// at 'enum': Identifier '{' (EnumValueDeclaration (',' EnumValueDeclaration )*)? '}' ';'?
|
// at 'enum': Identifier '{' (EnumValueDeclaration (',' EnumValueDeclaration )*)? '}' ';'?
|
||||||
|
|
||||||
var startPos = modifiers && modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
|
||||||
if (tn.next() != Token.IDENTIFIER) {
|
if (tn.next() != Token.IDENTIFIER) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Identifier_expected,
|
DiagnosticCode.Identifier_expected,
|
||||||
@ -793,7 +809,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
var members = new Array<EnumValueDeclaration>();
|
var members = new Array<EnumValueDeclaration>();
|
||||||
if (!tn.skip(Token.CLOSEBRACE)) {
|
if (!tn.skip(Token.CLOSEBRACE)) {
|
||||||
do {
|
do {
|
||||||
let member = this.parseEnumValue(tn);
|
let member = this.parseEnumValue(tn, CommonFlags.NONE);
|
||||||
if (!member) return null;
|
if (!member) return null;
|
||||||
members.push(<EnumValueDeclaration>member);
|
members.push(<EnumValueDeclaration>member);
|
||||||
} while (tn.skip(Token.COMMA));
|
} while (tn.skip(Token.COMMA));
|
||||||
@ -808,8 +824,8 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
var ret = Node.createEnumDeclaration(
|
var ret = Node.createEnumDeclaration(
|
||||||
identifier,
|
identifier,
|
||||||
members,
|
members,
|
||||||
modifiers,
|
|
||||||
decorators,
|
decorators,
|
||||||
|
flags,
|
||||||
tn.range(startPos, tn.pos)
|
tn.range(startPos, tn.pos)
|
||||||
);
|
);
|
||||||
tn.skip(Token.SEMICOLON);
|
tn.skip(Token.SEMICOLON);
|
||||||
@ -817,7 +833,8 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parseEnumValue(
|
parseEnumValue(
|
||||||
tn: Tokenizer
|
tn: Tokenizer,
|
||||||
|
parentFlags: CommonFlags
|
||||||
): EnumValueDeclaration | null {
|
): EnumValueDeclaration | null {
|
||||||
|
|
||||||
// before: Identifier ('=' Expression)?
|
// before: Identifier ('=' Expression)?
|
||||||
@ -838,6 +855,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
return Node.createEnumValueDeclaration(
|
return Node.createEnumValueDeclaration(
|
||||||
identifier,
|
identifier,
|
||||||
value,
|
value,
|
||||||
|
parentFlags,
|
||||||
Range.join(identifier.range, tn.range())
|
Range.join(identifier.range, tn.range())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1054,8 +1072,9 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
parseFunction(
|
parseFunction(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
modifiers: ModifierNode[] | null,
|
flags: CommonFlags,
|
||||||
decorators: DecoratorNode[] | null
|
decorators: DecoratorNode[] | null,
|
||||||
|
startPos: i32
|
||||||
): FunctionDeclaration | null {
|
): FunctionDeclaration | null {
|
||||||
|
|
||||||
// at 'function':
|
// at 'function':
|
||||||
@ -1065,8 +1084,6 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
// '{' Statement* '}'
|
// '{' Statement* '}'
|
||||||
// ';'?
|
// ';'?
|
||||||
|
|
||||||
var startPos = modifiers && modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
|
||||||
|
|
||||||
if (!tn.skip(Token.IDENTIFIER)) {
|
if (!tn.skip(Token.IDENTIFIER)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Identifier_expected,
|
DiagnosticCode.Identifier_expected,
|
||||||
@ -1083,6 +1100,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
signatureStart = tn.tokenPos;
|
signatureStart = tn.tokenPos;
|
||||||
typeParameters = this.parseTypeParameters(tn);
|
typeParameters = this.parseTypeParameters(tn);
|
||||||
if (!typeParameters) return null;
|
if (!typeParameters) return null;
|
||||||
|
flags |= CommonFlags.GENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tn.skip(Token.OPENPAREN)) {
|
if (!tn.skip(Token.OPENPAREN)) {
|
||||||
@ -1100,16 +1118,14 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
var parameters = this.parseParameters(tn);
|
var parameters = this.parseParameters(tn);
|
||||||
if (!parameters) return null;
|
if (!parameters) return null;
|
||||||
|
|
||||||
var isSetter = hasModifier(ModifierKind.SET, modifiers);
|
var isSetter = (flags & CommonFlags.SET) != 0;
|
||||||
if (isSetter) {
|
if (isSetter) {
|
||||||
|
|
||||||
if (parameters.length != 1) {
|
if (parameters.length != 1) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.A_set_accessor_must_have_exactly_one_parameter,
|
DiagnosticCode.A_set_accessor_must_have_exactly_one_parameter,
|
||||||
name.range
|
name.range
|
||||||
); // recoverable
|
); // recoverable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.length && parameters[0].initializer) {
|
if (parameters.length && parameters[0].initializer) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.A_set_accessor_parameter_cannot_have_an_initializer,
|
DiagnosticCode.A_set_accessor_parameter_cannot_have_an_initializer,
|
||||||
@ -1118,17 +1134,18 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isGetter = hasModifier(ModifierKind.GET, modifiers);
|
if (flags & CommonFlags.GET) {
|
||||||
if (isGetter && parameters.length) {
|
if (parameters.length) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.A_get_accessor_cannot_have_parameters,
|
DiagnosticCode.A_get_accessor_cannot_have_parameters,
|
||||||
name.range
|
name.range
|
||||||
); // recoverable
|
); // recoverable
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var returnType: CommonTypeNode | null = null;
|
var returnType: CommonTypeNode | null = null;
|
||||||
if (tn.skip(Token.COLON)) {
|
if (tn.skip(Token.COLON)) {
|
||||||
returnType = this.parseType(tn, isSetter);
|
returnType = this.parseType(tn, true, isSetter);
|
||||||
if (!returnType) return null;
|
if (!returnType) return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1152,11 +1169,20 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
tn.range(signatureStart, tn.pos)
|
tn.range(signatureStart, tn.pos)
|
||||||
);
|
);
|
||||||
|
|
||||||
var isDeclare = hasModifier(ModifierKind.DECLARE, modifiers);
|
if (flags & CommonFlags.DECLARE) {
|
||||||
|
if (flags & CommonFlags.AMBIENT) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context,
|
||||||
|
tn.range(this.currentDeclareStart, this.currentDeclareEnd)
|
||||||
|
); // recoverable
|
||||||
|
} else {
|
||||||
|
flags |= CommonFlags.AMBIENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var body: Statement | null = null;
|
var body: Statement | null = null;
|
||||||
if (tn.skip(Token.OPENBRACE)) {
|
if (tn.skip(Token.OPENBRACE)) {
|
||||||
if (isDeclare) {
|
if (flags & CommonFlags.AMBIENT) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts,
|
DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts,
|
||||||
tn.range()
|
tn.range()
|
||||||
@ -1165,7 +1191,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
body = this.parseBlockStatement(tn, false);
|
body = this.parseBlockStatement(tn, false);
|
||||||
if (!body) return null;
|
if (!body) return null;
|
||||||
} else if (!isDeclare) {
|
} else if (!(flags & CommonFlags.AMBIENT)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
|
DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
|
||||||
tn.range(tn.pos)
|
tn.range(tn.pos)
|
||||||
@ -1177,8 +1203,8 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
typeParameters,
|
typeParameters,
|
||||||
signature,
|
signature,
|
||||||
body,
|
body,
|
||||||
modifiers,
|
|
||||||
decorators,
|
decorators,
|
||||||
|
flags,
|
||||||
tn.range(startPos, tn.pos)
|
tn.range(startPos, tn.pos)
|
||||||
);
|
);
|
||||||
tn.skip(Token.SEMICOLON);
|
tn.skip(Token.SEMICOLON);
|
||||||
@ -1290,16 +1316,17 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
signature,
|
signature,
|
||||||
body,
|
body,
|
||||||
null,
|
null,
|
||||||
null,
|
isArrow ? CommonFlags.ARROW : CommonFlags.NONE,
|
||||||
tn.range(startPos, tn.pos)
|
tn.range(startPos, tn.pos)
|
||||||
);
|
);
|
||||||
return Node.createFunctionExpression(declaration, isArrow);
|
return Node.createFunctionExpression(declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseClass(
|
parseClass(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
modifiers: ModifierNode[] | null,
|
flags: CommonFlags,
|
||||||
decorators: DecoratorNode[] | null
|
decorators: DecoratorNode[] | null,
|
||||||
|
startPos: i32
|
||||||
): ClassDeclaration | null {
|
): ClassDeclaration | null {
|
||||||
|
|
||||||
// at 'class':
|
// at 'class':
|
||||||
@ -1309,28 +1336,29 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
// ('implements' Type (',' Type)*)?
|
// ('implements' Type (',' Type)*)?
|
||||||
// '{' ClassMember* '}'
|
// '{' ClassMember* '}'
|
||||||
|
|
||||||
var startPos = decorators && decorators.length
|
if (!tn.skip(Token.IDENTIFIER)) {
|
||||||
? decorators[0].range.start
|
this.error(
|
||||||
: modifiers && modifiers.length
|
DiagnosticCode.Identifier_expected,
|
||||||
? modifiers[0].range.start
|
tn.range()
|
||||||
: tn.tokenPos;
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (tn.skip(Token.IDENTIFIER)) {
|
var identifier = Node.createIdentifierExpression(
|
||||||
|
|
||||||
let identifier = Node.createIdentifierExpression(
|
|
||||||
tn.readIdentifier(),
|
tn.readIdentifier(),
|
||||||
tn.range()
|
tn.range()
|
||||||
);
|
);
|
||||||
|
|
||||||
let typeParameters: TypeParameterNode[] | null;
|
var typeParameters: TypeParameterNode[] | null;
|
||||||
if (tn.skip(Token.LESSTHAN)) {
|
if (tn.skip(Token.LESSTHAN)) {
|
||||||
typeParameters = this.parseTypeParameters(tn);
|
typeParameters = this.parseTypeParameters(tn);
|
||||||
if (!typeParameters) return null;
|
if (!typeParameters) return null;
|
||||||
|
flags |= CommonFlags.GENERIC;
|
||||||
} else {
|
} else {
|
||||||
typeParameters = [];
|
typeParameters = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
let extendsType: TypeNode | null = null;
|
var extendsType: TypeNode | null = null;
|
||||||
if (tn.skip(Token.EXTENDS)) {
|
if (tn.skip(Token.EXTENDS)) {
|
||||||
let t = this.parseType(tn);
|
let t = this.parseType(tn);
|
||||||
if (!t) return null;
|
if (!t) return null;
|
||||||
@ -1344,7 +1372,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
extendsType = <TypeNode>t;
|
extendsType = <TypeNode>t;
|
||||||
}
|
}
|
||||||
|
|
||||||
let implementsTypes = new Array<TypeNode>();
|
var implementsTypes = new Array<TypeNode>();
|
||||||
if (tn.skip(Token.IMPLEMENTS)) {
|
if (tn.skip(Token.IMPLEMENTS)) {
|
||||||
do {
|
do {
|
||||||
let type = this.parseType(tn);
|
let type = this.parseType(tn);
|
||||||
@ -1353,13 +1381,29 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
} while (tn.skip(Token.COMMA));
|
} while (tn.skip(Token.COMMA));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tn.skip(Token.OPENBRACE)) {
|
if (!tn.skip(Token.OPENBRACE)) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode._0_expected,
|
||||||
|
tn.range(), "{"
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let members = new Array<DeclarationStatement>();
|
if (flags & CommonFlags.DECLARE) {
|
||||||
|
if (flags & CommonFlags.AMBIENT) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context,
|
||||||
|
tn.range(this.currentDeclareStart, this.currentDeclareEnd)
|
||||||
|
); // recoverable
|
||||||
|
} else {
|
||||||
|
flags |= CommonFlags.AMBIENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var members = new Array<DeclarationStatement>();
|
||||||
if (!tn.skip(Token.CLOSEBRACE)) {
|
if (!tn.skip(Token.CLOSEBRACE)) {
|
||||||
let isDeclare = hasModifier(ModifierKind.DECLARE, modifiers);
|
|
||||||
do {
|
do {
|
||||||
let member = this.parseClassMember(tn, isDeclare);
|
let member = this.parseClassMember(tn, flags);
|
||||||
if (!member) return null;
|
if (!member) return null;
|
||||||
members.push(<DeclarationStatement>member);
|
members.push(<DeclarationStatement>member);
|
||||||
} while (!tn.skip(Token.CLOSEBRACE));
|
} while (!tn.skip(Token.CLOSEBRACE));
|
||||||
@ -1370,34 +1414,21 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
extendsType,
|
extendsType,
|
||||||
implementsTypes,
|
implementsTypes,
|
||||||
members,
|
members,
|
||||||
modifiers,
|
|
||||||
decorators,
|
decorators,
|
||||||
|
flags,
|
||||||
tn.range(startPos, tn.pos)
|
tn.range(startPos, tn.pos)
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
|
||||||
this.error(
|
|
||||||
DiagnosticCode._0_expected,
|
|
||||||
tn.range(), "{"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.error(
|
|
||||||
DiagnosticCode.Identifier_expected,
|
|
||||||
tn.range()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parseClassMember(
|
parseClassMember(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
parentIsDeclare: bool
|
parentFlags: CommonFlags
|
||||||
): DeclarationStatement | null {
|
): DeclarationStatement | null {
|
||||||
|
|
||||||
// before:
|
// before:
|
||||||
// ('public' | 'private' | 'protected')?
|
// ('public' | 'private' | 'protected')?
|
||||||
// ('static' | 'abstract')?
|
// ('static' | 'abstract')?
|
||||||
|
// 'readonly'?
|
||||||
// ('get' | 'set')?
|
// ('get' | 'set')?
|
||||||
// Identifier ...
|
// Identifier ...
|
||||||
|
|
||||||
@ -1410,66 +1441,131 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
decorators.push(<DecoratorNode>decorator);
|
decorators.push(<DecoratorNode>decorator);
|
||||||
}
|
}
|
||||||
|
|
||||||
var modifiers: ModifierNode[] | null = null;
|
var flags = parentFlags & CommonFlags.AMBIENT; // inherit
|
||||||
|
|
||||||
if (tn.skip(Token.PUBLIC)) {
|
if (tn.skip(Token.PUBLIC)) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.PUBLIC, tn.range()), modifiers);
|
flags |= CommonFlags.PUBLIC;
|
||||||
} else if (tn.skip(Token.PRIVATE)) {
|
} else if (tn.skip(Token.PRIVATE)) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.PRIVATE, tn.range()), modifiers);
|
flags |= CommonFlags.PRIVATE;
|
||||||
} else if (tn.skip(Token.PROTECTED)) {
|
} else if (tn.skip(Token.PROTECTED)) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.PROTECTED, tn.range()), modifiers);
|
flags |= CommonFlags.PROTECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var staticStart: i32 = 0;
|
||||||
|
var staticEnd: i32 = 0;
|
||||||
|
var abstractStart: i32 = 0;
|
||||||
|
var abstractEnd: i32 = 0;
|
||||||
if (tn.skip(Token.STATIC)) {
|
if (tn.skip(Token.STATIC)) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.STATIC, tn.range()), modifiers);
|
flags |= CommonFlags.STATIC;
|
||||||
|
staticStart = tn.tokenPos;
|
||||||
|
staticEnd = tn.pos;
|
||||||
} else if (tn.skip(Token.ABSTRACT)) {
|
} else if (tn.skip(Token.ABSTRACT)) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers);
|
flags |= (CommonFlags.ABSTRACT | CommonFlags.INSTANCE);
|
||||||
|
abstractStart = tn.tokenPos;
|
||||||
|
abstractEnd = tn.pos;
|
||||||
|
} else {
|
||||||
|
flags |= CommonFlags.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var readonlyStart: i32 = 0;
|
||||||
|
var readonlyEnd: i32 = 0;
|
||||||
if (tn.skip(Token.READONLY)) {
|
if (tn.skip(Token.READONLY)) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.READONLY, tn.range()), modifiers);
|
flags |= CommonFlags.READONLY;
|
||||||
|
readonlyStart = tn.tokenPos;
|
||||||
|
readonlyEnd = tn.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if accessor: ('get' | 'set') ^\n Identifier
|
// check if accessor: ('get' | 'set') ^\n Identifier
|
||||||
var state = tn.mark();
|
var state = tn.mark();
|
||||||
|
var isConstructor = false;
|
||||||
var isGetter = false;
|
var isGetter = false;
|
||||||
|
var getStart: i32 = 0;
|
||||||
|
var getEnd: i32 = 0;
|
||||||
var isSetter = false;
|
var isSetter = false;
|
||||||
|
var setStart: i32 = 0;
|
||||||
if (isGetter = tn.skip(Token.GET)) {
|
var setEnd: i32 = 0;
|
||||||
|
if (tn.skip(Token.GET)) {
|
||||||
if (tn.peek(true, true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
|
if (tn.peek(true, true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.GET, tn.range()), modifiers);
|
flags |= CommonFlags.GET;
|
||||||
|
isGetter = true;
|
||||||
|
setStart = tn.tokenPos;
|
||||||
|
setEnd = tn.pos;
|
||||||
|
if (flags & CommonFlags.READONLY) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
|
tn.range(readonlyStart, readonlyEnd), "readonly"
|
||||||
|
); // recoverable
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tn.reset(state);
|
tn.reset(state);
|
||||||
isGetter = false;
|
|
||||||
}
|
}
|
||||||
|
} else if (tn.skip(Token.SET)) {
|
||||||
} else if (isSetter = tn.skip(Token.SET)) { // can't be both
|
|
||||||
if (tn.peek(true, true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
|
if (tn.peek(true, true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
|
||||||
modifiers = addModifier(Node.createModifier(ModifierKind.SET, tn.range()), modifiers);
|
flags |= CommonFlags.SET | CommonFlags.SET;
|
||||||
|
isSetter = true;
|
||||||
|
setStart = tn.tokenPos;
|
||||||
|
setEnd = tn.pos;
|
||||||
|
if (flags & CommonFlags.READONLY) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
|
tn.range(readonlyStart, readonlyEnd), "readonly"
|
||||||
|
); // recoverable
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tn.reset(state);
|
tn.reset(state);
|
||||||
isSetter = false;
|
}
|
||||||
|
} else if (tn.skip(Token.CONSTRUCTOR)) {
|
||||||
|
flags |= CommonFlags.CONSTRUCTOR;
|
||||||
|
isConstructor = true;
|
||||||
|
if (flags & CommonFlags.STATIC) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
|
tn.range(staticStart, staticEnd), "static"
|
||||||
|
); // recoverable
|
||||||
|
}
|
||||||
|
if (flags & CommonFlags.ABSTRACT) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
|
tn.range(abstractStart, abstractEnd), "abstract"
|
||||||
|
); // recoverable
|
||||||
|
}
|
||||||
|
if (flags & CommonFlags.READONLY) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
|
tn.range(readonlyStart, readonlyEnd), "readonly"
|
||||||
|
); // recoverable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isConstructor = tn.skip(Token.CONSTRUCTOR);
|
if (!isConstructor && !tn.skip(Token.IDENTIFIER)) {
|
||||||
if (isConstructor || tn.skip(Token.IDENTIFIER)) {
|
this.error(
|
||||||
|
DiagnosticCode.Identifier_expected,
|
||||||
|
tn.range()
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let name = isConstructor
|
var name = isConstructor
|
||||||
? Node.createConstructorExpression(tn.range())
|
? Node.createConstructorExpression(tn.range())
|
||||||
: Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
: Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
||||||
|
var typeParameters: TypeParameterNode[] | null = null;
|
||||||
let typeParameters: TypeParameterNode[] | null = null;
|
|
||||||
if (tn.skip(Token.LESSTHAN)) {
|
if (tn.skip(Token.LESSTHAN)) {
|
||||||
|
let typeParametersStart = tn.tokenPos;
|
||||||
|
typeParameters = this.parseTypeParameters(tn);
|
||||||
|
if (!typeParameters) return null;
|
||||||
if (isConstructor) {
|
if (isConstructor) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Type_parameters_cannot_appear_on_a_constructor_declaration,
|
DiagnosticCode.Type_parameters_cannot_appear_on_a_constructor_declaration,
|
||||||
tn.range()
|
tn.range(typeParametersStart, tn.pos)
|
||||||
); // recoverable
|
); // recoverable
|
||||||
|
} else if (isGetter || isSetter) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode.An_accessor_cannot_have_type_parameters,
|
||||||
|
tn.range(typeParametersStart, tn.pos)
|
||||||
|
); // recoverable
|
||||||
|
} else {
|
||||||
|
flags |= CommonFlags.GENERIC;
|
||||||
}
|
}
|
||||||
typeParameters = this.parseTypeParameters(tn);
|
|
||||||
if (!typeParameters) return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// method: '(' Parameters (':' Type)? '{' Statement* '}' ';'?
|
// method: '(' Parameters (':' Type)? '{' Statement* '}' ';'?
|
||||||
@ -1478,14 +1574,14 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
let parameters = this.parseParameters(tn);
|
let parameters = this.parseParameters(tn);
|
||||||
if (!parameters) return null;
|
if (!parameters) return null;
|
||||||
|
|
||||||
if (isGetter && parameters.length) {
|
if (isGetter) {
|
||||||
|
if (parameters.length) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.A_get_accessor_cannot_have_parameters,
|
DiagnosticCode.A_get_accessor_cannot_have_parameters,
|
||||||
name.range
|
name.range
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (isSetter) {
|
||||||
if (isSetter) {
|
|
||||||
if (parameters.length != 1) {
|
if (parameters.length != 1) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.A_set_accessor_must_have_exactly_one_parameter,
|
DiagnosticCode.A_set_accessor_must_have_exactly_one_parameter,
|
||||||
@ -1535,7 +1631,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
let body: Statement | null = null;
|
let body: Statement | null = null;
|
||||||
if (tn.skip(Token.OPENBRACE)) {
|
if (tn.skip(Token.OPENBRACE)) {
|
||||||
if (parentIsDeclare) {
|
if (flags & CommonFlags.AMBIENT) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts,
|
DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts,
|
||||||
tn.range()
|
tn.range()
|
||||||
@ -1543,7 +1639,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
body = this.parseBlockStatement(tn, false);
|
body = this.parseBlockStatement(tn, false);
|
||||||
if (!body) return null;
|
if (!body) return null;
|
||||||
} else if (!parentIsDeclare) {
|
} else if (!(flags & CommonFlags.AMBIENT)) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
|
DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
|
||||||
tn.range()
|
tn.range()
|
||||||
@ -1555,8 +1651,8 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
typeParameters,
|
typeParameters,
|
||||||
signature,
|
signature,
|
||||||
body,
|
body,
|
||||||
modifiers,
|
|
||||||
decorators,
|
decorators,
|
||||||
|
flags,
|
||||||
tn.range(startPos, tn.pos)
|
tn.range(startPos, tn.pos)
|
||||||
);
|
);
|
||||||
tn.skip(Token.SEMICOLON);
|
tn.skip(Token.SEMICOLON);
|
||||||
@ -1576,26 +1672,24 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// field: (':' Type)? ('=' Expression)? ';'?
|
// field: (':' Type)? ('=' Expression)? ';'?
|
||||||
} else {
|
} else {
|
||||||
let modifier: ModifierNode | null;
|
if (flags & CommonFlags.ABSTRACT) {
|
||||||
|
|
||||||
if (modifier = getModifier(ModifierKind.ABSTRACT, modifiers)) {
|
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode._0_modifier_cannot_be_used_here,
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
modifier.range, "abstract"
|
tn.range(abstractStart, abstractEnd), "abstract"
|
||||||
); // recoverable
|
); // recoverable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modifier = getModifier(ModifierKind.GET, modifiers)) {
|
if (flags & CommonFlags.GET) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode._0_modifier_cannot_be_used_here,
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
modifier.range, "get"
|
tn.range(getStart, getEnd), "get"
|
||||||
); // recoverable
|
); // recoverable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modifier = getModifier(ModifierKind.SET, modifiers)) {
|
if (flags & CommonFlags.SET) {
|
||||||
this.error(
|
this.error(
|
||||||
DiagnosticCode._0_modifier_cannot_be_used_here,
|
DiagnosticCode._0_modifier_cannot_be_used_here,
|
||||||
modifier.range, "set"
|
tn.range(setStart, setEnd), "set"
|
||||||
); // recoverable
|
); // recoverable
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1618,31 +1712,25 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
initializer,
|
initializer,
|
||||||
modifiers,
|
|
||||||
decorators,
|
decorators,
|
||||||
|
flags,
|
||||||
tn.range(startPos, tn.pos)
|
tn.range(startPos, tn.pos)
|
||||||
);
|
);
|
||||||
tn.skip(Token.SEMICOLON);
|
tn.skip(Token.SEMICOLON);
|
||||||
return retField;
|
return retField;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
this.error(
|
|
||||||
DiagnosticCode.Identifier_expected,
|
|
||||||
tn.range()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
parseNamespace(
|
parseNamespace(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
modifiers: ModifierNode[] | null,
|
flags: CommonFlags,
|
||||||
decorators: DecoratorNode[] | null
|
decorators: DecoratorNode[] | null,
|
||||||
|
startPos: i32
|
||||||
): NamespaceDeclaration | null {
|
): NamespaceDeclaration | null {
|
||||||
|
|
||||||
// at 'namespace': Identifier '{' (Variable | Function)* '}'
|
// at 'namespace': Identifier '{' (Variable | Function)* '}'
|
||||||
|
|
||||||
var startPos = modifiers && modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
|
||||||
if (tn.skip(Token.IDENTIFIER)) {
|
if (tn.skip(Token.IDENTIFIER)) {
|
||||||
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
||||||
if (tn.skip(Token.OPENBRACE)) {
|
if (tn.skip(Token.OPENBRACE)) {
|
||||||
@ -1655,8 +1743,8 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
let ret = Node.createNamespaceDeclaration(
|
let ret = Node.createNamespaceDeclaration(
|
||||||
identifier,
|
identifier,
|
||||||
members,
|
members,
|
||||||
modifiers,
|
|
||||||
decorators,
|
decorators,
|
||||||
|
flags,
|
||||||
tn.range(startPos, tn.pos)
|
tn.range(startPos, tn.pos)
|
||||||
);
|
);
|
||||||
tn.skip(Token.SEMICOLON);
|
tn.skip(Token.SEMICOLON);
|
||||||
@ -1678,13 +1766,12 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
parseExport(
|
parseExport(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
modifiers: ModifierNode[] | null
|
flags: CommonFlags,
|
||||||
|
startPos: i32
|
||||||
): ExportStatement | null {
|
): ExportStatement | null {
|
||||||
|
|
||||||
// at 'export': '{' ExportMember (',' ExportMember)* }' ('from' StringLiteral)? ';'?
|
// at 'export': '{' ExportMember (',' ExportMember)* }' ('from' StringLiteral)? ';'?
|
||||||
|
|
||||||
var startPos = modifiers && modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
|
||||||
|
|
||||||
if (tn.skip(Token.OPENBRACE)) {
|
if (tn.skip(Token.OPENBRACE)) {
|
||||||
let members = new Array<ExportMember>();
|
let members = new Array<ExportMember>();
|
||||||
if (!tn.skip(Token.CLOSEBRACE)) {
|
if (!tn.skip(Token.CLOSEBRACE)) {
|
||||||
@ -1713,7 +1800,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let ret = Node.createExportStatement(members, path, modifiers, tn.range(startPos, tn.pos));
|
let ret = Node.createExportStatement(members, path, flags, tn.range(startPos, tn.pos));
|
||||||
if (ret.normalizedPath && !this.seenlog.has(<string>ret.normalizedPath)) {
|
if (ret.normalizedPath && !this.seenlog.has(<string>ret.normalizedPath)) {
|
||||||
this.backlog.push(<string>ret.normalizedPath);
|
this.backlog.push(<string>ret.normalizedPath);
|
||||||
this.seenlog.add(<string>ret.normalizedPath);
|
this.seenlog.add(<string>ret.normalizedPath);
|
||||||
@ -1884,7 +1971,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
parseExportImport(
|
parseExportImport(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
startRange: Range
|
startPos: i32
|
||||||
): ExportImportStatement | null {
|
): ExportImportStatement | null {
|
||||||
|
|
||||||
// at 'export' 'import': Identifier ('=' Identifier)? ';'?
|
// at 'export' 'import': Identifier ('=' Identifier)? ';'?
|
||||||
@ -1894,7 +1981,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
if (tn.skip(Token.EQUALS)) {
|
if (tn.skip(Token.EQUALS)) {
|
||||||
if (tn.skip(Token.IDENTIFIER)) {
|
if (tn.skip(Token.IDENTIFIER)) {
|
||||||
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
||||||
let ret = Node.createExportImportStatement(identifier, asIdentifier, Range.join(startRange, tn.range()));
|
let ret = Node.createExportImportStatement(identifier, asIdentifier, tn.range(startPos, tn.pos));
|
||||||
tn.skip(Token.SEMICOLON);
|
tn.skip(Token.SEMICOLON);
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
@ -1934,9 +2021,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.CONST: {
|
case Token.CONST: {
|
||||||
statement = this.parseVariable(tn, [
|
statement = this.parseVariable(tn, CommonFlags.CONST, null, tn.tokenPos);
|
||||||
Node.createModifier(ModifierKind.CONST, tn.range())
|
|
||||||
], null);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.CONTINUE: {
|
case Token.CONTINUE: {
|
||||||
@ -1956,13 +2041,11 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.LET: {
|
case Token.LET: {
|
||||||
statement = this.parseVariable(tn, [
|
statement = this.parseVariable(tn, CommonFlags.LET, null, tn.tokenPos);
|
||||||
Node.createModifier(ModifierKind.LET, tn.range())
|
|
||||||
], null);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.VAR: {
|
case Token.VAR: {
|
||||||
statement = this.parseVariable(tn, null, null);
|
statement = this.parseVariable(tn, CommonFlags.NONE, null, tn.tokenPos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.OPENBRACE: {
|
case Token.OPENBRACE: {
|
||||||
@ -1995,7 +2078,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.TYPE: {
|
case Token.TYPE: {
|
||||||
statement = this.parseTypeDeclaration(tn);
|
statement = this.parseTypeDeclaration(tn, CommonFlags.NONE, null, tn.tokenPos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token.VOID: {
|
case Token.VOID: {
|
||||||
@ -2142,11 +2225,14 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
var startPos = tn.tokenPos;
|
var startPos = tn.tokenPos;
|
||||||
|
|
||||||
if (tn.skip(Token.OPENPAREN)) {
|
if (tn.skip(Token.OPENPAREN)) {
|
||||||
|
|
||||||
let initializer: Statement | null = null;
|
let initializer: Statement | null = null;
|
||||||
|
|
||||||
if (tn.skip(Token.LET) || tn.skip(Token.CONST) || tn.skip(Token.VAR)) {
|
if (tn.skip(Token.CONST)) {
|
||||||
initializer = this.parseVariable(tn, null, null);
|
initializer = this.parseVariable(tn, CommonFlags.CONST, null, tn.tokenPos);
|
||||||
|
} else if (tn.skip(Token.LET)) {
|
||||||
|
initializer = this.parseVariable(tn, CommonFlags.LET, null, tn.tokenPos);
|
||||||
|
} else if (tn.skip(Token.VAR)) {
|
||||||
|
initializer = this.parseVariable(tn, CommonFlags.NONE, null, tn.tokenPos);
|
||||||
|
|
||||||
} else if (!tn.skip(Token.SEMICOLON)) {
|
} else if (!tn.skip(Token.SEMICOLON)) {
|
||||||
initializer = this.parseExpressionStatement(tn);
|
initializer = this.parseExpressionStatement(tn);
|
||||||
@ -2458,21 +2544,20 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
|
|
||||||
parseTypeDeclaration(
|
parseTypeDeclaration(
|
||||||
tn: Tokenizer,
|
tn: Tokenizer,
|
||||||
modifiers: ModifierNode[] | null = null,
|
flags: CommonFlags,
|
||||||
decorators: DecoratorNode[] | null = null
|
decorators: DecoratorNode[] | null,
|
||||||
|
startPos: i32
|
||||||
): TypeDeclaration | null {
|
): TypeDeclaration | null {
|
||||||
|
|
||||||
// at 'type': Identifier ('<' TypeParameters '>')? '=' Type ';'?
|
// at 'type': Identifier ('<' TypeParameters '>')? '=' Type ';'?
|
||||||
|
|
||||||
var startPos = decorators && decorators.length ? decorators[0].range.start
|
|
||||||
: modifiers && modifiers.length ? modifiers[0].range.start
|
|
||||||
: tn.tokenPos;
|
|
||||||
if (tn.skip(Token.IDENTIFIER)) {
|
if (tn.skip(Token.IDENTIFIER)) {
|
||||||
let name = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
let name = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
||||||
let typeParameters: TypeParameterNode[] | null = null;
|
let typeParameters: TypeParameterNode[] | null = null;
|
||||||
if (tn.skip(Token.LESSTHAN)) {
|
if (tn.skip(Token.LESSTHAN)) {
|
||||||
typeParameters = this.parseTypeParameters(tn);
|
typeParameters = this.parseTypeParameters(tn);
|
||||||
if (!typeParameters) return null;
|
if (!typeParameters) return null;
|
||||||
|
flags |= CommonFlags.GENERIC;
|
||||||
}
|
}
|
||||||
if (tn.skip(Token.EQUALS)) {
|
if (tn.skip(Token.EQUALS)) {
|
||||||
let type = this.parseType(tn);
|
let type = this.parseType(tn);
|
||||||
@ -2481,8 +2566,8 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
name,
|
name,
|
||||||
typeParameters,
|
typeParameters,
|
||||||
type,
|
type,
|
||||||
modifiers,
|
|
||||||
decorators,
|
decorators,
|
||||||
|
flags,
|
||||||
tn.range(startPos, tn.pos)
|
tn.range(startPos, tn.pos)
|
||||||
);
|
);
|
||||||
tn.skip(Token.SEMICOLON);
|
tn.skip(Token.SEMICOLON);
|
||||||
|
770
src/program.ts
770
src/program.ts
File diff suppressed because it is too large
Load Diff
@ -176,9 +176,7 @@ export enum Token {
|
|||||||
ENDOFFILE
|
ENDOFFILE
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace Token {
|
export function tokenFomKeyword(text: string): Token {
|
||||||
|
|
||||||
export function fromKeyword(text: string): Token {
|
|
||||||
switch (text) {
|
switch (text) {
|
||||||
case "abstract": return Token.ABSTRACT;
|
case "abstract": return Token.ABSTRACT;
|
||||||
case "as": return Token.AS;
|
case "as": return Token.AS;
|
||||||
@ -243,9 +241,9 @@ export namespace Token {
|
|||||||
case "yield": return Token.YIELD;
|
case "yield": return Token.YIELD;
|
||||||
default: return Token.INVALID;
|
default: return Token.INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isAlsoIdentifier(token: Token): bool {
|
export function tokenIsAlsoIdentifier(token: Token): bool {
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case Token.ABSTRACT:
|
case Token.ABSTRACT:
|
||||||
case Token.AS:
|
case Token.AS:
|
||||||
@ -263,9 +261,9 @@ export namespace Token {
|
|||||||
case Token.TYPE: return true;
|
case Token.TYPE: return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function operatorToString(token: Token): string {
|
export function operatorTokenToString(token: Token): string {
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case Token.DELETE: return "delete";
|
case Token.DELETE: return "delete";
|
||||||
case Token.IN: return "in";
|
case Token.IN: return "in";
|
||||||
@ -320,7 +318,6 @@ export namespace Token {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Range {
|
export class Range {
|
||||||
@ -356,23 +353,19 @@ export class Range {
|
|||||||
|
|
||||||
get line(): i32 {
|
get line(): i32 {
|
||||||
var text = this.source.text;
|
var text = this.source.text;
|
||||||
var pos = this.start;
|
|
||||||
var line = 1;
|
var line = 1;
|
||||||
while (pos-- > 0) {
|
for (let pos = this.start; pos >= 0; --pos) {
|
||||||
if (text.charCodeAt(pos) == CharCode.LINEFEED) {
|
if (text.charCodeAt(pos) == CharCode.LINEFEED) line++;
|
||||||
line++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
get column(): i32 {
|
get column(): i32 {
|
||||||
var text = this.source.text;
|
var text = this.source.text;
|
||||||
var pos = this.start;
|
|
||||||
var column = 0;
|
var column = 0;
|
||||||
while (pos-- > 0) {
|
for (let pos = this.start - 1; pos >= 0; --pos) {
|
||||||
if (text.charCodeAt(pos) == CharCode.LINEFEED) break;
|
if (text.charCodeAt(pos) == CharCode.LINEFEED) break;
|
||||||
column++;
|
++column;
|
||||||
}
|
}
|
||||||
return column;
|
return column;
|
||||||
}
|
}
|
||||||
@ -396,6 +389,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
tokenPos: i32 = 0;
|
tokenPos: i32 = 0;
|
||||||
|
|
||||||
nextToken: Token = -1;
|
nextToken: Token = -1;
|
||||||
|
nextTokenPos: i32 = 0;
|
||||||
nextTokenOnNewLine: bool = false;
|
nextTokenOnNewLine: bool = false;
|
||||||
|
|
||||||
constructor(source: Source, diagnostics: DiagnosticMessage[] | null = null) {
|
constructor(source: Source, diagnostics: DiagnosticMessage[] | null = null) {
|
||||||
@ -598,9 +592,12 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
// ) {
|
// ) {
|
||||||
// }
|
// }
|
||||||
while (++this.pos < this.end) {
|
while (++this.pos < this.end) {
|
||||||
if (isLineBreak(text.charCodeAt(this.pos))) break;
|
if (isLineBreak(text.charCodeAt(this.pos))) {
|
||||||
|
++this.pos;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.ASTERISK) { // multi-line
|
if (text.charCodeAt(this.pos) == CharCode.ASTERISK) { // multi-line
|
||||||
let closed = false;
|
let closed = false;
|
||||||
@ -622,7 +619,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
this.range(this.pos), "*/"
|
this.range(this.pos), "*/"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
++this.pos;
|
++this.pos;
|
||||||
@ -795,10 +792,10 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let keywordText = text.substring(posBefore, this.pos);
|
let keywordText = text.substring(posBefore, this.pos);
|
||||||
let keywordToken = Token.fromKeyword(keywordText);
|
let keywordToken = tokenFomKeyword(keywordText);
|
||||||
if (
|
if (
|
||||||
keywordToken != Token.INVALID &&
|
keywordToken != Token.INVALID &&
|
||||||
!(preferIdentifier && Token.isAlsoIdentifier(keywordToken))
|
!(preferIdentifier && tokenIsAlsoIdentifier(keywordToken))
|
||||||
) {
|
) {
|
||||||
return keywordToken;
|
return keywordToken;
|
||||||
}
|
}
|
||||||
@ -832,6 +829,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
let tokenBefore = this.token;
|
let tokenBefore = this.token;
|
||||||
let tokenPosBefore = this.tokenPos;
|
let tokenPosBefore = this.tokenPos;
|
||||||
this.nextToken = this.unsafeNext(preferIdentifier, maxCompoundLength);
|
this.nextToken = this.unsafeNext(preferIdentifier, maxCompoundLength);
|
||||||
|
this.nextTokenPos = this.tokenPos;
|
||||||
if (checkOnNewLine) {
|
if (checkOnNewLine) {
|
||||||
this.nextTokenOnNewLine = false;
|
this.nextTokenOnNewLine = false;
|
||||||
while (--this.tokenPos > posBefore) {
|
while (--this.tokenPos > posBefore) {
|
||||||
|
@ -100,10 +100,10 @@ export class Type {
|
|||||||
return ~0 >>> (targetType.size - this.size);
|
return ~0 >>> (targetType.size - this.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Tests if this type has the specified capabilities. */
|
/** Tests if this type has the specified flags. */
|
||||||
is(flags: TypeFlags): bool {
|
is(flags: TypeFlags): bool { return (this.flags & flags) == flags; }
|
||||||
return (this.flags & flags) == flags;
|
/** Tests if this type has any of the specified flags. */
|
||||||
}
|
isAny(flags: TypeFlags): bool { return (this.flags & flags) != 0; }
|
||||||
|
|
||||||
/** Tests if this type is a class type. */
|
/** Tests if this type is a class type. */
|
||||||
get isClass(): bool { return this.classType != null; }
|
get isClass(): bool { return this.classType != null; }
|
||||||
|
18
src/util/text.ts
Normal file
18
src/util/text.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const indentX1 = " ";
|
||||||
|
const indentX2 = " ";
|
||||||
|
const indentX4 = " ";
|
||||||
|
|
||||||
|
/** Creates an indentation matching the number of specified levels. */
|
||||||
|
export function indent(sb: string[], level: i32): void {
|
||||||
|
while (level >= 4) {
|
||||||
|
sb.push(indentX4);
|
||||||
|
level -= 4;
|
||||||
|
}
|
||||||
|
if (level >= 2) {
|
||||||
|
sb.push(indentX2);
|
||||||
|
level -= 2;
|
||||||
|
}
|
||||||
|
if (level) {
|
||||||
|
sb.push(indentX1);
|
||||||
|
}
|
||||||
|
}
|
2
std/portable.d.ts
vendored
2
std/portable.d.ts
vendored
@ -137,7 +137,7 @@ declare function bswap16<T = i16 | u16 | i32 | u32>(value: T): T;
|
|||||||
/** Changes the type of any value of `usize` kind to another one of `usize` kind. Useful for casting class instances to their pointer values and vice-versa. Beware that this is unsafe.*/
|
/** Changes the type of any value of `usize` kind to another one of `usize` kind. Useful for casting class instances to their pointer values and vice-versa. Beware that this is unsafe.*/
|
||||||
declare function changetype<T>(value: any): T;
|
declare function changetype<T>(value: any): T;
|
||||||
/** Traps if the specified value is not true-ish, otherwise returns the value. */
|
/** Traps if the specified value is not true-ish, otherwise returns the value. */
|
||||||
declare function assert<T>(isTrueish: T, message?: string): T & object; // any better way to model `: T != null`?
|
declare function assert<T>(isTrueish: T | null, message?: string): T;
|
||||||
/** Parses an integer string to a 64-bit float. */
|
/** Parses an integer string to a 64-bit float. */
|
||||||
declare function parseInt(str: string, radix?: i32): f64;
|
declare function parseInt(str: string, radix?: i32): f64;
|
||||||
/** Parses an integer string to a 32-bit integer. */
|
/** Parses an integer string to a 32-bit integer. */
|
||||||
|
@ -427,7 +427,6 @@
|
|||||||
(local $6 i32)
|
(local $6 i32)
|
||||||
(local $7 i32)
|
(local $7 i32)
|
||||||
(local $8 i32)
|
(local $8 i32)
|
||||||
(local $9 i32)
|
|
||||||
(if
|
(if
|
||||||
(i32.eqz
|
(i32.eqz
|
||||||
(i32.ne
|
(i32.ne
|
||||||
@ -493,14 +492,14 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
(block $break|0
|
(block $break|0
|
||||||
(set_local $9
|
(set_local $5
|
||||||
(get_local $7)
|
(get_local $7)
|
||||||
)
|
)
|
||||||
(loop $continue|0
|
(loop $continue|0
|
||||||
(if
|
(if
|
||||||
(i32.le_s
|
(i32.le_s
|
||||||
(i32.add
|
(i32.add
|
||||||
(get_local $9)
|
(get_local $5)
|
||||||
(get_local $8)
|
(get_local $8)
|
||||||
)
|
)
|
||||||
(get_local $4)
|
(get_local $4)
|
||||||
@ -516,7 +515,7 @@
|
|||||||
(i32.const 4)
|
(i32.const 4)
|
||||||
)
|
)
|
||||||
(i32.shl
|
(i32.shl
|
||||||
(get_local $9)
|
(get_local $5)
|
||||||
(i32.const 1)
|
(i32.const 1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -531,13 +530,13 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
(return
|
(return
|
||||||
(get_local $9)
|
(get_local $5)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(set_local $9
|
(set_local $5
|
||||||
(i32.add
|
(i32.add
|
||||||
(get_local $9)
|
(get_local $5)
|
||||||
(i32.const 1)
|
(i32.const 1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -21,10 +21,10 @@ glob.sync(filter, { cwd: __dirname + "/parser" }).forEach(filename => {
|
|||||||
|
|
||||||
var failed = false;
|
var failed = false;
|
||||||
var parser = new Parser();
|
var parser = new Parser();
|
||||||
var sourceText = fs.readFileSync(__dirname + "/parser/" + filename, { encoding: "utf8" }).replace(/\r?\n/g, "\n").replace(/^\/\/.*\r?\n/mg, "");
|
var sourceText = fs.readFileSync(__dirname + "/parser/" + filename, { encoding: "utf8" }).replace(/\r?\n/g, "\n");
|
||||||
parser.parseFile(sourceText, filename, true);
|
parser.parseFile(sourceText, filename, true);
|
||||||
var serializedSourceText = ASTBuilder.build(parser.program.sources[0]);
|
var serializedSourceText = ASTBuilder.build(parser.program.sources[0]);
|
||||||
var actual = serializedSourceText + parser.diagnostics.map(diagnostic => "// " + diagnostic + "\n").join("");
|
var actual = serializedSourceText + parser.diagnostics.map(diagnostic => "// " + diagnostic +"\n").join("");
|
||||||
var fixture = filename + ".fixture.ts";
|
var fixture = filename + ".fixture.ts";
|
||||||
|
|
||||||
if (isCreate) {
|
if (isCreate) {
|
||||||
|
@ -1,13 +1,27 @@
|
|||||||
export class Test<T> {
|
export class Valid<T> {
|
||||||
instanceFunction(): void {
|
constructor() {}
|
||||||
}
|
instanceFunction(): void {}
|
||||||
static staticFunction(): void {
|
static staticFunction(): void {}
|
||||||
}
|
get instanceGetter(): i32 {}
|
||||||
get instanceGetter(): i32 {
|
static set staticSetter(v: i32) {}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static set staticSetter(v: i32) {
|
|
||||||
}
|
|
||||||
instanceField: i32;
|
instanceField: i32;
|
||||||
static staticField: i32;
|
static staticField: i32;
|
||||||
}
|
}
|
||||||
|
export class Invalid<T> {
|
||||||
|
|
||||||
|
// 1092: Type parameters cannot appear on a constructor declaration
|
||||||
|
constructor<T>() {}
|
||||||
|
|
||||||
|
// 1110: Type expected.
|
||||||
|
instanceFunction() {}
|
||||||
|
|
||||||
|
// 1094: An accessor cannot have type parameters.
|
||||||
|
// 1054: A 'get' accessor cannot have parameters.
|
||||||
|
// 1110: Type expected.
|
||||||
|
get instanceGetter<T>(a: i32) {}
|
||||||
|
|
||||||
|
// 1094: An accessor cannot have type parameters.
|
||||||
|
// 1049: A 'set' accessor must have exactly one parameter.
|
||||||
|
// 1095: A 'set' accessor cannot have a return type annotation.
|
||||||
|
set instanceSetter<T>(): i32 {}
|
||||||
|
}
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
export class Test<T> {
|
export class Valid<T> {
|
||||||
instanceFunction(): void {
|
constructor() {}
|
||||||
|
instanceFunction(): void {}
|
||||||
|
static staticFunction(): void {}
|
||||||
|
get instanceGetter(): i32 {}
|
||||||
|
static set staticSetter(v: i32) {}
|
||||||
|
instanceField: i32;
|
||||||
|
static staticField: i32;
|
||||||
}
|
}
|
||||||
static staticFunction(): void {
|
export class Invalid<T> {
|
||||||
}
|
constructor<T>() {}
|
||||||
get instanceGetter(): i32 {
|
instanceFunction(): {}
|
||||||
return 0;
|
get instanceGetter<T>(a: i32): {}
|
||||||
}
|
set instanceSetter<T>() {}
|
||||||
static set staticSetter(v: i32) {
|
|
||||||
}
|
|
||||||
instanceField: i32;
|
|
||||||
static staticField: i32;
|
|
||||||
}
|
}
|
||||||
|
// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:13:13
|
||||||
|
// ERROR 1110: "Type expected." in class.ts:16:20
|
||||||
|
// ERROR 1094: "An accessor cannot have type parameters." in class.ts:21:20
|
||||||
|
// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts:21:6
|
||||||
|
// ERROR 1110: "Type expected." in class.ts:21:31
|
||||||
|
// ERROR 1094: "An accessor cannot have type parameters." in class.ts:26:20
|
||||||
|
// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts:26:6
|
||||||
|
// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts:26:25
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
var; while for let; a from "./other";
|
// 1003: Identifier expected.
|
||||||
|
var;
|
||||||
|
// 1005: '(' expected.
|
||||||
|
while for let; a from "./other";
|
||||||
do {
|
do {
|
||||||
;
|
;
|
||||||
} while (false);
|
} while (false);
|
||||||
|
@ -3,7 +3,7 @@ a;
|
|||||||
from;
|
from;
|
||||||
"./other";
|
"./other";
|
||||||
do {
|
do {
|
||||||
;
|
;
|
||||||
} while (false);
|
} while (false);
|
||||||
// ERROR 1003: "Identifier expected." in continue-on-error.ts @ 0,3
|
// ERROR 1003: "Identifier expected." in continue-on-error.ts:2:0
|
||||||
// ERROR 1005: "'(' expected." in continue-on-error.ts @ 5,10
|
// ERROR 1005: "'(' expected." in continue-on-error.ts:4:0
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
do {
|
do {
|
||||||
;
|
;
|
||||||
} while (a != b);
|
} while (a != b);
|
||||||
|
do b;
|
||||||
do b; while (a);
|
while (a);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
do {
|
do {
|
||||||
;
|
;
|
||||||
} while (a != b);
|
} while (a != b);
|
||||||
do b;
|
do b;
|
||||||
while (a);
|
while (a);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
export const enum A {
|
export const enum A {
|
||||||
B = 1,
|
B = 1,
|
||||||
C,
|
C,
|
||||||
D = 3
|
D = 3
|
||||||
}
|
}
|
||||||
enum E {
|
enum E {
|
||||||
F,
|
F,
|
||||||
G = 1 + 2,
|
G = 1 + 2,
|
||||||
H = 3 * 4
|
H = 3 * 4
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
for (var i: i32 = 0; i < 10; ++i) {
|
for (var i: i32 = 0; i < 10; ++i) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 10; ++i) {
|
for (i = 0; i < 10; ++i) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
var a = function(): void {
|
var a = function(): void {
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
var b = function someName(): void {
|
var b = function someName(): void {
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
var c = function(a: i32, b: i32): i32 {
|
var c = function(a: i32, b: i32): i32 {
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
var d = (): void => {
|
var d = (): void => {
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
var e = (a: i32, b: i32): i32 => {
|
var e = (a: i32, b: i32): i32 => {
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
var f = (a: i32): i32 => a;
|
var f = (a: i32): i32 => a;
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
function simple(): void {
|
function simple(): void {}
|
||||||
}
|
function typeparams<T, V extends T>(a: V | null = null): void {}
|
||||||
function typeparams<T, V extends T>(a: V | null = null): void {
|
|
||||||
}
|
|
||||||
@decorator()
|
@decorator()
|
||||||
function withdecorator(): void {
|
function withdecorator(): void {}
|
||||||
}
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
function simple(): void {
|
function simple(): void {}
|
||||||
}
|
function typeparams<T, V extends T>(a: V | null = null): void {}
|
||||||
function typeparams<T, V extends T>(a: V | null = null): void {
|
|
||||||
}
|
|
||||||
@decorator()
|
@decorator()
|
||||||
function withdecorator(): void {
|
function withdecorator(): void {}
|
||||||
}
|
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
import { A } from "./other";
|
import {
|
||||||
|
A
|
||||||
import { A, B, C } from "./other";
|
} from "./other";
|
||||||
|
import {
|
||||||
import { A as B, C, D as E, F } from "./other";
|
A,
|
||||||
|
B,
|
||||||
|
C
|
||||||
|
} from "./other";
|
||||||
|
import {
|
||||||
|
A as B,
|
||||||
|
C,
|
||||||
|
D as E,
|
||||||
|
F
|
||||||
|
} from "./other";
|
||||||
import * as A from "./other";
|
import * as A from "./other";
|
||||||
|
|
||||||
import "./other";
|
import "./other";
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
A
|
A
|
||||||
} from "./other";
|
} from "./other";
|
||||||
import {
|
import {
|
||||||
A,
|
A,
|
||||||
B,
|
B,
|
||||||
C
|
C
|
||||||
} from "./other";
|
} from "./other";
|
||||||
import {
|
import {
|
||||||
A as B,
|
A as B,
|
||||||
C,
|
C,
|
||||||
D as E,
|
D as E,
|
||||||
F
|
F
|
||||||
} from "./other";
|
} from "./other";
|
||||||
import * as A from "./other";
|
import * as A from "./other";
|
||||||
import "./other";
|
import "./other";
|
||||||
|
@ -45,7 +45,6 @@
|
|||||||
0b0;
|
0b0;
|
||||||
0b1;
|
0b1;
|
||||||
0b1111111111111111111111111111111;
|
0b1111111111111111111111111111111;
|
||||||
|
|
||||||
"123";
|
"123";
|
||||||
"1\"23";
|
"1\"23";
|
||||||
"1\"2\\3";
|
"1\"2\\3";
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
declare namespace A {
|
declare namespace A {
|
||||||
namespace B {
|
namespace B {
|
||||||
export namespace C {
|
export namespace C {
|
||||||
var aVar: i32;
|
var aVar: i32;
|
||||||
const aConst: i32 = 0;
|
const aConst: i32 = 0;
|
||||||
function aFunc(): void {
|
function aFunc(): void {}
|
||||||
}
|
enum AnEnum {}
|
||||||
enum AnEnum {
|
class AClass {}
|
||||||
}
|
}
|
||||||
class AClass {
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
function restValid(a: i32, ...b: i32[]): void {}
|
function restValid(a: i32, ...b: i32[]): void {}
|
||||||
|
function optionalValid(a: i32, b?: i32): void {}
|
||||||
|
|
||||||
|
// 1014: A rest parameter must be last in a parameter list.
|
||||||
function restParameterMustBeLast(...a: i32[], b: i32): void {}
|
function restParameterMustBeLast(...a: i32[], b: i32): void {}
|
||||||
|
|
||||||
function optionalValid(a: i32, b?: i32): void {}
|
// 1016: A required parameter cannot follow an optional parameter.
|
||||||
function optionalCannotPrecedeRequired(a?: i32, b: i32): void {}
|
function optionalCannotPrecedeRequired(a?: i32, b: i32): void {}
|
||||||
|
|
||||||
|
// 1016: A required parameter cannot follow an optional parameter.
|
||||||
function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {}
|
function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {}
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
function restValid(a: i32, ...b: Array<i32>): void {
|
function restValid(a: i32, ...b: Array<i32>): void {}
|
||||||
}
|
function optionalValid(a: i32, b?: i32): void {}
|
||||||
function restParameterMustBeLast(...a: Array<i32>, b: i32): void {
|
function restParameterMustBeLast(...a: Array<i32>, b: i32): void {}
|
||||||
}
|
function optionalCannotPrecedeRequired(a?: i32, b: i32): void {}
|
||||||
function optionalValid(a: i32, b?: i32): void {
|
function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {}
|
||||||
}
|
// ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts:5:36
|
||||||
function optionalCannotPrecedeRequired(a?: i32, b: i32): void {
|
// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts:8:48
|
||||||
}
|
// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts:11:66
|
||||||
function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {
|
|
||||||
}
|
|
||||||
// ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts @ 85,86
|
|
||||||
// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts @ 210,211
|
|
||||||
// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts @ 293,294
|
|
||||||
|
@ -1,30 +1,10 @@
|
|||||||
// with modifiers
|
/(abc)\//ig; // with modifiers
|
||||||
/(abc)\//ig;
|
/(abc)\//; // without modifiers
|
||||||
|
var re = /(abc)\//ig; // can be assigned
|
||||||
// without modifiers
|
var noRe = !/(abc)\//i; // generally behaves like an expression
|
||||||
/(abc)\//;
|
|
||||||
|
|
||||||
// can be assigned
|
|
||||||
var re = /(abc)\//ig;
|
|
||||||
|
|
||||||
// generally behaves like an expression
|
|
||||||
var noRe = !/(abc)\//i;
|
|
||||||
|
|
||||||
// inner line break is unterminated
|
|
||||||
/a
|
/a
|
||||||
b/ig;
|
b/ig; // inner line break is unterminated
|
||||||
|
|
||||||
// just a comment
|
|
||||||
//ig;
|
//ig;
|
||||||
|
/(abc)\//iig; // duplicate flags
|
||||||
// duplicate flags
|
/(abc)\//iX; // invalid flags
|
||||||
|
false && /abc/gX.test(someString) || true; // surrounding AST remains intact
|
||||||
/(abc)\//iig;
|
|
||||||
|
|
||||||
// invalid flags
|
|
||||||
|
|
||||||
/(abc)\//iX;
|
|
||||||
|
|
||||||
// surrounding AST remains intact
|
|
||||||
|
|
||||||
false && /abc/gX.test(someString) || true;
|
|
||||||
|
@ -5,8 +5,8 @@ var noRe = !/(abc)\//i;
|
|||||||
/(abc)\//iig;
|
/(abc)\//iig;
|
||||||
/(abc)\//iX;
|
/(abc)\//iX;
|
||||||
false && /abc/gX.test(someString) || true;
|
false && /abc/gX.test(someString) || true;
|
||||||
// ERROR 1161: "Unterminated regular expression literal." in regexp.ts @ 75,76
|
// ERROR 1161: "Unterminated regular expression literal." in regexp.ts:5:1
|
||||||
// ERROR 1005: "'/' expected." in regexp.ts @ 74,76
|
// ERROR 1005: "'/' expected." in regexp.ts:5:0
|
||||||
// ERROR 209: "Invalid regular expression flags." in regexp.ts @ 95,98
|
// ERROR 209: "Invalid regular expression flags." in regexp.ts:8:9
|
||||||
// ERROR 209: "Invalid regular expression flags." in regexp.ts @ 111,113
|
// ERROR 209: "Invalid regular expression flags." in regexp.ts:9:9
|
||||||
// ERROR 209: "Invalid regular expression flags." in regexp.ts @ 131,133
|
// ERROR 209: "Invalid regular expression flags." in regexp.ts:10:14
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// a host-bindings syntax experiment
|
// a host-bindings syntax experiment
|
||||||
|
|
||||||
@binding(BindingCall.NEW, [ BindingType.STRING ], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.NEW, [ BindingType.STRING ], BindingType.OBJECT_HANDLE)
|
||||||
export class ExternalString {
|
export class ExternalString {
|
||||||
|
|
||||||
|
@ -1,65 +1,65 @@
|
|||||||
@binding(BindingCall.NEW, [BindingType.STRING], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.NEW, [BindingType.STRING], BindingType.OBJECT_HANDLE)
|
||||||
export class ExternalString {
|
export class ExternalString {
|
||||||
@binding(BindingCall.FUNCTION, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.FUNCTION, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||||
static fromCharCode(char: u16, schar: u16 = <u16>-1): String {
|
static fromCharCode(char: u16, schar: u16 = <u16>-1): String {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.FUNCTION, [BindingType.U32], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.FUNCTION, [BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||||
static fromCodePoint(codepoint: u32): String {
|
static fromCodePoint(codepoint: u32): String {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.U32], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.THIS, [BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||||
charAt(index: u32): String {
|
charAt(index: u32): String {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU)
|
@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU)
|
||||||
charCodeAt(index: u32): u16 {
|
charCodeAt(index: u32): u16 {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU)
|
@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU)
|
||||||
codePointAt(index: u32): u32 {
|
codePointAt(index: u32): u32 {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.OBJECT_HANDLE)
|
||||||
@operator("+")
|
@operator("+")
|
||||||
concat(other: String): String {
|
concat(other: String): String {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||||
endsWith(other: String): bool {
|
endsWith(other: String): bool {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||||
indexOf(other: String): i32 {
|
indexOf(other: String): i32 {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||||
startsWith(other: String): bool {
|
startsWith(other: String): bool {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||||
substr(start: i32, length: i32): String {
|
substr(start: i32, length: i32): String {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||||
substring(start: i32, end: i32): String {
|
substring(start: i32, end: i32): String {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
||||||
trim(): String {
|
trim(): String {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
||||||
trimLeft(): String {
|
trimLeft(): String {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
||||||
trimRight(): String {
|
trimRight(): String {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||||
@operator("==")
|
@operator("==")
|
||||||
equals(other: String): bool {
|
equals(other: String): bool {
|
||||||
return unreachable();
|
return unreachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,8 @@ var b: i32;
|
|||||||
const c: i32 = 0;
|
const c: i32 = 0;
|
||||||
var d = 2;
|
var d = 2;
|
||||||
|
|
||||||
var e; // type expected
|
// 1110: Type expected.
|
||||||
const f: i32; // must be initialized
|
var e;
|
||||||
|
|
||||||
|
// 1155: 'const' declarations must be initialized.
|
||||||
|
const f: i32;
|
||||||
|
@ -4,5 +4,5 @@ const c: i32 = 0;
|
|||||||
var d = 2;
|
var d = 2;
|
||||||
var e;
|
var e;
|
||||||
const f: i32;
|
const f: i32;
|
||||||
// ERROR 1110: "Type expected." in var.ts @ 59,59
|
// ERROR 1110: "Type expected." in var.ts:7:5
|
||||||
// ERROR 1155: "'const' declarations must be initialized." in var.ts @ 84,85
|
// ERROR 1155: "'const' declarations must be initialized." in var.ts:10:6
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
while (1) {
|
while (1) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
while (false) {
|
while (false) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
while ("str") {
|
while ("str") {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
while (1) ;
|
while (1);
|
||||||
|
@ -7,24 +7,27 @@ require("../src/glue/js");
|
|||||||
const { Tokenizer, Token } = require("../src/tokenizer");
|
const { Tokenizer, Token } = require("../src/tokenizer");
|
||||||
const { Source, SourceKind } = require("../src/ast");
|
const { Source, SourceKind } = require("../src/ast");
|
||||||
|
|
||||||
const text = fs.readFileSync(__dirname + "/../src/tokenizer.ts").toString();
|
var file = process.argv.length > 2 ? process.argv[2] : path.join(__dirname, "..", "src", "tokenizer.ts");
|
||||||
|
const text = fs.readFileSync(file).toString();
|
||||||
const tn = new Tokenizer(new Source("compiler.ts", text, SourceKind.ENTRY));
|
const tn = new Tokenizer(new Source("compiler.ts", text, SourceKind.ENTRY));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let token = tn.next();
|
let token = tn.next();
|
||||||
|
let range = tn.range();
|
||||||
|
process.stdout.write(Token[token] + " @ " + range.line + ":" + range.column);
|
||||||
if (token == Token.IDENTIFIER) {
|
if (token == Token.IDENTIFIER) {
|
||||||
console.log(Token[token] + " > " + tn.readIdentifier());
|
process.stdout.write(" > " + tn.readIdentifier());
|
||||||
} else if (token == Token.INTEGERLITERAL) {
|
} else if (token == Token.INTEGERLITERAL) {
|
||||||
console.log(Token[token] + " > " + tn.readInteger());
|
process.stdout.write(" > " + tn.readInteger());
|
||||||
} else if (token == Token.FLOATLITERAL) {
|
} else if (token == Token.FLOATLITERAL) {
|
||||||
console.log(Token[token] + " > " + tn.readFloat());
|
process.stdout.write(" > " + tn.readFloat());
|
||||||
} else if (token == Token.STRINGLITERAL) {
|
} else if (token == Token.STRINGLITERAL) {
|
||||||
console.log(Token[token] + " > " + tn.readString());
|
process.stdout.write(" > " + tn.readString());
|
||||||
} else if (token == Token.ENDOFFILE) {
|
} else if (token == Token.ENDOFFILE) {
|
||||||
console.log(Token[token]);
|
process.stdout.write("\n");
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
let range = tn.range();
|
process.stdout.write(" > " + range.source.text.substring(range.start, range.end));
|
||||||
console.log(Token[token] + " > " + range.source.text.substring(range.start, range.end));
|
|
||||||
}
|
}
|
||||||
|
process.stdout.write("\n");
|
||||||
} while (true);
|
} while (true);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user