AST cleanup; Definition generators scaffolding

This commit is contained in:
dcodeIO 2018-03-17 01:37:05 +01:00
parent eef923d124
commit faac3c31eb
50 changed files with 3272 additions and 2690 deletions

View File

@ -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();

View File

@ -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

File diff suppressed because one or more lines are too long

2
dist/asc.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

19
lib/demangle/index.js Normal file
View 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;
}

View File

@ -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/",

View File

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

View File

@ -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

View File

@ -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
View 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?

View File

@ -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.";

View File

@ -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,

View File

@ -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 (

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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) {

View File

@ -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
View 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
View File

@ -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. */

View File

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

View File

@ -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) {

View File

@ -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 {}
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -1,5 +1,5 @@
do {
;
} while (a != b);
do b; while (a);
do b;
while (a);

View File

@ -1,5 +1,5 @@
do {
;
;
} while (a != b);
do b;
while (a);

View File

@ -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
}

View File

@ -1,9 +1,9 @@
for (var i: i32 = 0; i < 10; ++i) {
;
;
}
for (i = 0; i < 10; ++i) {
;
;
}
for (;;) {
;
;
}

View File

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

View File

@ -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 {}

View File

@ -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 {}

View File

@ -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";

View File

@ -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";

View File

@ -45,7 +45,6 @@
0b0;
0b1;
0b1111111111111111111111111111111;
"123";
"1\"23";
"1\"2\\3";

View File

@ -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 {}
}
}
}

View File

@ -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 {}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,5 +1,4 @@
// a host-bindings syntax experiment
@binding(BindingCall.NEW, [ BindingType.STRING ], BindingType.OBJECT_HANDLE)
export class ExternalString {

View File

@ -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();
}
}

View File

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

View File

@ -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

View File

@ -1,10 +1,10 @@
while (1) {
;
;
}
while (false) {
;
;
}
while ("str") {
;
;
}
while (1) ;
while (1);

View File

@ -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);