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

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