mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 07:02:13 +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
|
||||
const compilerOptions = assemblyscript.createOptions();
|
||||
assemblyscript.setTarget(compilerOptions, 0);
|
||||
@ -301,7 +304,7 @@ exports.main = function main(argv, options, callback) {
|
||||
(() => {
|
||||
try {
|
||||
stats.compileTime += measure(() => {
|
||||
module = assemblyscript.compile(parser, compilerOptions);
|
||||
module = assemblyscript.compileProgram(program, compilerOptions);
|
||||
});
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
@ -434,23 +437,23 @@ exports.main = function main(argv, options, callback) {
|
||||
: path.basename(args.binaryFile) + ".map"
|
||||
: null;
|
||||
|
||||
let binary;
|
||||
let wasm;
|
||||
stats.emitCount++;
|
||||
stats.emitTime += measure(() => {
|
||||
binary = module.toBinary(sourceMapURL)
|
||||
wasm = module.toBinary(sourceMapURL)
|
||||
});
|
||||
|
||||
if (args.binaryFile.length) {
|
||||
writeFile(path.join(baseDir, args.binaryFile), binary.output);
|
||||
writeFile(path.join(baseDir, args.binaryFile), wasm.output);
|
||||
} else {
|
||||
writeStdout(binary.output);
|
||||
writeStdout(wasm.output);
|
||||
hasStdout = true;
|
||||
}
|
||||
|
||||
// Post-process source map
|
||||
if (binary.sourceMap != null) {
|
||||
if (wasm.sourceMap != null) {
|
||||
if (args.binaryFile.length) {
|
||||
let sourceMap = JSON.parse(binary.sourceMap);
|
||||
let sourceMap = JSON.parse(wasm.sourceMap);
|
||||
sourceMap.sourceRoot = exports.sourceMapRoot;
|
||||
sourceMap.sources.forEach((name, index) => {
|
||||
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
|
||||
if (args.asmjsFile != null) {
|
||||
let asm;
|
||||
@ -524,6 +503,62 @@ exports.main = function main(argv, options, callback) {
|
||||
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();
|
||||
|
10
bin/asc.json
10
bin/asc.json
@ -62,6 +62,16 @@
|
||||
"type": "string",
|
||||
"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": {
|
||||
"desc": [
|
||||
"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: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: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": [
|
||||
"bin/",
|
||||
|
178
src/ast.ts
178
src/ast.ts
@ -1,4 +1,5 @@
|
||||
import {
|
||||
CommonFlags,
|
||||
PATH_DELIMITER,
|
||||
STATIC_DELIMITER,
|
||||
INSTANCE_DELIMITER
|
||||
@ -37,7 +38,6 @@ export enum NodeKind {
|
||||
ELEMENTACCESS,
|
||||
FALSE,
|
||||
FUNCTION,
|
||||
FUNCTIONARROW,
|
||||
LITERAL,
|
||||
NEW,
|
||||
NULL,
|
||||
@ -86,7 +86,6 @@ export enum NodeKind {
|
||||
|
||||
// special
|
||||
DECORATOR,
|
||||
MODIFIER,
|
||||
EXPORTMEMBER,
|
||||
SWITCHCASE
|
||||
}
|
||||
@ -100,6 +99,15 @@ export abstract class Node {
|
||||
range: Range;
|
||||
/** Parent node. */
|
||||
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
|
||||
|
||||
@ -212,13 +220,6 @@ export abstract class Node {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createModifier(kind: ModifierKind, range: Range): ModifierNode {
|
||||
var elem = new ModifierNode();
|
||||
elem.range = range;
|
||||
elem.modifierKind = kind;
|
||||
return elem;
|
||||
}
|
||||
|
||||
// expressions
|
||||
|
||||
static createIdentifierExpression(
|
||||
@ -341,12 +342,10 @@ export abstract class Node {
|
||||
}
|
||||
|
||||
static createFunctionExpression(
|
||||
declaration: FunctionDeclaration,
|
||||
isArrow: bool = false
|
||||
declaration: FunctionDeclaration
|
||||
): FunctionExpression {
|
||||
var expr = isArrow
|
||||
? new FunctionArrowExpression()
|
||||
: new FunctionExpression();
|
||||
var expr = new FunctionExpression();
|
||||
expr.flags = declaration.flags & CommonFlags.ARROW;
|
||||
expr.range = declaration.range;
|
||||
expr.declaration = declaration;
|
||||
return expr;
|
||||
@ -518,18 +517,18 @@ export abstract class Node {
|
||||
extendsType: TypeNode | null, // can't be a function
|
||||
implementsTypes: TypeNode[], // can't be a function
|
||||
members: DeclarationStatement[],
|
||||
modifiers: ModifierNode[] | null,
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): ClassDeclaration {
|
||||
var stmt = new ClassDeclaration();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = identifier; identifier.parent = stmt;
|
||||
stmt.typeParameters = typeParameters; setParent(typeParameters, stmt);
|
||||
stmt.extendsType = extendsType; if (extendsType) extendsType.parent = stmt;
|
||||
stmt.implementsTypes = implementsTypes; setParent(implementsTypes, stmt);
|
||||
stmt.members = members; setParent(members, stmt);
|
||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||
return stmt;
|
||||
}
|
||||
@ -567,15 +566,15 @@ export abstract class Node {
|
||||
static createEnumDeclaration(
|
||||
name: IdentifierExpression,
|
||||
members: EnumValueDeclaration[],
|
||||
modifiers: ModifierNode[] | null,
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): EnumDeclaration {
|
||||
var stmt = new EnumDeclaration();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = name; name.parent = stmt;
|
||||
stmt.values = members; setParent(members, stmt);
|
||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||
return stmt;
|
||||
}
|
||||
@ -583,10 +582,12 @@ export abstract class Node {
|
||||
static createEnumValueDeclaration(
|
||||
name: IdentifierExpression,
|
||||
value: Expression | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): EnumValueDeclaration {
|
||||
var stmt = new EnumValueDeclaration();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = name; name.parent = stmt;
|
||||
stmt.value = value; if (value) value.parent = stmt;
|
||||
return stmt;
|
||||
@ -595,11 +596,12 @@ export abstract class Node {
|
||||
static createExportStatement(
|
||||
members: ExportMember[],
|
||||
path: StringLiteralExpression | null,
|
||||
modifiers: ModifierNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): ExportStatement {
|
||||
var stmt = new ExportStatement();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.members = members; setParent(members, stmt);
|
||||
stmt.path = path;
|
||||
if (path) {
|
||||
@ -617,7 +619,6 @@ export abstract class Node {
|
||||
stmt.normalizedPath = null;
|
||||
stmt.internalPath = null;
|
||||
}
|
||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@ -735,15 +736,15 @@ export abstract class Node {
|
||||
name: IdentifierExpression,
|
||||
extendsType: TypeNode | null, // can't be a function
|
||||
members: DeclarationStatement[],
|
||||
modifiers: ModifierNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): InterfaceDeclaration {
|
||||
var stmt = new InterfaceDeclaration();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = name; name.parent = stmt;
|
||||
stmt.extendsType = extendsType; if (extendsType) extendsType.parent = stmt;
|
||||
stmt.members = members; setParent(members, stmt);
|
||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@ -751,16 +752,16 @@ export abstract class Node {
|
||||
name: IdentifierExpression,
|
||||
type: CommonTypeNode | null,
|
||||
initializer: Expression | null,
|
||||
modifiers: ModifierNode[] | null,
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): FieldDeclaration {
|
||||
var stmt = new FieldDeclaration();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = name; name.parent = stmt;
|
||||
stmt.type = type; if (type) type.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);
|
||||
return stmt;
|
||||
}
|
||||
@ -786,17 +787,17 @@ export abstract class Node {
|
||||
typeParameters: TypeParameterNode[] | null,
|
||||
signature: SignatureNode,
|
||||
body: Statement | null,
|
||||
modifiers: ModifierNode[] | null,
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): FunctionDeclaration {
|
||||
var stmt = new FunctionDeclaration();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = name; name.parent = stmt;
|
||||
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
||||
stmt.signature = signature; signature.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);
|
||||
return stmt;
|
||||
}
|
||||
@ -806,17 +807,17 @@ export abstract class Node {
|
||||
typeParameters: TypeParameterNode[] | null,
|
||||
signature: SignatureNode,
|
||||
body: Statement | null,
|
||||
modifiers: ModifierNode[] | null,
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): MethodDeclaration {
|
||||
var stmt = new MethodDeclaration();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = name; name.parent = stmt;
|
||||
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
||||
stmt.signature = signature; signature.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);
|
||||
return stmt;
|
||||
}
|
||||
@ -824,15 +825,15 @@ export abstract class Node {
|
||||
static createNamespaceDeclaration(
|
||||
name: IdentifierExpression,
|
||||
members: Statement[],
|
||||
modifiers: ModifierNode[] | null,
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): NamespaceDeclaration {
|
||||
var stmt = new NamespaceDeclaration();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = name; name.parent = stmt;
|
||||
stmt.members = members; setParent(members, stmt);
|
||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||
return stmt;
|
||||
}
|
||||
@ -904,30 +905,30 @@ export abstract class Node {
|
||||
name: IdentifierExpression,
|
||||
typeParameters: TypeParameterNode[] | null,
|
||||
alias: CommonTypeNode,
|
||||
modifiers: ModifierNode[] | null,
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): TypeDeclaration {
|
||||
var stmt = new TypeDeclaration();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.name = name; name.parent = stmt;
|
||||
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
|
||||
stmt.type = alias; alias.parent = stmt;
|
||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createVariableStatement(
|
||||
declarations: VariableDeclaration[],
|
||||
modifiers: ModifierNode[] | null,
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): VariableStatement {
|
||||
var stmt = new VariableStatement();
|
||||
stmt.range = range;
|
||||
stmt.flags = flags;
|
||||
stmt.declarations = declarations; setParent(declarations, stmt);
|
||||
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
|
||||
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
|
||||
return stmt;
|
||||
}
|
||||
@ -936,16 +937,16 @@ export abstract class Node {
|
||||
name: IdentifierExpression,
|
||||
type: CommonTypeNode | null,
|
||||
initializer: Expression | null,
|
||||
modifiers: ModifierNode[] | null,
|
||||
decorators: DecoratorNode[] | null,
|
||||
flags: CommonFlags,
|
||||
range: Range
|
||||
): VariableDeclaration {
|
||||
var elem = new VariableDeclaration();
|
||||
elem.range = range;
|
||||
elem.flags = flags;
|
||||
elem.name = name; name.parent = elem;
|
||||
elem.type = type; if (type) type.parent = elem;
|
||||
elem.initializer = initializer; if (initializer) initializer.parent = elem;
|
||||
elem.modifiers = modifiers; // inherited from parent VariableStatement
|
||||
elem.decorators = decorators; // inherited
|
||||
return elem;
|
||||
}
|
||||
@ -1061,32 +1062,6 @@ export class DecoratorNode extends Node {
|
||||
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
|
||||
|
||||
/** Base class of all expression nodes. */
|
||||
@ -1208,11 +1183,6 @@ export class FunctionExpression extends Expression {
|
||||
declaration: FunctionDeclaration;
|
||||
}
|
||||
|
||||
/** Represents an arrow function expression. */
|
||||
export class FunctionArrowExpression extends FunctionExpression {
|
||||
kind = NodeKind.FUNCTIONARROW;
|
||||
}
|
||||
|
||||
/** Represents an integer literal expression. */
|
||||
export class IntegerLiteralExpression extends LiteralExpression {
|
||||
literalKind = LiteralKind.INTEGER;
|
||||
@ -1380,8 +1350,6 @@ export abstract class DeclarationStatement extends Statement {
|
||||
|
||||
/** Simple name being declared. */
|
||||
name: IdentifierExpression;
|
||||
/** Array of modifiers. */
|
||||
modifiers: ModifierNode[] | null;
|
||||
/** Array of decorators. */
|
||||
decorators: DecoratorNode[] | null = null;
|
||||
|
||||
@ -1423,21 +1391,12 @@ export abstract class DeclarationStatement extends Statement {
|
||||
return false;
|
||||
}
|
||||
if (parent.kind == NodeKind.NAMESPACEDECLARATION) {
|
||||
return (
|
||||
hasModifier(ModifierKind.EXPORT, this.modifiers) &&
|
||||
(<NamespaceDeclaration>parent).isTopLevelExport
|
||||
);
|
||||
return this.is(CommonFlags.EXPORT) && (<NamespaceDeclaration>parent).isTopLevelExport;
|
||||
}
|
||||
if (parent.kind == NodeKind.CLASSDECLARATION) {
|
||||
return (
|
||||
hasModifier(ModifierKind.STATIC, this.modifiers) &&
|
||||
(<ClassDeclaration>parent).isTopLevelExport
|
||||
);
|
||||
return this.is(CommonFlags.STATIC) && (<ClassDeclaration>parent).isTopLevelExport;
|
||||
}
|
||||
return (
|
||||
parent.kind == NodeKind.SOURCE &&
|
||||
hasModifier(ModifierKind.EXPORT, this.modifiers)
|
||||
);
|
||||
return parent.kind == NodeKind.SOURCE && this.is(CommonFlags.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. */
|
||||
export class EnumValueDeclaration extends DeclarationStatement {
|
||||
kind = NodeKind.ENUMVALUEDECLARATION;
|
||||
modifiers = null;
|
||||
// name is inherited
|
||||
|
||||
/** Value expression. */
|
||||
@ -1562,8 +1520,6 @@ export class ExportMember extends Node {
|
||||
export class ExportStatement extends Statement {
|
||||
kind = NodeKind.EXPORT;
|
||||
|
||||
/** Array of modifiers. */
|
||||
modifiers: ModifierNode[] | null;
|
||||
/** Array of members. */
|
||||
members: ExportMember[];
|
||||
/** Path being exported from, if applicable. */
|
||||
@ -1636,7 +1592,6 @@ export class IfStatement extends Statement {
|
||||
/** Represents an `import` declaration part of an {@link ImportStatement}. */
|
||||
export class ImportDeclaration extends DeclarationStatement {
|
||||
kind = NodeKind.IMPORTDECLARATION;
|
||||
modifiers = null;
|
||||
|
||||
/** Identifier being imported. */
|
||||
externalName: IdentifierExpression;
|
||||
@ -1739,17 +1694,12 @@ export class TypeDeclaration extends DeclarationStatement {
|
||||
/** Represents a variable declaration part of a {@link VariableStatement}. */
|
||||
export class VariableDeclaration extends VariableLikeDeclarationStatement {
|
||||
kind = NodeKind.VARIABLEDECLARATION;
|
||||
|
||||
/** Array of modifiers. */
|
||||
modifiers: ModifierNode[] | null;
|
||||
}
|
||||
|
||||
/** Represents a variable statement wrapping {@link VariableDeclaration}s. */
|
||||
export class VariableStatement extends Statement {
|
||||
kind = NodeKind.VARIABLE;
|
||||
|
||||
/** Array of modifiers. */
|
||||
modifiers: ModifierNode[] | null;
|
||||
/** Array of decorators. */
|
||||
decorators: DecoratorNode[] | null;
|
||||
/** Array of member declarations. */
|
||||
@ -1774,52 +1724,6 @@ export class WhileStatement extends 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. */
|
||||
export function getFirstDecorator(name: string, decorators: DecoratorNode[] | null): DecoratorNode | null {
|
||||
if (decorators) {
|
||||
@ -1852,7 +1756,7 @@ export function mangleInternalName(declaration: DeclarationStatement, asGlobal:
|
||||
}
|
||||
if (parent.kind == NodeKind.CLASSDECLARATION) {
|
||||
return mangleInternalName(<ClassDeclaration>parent, asGlobal) + (
|
||||
hasModifier(ModifierKind.STATIC, declaration.modifiers)
|
||||
declaration.is(CommonFlags.STATIC)
|
||||
? STATIC_DELIMITER
|
||||
: INSTANCE_DELIMITER
|
||||
) + name;
|
||||
|
@ -2338,7 +2338,7 @@ export function compileAllocate(
|
||||
var module = compiler.module;
|
||||
var options = compiler.options;
|
||||
|
||||
var prototype = program.elements.get(options.allocateImpl);
|
||||
var prototype = program.elementsLookup.get(options.allocateImpl);
|
||||
if (!prototype) {
|
||||
program.error(
|
||||
DiagnosticCode.Cannot_find_name_0,
|
||||
@ -2377,10 +2377,10 @@ export function compileAbort(
|
||||
var program = compiler.program;
|
||||
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();
|
||||
|
||||
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();
|
||||
|
||||
var abortInstance = (<FunctionPrototype>abortPrototype).resolve(); // reports
|
||||
|
214
src/compiler.ts
214
src/compiler.ts
@ -39,7 +39,7 @@ import {
|
||||
Property,
|
||||
VariableLikeElement,
|
||||
FlowFlags,
|
||||
ElementFlags,
|
||||
CommonFlags,
|
||||
ConstantValueKind,
|
||||
|
||||
PATH_DELIMITER,
|
||||
@ -47,7 +47,8 @@ import {
|
||||
} from "./program";
|
||||
|
||||
import {
|
||||
Token
|
||||
Token,
|
||||
operatorTokenToString
|
||||
} from "./tokenizer";
|
||||
|
||||
import {
|
||||
@ -72,7 +73,6 @@ import {
|
||||
IfStatement,
|
||||
ImportStatement,
|
||||
InterfaceDeclaration,
|
||||
ModifierKind,
|
||||
NamespaceDeclaration,
|
||||
ReturnStatement,
|
||||
SwitchStatement,
|
||||
@ -102,9 +102,7 @@ import {
|
||||
ArrayLiteralExpression,
|
||||
StringLiteralExpression,
|
||||
UnaryPostfixExpression,
|
||||
UnaryPrefixExpression,
|
||||
|
||||
hasModifier
|
||||
UnaryPrefixExpression
|
||||
} from "./ast";
|
||||
|
||||
import {
|
||||
@ -239,14 +237,13 @@ export class Compiler extends DiagnosticEmitter {
|
||||
program.initialize(options);
|
||||
|
||||
// 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);
|
||||
var startFunctionInstance = new Function(
|
||||
<FunctionPrototype>startFunctionPrototype,
|
||||
startFunctionPrototype.internalName,
|
||||
new Signature([], Type.void)
|
||||
);
|
||||
startFunctionInstance.set(ElementFlags.START);
|
||||
this.startFunction = startFunctionInstance;
|
||||
this.currentFunction = startFunctionInstance;
|
||||
|
||||
@ -383,10 +380,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
switch (statement.kind) {
|
||||
case NodeKind.CLASSDECLARATION: {
|
||||
if (
|
||||
(
|
||||
noTreeShaking ||
|
||||
(isEntry && hasModifier(ModifierKind.EXPORT, (<ClassDeclaration>statement).modifiers))
|
||||
) &&
|
||||
(noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) &&
|
||||
!(<ClassDeclaration>statement).isGeneric
|
||||
) {
|
||||
this.compileClassDeclaration(<ClassDeclaration>statement, []);
|
||||
@ -394,20 +388,14 @@ export class Compiler extends DiagnosticEmitter {
|
||||
break;
|
||||
}
|
||||
case NodeKind.ENUMDECLARATION: {
|
||||
if (
|
||||
noTreeShaking ||
|
||||
(isEntry && hasModifier(ModifierKind.EXPORT, (<EnumDeclaration>statement).modifiers))
|
||||
) {
|
||||
if (noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) {
|
||||
this.compileEnumDeclaration(<EnumDeclaration>statement);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeKind.FUNCTIONDECLARATION: {
|
||||
if (
|
||||
(
|
||||
noTreeShaking ||
|
||||
(isEntry && hasModifier(ModifierKind.EXPORT, (<FunctionDeclaration>statement).modifiers))
|
||||
) &&
|
||||
(noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) &&
|
||||
!(<FunctionDeclaration>statement).isGeneric
|
||||
) {
|
||||
this.compileFunctionDeclaration(<FunctionDeclaration>statement, []);
|
||||
@ -422,10 +410,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
break;
|
||||
}
|
||||
case NodeKind.NAMESPACEDECLARATION: {
|
||||
if (
|
||||
noTreeShaking ||
|
||||
(isEntry && hasModifier(ModifierKind.EXPORT, (<NamespaceDeclaration>statement).modifiers))
|
||||
) {
|
||||
if (noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) {
|
||||
this.compileNamespaceDeclaration(<NamespaceDeclaration>statement);
|
||||
}
|
||||
break;
|
||||
@ -462,15 +447,15 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
compileGlobalDeclaration(declaration: VariableDeclaration): Global | null {
|
||||
// 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);
|
||||
if (!this.compileGlobal(<Global>element)) return null; // reports
|
||||
return <Global>element;
|
||||
}
|
||||
|
||||
compileGlobal(global: Global): bool {
|
||||
if (global.is(ElementFlags.COMPILED) || global.is(ElementFlags.BUILTIN)) return true;
|
||||
global.set(ElementFlags.COMPILED); // ^ built-ins are compiled on use
|
||||
if (global.is(CommonFlags.COMPILED) || global.is(CommonFlags.BUILTIN)) return true;
|
||||
global.set(CommonFlags.COMPILED); // ^ built-ins are compiled on use
|
||||
|
||||
var module = this.module;
|
||||
var declaration = global.declaration;
|
||||
@ -520,10 +505,11 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var nativeType = global.type.toNativeType();
|
||||
|
||||
// handle imports
|
||||
if (global.is(ElementFlags.DECLARED)) {
|
||||
if (global.is(CommonFlags.DECLARE)) {
|
||||
|
||||
// constant global
|
||||
if (global.is(ElementFlags.CONSTANT)) {
|
||||
if (global.is(CommonFlags.CONST)) {
|
||||
global.set(CommonFlags.MODULE_IMPORT);
|
||||
module.addGlobalImport(
|
||||
global.internalName,
|
||||
global.namespace
|
||||
@ -532,7 +518,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
global.simpleName,
|
||||
nativeType
|
||||
);
|
||||
global.set(ElementFlags.COMPILED);
|
||||
global.set(CommonFlags.COMPILED);
|
||||
return true;
|
||||
|
||||
// importing mutable globals is not supported in the MVP
|
||||
@ -550,7 +536,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var initializeInStart = false;
|
||||
|
||||
// inlined constant can be compiled as-is
|
||||
if (global.is(ElementFlags.INLINED)) {
|
||||
if (global.is(CommonFlags.INLINED)) {
|
||||
initExpr = this.compileInlineConstant(global, global.type, true);
|
||||
|
||||
} else {
|
||||
@ -565,7 +551,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
||||
|
||||
// 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);
|
||||
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
||||
this.warning(
|
||||
@ -593,7 +579,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
} else { // compile as-is
|
||||
|
||||
if (global.is(ElementFlags.CONSTANT)) {
|
||||
if (global.is(CommonFlags.CONST)) {
|
||||
let exprType = _BinaryenExpressionGetType(initExpr);
|
||||
switch (exprType) {
|
||||
case NativeType.I32: {
|
||||
@ -630,7 +616,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
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
|
||||
module.addGlobal(internalName, nativeType, false, initExpr);
|
||||
}
|
||||
@ -639,7 +625,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
} else /* mutable */ {
|
||||
module.addGlobal(internalName, nativeType, !global.is(ElementFlags.CONSTANT), initExpr);
|
||||
module.addGlobal(internalName, nativeType, !global.is(CommonFlags.CONST), initExpr);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -648,15 +634,15 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// enums
|
||||
|
||||
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);
|
||||
if (!this.compileEnum(<Enum>element)) return null;
|
||||
return <Enum>element;
|
||||
}
|
||||
|
||||
compileEnum(element: Enum): bool {
|
||||
if (element.is(ElementFlags.COMPILED)) return true;
|
||||
element.set(ElementFlags.COMPILED);
|
||||
if (element.is(CommonFlags.COMPILED)) return true;
|
||||
element.set(CommonFlags.COMPILED);
|
||||
|
||||
var module = this.module;
|
||||
this.currentEnum = element;
|
||||
@ -668,8 +654,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
let initInStart = false;
|
||||
let val = <EnumValue>member;
|
||||
let valueDeclaration = val.declaration;
|
||||
val.set(ElementFlags.COMPILED);
|
||||
if (val.is(ElementFlags.INLINED)) {
|
||||
val.set(CommonFlags.COMPILED);
|
||||
if (val.is(CommonFlags.INLINED)) {
|
||||
if (element.declaration.isTopLevelExport) {
|
||||
module.addGlobal(
|
||||
val.internalName,
|
||||
@ -685,7 +671,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
||||
initExpr = this.precomputeExpressionRef(initExpr);
|
||||
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
|
||||
if (element.is(ElementFlags.CONSTANT)) {
|
||||
if (element.is(CommonFlags.CONST)) {
|
||||
this.warning(
|
||||
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
|
||||
valueDeclaration.range
|
||||
@ -696,7 +682,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
} else if (previousValue == null) {
|
||||
initExpr = module.createI32(0);
|
||||
} else if (previousValue.is(ElementFlags.INLINED)) {
|
||||
} else if (previousValue.is(CommonFlags.INLINED)) {
|
||||
initExpr = module.createI32(previousValue.constantValue + 1);
|
||||
} else {
|
||||
// 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.createI32(1)
|
||||
);
|
||||
if (element.is(ElementFlags.CONSTANT)) {
|
||||
if (element.is(CommonFlags.CONST)) {
|
||||
this.warning(
|
||||
DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable,
|
||||
valueDeclaration.range
|
||||
@ -724,7 +710,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
module.addGlobal(val.internalName, NativeType.I32, false, initExpr);
|
||||
if (_BinaryenExpressionGetType(initExpr) == NativeType.I32) {
|
||||
val.constantValue = _BinaryenConstGetValueI32(initExpr);
|
||||
val.set(ElementFlags.INLINED);
|
||||
val.set(CommonFlags.INLINED);
|
||||
} else {
|
||||
assert(false);
|
||||
this.error(
|
||||
@ -739,7 +725,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// export values if the enum is exported
|
||||
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);
|
||||
} else if (valueDeclaration) {
|
||||
this.warning(
|
||||
@ -762,7 +748,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
typeArguments: TypeNode[],
|
||||
contextualTypeArguments: Map<string,Type> | null = 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);
|
||||
return this.compileFunctionUsingTypeArguments( // reports
|
||||
<FunctionPrototype>element,
|
||||
@ -816,22 +802,22 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
/** Compiles a readily resolved function instance. */
|
||||
compileFunction(instance: Function): bool {
|
||||
if (instance.is(ElementFlags.COMPILED)) return true;
|
||||
assert(!instance.is(ElementFlags.BUILTIN) || instance.simpleName == "abort");
|
||||
instance.set(ElementFlags.COMPILED);
|
||||
if (instance.is(CommonFlags.COMPILED)) return true;
|
||||
assert(!instance.is(CommonFlags.BUILTIN) || instance.simpleName == "abort");
|
||||
instance.set(CommonFlags.COMPILED);
|
||||
|
||||
// check that modifiers are matching but still compile as-is
|
||||
var declaration = instance.prototype.declaration;
|
||||
var body = declaration.body;
|
||||
if (body) {
|
||||
if (instance.is(ElementFlags.DECLARED)) {
|
||||
if (instance.is(CommonFlags.DECLARE)) {
|
||||
this.error(
|
||||
DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts,
|
||||
declaration.name.range
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!instance.is(ElementFlags.DECLARED)) {
|
||||
if (!instance.is(CommonFlags.DECLARE)) {
|
||||
this.error(
|
||||
DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
|
||||
declaration.name.range
|
||||
@ -869,7 +855,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
);
|
||||
|
||||
} else {
|
||||
instance.set(ElementFlags.IMPORTED);
|
||||
instance.set(CommonFlags.MODULE_IMPORT);
|
||||
|
||||
// create the function import
|
||||
let namespace = instance.prototype.namespace;
|
||||
@ -902,10 +888,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
switch (member.kind) {
|
||||
case NodeKind.CLASSDECLARATION: {
|
||||
if (
|
||||
(
|
||||
noTreeShaking ||
|
||||
hasModifier(ModifierKind.EXPORT, (<ClassDeclaration>member).modifiers)
|
||||
) && !(<ClassDeclaration>member).isGeneric
|
||||
(noTreeShaking || member.is(CommonFlags.EXPORT)) &&
|
||||
!(<ClassDeclaration>member).isGeneric
|
||||
) {
|
||||
this.compileClassDeclaration(<ClassDeclaration>member, []);
|
||||
}
|
||||
@ -913,30 +897,22 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
case NodeKind.INTERFACEDECLARATION: {
|
||||
if (
|
||||
(
|
||||
noTreeShaking ||
|
||||
hasModifier(ModifierKind.EXPORT, (<InterfaceDeclaration>member).modifiers)
|
||||
) && !(<InterfaceDeclaration>member).isGeneric
|
||||
(noTreeShaking || member.is(CommonFlags.EXPORT)) &&
|
||||
!(<InterfaceDeclaration>member).isGeneric
|
||||
) {
|
||||
this.compileInterfaceDeclaration(<InterfaceDeclaration>member, []);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeKind.ENUMDECLARATION: {
|
||||
if (
|
||||
noTreeShaking ||
|
||||
hasModifier(ModifierKind.EXPORT, (<EnumDeclaration>member).modifiers)
|
||||
) {
|
||||
if (noTreeShaking || member.is(CommonFlags.EXPORT)) {
|
||||
this.compileEnumDeclaration(<EnumDeclaration>member);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeKind.FUNCTIONDECLARATION: {
|
||||
if (
|
||||
(
|
||||
noTreeShaking ||
|
||||
hasModifier(ModifierKind.EXPORT, (<FunctionDeclaration>member).modifiers)
|
||||
) &&
|
||||
(noTreeShaking || member.is(CommonFlags.EXPORT)) &&
|
||||
!(<FunctionDeclaration>member).isGeneric
|
||||
) {
|
||||
this.compileFunctionDeclaration(<FunctionDeclaration>member, []);
|
||||
@ -944,19 +920,13 @@ export class Compiler extends DiagnosticEmitter {
|
||||
break;
|
||||
}
|
||||
case NodeKind.NAMESPACEDECLARATION: {
|
||||
if (
|
||||
noTreeShaking ||
|
||||
hasModifier(ModifierKind.EXPORT, (<NamespaceDeclaration>member).modifiers)
|
||||
) {
|
||||
if (noTreeShaking || member.is(CommonFlags.EXPORT)) {
|
||||
this.compileNamespaceDeclaration(<NamespaceDeclaration>member);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeKind.VARIABLE: {
|
||||
if (
|
||||
noTreeShaking ||
|
||||
hasModifier(ModifierKind.EXPORT, (<VariableStatement>member).modifiers)
|
||||
) {
|
||||
if (noTreeShaking || member.is(CommonFlags.EXPORT)) {
|
||||
let variableInit = this.compileVariableStatement(<VariableStatement>member, true);
|
||||
if (variableInit) this.startFunctionBody.push(variableInit);
|
||||
}
|
||||
@ -984,8 +954,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
if (
|
||||
(
|
||||
noTreeShaking ||
|
||||
(<ClassPrototype>element).is(ElementFlags.EXPORTED)
|
||||
) && !(<ClassPrototype>element).is(ElementFlags.GENERIC)
|
||||
(<ClassPrototype>element).is(CommonFlags.EXPORT)
|
||||
) && !(<ClassPrototype>element).is(CommonFlags.GENERIC)
|
||||
) {
|
||||
this.compileClassUsingTypeArguments(<ClassPrototype>element, []);
|
||||
}
|
||||
@ -998,8 +968,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||
if (
|
||||
(
|
||||
noTreeShaking || (<FunctionPrototype>element).is(ElementFlags.EXPORTED)
|
||||
) && !(<FunctionPrototype>element).is(ElementFlags.GENERIC)
|
||||
noTreeShaking || (<FunctionPrototype>element).is(CommonFlags.EXPORT)
|
||||
) && !(<FunctionPrototype>element).is(CommonFlags.GENERIC)
|
||||
) {
|
||||
this.compileFunctionUsingTypeArguments(
|
||||
<FunctionPrototype>element,
|
||||
@ -1026,7 +996,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
compileExportStatement(statement: ExportStatement): void {
|
||||
var module = this.module;
|
||||
var exports = this.program.exports;
|
||||
var exports = this.program.fileLevelExports;
|
||||
var members = statement.members;
|
||||
for (let i = 0, k = members.length; i < k; ++i) {
|
||||
let member = members[i];
|
||||
@ -1039,7 +1009,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
if (!element) continue; // reported in Program#initialize
|
||||
switch (element.kind) {
|
||||
case ElementKind.CLASS_PROTOTYPE: {
|
||||
if (!(<ClassPrototype>element).is(ElementFlags.GENERIC)) {
|
||||
if (!(<ClassPrototype>element).is(CommonFlags.GENERIC)) {
|
||||
this.compileClassUsingTypeArguments(<ClassPrototype>element, []);
|
||||
}
|
||||
break;
|
||||
@ -1050,7 +1020,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
case ElementKind.FUNCTION_PROTOTYPE: {
|
||||
if (
|
||||
!(<FunctionPrototype>element).is(ElementFlags.GENERIC) &&
|
||||
!(<FunctionPrototype>element).is(CommonFlags.GENERIC) &&
|
||||
statement.range.source.isEntry
|
||||
) {
|
||||
let functionInstance = this.compileFunctionUsingTypeArguments(
|
||||
@ -1072,7 +1042,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
if (this.compileGlobal(<Global>element) && statement.range.source.isEntry) {
|
||||
let globalDeclaration = (<Global>element).declaration;
|
||||
if (globalDeclaration && globalDeclaration.needsExplicitExport(member)) {
|
||||
if ((<Global>element).is(ElementFlags.INLINED)) {
|
||||
if ((<Global>element).is(CommonFlags.INLINED)) {
|
||||
module.addGlobalExport(element.internalName, member.externalName.text);
|
||||
} else {
|
||||
this.warning(
|
||||
@ -1100,7 +1070,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
contextualTypeArguments: Map<string,Type> | null = null,
|
||||
alternativeReportNode: Node | null = null
|
||||
): 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);
|
||||
this.compileClassUsingTypeArguments(
|
||||
<ClassPrototype>element,
|
||||
@ -1126,8 +1096,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
compileClass(instance: Class): bool {
|
||||
if (instance.is(ElementFlags.COMPILED)) return true;
|
||||
instance.set(ElementFlags.COMPILED);
|
||||
if (instance.is(CommonFlags.COMPILED)) return true;
|
||||
instance.set(CommonFlags.COMPILED);
|
||||
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. */
|
||||
ensureFunctionTableEntry(func: Function): i32 {
|
||||
assert(func.is(ElementFlags.COMPILED));
|
||||
assert(func.is(CommonFlags.COMPILED));
|
||||
if (func.functionTableIndex >= 0) {
|
||||
return func.functionTableIndex;
|
||||
}
|
||||
@ -1671,7 +1641,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (hasModifier(ModifierKind.CONST, declaration.modifiers)) {
|
||||
if (declaration.is(CommonFlags.CONST)) {
|
||||
if (init) {
|
||||
init = this.precomputeExpressionRef(init);
|
||||
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
|
||||
} else {
|
||||
currentFunction.addLocal(type, name); // reports
|
||||
@ -1809,7 +1779,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
contextualType: Type,
|
||||
retainType: bool
|
||||
): ExpressionRef {
|
||||
assert(element.is(ElementFlags.INLINED));
|
||||
assert(element.is(CommonFlags.INLINED));
|
||||
var type = element.type;
|
||||
switch (
|
||||
!retainType &&
|
||||
@ -1913,8 +1883,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
expr = this.compileElementAccessExpression(<ElementAccessExpression>expression, contextualType);
|
||||
break;
|
||||
}
|
||||
case NodeKind.FUNCTION:
|
||||
case NodeKind.FUNCTIONARROW: {
|
||||
case NodeKind.FUNCTION: {
|
||||
expr = this.compileFunctionExpression(<FunctionExpression>expression, contextualType);
|
||||
break;
|
||||
}
|
||||
@ -2582,7 +2551,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
} else {
|
||||
this.error(
|
||||
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;
|
||||
return module.createUnreachable();
|
||||
@ -2648,7 +2617,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
} else {
|
||||
this.error(
|
||||
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;
|
||||
return module.createUnreachable();
|
||||
@ -3183,7 +3152,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case TypeKind.F64: {
|
||||
this.error(
|
||||
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();
|
||||
}
|
||||
@ -3257,7 +3226,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case TypeKind.F64: {
|
||||
this.error(
|
||||
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();
|
||||
}
|
||||
@ -3739,7 +3708,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
switch (element.kind) {
|
||||
case ElementKind.LOCAL: {
|
||||
this.currentType = tee ? (<Local>element).type : Type.void;
|
||||
if ((<Local>element).is(ElementFlags.CONSTANT)) {
|
||||
if ((<Local>element).is(CommonFlags.CONST)) {
|
||||
this.error(
|
||||
DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
|
||||
expression.range, (<Local>element).internalName
|
||||
@ -3755,7 +3724,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
let type = (<Global>element).type;
|
||||
assert(type != Type.void);
|
||||
this.currentType = tee ? type : Type.void;
|
||||
if ((<Local>element).is(ElementFlags.CONSTANT)) {
|
||||
if ((<Local>element).is(CommonFlags.CONST)) {
|
||||
this.error(
|
||||
DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
|
||||
expression.range,
|
||||
@ -3775,7 +3744,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
case ElementKind.FIELD: {
|
||||
if ((<Field>element).prototype.isReadonly) {
|
||||
if ((<Field>element).is(CommonFlags.READONLY)) {
|
||||
this.error(
|
||||
DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
|
||||
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
|
||||
if (!tee) {
|
||||
if (setterInstance.is(ElementFlags.INSTANCE)) {
|
||||
if (setterInstance.is(CommonFlags.INSTANCE)) {
|
||||
assert(resolved.isInstanceTarget);
|
||||
let thisArg = this.compileExpression(
|
||||
<Expression>resolved.targetExpression,
|
||||
@ -3842,7 +3811,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
if (!getterInstance) return module.createUnreachable();
|
||||
let returnType = getterInstance.signature.returnType;
|
||||
let nativeReturnType = returnType.toNativeType();
|
||||
if (setterInstance.is(ElementFlags.INSTANCE)) {
|
||||
if (setterInstance.is(CommonFlags.INSTANCE)) {
|
||||
assert(resolved.isInstanceTarget);
|
||||
let thisArg = this.compileExpression(
|
||||
<Expression>resolved.targetExpression,
|
||||
@ -3956,7 +3925,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
let prototype = <FunctionPrototype>element;
|
||||
|
||||
// builtins are compiled on the fly
|
||||
if (prototype.is(ElementFlags.BUILTIN)) {
|
||||
if (prototype.is(CommonFlags.BUILTIN)) {
|
||||
let expr = compileBuiltinCall( // reports
|
||||
this,
|
||||
prototype,
|
||||
@ -3986,7 +3955,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
);
|
||||
if (!instance) return module.createUnreachable();
|
||||
let thisArg: ExpressionRef = 0;
|
||||
if (instance.is(ElementFlags.INSTANCE)) {
|
||||
if (instance.is(CommonFlags.INSTANCE)) {
|
||||
assert(resolved.isInstanceTarget);
|
||||
thisArg = this.compileExpression(
|
||||
<Expression>resolved.targetExpression,
|
||||
@ -4174,7 +4143,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var originalParameterDeclarations = original.prototype.declaration.signature.parameterTypes;
|
||||
var commonReturnType = originalSignature.returnType;
|
||||
var commonThisType = originalSignature.thisType;
|
||||
var isInstance = original.is(ElementFlags.INSTANCE);
|
||||
var isInstance = original.is(CommonFlags.INSTANCE);
|
||||
|
||||
// arguments excl. `this`, operands incl. `this`
|
||||
var minArguments = originalSignature.requiredParameters;
|
||||
@ -4216,7 +4185,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var trampolineName = originalName + "|trampoline";
|
||||
trampolineSignature.requiredParameters = maxArguments + 1;
|
||||
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;
|
||||
|
||||
// compile initializers of omitted arguments in scope of the trampoline function
|
||||
@ -4278,7 +4248,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var minOperands = minArguments;
|
||||
var maxArguments = instance.signature.parameterTypes.length;
|
||||
var maxOperands = maxArguments;
|
||||
if (instance.is(ElementFlags.INSTANCE)) {
|
||||
if (instance.is(CommonFlags.INSTANCE)) {
|
||||
++minOperands;
|
||||
++maxOperands;
|
||||
--numArguments;
|
||||
@ -4300,7 +4270,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
var returnType = instance.signature.returnType;
|
||||
this.currentType = returnType;
|
||||
if (instance.is(ElementFlags.IMPORTED)) {
|
||||
if (instance.is(CommonFlags.MODULE_IMPORT)) {
|
||||
return module.createCallImport(instance.internalName, operands, returnType.toNativeType());
|
||||
} else {
|
||||
return module.createCall(instance.internalName, operands, returnType.toNativeType());
|
||||
@ -4445,7 +4415,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
case NodeKind.THIS: {
|
||||
let currentFunction = this.currentFunction;
|
||||
if (currentFunction.is(ElementFlags.INSTANCE)) {
|
||||
if (currentFunction.is(CommonFlags.INSTANCE)) {
|
||||
let thisType = assert(currentFunction.instanceMethodOf).type;
|
||||
this.currentType = thisType;
|
||||
return module.createGetLocal(0, thisType.toNativeType());
|
||||
@ -4459,7 +4429,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
case NodeKind.SUPER: {
|
||||
let currentFunction = this.currentFunction;
|
||||
if (currentFunction.is(ElementFlags.INSTANCE)) {
|
||||
if (currentFunction.is(CommonFlags.INSTANCE)) {
|
||||
let base = assert(currentFunction.instanceMethodOf).base;
|
||||
if (base) {
|
||||
let superType = base.type;
|
||||
@ -4487,7 +4457,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var element = resolved.element;
|
||||
switch (element.kind) {
|
||||
case ElementKind.LOCAL: {
|
||||
if ((<Local>element).is(ElementFlags.INLINED)) {
|
||||
if ((<Local>element).is(CommonFlags.INLINED)) {
|
||||
return this.compileInlineConstant(<Local>element, contextualType, retainConstantType);
|
||||
}
|
||||
let localType = (<Local>element).type;
|
||||
@ -4497,7 +4467,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.module.createGetLocal(localIndex, localType.toNativeType());
|
||||
}
|
||||
case ElementKind.GLOBAL: {
|
||||
if (element.is(ElementFlags.BUILTIN)) {
|
||||
if (element.is(CommonFlags.BUILTIN)) {
|
||||
return compileBuiltinGetConstant(this, <Global>element, expression);
|
||||
}
|
||||
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;
|
||||
assert(globalType != Type.void);
|
||||
if ((<Global>element).is(ElementFlags.INLINED)) {
|
||||
if ((<Global>element).is(CommonFlags.INLINED)) {
|
||||
return this.compileInlineConstant(<Global>element, contextualType, retainConstantType);
|
||||
}
|
||||
this.currentType = globalType;
|
||||
return this.module.createGetGlobal((<Global>element).internalName, globalType.toNativeType());
|
||||
}
|
||||
case ElementKind.ENUMVALUE: { // here: if referenced from within the same enum
|
||||
if (!element.is(ElementFlags.COMPILED)) {
|
||||
if (!element.is(CommonFlags.COMPILED)) {
|
||||
this.error(
|
||||
DiagnosticCode.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums,
|
||||
expression.range
|
||||
@ -4521,7 +4491,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
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.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
||||
@ -4547,7 +4517,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
let classType = contextualType.classType;
|
||||
if (
|
||||
classType &&
|
||||
classType == this.program.elements.get("Array") &&
|
||||
classType == this.program.elementsLookup.get("Array") &&
|
||||
classType.typeArguments && classType.typeArguments.length == 1
|
||||
) {
|
||||
return this.compileStaticArray(
|
||||
@ -4698,7 +4668,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
stringSegments.set(stringValue, stringSegment);
|
||||
}
|
||||
var stringOffset = stringSegment.offset;
|
||||
var stringType = this.program.types.get("string");
|
||||
var stringType = this.program.typesLookup.get("string");
|
||||
this.currentType = stringType ? stringType : options.usizeType;
|
||||
if (options.isWasm64) {
|
||||
return module.createI64(i64_low(stringOffset), i64_high(stringOffset));
|
||||
@ -4825,7 +4795,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
if (member.kind == ElementKind.FIELD) {
|
||||
let field = <Field>member;
|
||||
let fieldDeclaration = field.prototype.declaration;
|
||||
if (field.is(ElementFlags.CONSTANT)) {
|
||||
if (field.is(CommonFlags.CONST)) {
|
||||
assert(false); // there are no built-in fields currently
|
||||
} else if (fieldDeclaration && fieldDeclaration.initializer) {
|
||||
initializers.push(module.createStore(field.type.byteSize,
|
||||
@ -4899,7 +4869,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var targetExpr: ExpressionRef;
|
||||
switch (element.kind) {
|
||||
case ElementKind.GLOBAL: { // static property
|
||||
if (element.is(ElementFlags.BUILTIN)) {
|
||||
if (element.is(CommonFlags.BUILTIN)) {
|
||||
return compileBuiltinGetConstant(this, <Global>element, propertyAccess);
|
||||
}
|
||||
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;
|
||||
assert(globalType != Type.void);
|
||||
if ((<Global>element).is(ElementFlags.INLINED)) {
|
||||
if ((<Global>element).is(CommonFlags.INLINED)) {
|
||||
return this.compileInlineConstant(<Global>element, contextualType, retainConstantType);
|
||||
}
|
||||
this.currentType = globalType;
|
||||
@ -4918,7 +4888,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
this.currentType = Type.i32;
|
||||
if ((<EnumValue>element).is(ElementFlags.INLINED)) {
|
||||
if ((<EnumValue>element).is(CommonFlags.INLINED)) {
|
||||
return module.createI32((<EnumValue>element).constantValue);
|
||||
}
|
||||
return module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
||||
@ -4949,7 +4919,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
if (!this.checkCallSignature( // reports
|
||||
signature,
|
||||
0,
|
||||
instance.is(ElementFlags.INSTANCE),
|
||||
instance.is(CommonFlags.INSTANCE),
|
||||
propertyAccess
|
||||
)) {
|
||||
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,
|
||||
Invalid_character = 1127,
|
||||
_case_or_default_expected = 1130,
|
||||
A_declare_modifier_cannot_be_used_in_an_already_ambient_context = 1038,
|
||||
Type_argument_expected = 1140,
|
||||
String_literal_expected = 1141,
|
||||
Line_break_not_permitted_here = 1142,
|
||||
@ -150,6 +151,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 1126: return "Unexpected end of text.";
|
||||
case 1127: return "Invalid character.";
|
||||
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 1141: return "String literal expected.";
|
||||
case 1142: return "Line break not permitted here.";
|
||||
|
@ -49,6 +49,7 @@
|
||||
"Unexpected end of text.": 1126,
|
||||
"Invalid character.": 1127,
|
||||
"'case' or 'default' expected.": 1130,
|
||||
"A 'declare' modifier cannot be used in an already ambient context.": 1038,
|
||||
"Type argument expected.": 1140,
|
||||
"String literal expected.": 1141,
|
||||
"Line break not permitted here.": 1142,
|
||||
|
@ -111,10 +111,10 @@ export class DiagnosticMessage {
|
||||
this.message +
|
||||
"\" in " +
|
||||
this.range.source.normalizedPath +
|
||||
" @ " +
|
||||
this.range.start.toString(10) +
|
||||
"," +
|
||||
this.range.end.toString(10)
|
||||
":" +
|
||||
this.range.line.toString(10) +
|
||||
":" +
|
||||
this.range.column.toString(10)
|
||||
);
|
||||
}
|
||||
return (
|
||||
|
2542
src/extra/ast.ts
2542
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
|
||||
} from "./decompiler";
|
||||
|
||||
import {
|
||||
IDLBuilder,
|
||||
TSDBuilder
|
||||
} from "./definitions";
|
||||
|
||||
import {
|
||||
DiagnosticMessage,
|
||||
DiagnosticCategory,
|
||||
@ -24,6 +29,11 @@ import {
|
||||
Parser
|
||||
} from "./parser";
|
||||
|
||||
import {
|
||||
Program,
|
||||
LIBRARY_PREFIX
|
||||
} from "./program";
|
||||
|
||||
/** Parses a source file. If `parser` has been omitted a new one is created. */
|
||||
export function parseFile(text: string, path: string, isEntry: bool = false,
|
||||
parser: Parser | null = null
|
||||
@ -107,19 +117,32 @@ export function setMemoryBase(options: Options, memoryBase: u32): void {
|
||||
options.memoryBase = memoryBase;
|
||||
}
|
||||
|
||||
/** Finishes parsing. */
|
||||
export function finishParsing(parser: Parser): Program {
|
||||
return parser.finish();
|
||||
}
|
||||
|
||||
/** Compiles the sources computed by the parser to a module. */
|
||||
export function compile(parser: Parser, options: Options | null = null): Module {
|
||||
var program = parser.finish();
|
||||
var compiler = new Compiler(program, options);
|
||||
return compiler.compile();
|
||||
export function compileProgram(program: Program, options: Options | null = null): Module {
|
||||
return new Compiler(program, options).compile();
|
||||
}
|
||||
|
||||
/** Decompiles a module to its (low level) source. */
|
||||
export function decompile(module: Module): string {
|
||||
export function decompileModule(module: Module): string {
|
||||
var decompiler = new Decompiler();
|
||||
decompiler.decompile(module);
|
||||
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. */
|
||||
export { LIBRARY_PREFIX } from "./program";
|
||||
export { LIBRARY_PREFIX };
|
||||
|
817
src/parser.ts
817
src/parser.ts
File diff suppressed because it is too large
Load Diff
772
src/program.ts
772
src/program.ts
File diff suppressed because it is too large
Load Diff
302
src/tokenizer.ts
302
src/tokenizer.ts
@ -176,149 +176,146 @@ export enum Token {
|
||||
ENDOFFILE
|
||||
}
|
||||
|
||||
export namespace Token {
|
||||
|
||||
export function fromKeyword(text: string): Token {
|
||||
switch (text) {
|
||||
case "abstract": return Token.ABSTRACT;
|
||||
case "as": return Token.AS;
|
||||
case "async": return Token.ASYNC;
|
||||
case "await": return Token.AWAIT;
|
||||
case "break": return Token.BREAK;
|
||||
case "case": return Token.CASE;
|
||||
case "catch": return Token.CATCH;
|
||||
case "class": return Token.CLASS;
|
||||
case "continue": return Token.CONTINUE;
|
||||
case "const": return Token.CONST;
|
||||
case "constructor": return Token.CONSTRUCTOR;
|
||||
case "debugger": return Token.DEBUGGER;
|
||||
case "declare": return Token.DECLARE;
|
||||
case "default": return Token.DEFAULT;
|
||||
case "delete": return Token.DELETE;
|
||||
case "do": return Token.DO;
|
||||
case "else": return Token.ELSE;
|
||||
case "enum": return Token.ENUM;
|
||||
case "export": return Token.EXPORT;
|
||||
case "extends": return Token.EXTENDS;
|
||||
case "false": return Token.FALSE;
|
||||
case "finally": return Token.FINALLY;
|
||||
case "for": return Token.FOR;
|
||||
case "from": return Token.FROM;
|
||||
case "function": return Token.FUNCTION;
|
||||
case "get": return Token.GET;
|
||||
case "if": return Token.IF;
|
||||
case "implements": return Token.IMPLEMENTS;
|
||||
case "import": return Token.IMPORT;
|
||||
case "in": return Token.IN;
|
||||
case "instanceof": return Token.INSTANCEOF;
|
||||
case "interface": return Token.INTERFACE;
|
||||
case "is": return Token.IS;
|
||||
case "keyof": return Token.KEYOF;
|
||||
case "let": return Token.LET;
|
||||
case "module": return Token.MODULE;
|
||||
case "namespace": return Token.NAMESPACE;
|
||||
case "new": return Token.NEW;
|
||||
case "null": return Token.NULL;
|
||||
case "of": return Token.OF;
|
||||
case "package": return Token.PACKAGE;
|
||||
case "private": return Token.PRIVATE;
|
||||
case "protected": return Token.PROTECTED;
|
||||
case "public": return Token.PUBLIC;
|
||||
case "readonly": return Token.READONLY;
|
||||
case "return": return Token.RETURN;
|
||||
case "set": return Token.SET;
|
||||
case "static": return Token.STATIC;
|
||||
case "super": return Token.SUPER;
|
||||
case "switch": return Token.SWITCH;
|
||||
case "this": return Token.THIS;
|
||||
case "throw": return Token.THROW;
|
||||
case "true": return Token.TRUE;
|
||||
case "try": return Token.TRY;
|
||||
case "type": return Token.TYPE;
|
||||
case "typeof": return Token.TYPEOF;
|
||||
case "var": return Token.VAR;
|
||||
case "void": return Token.VOID;
|
||||
case "while": return Token.WHILE;
|
||||
case "with": return Token.WITH;
|
||||
case "yield": return Token.YIELD;
|
||||
default: return Token.INVALID;
|
||||
}
|
||||
export function tokenFomKeyword(text: string): Token {
|
||||
switch (text) {
|
||||
case "abstract": return Token.ABSTRACT;
|
||||
case "as": return Token.AS;
|
||||
case "async": return Token.ASYNC;
|
||||
case "await": return Token.AWAIT;
|
||||
case "break": return Token.BREAK;
|
||||
case "case": return Token.CASE;
|
||||
case "catch": return Token.CATCH;
|
||||
case "class": return Token.CLASS;
|
||||
case "continue": return Token.CONTINUE;
|
||||
case "const": return Token.CONST;
|
||||
case "constructor": return Token.CONSTRUCTOR;
|
||||
case "debugger": return Token.DEBUGGER;
|
||||
case "declare": return Token.DECLARE;
|
||||
case "default": return Token.DEFAULT;
|
||||
case "delete": return Token.DELETE;
|
||||
case "do": return Token.DO;
|
||||
case "else": return Token.ELSE;
|
||||
case "enum": return Token.ENUM;
|
||||
case "export": return Token.EXPORT;
|
||||
case "extends": return Token.EXTENDS;
|
||||
case "false": return Token.FALSE;
|
||||
case "finally": return Token.FINALLY;
|
||||
case "for": return Token.FOR;
|
||||
case "from": return Token.FROM;
|
||||
case "function": return Token.FUNCTION;
|
||||
case "get": return Token.GET;
|
||||
case "if": return Token.IF;
|
||||
case "implements": return Token.IMPLEMENTS;
|
||||
case "import": return Token.IMPORT;
|
||||
case "in": return Token.IN;
|
||||
case "instanceof": return Token.INSTANCEOF;
|
||||
case "interface": return Token.INTERFACE;
|
||||
case "is": return Token.IS;
|
||||
case "keyof": return Token.KEYOF;
|
||||
case "let": return Token.LET;
|
||||
case "module": return Token.MODULE;
|
||||
case "namespace": return Token.NAMESPACE;
|
||||
case "new": return Token.NEW;
|
||||
case "null": return Token.NULL;
|
||||
case "of": return Token.OF;
|
||||
case "package": return Token.PACKAGE;
|
||||
case "private": return Token.PRIVATE;
|
||||
case "protected": return Token.PROTECTED;
|
||||
case "public": return Token.PUBLIC;
|
||||
case "readonly": return Token.READONLY;
|
||||
case "return": return Token.RETURN;
|
||||
case "set": return Token.SET;
|
||||
case "static": return Token.STATIC;
|
||||
case "super": return Token.SUPER;
|
||||
case "switch": return Token.SWITCH;
|
||||
case "this": return Token.THIS;
|
||||
case "throw": return Token.THROW;
|
||||
case "true": return Token.TRUE;
|
||||
case "try": return Token.TRY;
|
||||
case "type": return Token.TYPE;
|
||||
case "typeof": return Token.TYPEOF;
|
||||
case "var": return Token.VAR;
|
||||
case "void": return Token.VOID;
|
||||
case "while": return Token.WHILE;
|
||||
case "with": return Token.WITH;
|
||||
case "yield": return Token.YIELD;
|
||||
default: return Token.INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
export function isAlsoIdentifier(token: Token): bool {
|
||||
switch (token) {
|
||||
case Token.ABSTRACT:
|
||||
case Token.AS:
|
||||
case Token.CONSTRUCTOR:
|
||||
case Token.DECLARE:
|
||||
case Token.DELETE:
|
||||
case Token.FROM:
|
||||
case Token.GET:
|
||||
case Token.IS:
|
||||
case Token.KEYOF:
|
||||
case Token.MODULE:
|
||||
case Token.NAMESPACE:
|
||||
case Token.READONLY:
|
||||
case Token.SET:
|
||||
case Token.TYPE: return true;
|
||||
default: return false;
|
||||
}
|
||||
export function tokenIsAlsoIdentifier(token: Token): bool {
|
||||
switch (token) {
|
||||
case Token.ABSTRACT:
|
||||
case Token.AS:
|
||||
case Token.CONSTRUCTOR:
|
||||
case Token.DECLARE:
|
||||
case Token.DELETE:
|
||||
case Token.FROM:
|
||||
case Token.GET:
|
||||
case Token.IS:
|
||||
case Token.KEYOF:
|
||||
case Token.MODULE:
|
||||
case Token.NAMESPACE:
|
||||
case Token.READONLY:
|
||||
case Token.SET:
|
||||
case Token.TYPE: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function operatorToString(token: Token): string {
|
||||
switch (token) {
|
||||
case Token.DELETE: return "delete";
|
||||
case Token.IN: return "in";
|
||||
case Token.INSTANCEOF: return "instanceof";
|
||||
case Token.NEW: return "new";
|
||||
case Token.TYPEOF: return "typeof";
|
||||
case Token.VOID: return "void";
|
||||
case Token.YIELD: return "yield";
|
||||
case Token.DOT_DOT_DOT: return "...";
|
||||
case Token.COMMA: return ",";
|
||||
case Token.LESSTHAN: return "<";
|
||||
case Token.GREATERTHAN: return ">";
|
||||
case Token.LESSTHAN_EQUALS: return "<=";
|
||||
case Token.GREATERTHAN_EQUALS: return ">=";
|
||||
case Token.EQUALS_EQUALS: return "==";
|
||||
case Token.EXCLAMATION_EQUALS: return "!=";
|
||||
case Token.EQUALS_EQUALS_EQUALS: return "===";
|
||||
case Token.EXCLAMATION_EQUALS_EQUALS: return "!==";
|
||||
case Token.PLUS: return "+";
|
||||
case Token.MINUS: return "-";
|
||||
case Token.ASTERISK_ASTERISK: return "**";
|
||||
case Token.ASTERISK: return "*";
|
||||
case Token.SLASH: return "/";
|
||||
case Token.PERCENT: return "%";
|
||||
case Token.PLUS_PLUS: return "++";
|
||||
case Token.MINUS_MINUS: return "--";
|
||||
case Token.LESSTHAN_LESSTHAN: return "<<";
|
||||
case Token.GREATERTHAN_GREATERTHAN: return ">>";
|
||||
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: return ">>>";
|
||||
case Token.AMPERSAND: return "&";
|
||||
case Token.BAR: return "|";
|
||||
case Token.CARET: return "^";
|
||||
case Token.EXCLAMATION: return "!";
|
||||
case Token.TILDE: return "~";
|
||||
case Token.AMPERSAND_AMPERSAND: return "&&";
|
||||
case Token.BAR_BAR: return "||";
|
||||
case Token.EQUALS: return "=";
|
||||
case Token.PLUS_EQUALS: return "+=";
|
||||
case Token.MINUS_EQUALS: return "-=";
|
||||
case Token.ASTERISK_EQUALS: return "*=";
|
||||
case Token.ASTERISK_ASTERISK_EQUALS: return "**=";
|
||||
case Token.SLASH_EQUALS: return "/=";
|
||||
case Token.PERCENT_EQUALS: return "%=";
|
||||
case Token.LESSTHAN_LESSTHAN_EQUALS: return "<<=";
|
||||
case Token.GREATERTHAN_GREATERTHAN_EQUALS: return ">>=";
|
||||
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: return ">>>=";
|
||||
case Token.AMPERSAND_EQUALS: return "&=";
|
||||
case Token.BAR_EQUALS: return "|=";
|
||||
case Token.CARET_EQUALS: return "^=";
|
||||
default: {
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
export function operatorTokenToString(token: Token): string {
|
||||
switch (token) {
|
||||
case Token.DELETE: return "delete";
|
||||
case Token.IN: return "in";
|
||||
case Token.INSTANCEOF: return "instanceof";
|
||||
case Token.NEW: return "new";
|
||||
case Token.TYPEOF: return "typeof";
|
||||
case Token.VOID: return "void";
|
||||
case Token.YIELD: return "yield";
|
||||
case Token.DOT_DOT_DOT: return "...";
|
||||
case Token.COMMA: return ",";
|
||||
case Token.LESSTHAN: return "<";
|
||||
case Token.GREATERTHAN: return ">";
|
||||
case Token.LESSTHAN_EQUALS: return "<=";
|
||||
case Token.GREATERTHAN_EQUALS: return ">=";
|
||||
case Token.EQUALS_EQUALS: return "==";
|
||||
case Token.EXCLAMATION_EQUALS: return "!=";
|
||||
case Token.EQUALS_EQUALS_EQUALS: return "===";
|
||||
case Token.EXCLAMATION_EQUALS_EQUALS: return "!==";
|
||||
case Token.PLUS: return "+";
|
||||
case Token.MINUS: return "-";
|
||||
case Token.ASTERISK_ASTERISK: return "**";
|
||||
case Token.ASTERISK: return "*";
|
||||
case Token.SLASH: return "/";
|
||||
case Token.PERCENT: return "%";
|
||||
case Token.PLUS_PLUS: return "++";
|
||||
case Token.MINUS_MINUS: return "--";
|
||||
case Token.LESSTHAN_LESSTHAN: return "<<";
|
||||
case Token.GREATERTHAN_GREATERTHAN: return ">>";
|
||||
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: return ">>>";
|
||||
case Token.AMPERSAND: return "&";
|
||||
case Token.BAR: return "|";
|
||||
case Token.CARET: return "^";
|
||||
case Token.EXCLAMATION: return "!";
|
||||
case Token.TILDE: return "~";
|
||||
case Token.AMPERSAND_AMPERSAND: return "&&";
|
||||
case Token.BAR_BAR: return "||";
|
||||
case Token.EQUALS: return "=";
|
||||
case Token.PLUS_EQUALS: return "+=";
|
||||
case Token.MINUS_EQUALS: return "-=";
|
||||
case Token.ASTERISK_EQUALS: return "*=";
|
||||
case Token.ASTERISK_ASTERISK_EQUALS: return "**=";
|
||||
case Token.SLASH_EQUALS: return "/=";
|
||||
case Token.PERCENT_EQUALS: return "%=";
|
||||
case Token.LESSTHAN_LESSTHAN_EQUALS: return "<<=";
|
||||
case Token.GREATERTHAN_GREATERTHAN_EQUALS: return ">>=";
|
||||
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: return ">>>=";
|
||||
case Token.AMPERSAND_EQUALS: return "&=";
|
||||
case Token.BAR_EQUALS: return "|=";
|
||||
case Token.CARET_EQUALS: return "^=";
|
||||
default: {
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -356,23 +353,19 @@ export class Range {
|
||||
|
||||
get line(): i32 {
|
||||
var text = this.source.text;
|
||||
var pos = this.start;
|
||||
var line = 1;
|
||||
while (pos-- > 0) {
|
||||
if (text.charCodeAt(pos) == CharCode.LINEFEED) {
|
||||
line++;
|
||||
}
|
||||
for (let pos = this.start; pos >= 0; --pos) {
|
||||
if (text.charCodeAt(pos) == CharCode.LINEFEED) line++;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
get column(): i32 {
|
||||
var text = this.source.text;
|
||||
var pos = this.start;
|
||||
var column = 0;
|
||||
while (pos-- > 0) {
|
||||
for (let pos = this.start - 1; pos >= 0; --pos) {
|
||||
if (text.charCodeAt(pos) == CharCode.LINEFEED) break;
|
||||
column++;
|
||||
++column;
|
||||
}
|
||||
return column;
|
||||
}
|
||||
@ -396,6 +389,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
||||
tokenPos: i32 = 0;
|
||||
|
||||
nextToken: Token = -1;
|
||||
nextTokenPos: i32 = 0;
|
||||
nextTokenOnNewLine: bool = false;
|
||||
|
||||
constructor(source: Source, diagnostics: DiagnosticMessage[] | null = null) {
|
||||
@ -598,9 +592,12 @@ export class Tokenizer extends DiagnosticEmitter {
|
||||
// ) {
|
||||
// }
|
||||
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
|
||||
let closed = false;
|
||||
@ -622,7 +619,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
||||
this.range(this.pos), "*/"
|
||||
);
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||
++this.pos;
|
||||
@ -795,10 +792,10 @@ export class Tokenizer extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
let keywordText = text.substring(posBefore, this.pos);
|
||||
let keywordToken = Token.fromKeyword(keywordText);
|
||||
let keywordToken = tokenFomKeyword(keywordText);
|
||||
if (
|
||||
keywordToken != Token.INVALID &&
|
||||
!(preferIdentifier && Token.isAlsoIdentifier(keywordToken))
|
||||
!(preferIdentifier && tokenIsAlsoIdentifier(keywordToken))
|
||||
) {
|
||||
return keywordToken;
|
||||
}
|
||||
@ -832,6 +829,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
||||
let tokenBefore = this.token;
|
||||
let tokenPosBefore = this.tokenPos;
|
||||
this.nextToken = this.unsafeNext(preferIdentifier, maxCompoundLength);
|
||||
this.nextTokenPos = this.tokenPos;
|
||||
if (checkOnNewLine) {
|
||||
this.nextTokenOnNewLine = false;
|
||||
while (--this.tokenPos > posBefore) {
|
||||
|
@ -100,10 +100,10 @@ export class Type {
|
||||
return ~0 >>> (targetType.size - this.size);
|
||||
}
|
||||
|
||||
/** Tests if this type has the specified capabilities. */
|
||||
is(flags: TypeFlags): bool {
|
||||
return (this.flags & flags) == flags;
|
||||
}
|
||||
/** Tests if this type has the specified flags. */
|
||||
is(flags: TypeFlags): bool { 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. */
|
||||
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.*/
|
||||
declare function changetype<T>(value: any): T;
|
||||
/** 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. */
|
||||
declare function parseInt(str: string, radix?: i32): f64;
|
||||
/** Parses an integer string to a 32-bit integer. */
|
||||
|
@ -427,7 +427,6 @@
|
||||
(local $6 i32)
|
||||
(local $7 i32)
|
||||
(local $8 i32)
|
||||
(local $9 i32)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.ne
|
||||
@ -493,14 +492,14 @@
|
||||
)
|
||||
)
|
||||
(block $break|0
|
||||
(set_local $9
|
||||
(set_local $5
|
||||
(get_local $7)
|
||||
)
|
||||
(loop $continue|0
|
||||
(if
|
||||
(i32.le_s
|
||||
(i32.add
|
||||
(get_local $9)
|
||||
(get_local $5)
|
||||
(get_local $8)
|
||||
)
|
||||
(get_local $4)
|
||||
@ -516,7 +515,7 @@
|
||||
(i32.const 4)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $9)
|
||||
(get_local $5)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
@ -531,13 +530,13 @@
|
||||
)
|
||||
)
|
||||
(return
|
||||
(get_local $9)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $9
|
||||
(set_local $5
|
||||
(i32.add
|
||||
(get_local $9)
|
||||
(get_local $5)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
|
@ -21,10 +21,10 @@ glob.sync(filter, { cwd: __dirname + "/parser" }).forEach(filename => {
|
||||
|
||||
var failed = false;
|
||||
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);
|
||||
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";
|
||||
|
||||
if (isCreate) {
|
||||
|
@ -1,13 +1,27 @@
|
||||
export class Test<T> {
|
||||
instanceFunction(): void {
|
||||
}
|
||||
static staticFunction(): void {
|
||||
}
|
||||
get instanceGetter(): i32 {
|
||||
return 0;
|
||||
}
|
||||
static set staticSetter(v: i32) {
|
||||
}
|
||||
export class Valid<T> {
|
||||
constructor() {}
|
||||
instanceFunction(): void {}
|
||||
static staticFunction(): void {}
|
||||
get instanceGetter(): i32 {}
|
||||
static set staticSetter(v: i32) {}
|
||||
instanceField: 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> {
|
||||
instanceFunction(): void {
|
||||
export class Valid<T> {
|
||||
constructor() {}
|
||||
instanceFunction(): void {}
|
||||
static staticFunction(): void {}
|
||||
get instanceGetter(): i32 {}
|
||||
static set staticSetter(v: i32) {}
|
||||
instanceField: i32;
|
||||
static staticField: i32;
|
||||
}
|
||||
static staticFunction(): void {
|
||||
}
|
||||
get instanceGetter(): i32 {
|
||||
return 0;
|
||||
}
|
||||
static set staticSetter(v: i32) {
|
||||
}
|
||||
instanceField: i32;
|
||||
static staticField: i32;
|
||||
export class Invalid<T> {
|
||||
constructor<T>() {}
|
||||
instanceFunction(): {}
|
||||
get instanceGetter<T>(a: i32): {}
|
||||
set instanceSetter<T>() {}
|
||||
}
|
||||
// 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 {
|
||||
;
|
||||
} while (false);
|
||||
|
@ -3,7 +3,7 @@ a;
|
||||
from;
|
||||
"./other";
|
||||
do {
|
||||
;
|
||||
;
|
||||
} while (false);
|
||||
// ERROR 1003: "Identifier expected." in continue-on-error.ts @ 0,3
|
||||
// ERROR 1005: "'(' expected." in continue-on-error.ts @ 5,10
|
||||
// ERROR 1003: "Identifier expected." in continue-on-error.ts:2:0
|
||||
// ERROR 1005: "'(' expected." in continue-on-error.ts:4:0
|
||||
|
@ -1,5 +1,5 @@
|
||||
do {
|
||||
;
|
||||
} while (a != b);
|
||||
|
||||
do b; while (a);
|
||||
do b;
|
||||
while (a);
|
||||
|
@ -1,5 +1,5 @@
|
||||
do {
|
||||
;
|
||||
;
|
||||
} while (a != b);
|
||||
do b;
|
||||
while (a);
|
||||
|
@ -1,10 +1,10 @@
|
||||
export const enum A {
|
||||
B = 1,
|
||||
C,
|
||||
D = 3
|
||||
B = 1,
|
||||
C,
|
||||
D = 3
|
||||
}
|
||||
enum E {
|
||||
F,
|
||||
G = 1 + 2,
|
||||
H = 3 * 4
|
||||
F,
|
||||
G = 1 + 2,
|
||||
H = 3 * 4
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
for (var i: i32 = 0; i < 10; ++i) {
|
||||
;
|
||||
;
|
||||
}
|
||||
for (i = 0; i < 10; ++i) {
|
||||
;
|
||||
;
|
||||
}
|
||||
for (;;) {
|
||||
;
|
||||
;
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
var a = function(): void {
|
||||
;
|
||||
;
|
||||
};
|
||||
var b = function someName(): void {
|
||||
;
|
||||
;
|
||||
};
|
||||
var c = function(a: i32, b: i32): i32 {
|
||||
;
|
||||
;
|
||||
};
|
||||
var d = (): void => {
|
||||
;
|
||||
;
|
||||
};
|
||||
var e = (a: i32, b: i32): i32 => {
|
||||
;
|
||||
;
|
||||
};
|
||||
var f = (a: i32): i32 => a;
|
||||
|
@ -1,7 +1,4 @@
|
||||
function simple(): void {
|
||||
}
|
||||
function typeparams<T, V extends T>(a: V | null = null): void {
|
||||
}
|
||||
function simple(): void {}
|
||||
function typeparams<T, V extends T>(a: V | null = null): void {}
|
||||
@decorator()
|
||||
function withdecorator(): void {
|
||||
}
|
||||
function withdecorator(): void {}
|
||||
|
@ -1,7 +1,4 @@
|
||||
function simple(): void {
|
||||
}
|
||||
function typeparams<T, V extends T>(a: V | null = null): void {
|
||||
}
|
||||
function simple(): void {}
|
||||
function typeparams<T, V extends T>(a: V | null = null): void {}
|
||||
@decorator()
|
||||
function withdecorator(): void {
|
||||
}
|
||||
function withdecorator(): void {}
|
||||
|
@ -1,9 +1,16 @@
|
||||
import { A } from "./other";
|
||||
|
||||
import { A, B, C } from "./other";
|
||||
|
||||
import { A as B, C, D as E, F } from "./other";
|
||||
|
||||
import {
|
||||
A
|
||||
} from "./other";
|
||||
import {
|
||||
A,
|
||||
B,
|
||||
C
|
||||
} from "./other";
|
||||
import {
|
||||
A as B,
|
||||
C,
|
||||
D as E,
|
||||
F
|
||||
} from "./other";
|
||||
import * as A from "./other";
|
||||
|
||||
import "./other";
|
||||
|
@ -1,16 +1,16 @@
|
||||
import {
|
||||
A
|
||||
A
|
||||
} from "./other";
|
||||
import {
|
||||
A,
|
||||
B,
|
||||
C
|
||||
A,
|
||||
B,
|
||||
C
|
||||
} from "./other";
|
||||
import {
|
||||
A as B,
|
||||
C,
|
||||
D as E,
|
||||
F
|
||||
A as B,
|
||||
C,
|
||||
D as E,
|
||||
F
|
||||
} from "./other";
|
||||
import * as A from "./other";
|
||||
import "./other";
|
||||
|
@ -45,7 +45,6 @@
|
||||
0b0;
|
||||
0b1;
|
||||
0b1111111111111111111111111111111;
|
||||
|
||||
"123";
|
||||
"1\"23";
|
||||
"1\"2\\3";
|
||||
|
@ -1,14 +1,11 @@
|
||||
declare namespace A {
|
||||
namespace B {
|
||||
export namespace C {
|
||||
var aVar: i32;
|
||||
const aConst: i32 = 0;
|
||||
function aFunc(): void {
|
||||
}
|
||||
enum AnEnum {
|
||||
}
|
||||
class AClass {
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace B {
|
||||
export namespace C {
|
||||
var aVar: i32;
|
||||
const aConst: i32 = 0;
|
||||
function aFunc(): void {}
|
||||
enum AnEnum {}
|
||||
class AClass {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,11 @@
|
||||
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 optionalValid(a: i32, b?: i32): void {}
|
||||
// 1016: A required parameter cannot follow an optional parameter.
|
||||
function optionalCannotPrecedeRequired(a?: i32, b: i32): void {}
|
||||
|
||||
// 1016: A required parameter cannot follow an optional parameter.
|
||||
function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {}
|
||||
|
@ -1,13 +1,8 @@
|
||||
function restValid(a: i32, ...b: Array<i32>): void {
|
||||
}
|
||||
function restParameterMustBeLast(...a: Array<i32>, b: i32): void {
|
||||
}
|
||||
function optionalValid(a: i32, b?: i32): void {
|
||||
}
|
||||
function optionalCannotPrecedeRequired(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 @ 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
|
||||
function restValid(a: i32, ...b: Array<i32>): void {}
|
||||
function optionalValid(a: i32, b?: i32): void {}
|
||||
function restParameterMustBeLast(...a: Array<i32>, b: i32): void {}
|
||||
function optionalCannotPrecedeRequired(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
|
||||
// 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
|
||||
|
@ -1,30 +1,10 @@
|
||||
// with modifiers
|
||||
/(abc)\//ig;
|
||||
|
||||
// without modifiers
|
||||
/(abc)\//;
|
||||
|
||||
// can be assigned
|
||||
var re = /(abc)\//ig;
|
||||
|
||||
// generally behaves like an expression
|
||||
var noRe = !/(abc)\//i;
|
||||
|
||||
// inner line break is unterminated
|
||||
/(abc)\//ig; // with modifiers
|
||||
/(abc)\//; // without modifiers
|
||||
var re = /(abc)\//ig; // can be assigned
|
||||
var noRe = !/(abc)\//i; // generally behaves like an expression
|
||||
/a
|
||||
b/ig;
|
||||
|
||||
// just a comment
|
||||
b/ig; // inner line break is unterminated
|
||||
//ig;
|
||||
|
||||
// duplicate flags
|
||||
|
||||
/(abc)\//iig;
|
||||
|
||||
// invalid flags
|
||||
|
||||
/(abc)\//iX;
|
||||
|
||||
// surrounding AST remains intact
|
||||
|
||||
false && /abc/gX.test(someString) || true;
|
||||
/(abc)\//iig; // duplicate flags
|
||||
/(abc)\//iX; // invalid flags
|
||||
false && /abc/gX.test(someString) || true; // surrounding AST remains intact
|
||||
|
@ -5,8 +5,8 @@ var noRe = !/(abc)\//i;
|
||||
/(abc)\//iig;
|
||||
/(abc)\//iX;
|
||||
false && /abc/gX.test(someString) || true;
|
||||
// ERROR 1161: "Unterminated regular expression literal." in regexp.ts @ 75,76
|
||||
// ERROR 1005: "'/' expected." in regexp.ts @ 74,76
|
||||
// ERROR 209: "Invalid regular expression flags." in regexp.ts @ 95,98
|
||||
// ERROR 209: "Invalid regular expression flags." in regexp.ts @ 111,113
|
||||
// ERROR 209: "Invalid regular expression flags." in regexp.ts @ 131,133
|
||||
// ERROR 1161: "Unterminated regular expression literal." in regexp.ts:5:1
|
||||
// ERROR 1005: "'/' expected." in regexp.ts:5:0
|
||||
// ERROR 209: "Invalid regular expression flags." in regexp.ts:8:9
|
||||
// ERROR 209: "Invalid regular expression flags." in regexp.ts:9:9
|
||||
// ERROR 209: "Invalid regular expression flags." in regexp.ts:10:14
|
||||
|
@ -1,5 +1,4 @@
|
||||
// a host-bindings syntax experiment
|
||||
|
||||
@binding(BindingCall.NEW, [ BindingType.STRING ], BindingType.OBJECT_HANDLE)
|
||||
export class ExternalString {
|
||||
|
||||
|
@ -1,65 +1,65 @@
|
||||
@binding(BindingCall.NEW, [BindingType.STRING], BindingType.OBJECT_HANDLE)
|
||||
export class ExternalString {
|
||||
@binding(BindingCall.FUNCTION, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
static fromCharCode(char: u16, schar: u16 = <u16>-1): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.FUNCTION, [BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
static fromCodePoint(codepoint: u32): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
charAt(index: u32): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU)
|
||||
charCodeAt(index: u32): u16 {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU)
|
||||
codePointAt(index: u32): u32 {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.OBJECT_HANDLE)
|
||||
@operator("+")
|
||||
concat(other: String): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||
endsWith(other: String): bool {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||
indexOf(other: String): i32 {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||
startsWith(other: String): bool {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
substr(start: i32, length: i32): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
substring(start: i32, end: i32): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
||||
trim(): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
||||
trimLeft(): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
||||
trimRight(): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||
@operator("==")
|
||||
equals(other: String): bool {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.FUNCTION, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
static fromCharCode(char: u16, schar: u16 = <u16>-1): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.FUNCTION, [BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
static fromCodePoint(codepoint: u32): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
charAt(index: u32): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU)
|
||||
charCodeAt(index: u32): u16 {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU)
|
||||
codePointAt(index: u32): u32 {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.OBJECT_HANDLE)
|
||||
@operator("+")
|
||||
concat(other: String): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||
endsWith(other: String): bool {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||
indexOf(other: String): i32 {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||
startsWith(other: String): bool {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
substr(start: i32, length: i32): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
|
||||
substring(start: i32, end: i32): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
||||
trim(): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
||||
trimLeft(): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE)
|
||||
trimRight(): String {
|
||||
return unreachable();
|
||||
}
|
||||
@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU)
|
||||
@operator("==")
|
||||
equals(other: String): bool {
|
||||
return unreachable();
|
||||
}
|
||||
}
|
||||
|
@ -3,5 +3,8 @@ var b: i32;
|
||||
const c: i32 = 0;
|
||||
var d = 2;
|
||||
|
||||
var e; // type expected
|
||||
const f: i32; // must be initialized
|
||||
// 1110: Type expected.
|
||||
var e;
|
||||
|
||||
// 1155: 'const' declarations must be initialized.
|
||||
const f: i32;
|
||||
|
@ -4,5 +4,5 @@ const c: i32 = 0;
|
||||
var d = 2;
|
||||
var e;
|
||||
const f: i32;
|
||||
// ERROR 1110: "Type expected." in var.ts @ 59,59
|
||||
// ERROR 1155: "'const' declarations must be initialized." in var.ts @ 84,85
|
||||
// ERROR 1110: "Type expected." in var.ts:7:5
|
||||
// ERROR 1155: "'const' declarations must be initialized." in var.ts:10:6
|
||||
|
@ -1,10 +1,10 @@
|
||||
while (1) {
|
||||
;
|
||||
;
|
||||
}
|
||||
while (false) {
|
||||
;
|
||||
;
|
||||
}
|
||||
while ("str") {
|
||||
;
|
||||
;
|
||||
}
|
||||
while (1) ;
|
||||
while (1);
|
||||
|
@ -7,24 +7,27 @@ require("../src/glue/js");
|
||||
const { Tokenizer, Token } = require("../src/tokenizer");
|
||||
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));
|
||||
|
||||
do {
|
||||
let token = tn.next();
|
||||
let range = tn.range();
|
||||
process.stdout.write(Token[token] + " @ " + range.line + ":" + range.column);
|
||||
if (token == Token.IDENTIFIER) {
|
||||
console.log(Token[token] + " > " + tn.readIdentifier());
|
||||
process.stdout.write(" > " + tn.readIdentifier());
|
||||
} else if (token == Token.INTEGERLITERAL) {
|
||||
console.log(Token[token] + " > " + tn.readInteger());
|
||||
process.stdout.write(" > " + tn.readInteger());
|
||||
} else if (token == Token.FLOATLITERAL) {
|
||||
console.log(Token[token] + " > " + tn.readFloat());
|
||||
process.stdout.write(" > " + tn.readFloat());
|
||||
} else if (token == Token.STRINGLITERAL) {
|
||||
console.log(Token[token] + " > " + tn.readString());
|
||||
process.stdout.write(" > " + tn.readString());
|
||||
} else if (token == Token.ENDOFFILE) {
|
||||
console.log(Token[token]);
|
||||
process.stdout.write("\n");
|
||||
break;
|
||||
} else {
|
||||
let range = tn.range();
|
||||
console.log(Token[token] + " > " + range.source.text.substring(range.start, range.end));
|
||||
process.stdout.write(" > " + range.source.text.substring(range.start, range.end));
|
||||
}
|
||||
process.stdout.write("\n");
|
||||
} while (true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user