More stdlib setup

This commit is contained in:
dcodeIO
2017-12-16 17:54:53 +01:00
parent 85a9fb1eb5
commit 2720515982
47 changed files with 875 additions and 733 deletions

View File

@ -1,71 +1,3 @@
/*
Similar to TypeScript's syntax tree of node interfaces, but class-based.
Node ~ NodeKind
├ ExportMember
├ Expression
│ ├ LiteralExpression ~ LiteralKind
│ │ ├ ArrayLiteralExpression
│ │ ├ FloatLiteralExpression
│ │ ├ IntegerLiteralExpression
│ │ ├ RegexpLiteralExpression
│ │ └ StringLiteralExpression
│ ├ AssertionExpression
│ ├ BinaryExpression
│ ├ CallExpression
│ ├ ElementAccessExpression
│ ├ IdentifierExpression
│ ├ ParenthesizedExpression
│ ├ NewExpression
│ ├ PropertyAccessExpression
│ ├ TernaryExpression
│ └ UnaryExpression
│ ├ UnaryPostfixExpression
│ └ UnaryPrefixExpression
├ Statement
│ ├ BlockStatement
│ ├ BreakStatement
│ ├ ContinueStatement
│ ├ DeclarationStatement
│ │ ├ ClassDeclaration <> TypeParameter
│ │ ├ EnumDeclaration <> EnumValueDeclaration
│ │ ├ EnumValueDeclaration
│ │ ├ FieldDeclaration
│ │ ├ FunctionDeclaration <> TypeParameter, Parameter
│ │ │ └ MethodDeclaration
│ │ ├ ImportDeclaration
│ │ ├ InterfaceDeclaration
│ │ ├ NamespaceDeclaration
│ │ └ VariableDeclaration
│ ├ DoStatement
│ ├ EmptyStatement
│ ├ ExportImportStatement
│ ├ ExportStatement <> ExportMember
│ ├ ExpressionStatement
│ ├ ForStatement
│ ├ IfStatement
│ ├ ImportStatement <> ImportDeclaration
│ ├ ReturnStatement
│ ├ SwitchStatement <> SwitchCase
│ ├ ThrowStatement
│ ├ TryStatement
│ ├ VariableStatement <> VariableDeclaration
│ └ WhileStatement
├ Parameter
├ Source
├ SwitchCase
├ TypeNode
└ TypeParameter
All nodes are backwards-serializable to their respective source except that
formatting is lost, long integers become hex literals and semicolons will be
inserted. Useful for testing.
serialize(node)
*/
import { GETTER_PREFIX, SETTER_PREFIX, PATH_DELIMITER, PARENT_SUBST, STATIC_DELIMITER, INSTANCE_DELIMITER } from "./constants";
import { Token, Tokenizer, operatorTokenToString, Range } from "./tokenizer";
import { CharCode } from "./util/charcode";
@ -74,17 +6,7 @@ import { normalize as normalizePath, resolve as resolvePath } from "./util/path"
export { Range } from "./tokenizer";
/** Base class of all AST nodes. */
export abstract class Node {
kind: NodeKind;
range: Range;
parent: Node | null = null;
/** Serializes this node to its TypeScript representation. */
abstract serialize(sb: string[]): void;
}
/** Indicates the kind of a node. */
export enum NodeKind {
SOURCE,
@ -145,58 +67,31 @@ export enum NodeKind {
WHILE
}
// types
/** Base class of all nodes. */
export abstract class Node {
export class TypeNode extends Node {
/** Node kind indicator. */
kind: NodeKind;
/** Source range. */
range: Range;
/** Parent node. */
parent: Node | null = null;
kind = NodeKind.TYPE;
identifier: IdentifierExpression;
parameters: TypeNode[];
nullable: bool;
/** Serializes this node to its TypeScript representation. Note that formatting is lost and long integers become hex literals. */
abstract serialize(sb: string[]): void;
static create(identifier: IdentifierExpression, parameters: TypeNode[], nullable: bool, range: Range): TypeNode {
// types
static createType(identifier: IdentifierExpression, typeArguments: TypeNode[], isNullable: bool, range: Range): TypeNode {
const type: TypeNode = new TypeNode();
type.range = range;
type.identifier = identifier;
type.parameters = parameters;
type.nullable = nullable;
type.typeArguments = typeArguments;
type.isNullable = isNullable;
return type;
}
serialize(sb: string[]): void {
this.identifier.serialize(sb);
if (this.parameters.length) {
sb.push("<");
for (let i: i32 = 0, k: i32 = this.parameters.length; i < k; ++i) {
if (i > 0)
sb.push(", ");
this.parameters[i].serialize(sb);
}
sb.push(">");
}
if (this.nullable)
sb.push(" | null");
}
}
export class TypeParameter extends Node {
kind = NodeKind.TYPEPARAMETER;
identifier: IdentifierExpression;
extendsType: TypeNode | null;
serialize(sb: string[]): void {
this.identifier.serialize(sb);
if (this.extendsType) {
sb.push(" extends ");
(<TypeNode>this.extendsType).serialize(sb);
}
}
}
// expressions
export abstract class Expression extends Node {
// expressions
static createIdentifier(name: string, range: Range): IdentifierExpression {
const expr: IdentifierExpression = new IdentifierExpression();
@ -362,8 +257,370 @@ export abstract class Expression extends Node {
(expr.expression = expression).parent = expr;
return expr;
}
// statements
static createBlock(statements: Statement[], range: Range): BlockStatement {
const stmt: BlockStatement = new BlockStatement();
stmt.range = range;
for (let i: i32 = 0, k: i32 = (stmt.statements = statements).length; i < k; ++i) statements[i].parent = stmt;
return stmt;
}
static createBreak(label: IdentifierExpression | null, range: Range): BreakStatement {
const stmt: BreakStatement = new BreakStatement();
stmt.range = range;
if (stmt.label = label) (<IdentifierExpression>label).parent = stmt;
return stmt;
}
static createClass(identifier: IdentifierExpression, typeParameters: TypeParameter[], extendsType: TypeNode | null, implementsTypes: TypeNode[], members: DeclarationStatement[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): ClassDeclaration {
const stmt: ClassDeclaration = new ClassDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
if (stmt.extendsType = extendsType) (<TypeNode>extendsType).parent = stmt;
for (i = 0, k = (stmt.implementsTypes = implementsTypes).length; i < k; ++i) implementsTypes[i].parent = stmt;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createContinue(label: IdentifierExpression | null, range: Range): ContinueStatement {
const stmt: ContinueStatement = new ContinueStatement();
stmt.range = range;
if (stmt.label = label) (<IdentifierExpression>label).parent = stmt;
return stmt;
}
static createDecorator(expression: Expression, args: Expression[], range: Range): Decorator {
const stmt: Decorator = new Decorator();
stmt.range = range;
(stmt.expression = expression).parent = stmt;
for (let i: i32 = 0, k: i32 = (stmt.arguments = args).length; i < k; ++i) args[i].parent = stmt;
return stmt;
}
static createDo(statement: Statement, condition: Expression, range: Range): DoStatement {
const stmt: DoStatement = new DoStatement();
stmt.range = range;
(stmt.statement = statement).parent = stmt;
(stmt.condition = condition).parent = stmt;
return stmt;
}
static createEmpty(range: Range): EmptyStatement {
const stmt: EmptyStatement = new EmptyStatement();
stmt.range = range;
return stmt;
}
static createEnum(identifier: IdentifierExpression, members: EnumValueDeclaration[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): EnumDeclaration {
const stmt: EnumDeclaration = new EnumDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createEnumValue(identifier: IdentifierExpression, value: Expression | null, range: Range): EnumValueDeclaration {
const stmt: EnumValueDeclaration = new EnumValueDeclaration();
stmt.range = range;
(stmt.identifier = identifier).parent = stmt;
if (stmt.value = value) (<Expression>value).parent = stmt;
return stmt;
}
static createExport(members: ExportMember[], path: StringLiteralExpression | null, modifiers: Modifier[] | null, range: Range): ExportStatement {
const stmt: ExportStatement = new ExportStatement();
stmt.range = range;
let i: i32, k: i32;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
stmt.path = path;
stmt.normalizedPath = path ? resolvePath(normalizePath(path.value), range.source.normalizedPath) : null;
stmt.internalPath = stmt.normalizedPath ? mangleInternalPath(stmt.normalizedPath) : null;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
return stmt;
}
static createExportImport(identifier: IdentifierExpression, asIdentifier: IdentifierExpression, range: Range): ExportImportStatement {
const stmt: ExportImportStatement = new ExportImportStatement();
stmt.range = range;
(stmt.identifier = identifier).parent = stmt;
(stmt.asIdentifier = asIdentifier).parent = stmt;
return stmt;
}
static createExportMember(identifier: IdentifierExpression, externalIdentifier: IdentifierExpression | null, range: Range): ExportMember {
const elem: ExportMember = new ExportMember();
elem.range = range;
(elem.identifier = identifier).parent = elem;
(elem.externalIdentifier = externalIdentifier ? <IdentifierExpression>externalIdentifier : identifier).parent = elem;
return elem;
}
/** Creates an expression statement. */
static createExpression(expression: Expression): ExpressionStatement {
const stmt: ExpressionStatement = new ExpressionStatement();
stmt.range = expression.range;
(stmt.expression = expression).parent = stmt;
return stmt;
}
static createIf(condition: Expression, statement: Statement, elseStatement: Statement | null, range: Range): IfStatement {
const stmt: IfStatement = new IfStatement();
stmt.range = range;
(stmt.condition = condition).parent = stmt;
(stmt.statement = statement).parent = stmt;
if (stmt.elseStatement = elseStatement) (<Statement>elseStatement).parent = stmt;
return stmt;
}
static createImport(declarations: ImportDeclaration[], path: StringLiteralExpression, range: Range): ImportStatement {
const stmt: ImportStatement = new ImportStatement();
stmt.range = range;
for (let i: i32 = 0, k: i32 = (stmt.declarations = declarations).length; i < k; ++i) declarations[i].parent = stmt;
stmt.path = path;
stmt.normalizedPath = resolvePath(normalizePath(path.value), range.source.normalizedPath);
stmt.internalPath = mangleInternalPath(stmt.normalizedPath);
return stmt;
}
static createImportDeclaration(externalIdentifier: IdentifierExpression, identifier: IdentifierExpression | null, range: Range): ImportDeclaration {
const elem: ImportDeclaration = new ImportDeclaration();
elem.range = range;
(elem.identifier = identifier ? <IdentifierExpression>identifier : externalIdentifier).parent = elem;
(elem.externalIdentifier = externalIdentifier).parent = elem;
return elem;
}
static createInterface(identifier: IdentifierExpression, extendsType: TypeNode | null, members: DeclarationStatement[], modifiers: Modifier[] | null, range: Range): InterfaceDeclaration {
const stmt: InterfaceDeclaration = new InterfaceDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
if (stmt.extendsType = extendsType) (<TypeNode>extendsType).parent = stmt;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
return stmt;
}
static createField(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): FieldDeclaration {
const stmt: FieldDeclaration = new FieldDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
if (stmt.type = type) (<TypeNode>type).parent = stmt;
if (stmt.initializer = initializer) (<Expression>initializer).parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createFor(initializer: Statement | null, condition: Expression | null, incrementor: Expression | null, statement: Statement, range: Range): ForStatement {
const stmt: ForStatement = new ForStatement();
stmt.range = range;
if (stmt.initializer = initializer) (<Statement>initializer).parent = stmt;
if (stmt.condition = condition) (<Expression>condition).parent = stmt;
if (stmt.incrementor = incrementor) (<Expression>incrementor).parent = stmt;
(stmt.statement = statement).parent = stmt;
return stmt;
}
static createTypeParameter(identifier: IdentifierExpression, extendsType: TypeNode | null, range: Range): TypeParameter {
const elem: TypeParameter = new TypeParameter();
elem.range = range;
(elem.identifier = identifier).parent = elem;
if (elem.extendsType = extendsType) (<TypeNode>extendsType).parent = elem;
return elem;
}
static createParameter(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, multiple: bool, range: Range): Parameter {
const elem: Parameter = new Parameter();
elem.range = range;
(elem.identifier = identifier).parent = elem;
if (elem.type = type) (<TypeNode>type).parent = elem;
if (elem.initializer = initializer) (<Expression>initializer).parent = elem;
elem.multiple = multiple;
return elem;
}
static createFunction(identifier: IdentifierExpression, typeParameters: TypeParameter[], parameters: Parameter[], returnType: TypeNode | null, statements: Statement[] | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): FunctionDeclaration {
const stmt: FunctionDeclaration = new FunctionDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
for (i = 0, k = (stmt.parameters = parameters).length; i < k; ++i) parameters[i].parent = stmt;
if (stmt.returnType = returnType) (<TypeNode>returnType).parent = stmt;
if (stmt.statements = statements) for (i = 0, k = (<Statement[]>statements).length; i < k; ++i) (<Statement[]>statements)[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createMethod(identifier: IdentifierExpression, typeParameters: TypeParameter[], parameters: Parameter[], returnType: TypeNode | null, statements: Statement[] | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): MethodDeclaration {
const stmt: MethodDeclaration = new MethodDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
for (i = 0, k = (stmt.parameters = parameters).length; i < k; ++i) parameters[i].parent = stmt;
if (stmt.returnType = returnType) (<TypeNode>returnType).parent = stmt;;
if (stmt.statements = statements) for (i = 0, k = (<Statement[]>statements).length; i < k; ++i) (<Statement[]>statements)[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createModifier(kind: ModifierKind, range: Range): Modifier {
const elem: Modifier = new Modifier();
elem.range = range;
elem.modifierKind = kind;
return elem;
}
static createNamespace(identifier: IdentifierExpression, members: Statement[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): NamespaceDeclaration {
const stmt: NamespaceDeclaration = new NamespaceDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createReturn(expression: Expression | null, range: Range): ReturnStatement {
const stmt: ReturnStatement = new ReturnStatement();
stmt.range = range;
if (stmt.expression = expression) (<Expression>expression).parent = stmt;
return stmt;
}
static createSwitch(expression: Expression, cases: SwitchCase[], range: Range): SwitchStatement {
const stmt: SwitchStatement = new SwitchStatement();
stmt.range = range;
(stmt.expression = expression).parent = stmt;
for (let i: i32 = 0, k: i32 = (stmt.cases = cases).length; i < k; ++i) cases[i].parent = stmt;
return stmt;
}
static createSwitchCase(label: Expression | null, statements: Statement[], range: Range): SwitchCase {
const elem: SwitchCase = new SwitchCase();
elem.range = range;
if (elem.label = label) (<Expression>label).parent = elem;
for (let i: i32 = 0, k: i32 = (elem.statements = statements).length; i < k; ++i) statements[i].parent = elem;
return elem;
}
static createThrow(expression: Expression, range: Range): ThrowStatement {
const stmt: ThrowStatement = new ThrowStatement();
stmt.range = range;
(stmt.expression = expression).parent = stmt;
return stmt;
}
static createTry(statements: Statement[], catchVariable: IdentifierExpression | null, catchStatements: Statement[] | null, finallyStatements: Statement[] | null, range: Range): TryStatement {
const stmt: TryStatement = new TryStatement();
stmt.range = range;
let i: i32, k: i32;
for (i = 0, k = (stmt.statements = statements).length; i < k; ++i) statements[i].parent = stmt;
if (stmt.catchVariable = catchVariable) (<IdentifierExpression>catchVariable).parent = stmt;
if (stmt.catchStatements = catchStatements) for (i = 0, k = (<Statement[]>catchStatements).length; i < k; ++i) (<Statement[]>catchStatements)[i].parent = stmt;
if (stmt.finallyStatements = finallyStatements) for (i = 0, k = (<Statement[]>finallyStatements).length; i < k; ++i) (<Statement[]>finallyStatements)[i].parent = stmt;
return stmt;
}
static createVariable(declarations: VariableDeclaration[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): VariableStatement {
const stmt: VariableStatement = new VariableStatement();
stmt.range = range;
let i: i32, k: i32;
for (i = 0, k = (stmt.declarations = declarations).length; i < k; ++i) declarations[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createVariableDeclaration(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): VariableDeclaration {
const elem: VariableDeclaration = new VariableDeclaration();
elem.range = range;
(elem.identifier = identifier).parent = elem;
if (elem.type = type) (<TypeNode>type).parent = elem;
if (elem.initializer = initializer) (<Expression>initializer).parent = elem;
elem.modifiers = modifiers;
elem.decorators = decorators;
return elem;
}
static createWhile(condition: Expression, statement: Statement, range: Range): WhileStatement {
const stmt: WhileStatement = new WhileStatement();
stmt.range = range;
(stmt.condition = condition).parent = stmt;
(stmt.statement = statement).parent = stmt;
return stmt;
}
}
// types
/** Represents a type annotation. */
export class TypeNode extends Node {
kind = NodeKind.TYPE;
/** Identifier reference. */
identifier: IdentifierExpression;
/** Type argument references. */
typeArguments: TypeNode[];
/** Whether nullable or not. */
isNullable: bool;
serialize(sb: string[]): void {
this.identifier.serialize(sb);
if (this.typeArguments.length) {
sb.push("<");
for (let i: i32 = 0, k: i32 = this.typeArguments.length; i < k; ++i) {
if (i > 0)
sb.push(", ");
this.typeArguments[i].serialize(sb);
}
sb.push(">");
}
if (this.isNullable)
sb.push(" | null");
}
}
/** Represents a type parameter. */
export class TypeParameter extends Node {
kind = NodeKind.TYPEPARAMETER;
/** Identifier reference. */
identifier: IdentifierExpression;
/** Extended type reference, if any. */
extendsType: TypeNode | null;
serialize(sb: string[]): void {
this.identifier.serialize(sb);
if (this.extendsType) {
sb.push(" extends ");
(<TypeNode>this.extendsType).serialize(sb);
}
}
}
// expressions
/** Base class of all expression nodes. */
export abstract class Expression extends Node { }
export class IdentifierExpression extends Expression {
kind = NodeKind.IDENTIFIER;
@ -658,313 +915,8 @@ export enum ModifierKind {
SET,
}
export abstract class Statement extends Node {
static createBlock(statements: Statement[], range: Range): BlockStatement {
const stmt: BlockStatement = new BlockStatement();
stmt.range = range;
for (let i: i32 = 0, k: i32 = (stmt.statements = statements).length; i < k; ++i) statements[i].parent = stmt;
return stmt;
}
static createBreak(label: IdentifierExpression | null, range: Range): BreakStatement {
const stmt: BreakStatement = new BreakStatement();
stmt.range = range;
if (stmt.label = label) (<IdentifierExpression>label).parent = stmt;
return stmt;
}
static createClass(identifier: IdentifierExpression, typeParameters: TypeParameter[], extendsType: TypeNode | null, implementsTypes: TypeNode[], members: DeclarationStatement[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): ClassDeclaration {
const stmt: ClassDeclaration = new ClassDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
if (stmt.extendsType = extendsType) (<TypeNode>extendsType).parent = stmt;
for (i = 0, k = (stmt.implementsTypes = implementsTypes).length; i < k; ++i) implementsTypes[i].parent = stmt;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createContinue(label: IdentifierExpression | null, range: Range): ContinueStatement {
const stmt: ContinueStatement = new ContinueStatement();
stmt.range = range;
if (stmt.label = label) (<IdentifierExpression>label).parent = stmt;
return stmt;
}
static createDecorator(expression: Expression, args: Expression[], range: Range): Decorator {
const stmt: Decorator = new Decorator();
stmt.range = range;
(stmt.expression = expression).parent = stmt;
for (let i: i32 = 0, k: i32 = (stmt.arguments = args).length; i < k; ++i) args[i].parent = stmt;
return stmt;
}
static createDo(statement: Statement, condition: Expression, range: Range): DoStatement {
const stmt: DoStatement = new DoStatement();
stmt.range = range;
(stmt.statement = statement).parent = stmt;
(stmt.condition = condition).parent = stmt;
return stmt;
}
static createEmpty(range: Range): EmptyStatement {
const stmt: EmptyStatement = new EmptyStatement();
stmt.range = range;
return stmt;
}
static createEnum(identifier: IdentifierExpression, members: EnumValueDeclaration[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): EnumDeclaration {
const stmt: EnumDeclaration = new EnumDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createEnumValue(identifier: IdentifierExpression, value: Expression | null, range: Range): EnumValueDeclaration {
const stmt: EnumValueDeclaration = new EnumValueDeclaration();
stmt.range = range;
(stmt.identifier = identifier).parent = stmt;
if (stmt.value = value) (<Expression>value).parent = stmt;
return stmt;
}
static createExport(members: ExportMember[], path: StringLiteralExpression | null, modifiers: Modifier[] | null, range: Range): ExportStatement {
const stmt: ExportStatement = new ExportStatement();
stmt.range = range;
let i: i32, k: i32;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
stmt.path = path;
stmt.normalizedPath = path ? resolvePath(normalizePath(path.value), range.source.normalizedPath) : null;
stmt.internalPath = stmt.normalizedPath ? mangleInternalPath(stmt.normalizedPath) : null;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
return stmt;
}
static createExportImport(identifier: IdentifierExpression, asIdentifier: IdentifierExpression, range: Range): ExportImportStatement {
const stmt: ExportImportStatement = new ExportImportStatement();
stmt.range = range;
(stmt.identifier = identifier).parent = stmt;
(stmt.asIdentifier = asIdentifier).parent = stmt;
return stmt;
}
static createExportMember(identifier: IdentifierExpression, externalIdentifier: IdentifierExpression | null, range: Range): ExportMember {
const elem: ExportMember = new ExportMember();
elem.range = range;
(elem.identifier = identifier).parent = elem;
(elem.externalIdentifier = externalIdentifier ? <IdentifierExpression>externalIdentifier : identifier).parent = elem;
return elem;
}
static createExpression(expression: Expression): ExpressionStatement {
const stmt: ExpressionStatement = new ExpressionStatement();
stmt.range = expression.range;
(stmt.expression = expression).parent = stmt;
return stmt;
}
static createIf(condition: Expression, statement: Statement, elseStatement: Statement | null, range: Range): IfStatement {
const stmt: IfStatement = new IfStatement();
stmt.range = range;
(stmt.condition = condition).parent = stmt;
(stmt.statement = statement).parent = stmt;
if (stmt.elseStatement = elseStatement) (<Statement>elseStatement).parent = stmt;
return stmt;
}
static createImport(declarations: ImportDeclaration[], path: StringLiteralExpression, range: Range): ImportStatement {
const stmt: ImportStatement = new ImportStatement();
stmt.range = range;
for (let i: i32 = 0, k: i32 = (stmt.declarations = declarations).length; i < k; ++i) declarations[i].parent = stmt;
stmt.path = path;
stmt.normalizedPath = resolvePath(normalizePath(path.value), range.source.normalizedPath);
stmt.internalPath = mangleInternalPath(stmt.normalizedPath);
return stmt;
}
static createImportDeclaration(externalIdentifier: IdentifierExpression, identifier: IdentifierExpression | null, range: Range): ImportDeclaration {
const elem: ImportDeclaration = new ImportDeclaration();
elem.range = range;
(elem.identifier = identifier ? <IdentifierExpression>identifier : externalIdentifier).parent = elem;
(elem.externalIdentifier = externalIdentifier).parent = elem;
return elem;
}
static createInterface(identifier: IdentifierExpression, extendsType: TypeNode | null, members: DeclarationStatement[], modifiers: Modifier[] | null, range: Range): InterfaceDeclaration {
const stmt: InterfaceDeclaration = new InterfaceDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
if (stmt.extendsType = extendsType) (<TypeNode>extendsType).parent = stmt;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
return stmt;
}
static createField(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): FieldDeclaration {
const stmt: FieldDeclaration = new FieldDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
if (stmt.type = type) (<TypeNode>type).parent = stmt;
if (stmt.initializer = initializer) (<Expression>initializer).parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createFor(initializer: Statement | null, condition: Expression | null, incrementor: Expression | null, statement: Statement, range: Range): ForStatement {
const stmt: ForStatement = new ForStatement();
stmt.range = range;
if (stmt.initializer = initializer) (<Statement>initializer).parent = stmt;
if (stmt.condition = condition) (<Expression>condition).parent = stmt;
if (stmt.incrementor = incrementor) (<Expression>incrementor).parent = stmt;
(stmt.statement = statement).parent = stmt;
return stmt;
}
static createTypeParameter(identifier: IdentifierExpression, extendsType: TypeNode | null, range: Range): TypeParameter {
const elem: TypeParameter = new TypeParameter();
elem.range = range;
(elem.identifier = identifier).parent = elem;
if (elem.extendsType = extendsType) (<TypeNode>extendsType).parent = elem;
return elem;
}
static createParameter(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, multiple: bool, range: Range): Parameter {
const elem: Parameter = new Parameter();
elem.range = range;
(elem.identifier = identifier).parent = elem;
if (elem.type = type) (<TypeNode>type).parent = elem;
if (elem.initializer = initializer) (<Expression>initializer).parent = elem;
elem.multiple = multiple;
return elem;
}
static createFunction(identifier: IdentifierExpression, typeParameters: TypeParameter[], parameters: Parameter[], returnType: TypeNode | null, statements: Statement[] | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): FunctionDeclaration {
const stmt: FunctionDeclaration = new FunctionDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
for (i = 0, k = (stmt.parameters = parameters).length; i < k; ++i) parameters[i].parent = stmt;
if (stmt.returnType = returnType) (<TypeNode>returnType).parent = stmt;
if (stmt.statements = statements) for (i = 0, k = (<Statement[]>statements).length; i < k; ++i) (<Statement[]>statements)[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createMethod(identifier: IdentifierExpression, typeParameters: TypeParameter[], parameters: Parameter[], returnType: TypeNode | null, statements: Statement[] | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): MethodDeclaration {
const stmt: MethodDeclaration = new MethodDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
for (i = 0, k = (stmt.parameters = parameters).length; i < k; ++i) parameters[i].parent = stmt;
if (stmt.returnType = returnType) (<TypeNode>returnType).parent = stmt;;
if (stmt.statements = statements) for (i = 0, k = (<Statement[]>statements).length; i < k; ++i) (<Statement[]>statements)[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createModifier(kind: ModifierKind, range: Range): Modifier {
const elem: Modifier = new Modifier();
elem.range = range;
elem.modifierKind = kind;
return elem;
}
static createNamespace(identifier: IdentifierExpression, members: Statement[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): NamespaceDeclaration {
const stmt: NamespaceDeclaration = new NamespaceDeclaration();
stmt.range = range;
let i: i32, k: i32;
(stmt.identifier = identifier).parent = stmt;
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createReturn(expression: Expression | null, range: Range): ReturnStatement {
const stmt: ReturnStatement = new ReturnStatement();
stmt.range = range;
if (stmt.expression = expression) (<Expression>expression).parent = stmt;
return stmt;
}
static createSwitch(expression: Expression, cases: SwitchCase[], range: Range): SwitchStatement {
const stmt: SwitchStatement = new SwitchStatement();
stmt.range = range;
(stmt.expression = expression).parent = stmt;
for (let i: i32 = 0, k: i32 = (stmt.cases = cases).length; i < k; ++i) cases[i].parent = stmt;
return stmt;
}
static createSwitchCase(label: Expression | null, statements: Statement[], range: Range): SwitchCase {
const elem: SwitchCase = new SwitchCase();
elem.range = range;
if (elem.label = label) (<Expression>label).parent = elem;
for (let i: i32 = 0, k: i32 = (elem.statements = statements).length; i < k; ++i) statements[i].parent = elem;
return elem;
}
static createThrow(expression: Expression, range: Range): ThrowStatement {
const stmt: ThrowStatement = new ThrowStatement();
stmt.range = range;
(stmt.expression = expression).parent = stmt;
return stmt;
}
static createTry(statements: Statement[], catchVariable: IdentifierExpression | null, catchStatements: Statement[] | null, finallyStatements: Statement[] | null, range: Range): TryStatement {
const stmt: TryStatement = new TryStatement();
stmt.range = range;
let i: i32, k: i32;
for (i = 0, k = (stmt.statements = statements).length; i < k; ++i) statements[i].parent = stmt;
if (stmt.catchVariable = catchVariable) (<IdentifierExpression>catchVariable).parent = stmt;
if (stmt.catchStatements = catchStatements) for (i = 0, k = (<Statement[]>catchStatements).length; i < k; ++i) (<Statement[]>catchStatements)[i].parent = stmt;
if (stmt.finallyStatements = finallyStatements) for (i = 0, k = (<Statement[]>finallyStatements).length; i < k; ++i) (<Statement[]>finallyStatements)[i].parent = stmt;
return stmt;
}
static createVariable(declarations: VariableDeclaration[], modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): VariableStatement {
const stmt: VariableStatement = new VariableStatement();
stmt.range = range;
let i: i32, k: i32;
for (i = 0, k = (stmt.declarations = declarations).length; i < k; ++i) declarations[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
return stmt;
}
static createVariableDeclaration(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): VariableDeclaration {
const elem: VariableDeclaration = new VariableDeclaration();
elem.range = range;
(elem.identifier = identifier).parent = elem;
if (elem.type = type) (<TypeNode>type).parent = elem;
if (elem.initializer = initializer) (<Expression>initializer).parent = elem;
elem.modifiers = modifiers;
elem.decorators = decorators;
return elem;
}
static createWhile(condition: Expression, statement: Statement, range: Range): WhileStatement {
const stmt: WhileStatement = new WhileStatement();
stmt.range = range;
(stmt.condition = condition).parent = stmt;
(stmt.statement = statement).parent = stmt;
return stmt;
}
}
/** Base class of all statement nodes. */
export abstract class Statement extends Node { }
export class Source extends Node {
@ -1064,11 +1016,7 @@ export class ClassDeclaration extends DeclarationStatement {
get internalName(): string {
if (this._cachedInternalName !== null)
return this._cachedInternalName;
const globalDecorator: Decorator | null = this.decorators ? getDecoratorByName("global", this.decorators) : null;
if (globalDecorator)
return this._cachedInternalName = this.identifier.name;
else
return this._cachedInternalName = mangleInternalName(this);
return this._cachedInternalName = mangleInternalName(this);
}
serialize(sb: string[]): void {
@ -1350,11 +1298,7 @@ export class FunctionDeclaration extends DeclarationStatement {
get internalName(): string {
if (this._cachedInternalName !== null)
return this._cachedInternalName;
const globalDecorator: Decorator | null = this.decorators ? getDecoratorByName("global", this.decorators) : null;
if (globalDecorator && globalDecorator.expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>globalDecorator.expression).name == "global")
return this._cachedInternalName = this.identifier.name;
else
return this._cachedInternalName = mangleInternalName(this);
return this._cachedInternalName = mangleInternalName(this);
}
serialize(sb: string[]): void {
@ -1591,21 +1535,25 @@ export class Modifier extends Node {
modifierKind: ModifierKind;
serialize(sb: string[]): void {
sb.push(this.toString());
}
toString(): string {
switch (this.modifierKind) {
case ModifierKind.ABSTRACT: sb.push("abstract"); break;
case ModifierKind.ASYNC: sb.push("async"); break;
case ModifierKind.CONST: sb.push("const"); break;
case ModifierKind.DECLARE: sb.push("declare"); break;
case ModifierKind.EXPORT: sb.push("export"); break;
case ModifierKind.GET: sb.push("get"); break;
case ModifierKind.IMPORT: sb.push("import"); break;
case ModifierKind.PRIVATE: sb.push("private"); break;
case ModifierKind.PROTECTED: sb.push("protected"); break;
case ModifierKind.PUBLIC: sb.push("public"); break;
case ModifierKind.READONLY: sb.push("readonly"); break;
case ModifierKind.SET: sb.push("set"); break;
case ModifierKind.STATIC: sb.push("static"); break;
default: throw new Error("unexpected modifier kind");
case ModifierKind.ABSTRACT: return "abstract";
case ModifierKind.ASYNC: return "async";
case ModifierKind.CONST: return "const";
case ModifierKind.DECLARE: return "declare";
case ModifierKind.EXPORT: return "export";
case ModifierKind.GET: return "get";
case ModifierKind.IMPORT: return "import";
case ModifierKind.PRIVATE: return "private";
case ModifierKind.PROTECTED: return "protected";
case ModifierKind.PUBLIC: return "public";
case ModifierKind.READONLY: return "readonly";
case ModifierKind.SET: return "set";
case ModifierKind.STATIC: return "static";
default: return "INVALID_MODIFIER";
}
}
}

View File

@ -99,11 +99,11 @@ export function initialize(program: Program): void {
if (program.target == Target.WASM64) {
program.elements.set("isize", <Element>program.elements.get("i64"));
program.elements.set("usize", <Element>program.elements.get("u64"));
addConstant(program, "HEAP_START", Type.usize64);
addConstant(program, "HEAP_BASE", Type.usize64);
} else {
program.elements.set("isize", <Element>program.elements.get("i32"));
program.elements.set("usize", <Element>program.elements.get("u32"));
addConstant(program, "HEAP_START", Type.usize32);
addConstant(program, "HEAP_BASE", Type.usize32);
}
}
@ -126,6 +126,7 @@ function addFunction(program: Program, name: string, isGeneric: bool = false): F
return prototype;
}
/** Compiles a get of a built-in global. */
export function compileGetGlobal(compiler: Compiler, global: Global): ExpressionRef {
switch (global.internalName) {
@ -141,8 +142,8 @@ export function compileGetGlobal(compiler: Compiler, global: Global): Expression
compiler.currentType = Type.f64;
return compiler.module.createF64(Infinity);
case "HEAP_START": // never inlined
return compiler.module.createGetGlobal("HEAP_START", typeToNativeType(<Type>global.type));
case "HEAP_BASE": // constant, but never inlined
return compiler.module.createGetGlobal("HEAP_BASE", typeToNativeType(compiler.currentType = <Type>global.type));
default:
throw new Error("not implemented: " + global.internalName);
@ -162,8 +163,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
let tempLocal0: Local;
let tempLocal1: Local;
let type: Type;
var ftype: FunctionTypeRef;
let ftype: FunctionTypeRef;
switch (prototype.internalName) {

View File

@ -215,9 +215,9 @@ export class Compiler extends DiagnosticEmitter {
// set up memory
const initial: U64 = this.memoryOffset.clone();
if (this.options.target == Target.WASM64)
this.module.addGlobal("HEAP_START", NativeType.I64, false, this.module.createI64(initial.lo, initial.hi));
this.module.addGlobal("HEAP_BASE", NativeType.I64, false, this.module.createI64(initial.lo, initial.hi));
else
this.module.addGlobal("HEAP_START", NativeType.I32, false, this.module.createI32(initial.lo));
this.module.addGlobal("HEAP_BASE", NativeType.I32, false, this.module.createI32(initial.lo));
// determine initial page size
const initialOverlaps: U64 = initial.clone();

View File

@ -117,10 +117,10 @@ export class Parser extends DiagnosticEmitter {
let modifiers: Modifier[] | null = null;
if (tn.skip(Token.EXPORT))
modifiers = addModifier(Statement.createModifier(ModifierKind.EXPORT, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.EXPORT, tn.range()), modifiers);
if (tn.skip(Token.DECLARE)) {
modifiers = addModifier(Statement.createModifier(ModifierKind.DECLARE, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.DECLARE, tn.range()), modifiers);
tn.peek(true);
if (tn.nextTokenOnNewLine)
this.error(DiagnosticCode.Line_break_not_permitted_here, tn.range(tn.pos)); // recoverable, compatibility
@ -132,7 +132,7 @@ export class Parser extends DiagnosticEmitter {
switch (tn.next()) {
case Token.CONST:
modifiers = addModifier(Statement.createModifier(ModifierKind.CONST, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.CONST, tn.range()), modifiers);
if (tn.skip(Token.ENUM)) {
statement = this.parseEnum(tn, modifiers, decorators);
@ -161,7 +161,7 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode._0_expected, tn.range(tn.pos), "class");
break;
}
modifiers = addModifier(Statement.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers);
// fall through
case Token.CLASS:
@ -236,7 +236,7 @@ export class Parser extends DiagnosticEmitter {
// void
if (token == Token.VOID)
return TypeNode.create(Expression.createIdentifier("void", tn.range()), [], false, tn.range(startPos, tn.pos));
return Node.createType(Node.createIdentifier("void", tn.range()), [], false, tn.range(startPos, tn.pos));
let type: TypeNode;
@ -256,20 +256,20 @@ export class Parser extends DiagnosticEmitter {
// this
} else if (token == Token.THIS) {
type = TypeNode.create(Expression.createThis(tn.range()), [], false, tn.range(startPos, tn.pos));
type = Node.createType(Node.createThis(tn.range()), [], false, tn.range(startPos, tn.pos));
// true
} else if (token == Token.TRUE || token == Token.FALSE) {
type = TypeNode.create(Expression.createIdentifier("bool", tn.range()), [], false, tn.range(startPos, tn.pos));
type = Node.createType(Node.createIdentifier("bool", tn.range()), [], false, tn.range(startPos, tn.pos));
// string literal
} else if (token == Token.STRINGLITERAL) {
tn.readString();
type = TypeNode.create(Expression.createIdentifier("string", tn.range()), [], false, tn.range(startPos, tn.pos));
type = Node.createType(Node.createIdentifier("string", tn.range()), [], false, tn.range(startPos, tn.pos));
// Name
} else if (token == Token.IDENTIFIER) {
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
const parameters: TypeNode[] = new Array();
let nullable: bool = false;
@ -297,7 +297,7 @@ export class Parser extends DiagnosticEmitter {
return null;
}
}
type = TypeNode.create(identifier, parameters, nullable, tn.range(startPos, tn.pos));
type = Node.createType(identifier, parameters, nullable, tn.range(startPos, tn.pos));
} else {
if (!suppressErrors)
@ -325,7 +325,7 @@ export class Parser extends DiagnosticEmitter {
return null;
}
}
type = TypeNode.create(Expression.createIdentifier("Array", bracketRange), [ type ], nullable, tn.range(startPos, tn.pos));
type = Node.createType(Node.createIdentifier("Array", bracketRange), [ type ], nullable, tn.range(startPos, tn.pos));
if (nullable)
break;
}
@ -340,11 +340,11 @@ export class Parser extends DiagnosticEmitter {
const startPos: i32 = tn.tokenPos;
if (tn.skip(Token.IDENTIFIER)) {
let name: string = tn.readIdentifier();
let expression: Expression = Expression.createIdentifier(name, tn.range(startPos, tn.pos));
let expression: Expression = Node.createIdentifier(name, tn.range(startPos, tn.pos));
while (tn.skip(Token.DOT)) {
if (tn.skip(Token.IDENTIFIER)) {
name = tn.readIdentifier();
expression = Expression.createPropertyAccess(expression, Expression.createIdentifier(name, tn.range()), tn.range(startPos, tn.pos));
expression = Node.createPropertyAccess(expression, Node.createIdentifier(name, tn.range()), tn.range(startPos, tn.pos));
} else {
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
@ -353,7 +353,7 @@ export class Parser extends DiagnosticEmitter {
if (tn.skip(Token.OPENPAREN)) {
const args: Expression[] | null = this.parseArguments(tn);
if (args)
return Statement.createDecorator(expression, <Expression[]>args, tn.range(startPos, tn.pos));
return Node.createDecorator(expression, <Expression[]>args, tn.range(startPos, tn.pos));
} else
this.error(DiagnosticCode._0_expected, tn.range(), "(");
} else
@ -373,7 +373,7 @@ export class Parser extends DiagnosticEmitter {
members.push(<VariableDeclaration>member);
} while (tn.skip(Token.COMMA));
const ret: VariableStatement = Statement.createVariable(members, modifiers, decorators, tn.range(startPos, tn.pos));
const ret: VariableStatement = Node.createVariable(members, modifiers, decorators, tn.range(startPos, tn.pos));
tn.skip(Token.SEMICOLON);
return ret;
}
@ -384,7 +384,7 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
}
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
let type: TypeNode | null = null;
if (tn.skip(Token.COLON))
@ -403,7 +403,7 @@ export class Parser extends DiagnosticEmitter {
else if (!type) // neither type nor initializer
this.error(DiagnosticCode.Type_expected, tn.range(tn.pos)); // recoverable
}
return Statement.createVariableDeclaration(identifier, type, initializer, parentModifiers, parentDecorators, Range.join(identifier.range, tn.range()));
return Node.createVariableDeclaration(identifier, type, initializer, parentModifiers, parentDecorators, Range.join(identifier.range, tn.range()));
}
parseEnum(tn: Tokenizer, modifiers: Modifier[] | null, decorators: Decorator[] | null): EnumDeclaration | null {
@ -413,7 +413,7 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
}
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
if (tn.next() != Token.OPENBRACE) {
this.error(DiagnosticCode._0_expected, tn.range(), "{");
return null;
@ -431,7 +431,7 @@ export class Parser extends DiagnosticEmitter {
return null;
}
}
const ret: EnumDeclaration = Statement.createEnum(identifier, members, modifiers, decorators, tn.range(startPos, tn.pos));
const ret: EnumDeclaration = Node.createEnum(identifier, members, modifiers, decorators, tn.range(startPos, tn.pos));
tn.skip(Token.SEMICOLON);
return ret;
}
@ -442,14 +442,14 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
}
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
let value: Expression | null = null;
if (tn.skip(Token.EQUALS)) {
value = this.parseExpression(tn, Precedence.COMMA + 1);
if (!value)
return null;
}
return Statement.createEnumValue(identifier, value, Range.join(identifier.range, tn.range()));
return Node.createEnumValue(identifier, value, Range.join(identifier.range, tn.range()));
}
parseReturn(tn: Tokenizer): ReturnStatement | null {
@ -460,7 +460,7 @@ export class Parser extends DiagnosticEmitter {
if (!expr)
return null;
}
const ret: ReturnStatement = Statement.createReturn(expr, tn.range());
const ret: ReturnStatement = Node.createReturn(expr, tn.range());
tn.skip(Token.SEMICOLON);
return ret;
}
@ -487,14 +487,14 @@ export class Parser extends DiagnosticEmitter {
parseTypeParameter(tn: Tokenizer): TypeParameter | null {
// Identifier ('extends' Type)?
if (tn.next() == Token.IDENTIFIER) {
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
let extendsType: TypeNode | null = null;
if (tn.skip(Token.EXTENDS)) {
extendsType = this.parseType(tn);
if (!extendsType)
return null;
}
return Statement.createTypeParameter(identifier, extendsType, Range.join(identifier.range, tn.range()));
return Node.createTypeParameter(identifier, extendsType, Range.join(identifier.range, tn.range()));
} else
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
@ -529,7 +529,7 @@ export class Parser extends DiagnosticEmitter {
if (tn.skip(Token.IDENTIFIER)) {
if (!multiple)
startRange = tn.range();
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
let type: TypeNode | null = null;
if (tn.skip(Token.COLON)) {
type = this.parseType(tn);
@ -542,7 +542,7 @@ export class Parser extends DiagnosticEmitter {
if (!initializer)
return null;
}
return Statement.createParameter(identifier, type, initializer, multiple, Range.join(<Range>startRange, tn.range()));
return Node.createParameter(identifier, type, initializer, multiple, Range.join(<Range>startRange, tn.range()));
} else
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
@ -556,7 +556,7 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode.Identifier_expected, tn.range(tn.pos));
return null;
}
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
let typeParameters: TypeParameter[] | null = null;
if (tn.skip(Token.LESSTHAN)) {
typeParameters = this.parseTypeParameters(tn);
@ -607,7 +607,7 @@ export class Parser extends DiagnosticEmitter {
}
} else if (!isDeclare)
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, tn.range(tn.pos));
const ret: FunctionDeclaration = Statement.createFunction(identifier, typeParameters, <Parameter[]>parameters, returnType, statements, modifiers, decorators, tn.range(startPos, tn.pos));
const ret: FunctionDeclaration = Node.createFunction(identifier, typeParameters, <Parameter[]>parameters, returnType, statements, modifiers, decorators, tn.range(startPos, tn.pos));
tn.skip(Token.SEMICOLON);
return ret;
}
@ -621,7 +621,7 @@ export class Parser extends DiagnosticEmitter {
: tn.tokenPos;
if (tn.skip(Token.IDENTIFIER)) {
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
let typeParameters: TypeParameter[] | null;
if (tn.skip(Token.LESSTHAN)) {
@ -659,7 +659,7 @@ export class Parser extends DiagnosticEmitter {
members.push(<DeclarationStatement>member);
} while (!tn.skip(Token.CLOSEBRACE));
}
return Statement.createClass(identifier, <TypeParameter[]>typeParameters, extendsType, implementsTypes, members, modifiers, decorators, tn.range(startPos, tn.pos));
return Node.createClass(identifier, <TypeParameter[]>typeParameters, extendsType, implementsTypes, members, modifiers, decorators, tn.range(startPos, tn.pos));
} else
this.error(DiagnosticCode._0_expected, tn.range(), "{");
} else
@ -683,34 +683,34 @@ export class Parser extends DiagnosticEmitter {
let modifiers: Modifier[] | null = null;
if (tn.skip(Token.PUBLIC))
modifiers = addModifier(Statement.createModifier(ModifierKind.PUBLIC, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.PUBLIC, tn.range()), modifiers);
else if (tn.skip(Token.PRIVATE))
modifiers = addModifier(Statement.createModifier(ModifierKind.PRIVATE, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.PRIVATE, tn.range()), modifiers);
else if (tn.skip(Token.PROTECTED))
modifiers = addModifier(Statement.createModifier(ModifierKind.PROTECTED, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.PROTECTED, tn.range()), modifiers);
if (tn.skip(Token.STATIC))
modifiers = addModifier(Statement.createModifier(ModifierKind.STATIC, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.STATIC, tn.range()), modifiers);
else if (tn.skip(Token.ABSTRACT))
modifiers = addModifier(Statement.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers);
if (tn.skip(Token.READONLY))
modifiers = addModifier(Statement.createModifier(ModifierKind.READONLY, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.READONLY, tn.range()), modifiers);
let isGetter: bool = false;
let isSetter: bool = false;
if (tn.skip(Token.GET)) {
modifiers = addModifier(Statement.createModifier(ModifierKind.GET, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.GET, tn.range()), modifiers);
isGetter = true;
} else if (tn.skip(Token.SET)) { // can't be both
modifiers = addModifier(Statement.createModifier(ModifierKind.SET, tn.range()), modifiers);
modifiers = addModifier(Node.createModifier(ModifierKind.SET, tn.range()), modifiers);
isSetter = true;
}
if (tn.skip(Token.IDENTIFIER) || tn.skip(Token.CONSTRUCTOR)) {
const identifier: IdentifierExpression = tn.token == Token.CONSTRUCTOR
? Expression.createConstructor(tn.range())
: Expression.createIdentifier(tn.readIdentifier(), tn.range());
? Node.createConstructor(tn.range())
: Node.createIdentifier(tn.readIdentifier(), tn.range());
let typeParameters: TypeParameter[] | null;
if (tn.skip(Token.LESSTHAN)) {
if (identifier.kind == NodeKind.CONSTRUCTOR)
@ -769,7 +769,7 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, tn.range()); // recoverable
}
const ret: MethodDeclaration = Statement.createMethod(identifier, <TypeParameter[]>typeParameters, <Parameter[]>parameters, returnType, statements, modifiers, decorators, Range.join(startRange, tn.range()));
const ret: MethodDeclaration = Node.createMethod(identifier, <TypeParameter[]>typeParameters, <Parameter[]>parameters, returnType, statements, modifiers, decorators, Range.join(startRange, tn.range()));
tn.skip(Token.SEMICOLON);
return ret;
@ -794,7 +794,7 @@ export class Parser extends DiagnosticEmitter {
if (!initializer)
return null;
}
const ret: FieldDeclaration = Statement.createField(identifier, type, initializer, modifiers, decorators, Range.join(startRange, tn.range()));
const ret: FieldDeclaration = Node.createField(identifier, type, initializer, modifiers, decorators, Range.join(startRange, tn.range()));
tn.skip(Token.SEMICOLON);
return ret;
}
@ -807,7 +807,7 @@ export class Parser extends DiagnosticEmitter {
// at 'namespace': Identifier '{' (Variable | Function)* '}'
const startRange: Range = modifiers && modifiers.length ? modifiers[0].range : tn.range();
if (tn.skip(Token.IDENTIFIER)) {
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
if (tn.skip(Token.OPENBRACE)) {
const members: Statement[] = new Array();
while (!tn.skip(Token.CLOSEBRACE)) {
@ -816,7 +816,7 @@ export class Parser extends DiagnosticEmitter {
return null;
members.push(member);
}
const ret: NamespaceDeclaration = Statement.createNamespace(identifier, members, modifiers, decorators, Range.join(startRange, tn.range()));
const ret: NamespaceDeclaration = Node.createNamespace(identifier, members, modifiers, decorators, Range.join(startRange, tn.range()));
tn.skip(Token.SEMICOLON);
return ret;
} else
@ -846,13 +846,13 @@ export class Parser extends DiagnosticEmitter {
let path: StringLiteralExpression | null = null;
if (tn.skip(Token.FROM)) {
if (tn.skip(Token.STRINGLITERAL))
path = Expression.createStringLiteral(tn.readString(), tn.range());
path = Node.createStringLiteral(tn.readString(), tn.range());
else {
this.error(DiagnosticCode.String_literal_expected, tn.range());
return null;
}
}
const ret: ExportStatement = Statement.createExport(members, path, modifiers, Range.join(startRange, tn.range()));
const ret: ExportStatement = Node.createExport(members, path, modifiers, Range.join(startRange, tn.range()));
if (ret.normalizedPath && !this.seenlog.has(<string>ret.normalizedPath)) {
this.backlog.push(<string>ret.normalizedPath);
this.seenlog.add(<string>ret.normalizedPath);
@ -867,17 +867,17 @@ export class Parser extends DiagnosticEmitter {
parseExportMember(tn: Tokenizer): ExportMember | null {
// Identifier ('as' Identifier)?
if (tn.skip(Token.IDENTIFIER)) {
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
let asIdentifier: IdentifierExpression | null = null;
if (tn.skip(Token.AS)) {
if (tn.skip(Token.IDENTIFIER))
asIdentifier = Expression.createIdentifier(tn.readIdentifier(), tn.range());
asIdentifier = Node.createIdentifier(tn.readIdentifier(), tn.range());
else {
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
}
}
return Statement.createExportMember(identifier, asIdentifier, asIdentifier ? Range.join(identifier.range, asIdentifier.range) : identifier.range);
return Node.createExportMember(identifier, asIdentifier, asIdentifier ? Range.join(identifier.range, asIdentifier.range) : identifier.range);
} else
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
@ -902,8 +902,8 @@ export class Parser extends DiagnosticEmitter {
}
if (tn.skip(Token.FROM)) {
if (tn.skip(Token.STRINGLITERAL)) {
const path: StringLiteralExpression = Expression.createStringLiteral(tn.readString(), tn.range());
const ret: ImportStatement = Statement.createImport(members, path, Range.join(startRange, tn.range()));
const path: StringLiteralExpression = Node.createStringLiteral(tn.readString(), tn.range());
const ret: ImportStatement = Node.createImport(members, path, Range.join(startRange, tn.range()));
if (!this.seenlog.has(ret.normalizedPath)) {
this.backlog.push(ret.normalizedPath);
this.seenlog.add(ret.normalizedPath);
@ -922,17 +922,17 @@ export class Parser extends DiagnosticEmitter {
parseImportDeclaration(tn: Tokenizer): ImportDeclaration | null {
// Identifier ('as' Identifier)?
if (tn.skip(Token.IDENTIFIER)) {
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
let asIdentifier: IdentifierExpression | null = null;
if (tn.skip(Token.AS)) {
if (tn.skip(Token.IDENTIFIER))
asIdentifier = Expression.createIdentifier(tn.readIdentifier(), tn.range());
asIdentifier = Node.createIdentifier(tn.readIdentifier(), tn.range());
else {
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
}
}
return Statement.createImportDeclaration(identifier, asIdentifier, asIdentifier ? Range.join(identifier.range, asIdentifier.range) : identifier.range);
return Node.createImportDeclaration(identifier, asIdentifier, asIdentifier ? Range.join(identifier.range, asIdentifier.range) : identifier.range);
} else
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
@ -941,11 +941,11 @@ export class Parser extends DiagnosticEmitter {
parseExportImport(tn: Tokenizer, startRange: Range): ExportImportStatement | null {
// at 'export' 'import': Identifier ('=' Identifier)? ';'?
if (tn.skip(Token.IDENTIFIER)) {
const asIdentifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const asIdentifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
if (tn.skip(Token.EQUALS)) {
if (tn.skip(Token.IDENTIFIER)) {
const identifier: IdentifierExpression = Expression.createIdentifier(tn.readIdentifier(), tn.range());
const ret: ExportImportStatement = Statement.createExportImport(identifier, asIdentifier, Range.join(startRange, tn.range()));
const identifier: IdentifierExpression = Node.createIdentifier(tn.readIdentifier(), tn.range());
const ret: ExportImportStatement = Node.createExportImport(identifier, asIdentifier, Range.join(startRange, tn.range()));
tn.skip(Token.SEMICOLON);
return ret;
} else
@ -967,7 +967,7 @@ export class Parser extends DiagnosticEmitter {
return this.parseBreak(tn);
case Token.CONST:
return this.parseVariable(tn, [ Statement.createModifier(ModifierKind.CONST, tn.range()) ], null);
return this.parseVariable(tn, [ Node.createModifier(ModifierKind.CONST, tn.range()) ], null);
case Token.CONTINUE:
return this.parseContinue(tn);
@ -994,7 +994,7 @@ export class Parser extends DiagnosticEmitter {
return this.parseReturn(tn);
case Token.SEMICOLON:
return Statement.createEmpty(tn.range(tn.tokenPos));
return Node.createEmpty(tn.range(tn.tokenPos));
case Token.SWITCH:
return this.parseSwitchStatement(tn);
@ -1024,7 +1024,7 @@ export class Parser extends DiagnosticEmitter {
return null;
statements.push(statement);
}
const ret: BlockStatement = Statement.createBlock(statements, tn.range(startPos, tn.pos));
const ret: BlockStatement = Node.createBlock(statements, tn.range(startPos, tn.pos));
tn.skip(Token.SEMICOLON);
return ret;
}
@ -1034,9 +1034,9 @@ export class Parser extends DiagnosticEmitter {
let identifier: IdentifierExpression | null = null;
if (tn.peek(true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
tn.next(true);
identifier = Expression.createIdentifier(tn.readIdentifier(), tn.range());
identifier = Node.createIdentifier(tn.readIdentifier(), tn.range());
}
const ret: ContinueStatement = Statement.createBreak(identifier, tn.range());
const ret: ContinueStatement = Node.createBreak(identifier, tn.range());
tn.skip(Token.SEMICOLON);
return ret;
}
@ -1046,9 +1046,9 @@ export class Parser extends DiagnosticEmitter {
let identifier: IdentifierExpression | null = null;
if (tn.peek(true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
tn.next(true);
identifier = Expression.createIdentifier(tn.readIdentifier(), tn.range());
identifier = Node.createIdentifier(tn.readIdentifier(), tn.range());
}
const ret: ContinueStatement = Statement.createContinue(identifier, tn.range());
const ret: ContinueStatement = Node.createContinue(identifier, tn.range());
tn.skip(Token.SEMICOLON);
return ret;
}
@ -1065,7 +1065,7 @@ export class Parser extends DiagnosticEmitter {
if (!condition)
return null;
if (tn.skip(Token.CLOSEPAREN)) {
const ret: DoStatement = Statement.createDo(<Statement>statement, <Expression>condition, tn.range(startPos, tn.pos));
const ret: DoStatement = Node.createDo(<Statement>statement, <Expression>condition, tn.range(startPos, tn.pos));
tn.skip(Token.SEMICOLON);
return ret;
}
@ -1082,7 +1082,7 @@ export class Parser extends DiagnosticEmitter {
const expr: Expression | null = this.parseExpression(tn);
if (!expr)
return null;
const ret: ExpressionStatement = Statement.createExpression(expr);
const ret: ExpressionStatement = Node.createExpression(expr);
tn.skip(Token.SEMICOLON);
return ret;
}
@ -1120,7 +1120,7 @@ export class Parser extends DiagnosticEmitter {
const statement: Statement | null = this.parseStatement(tn);
if (!statement)
return null;
return Statement.createFor(initializer, condition ? condition.expression : null, incrementor, statement, tn.range(startPos, tn.pos));
return Node.createFor(initializer, condition ? condition.expression : null, incrementor, statement, tn.range(startPos, tn.pos));
} else
this.error(DiagnosticCode._0_expected, tn.range(), ";");
} else
@ -1147,7 +1147,7 @@ export class Parser extends DiagnosticEmitter {
if (!elseStatement)
return null;
}
return Statement.createIf(<Expression>condition, <Statement>statement, elseStatement, Range.join(startRange, tn.range()));
return Node.createIf(<Expression>condition, <Statement>statement, elseStatement, Range.join(startRange, tn.range()));
}
this.error(DiagnosticCode._0_expected, tn.range(), ")");
} else
@ -1171,7 +1171,7 @@ export class Parser extends DiagnosticEmitter {
return null;
cases.push(<SwitchCase>case_);
}
const ret: SwitchStatement = Statement.createSwitch(condition, cases, tn.range(startPos, tn.pos));
const ret: SwitchStatement = Node.createSwitch(condition, cases, tn.range(startPos, tn.pos));
tn.skip(Token.SEMICOLON);
return ret;
} else
@ -1199,7 +1199,7 @@ export class Parser extends DiagnosticEmitter {
return null;
statements.push(<Statement>statement);
}
return Statement.createSwitchCase(<Expression>label, statements, tn.range(startPos, tn.pos));
return Node.createSwitchCase(<Expression>label, statements, tn.range(startPos, tn.pos));
} else
this.error(DiagnosticCode._0_expected, tn.range(), ":");
@ -1213,7 +1213,7 @@ export class Parser extends DiagnosticEmitter {
return null;
statements.push(<Statement>statement);
}
return Statement.createSwitchCase(null, statements, tn.range(startPos, tn.pos));
return Node.createSwitchCase(null, statements, tn.range(startPos, tn.pos));
} else
this.error(DiagnosticCode._0_expected, tn.range(), ":");
@ -1229,7 +1229,7 @@ export class Parser extends DiagnosticEmitter {
const expression: Expression | null = this.parseExpression(tn);
if (!expression)
return null;
const ret: ThrowStatement = Statement.createThrow(<Expression>expression, tn.range(startPos, tn.pos));
const ret: ThrowStatement = Node.createThrow(<Expression>expression, tn.range(startPos, tn.pos));
tn.skip(Token.SEMICOLON);
return ret;
}
@ -1257,7 +1257,7 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode.Identifier_expected, tn.range());
return null;
}
catchVariable = Expression.createIdentifier(tn.readIdentifier(), tn.range());
catchVariable = Node.createIdentifier(tn.readIdentifier(), tn.range());
if (!tn.skip(Token.CLOSEPAREN)) {
this.error(DiagnosticCode._0_expected, tn.range(), ")");
return null;
@ -1291,7 +1291,7 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode._0_expected, tn.range(), "catch");
return null;
}
const ret: TryStatement = Statement.createTry(statements, catchVariable, catchStatements, finallyStatements, Range.join(startRange, tn.range()));
const ret: TryStatement = Node.createTry(statements, catchVariable, catchStatements, finallyStatements, Range.join(startRange, tn.range()));
tn.skip(Token.SEMICOLON);
return ret;
} else
@ -1310,7 +1310,7 @@ export class Parser extends DiagnosticEmitter {
const statement: Statement | null = this.parseStatement(tn);
if (!statement)
return null;
const ret: WhileStatement = Statement.createWhile(<Expression>expression, <Statement>statement, Range.join(startRange, tn.range()));
const ret: WhileStatement = Node.createWhile(<Expression>expression, <Statement>statement, Range.join(startRange, tn.range()));
tn.skip(Token.SEMICOLON);
return ret;
} else
@ -1329,11 +1329,11 @@ export class Parser extends DiagnosticEmitter {
let expr: Expression | null = null;
if (token == Token.NULL)
return Expression.createNull(tn.range());
return Node.createNull(tn.range());
if (token == Token.TRUE)
return Expression.createTrue(tn.range());
return Node.createTrue(tn.range());
if (token == Token.FALSE)
return Expression.createFalse(tn.range());
return Node.createFalse(tn.range());
let p: Precedence = determinePrecedencePrefix(token);
if (p != Precedence.INVALID) {
@ -1347,7 +1347,7 @@ export class Parser extends DiagnosticEmitter {
if (!operand)
return null;
if (operand.kind == NodeKind.CALL)
return Expression.createNew((<CallExpression>operand).expression, (<CallExpression>operand).typeArguments, (<CallExpression>operand).arguments, tn.range(startPos, tn.pos));
return Node.createNew((<CallExpression>operand).expression, (<CallExpression>operand).typeArguments, (<CallExpression>operand).arguments, tn.range(startPos, tn.pos));
this.error(DiagnosticCode.Operation_not_supported, tn.range());
return null;
} else
@ -1357,7 +1357,7 @@ export class Parser extends DiagnosticEmitter {
if (token == Token.PLUS_PLUS || token == Token.MINUS_MINUS)
if ((<Expression>operand).kind != NodeKind.IDENTIFIER && (<Expression>operand).kind != NodeKind.ELEMENTACCESS && (<Expression>operand).kind != NodeKind.PROPERTYACCESS)
this.error(DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, (<Expression>operand).range);
return Expression.createUnaryPrefix(token, <Expression>operand, tn.range(startPos, tn.pos));
return Node.createUnaryPrefix(token, <Expression>operand, tn.range(startPos, tn.pos));
}
switch (token) {
@ -1371,7 +1371,7 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode._0_expected, tn.range(), ")");
return null;
}
return Expression.createParenthesized(expr, tn.range(startPos, tn.pos));
return Node.createParenthesized(expr, tn.range(startPos, tn.pos));
}
// ArrayLiteralExpression
@ -1393,7 +1393,7 @@ export class Parser extends DiagnosticEmitter {
return null;
}
}
return Expression.createArrayLiteral(elementExpressions, tn.range(startPos, tn.pos));
return Node.createArrayLiteral(elementExpressions, tn.range(startPos, tn.pos));
}
// AssertionExpression (unary prefix)
@ -1408,37 +1408,37 @@ export class Parser extends DiagnosticEmitter {
expr = this.parseExpression(tn, Precedence.CALL);
if (!expr)
return null;
return Expression.createAssertion(AssertionKind.PREFIX, <Expression>expr, <TypeNode>toType, tn.range(startPos, tn.pos));
return Node.createAssertion(AssertionKind.PREFIX, <Expression>expr, <TypeNode>toType, tn.range(startPos, tn.pos));
}
// IdentifierExpression
case Token.IDENTIFIER:
return Expression.createIdentifier(tn.readIdentifier(), tn.range(startPos, tn.pos));
return Node.createIdentifier(tn.readIdentifier(), tn.range(startPos, tn.pos));
case Token.THIS:
return Expression.createThis(tn.range(startPos, tn.pos));
return Node.createThis(tn.range(startPos, tn.pos));
case Token.CONSTRUCTOR:
return Expression.createConstructor(tn.range(startPos, tn.pos));
return Node.createConstructor(tn.range(startPos, tn.pos));
case Token.SUPER:
return Expression.createSuper(tn.range(startPos, tn.pos));
return Node.createSuper(tn.range(startPos, tn.pos));
// StringLiteralExpression
case Token.STRINGLITERAL:
return Expression.createStringLiteral(tn.readString(), tn.range(startPos, tn.pos));
return Node.createStringLiteral(tn.readString(), tn.range(startPos, tn.pos));
// IntegerLiteralExpression
case Token.INTEGERLITERAL:
return Expression.createIntegerLiteral(tn.readInteger(), tn.range(startPos, tn.pos));
return Node.createIntegerLiteral(tn.readInteger(), tn.range(startPos, tn.pos));
// FloatLiteralExpression
case Token.FLOATLITERAL:
return Expression.createFloatLiteral(tn.readFloat(), tn.range(startPos, tn.pos));
return Node.createFloatLiteral(tn.readFloat(), tn.range(startPos, tn.pos));
// RegexpLiteralExpression
case Token.REGEXPLITERAL:
return Expression.createRegexpLiteral(tn.readRegexp(), tn.range(startPos, tn.pos));
return Node.createRegexpLiteral(tn.readRegexp(), tn.range(startPos, tn.pos));
default:
this.error(DiagnosticCode.Expression_expected, tn.range());
@ -1500,7 +1500,7 @@ export class Parser extends DiagnosticEmitter {
const args: Expression[] | null = this.parseArguments(tn);
if (!args)
return null;
expr = Expression.createCall(expr, <TypeNode[]>(typeArguments ? typeArguments : []), args, tn.range(startPos, tn.pos));
expr = Node.createCall(expr, <TypeNode[]>(typeArguments ? typeArguments : []), args, tn.range(startPos, tn.pos));
}
let token: Token;
@ -1515,7 +1515,7 @@ export class Parser extends DiagnosticEmitter {
const toType: TypeNode | null = this.parseType(tn);
if (!toType)
return null;
expr = Expression.createAssertion(AssertionKind.AS, expr, toType, tn.range(startPos, tn.pos));
expr = Node.createAssertion(AssertionKind.AS, expr, toType, tn.range(startPos, tn.pos));
// ElementAccessExpression
} else if (token == Token.OPENBRACKET) {
@ -1524,7 +1524,7 @@ export class Parser extends DiagnosticEmitter {
return null;
if (tn.skip(Token.CLOSEBRACKET))
expr = Expression.createElementAccess(<Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
expr = Node.createElementAccess(<Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
else {
this.error(DiagnosticCode._0_expected, tn.range(), "]");
return null;
@ -1534,7 +1534,7 @@ export class Parser extends DiagnosticEmitter {
} else if (token == Token.PLUS_PLUS || token == Token.MINUS_MINUS) {
if (expr.kind != NodeKind.IDENTIFIER && expr.kind != NodeKind.ELEMENTACCESS && expr.kind != NodeKind.PROPERTYACCESS)
this.error(DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, expr.range);
expr = Expression.createUnaryPostfix(token, expr, tn.range(startPos, tn.pos));
expr = Node.createUnaryPostfix(token, expr, tn.range(startPos, tn.pos));
// TernaryExpression
} else if (token == Token.QUESTION) {
@ -1545,7 +1545,7 @@ export class Parser extends DiagnosticEmitter {
const ifElse: Expression | null = this.parseExpression(tn);
if (!ifElse)
return null;
expr = Expression.createTernary(<Expression>expr, <Expression>ifThen, <Expression>ifElse, tn.range(startPos, tn.pos));
expr = Node.createTernary(<Expression>expr, <Expression>ifThen, <Expression>ifElse, tn.range(startPos, tn.pos));
} else {
this.error(DiagnosticCode._0_expected, tn.range(), ":");
return null;
@ -1559,11 +1559,11 @@ export class Parser extends DiagnosticEmitter {
// PropertyAccessExpression
if (token == Token.DOT) {
if (next.kind == NodeKind.IDENTIFIER) {
expr = Expression.createPropertyAccess(<Expression>expr, <IdentifierExpression>next, tn.range(startPos, tn.pos));
expr = Node.createPropertyAccess(<Expression>expr, <IdentifierExpression>next, tn.range(startPos, tn.pos));
} else if (next.kind == NodeKind.CALL) { // amend
let propertyCall: CallExpression = <CallExpression>next;
if (propertyCall.expression.kind == NodeKind.IDENTIFIER) {
propertyCall.expression = Expression.createPropertyAccess(<Expression>expr, <IdentifierExpression>propertyCall.expression, tn.range(startPos, tn.pos));
propertyCall.expression = Node.createPropertyAccess(<Expression>expr, <IdentifierExpression>propertyCall.expression, tn.range(startPos, tn.pos));
} else
throw new Error("unexpected expression kind");
expr = propertyCall;
@ -1574,7 +1574,7 @@ export class Parser extends DiagnosticEmitter {
// BinaryExpression
} else
expr = Expression.createBinary(token, <Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
expr = Node.createBinary(token, <Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
}
}
return expr;

View File

@ -672,10 +672,10 @@ export class Program extends DiagnosticEmitter {
resolveType(node: TypeNode, contextualTypeArguments: Map<string,Type> | null = null, reportNotFound: bool = true): Type | null {
// resolve parameters
const k: i32 = node.parameters.length;
const k: i32 = node.typeArguments.length;
const paramTypes: Type[] = new Array(k);
for (let i: i32 = 0; i < k; ++i) {
const paramType: Type | null = this.resolveType(node.parameters[i], contextualTypeArguments, reportNotFound);
const paramType: Type | null = this.resolveType(node.typeArguments[i], contextualTypeArguments, reportNotFound);
if (!paramType)
return null;
paramTypes[i] = <Type>paramType;
@ -806,30 +806,34 @@ function hasDecorator(name: string, decorators: Decorator[] | null): bool {
/** Indicates the specific kind of an {@link Element}. */
export enum ElementKind {
/** A {@link ClassPrototype}. */
CLASS_PROTOTYPE,
/** A {@link Class}. */
CLASS,
/** A {@link Global}. */
GLOBAL,
/** A {@link Local}. */
LOCAL,
/** An {@link Enum}. */
ENUM,
/** An {@link EnumValue}. */
ENUMVALUE,
/** A {@link FieldPrototype}. */
FIELD_PROTOTYPE,
/** A {@link Field}. */
FIELD,
/** A {@link FunctionPrototype}. */
FUNCTION_PROTOTYPE,
/** A {@link Function}. */
FUNCTION,
/** A {@link Global}. */
GLOBAL,
/** A {@link ClassPrototype}. */
CLASS_PROTOTYPE,
/** A {@link Class}. */
CLASS,
/** An {@link InterfacePrototype}. */
INTERFACE_PROTOTYPE,
/** An {@link Interface}. */
INTERFACE,
/** A {@link Local}. */
LOCAL,
/** A {@link FieldPrototype}. */
FIELD_PROTOTYPE,
/** A {@link Field}. */
FIELD,
/** A {@link PropertyPrototype}. */
PROPERTY_PROTOTYPE,
/** A {@link Property}. */
PROPERTY,
/** A {@link Namespace}. */
NAMESPACE
}
@ -1113,7 +1117,11 @@ export class FunctionPrototype extends Element {
case ModifierKind.DECLARE: this.isDeclared = true; break;
case ModifierKind.GET: this.isGetter = true; break;
case ModifierKind.SET: this.isSetter = true; break;
case ModifierKind.STATIC: break; // already handled
case ModifierKind.STATIC:
case ModifierKind.ABSTRACT:
case ModifierKind.PRIVATE:
case ModifierKind.PROTECTED:
case ModifierKind.PUBLIC: break; // already handled
default: throw new Error("unexpected modifier");
}
}
@ -1360,7 +1368,11 @@ export class Function extends Element {
this.tempI32s = this.tempI64s = this.tempF32s = this.tempF64s = null;
}
/** Returns the TypeScript representation of this function. */
toString(): string { return this.prototype.simpleName; }
/** Returns the function type TypeScript representation of this function.*/
toTypeString(): string { throw new Error("not implemented"); }
}
/** A yet unresolved instance field prototype. */
@ -1416,6 +1428,76 @@ export class Field extends Element {
}
}
/** A yet unresolved property. */
export class PropertyPrototype extends Element {
kind = ElementKind.PROPERTY_PROTOTYPE;
/** Simple name. */
simpleName: string;
/** Parent class prototype. */
classPrototype: ClassPrototype;
/** Getter declaration reference. */
getterDeclaration: FunctionDeclaration | null;
/** Setter declaration reference. */
setterDeclaration: FunctionDeclaration | null;
/** Constructs a new propery prototype. */
constructor(classPrototype: ClassPrototype, simpleName: string, internalName: string, getterDeclaration: FunctionDeclaration | null = null, setterDeclaration: FunctionDeclaration | null = null) {
super(classPrototype.program, internalName);
this.simpleName = simpleName;
this.classPrototype = classPrototype;
let i: i32, k: i32;
if ((this.getterDeclaration = getterDeclaration) && this.getterDeclaration.modifiers) {
assert(this.getterDeclaration.typeParameters.length == 0);
assert(this.getterDeclaration.parameters.length == 0);
for (i = 0, k = this.getterDeclaration.modifiers.length; i < k; ++i) {
switch (this.getterDeclaration.modifiers[i].modifierKind) {
case ModifierKind.EXPORT: this.isExported = true; break;
case ModifierKind.GET:
case ModifierKind.STATIC: break; // already handled
default: assert(false);
}
}
}
if ((this.setterDeclaration = setterDeclaration) && this.setterDeclaration.modifiers) {
assert(this.setterDeclaration.typeParameters.length == 0);
assert(this.setterDeclaration.parameters.length == 1);
for (i = 0, k = this.setterDeclaration.modifiers.length; i < k; ++i) {
switch (this.setterDeclaration.modifiers[i].modifierKind) {
case ModifierKind.EXPORT: this.isExported = true; break;
case ModifierKind.SET:
case ModifierKind.STATIC: break; // already handled
default: assert(false);
}
}
}
}
}
/** A resolved property. */
export class Property extends Element {
kind = ElementKind.PROPERTY;
/** Prototype reference. */
prototype: PropertyPrototype;
/** Property type. */
type: Type;
/** Getter function. */
getter: Function | null = null;
/** Setter function. */
setter: Function | null = null;
/** Constructs a new property. */
constructor(prototype: PropertyPrototype, internalName: string, type: Type) {
super(prototype.program, internalName);
this.flags = prototype.flags;
this.type = type;
}
}
/** A yet unresolved class prototype. */
export class ClassPrototype extends Element {

View File

@ -1,6 +1,7 @@
import { Class } from "./program";
import { Class, Function } from "./program";
import { sb } from "./util/sb";
/** Indicates the kind of a type. */
export const enum TypeKind {
// signed integers
@ -22,18 +23,30 @@ export const enum TypeKind {
F32,
F64,
// other
VOID
// SYMBOL ?
}
/** Represents a resolved type. */
export class Type {
/** Type kind. */
kind: TypeKind;
/** Size in bits. */
size: i32;
/** Size in bytes. */
byteSize: i32;
/** Underlying class type, if a class type. */
classType: Class | null;
nullable: bool = false;
nullableType: Type | null = null; // cached, of this type
/** Underlying function type, if a function type. */
functionType: Function | null;
/** Whether nullable or not. */
isNullable: bool = false;
/** Respective nullable type, if nullable. */
nullableType: Type | null = null;
/** Constructs a new resolved type. */
constructor(kind: TypeKind, size: i32) {
this.kind = kind;
this.size = size;
@ -41,31 +54,51 @@ export class Type {
this.classType = null;
}
/** Sign-extending 32-bit shift, if a small signed integer. */
get smallIntegerShift(): i32 { return 32 - this.size; }
/** Truncating 32-bit mask, if a small unsigned integer. */
get smallIntegerMask(): i32 { return -1 >>> (32 - this.size); }
/** Tests if this type is of any integer kind. */
get isAnyInteger(): bool { return this.kind >= TypeKind.I8 && this.kind <= TypeKind.BOOL; }
/** Tests if this type is of any small integer kind. */
get isSmallInteger(): bool { return this.size != 0 && this.size < 32; }
/** Tests if this type is of any long integer kind. */
get isLongInteger(): bool { return this.size == 64 && this.kind != TypeKind.F64; }
/** Tests if this type is of any unsigned integer kind. */
get isUnsignedInteger(): bool { return this.kind >= TypeKind.U8 && this.kind <= TypeKind.BOOL; }
/** Tests if this type is of any signed integer kind. */
get isSignedInteger(): bool { return this.kind >= TypeKind.I8 && this.kind <= TypeKind.ISIZE; }
/** Tests if this type is of any size kind, i.e., `isize` or `usize`. */
get isAnySize(): bool { return this.kind == TypeKind.ISIZE || this.kind == TypeKind.USIZE; }
/** Tests if this type is of any float kind, i.e., `f32` or `f64`. */
get isAnyFloat(): bool { return this.kind == TypeKind.F32 || this.kind == TypeKind.F64; }
/** Composes a class type from this type and a class. */
asClass(classType: Class): Type {
assert(this.kind == TypeKind.USIZE);
const ret: Type = new Type(this.kind, this.size);
ret.classType = classType;
return ret;
}
/** Composes a function type from this type and a function. */
asFunction(functionType: Function): Type {
assert(this.kind == TypeKind.USIZE);
const ret: Type = new Type(this.kind, this.size);
ret.functionType = functionType;
return ret;
}
/** Composes the respective nullable type of this type. */
asNullable(): Type {
if (this.kind != TypeKind.USIZE)
throw new Error("unexpected non-usize nullable");
if (!this.nullableType)
(this.nullableType = new Type(this.kind, this.size)).nullable = true;
assert(this.kind == TypeKind.USIZE);
if (this.isNullable && !this.nullableType)
(this.nullableType = new Type(this.kind, this.size)).isNullable = true;
return <Type>this.nullableType;
}
/** Converts this type to its TypeScript representation. */
toString(kindOnly: bool = false): string {
switch (this.kind) {
case TypeKind.I8: return "i8";
@ -77,35 +110,56 @@ export class Type {
case TypeKind.U16: return "u16";
case TypeKind.U32: return "u32";
case TypeKind.U64: return "u64";
case TypeKind.USIZE: return this.classType != null && !kindOnly ? this.classType.toString() : "usize";
case TypeKind.USIZE:
if (kindOnly) return "usize";
return this.classType ? this.classType.toString()
: this.functionType ? this.functionType.toTypeString()
: "usize";
case TypeKind.BOOL: return "bool";
case TypeKind.F32: return "f32";
case TypeKind.F64: return "f64";
case TypeKind.VOID: return "void";
default:
throw new Error("unexpected type kind");
default: assert(false); return "INVALID";
}
}
/** An 8-bit signed integer. */
static readonly i8: Type = new Type(TypeKind.I8, 8);
/** A 16-bit signed integer. */
static readonly i16: Type = new Type(TypeKind.I16, 16);
/** A 32-bit signed integer. */
static readonly i32: Type = new Type(TypeKind.I32, 32);
/** A 64-bit signed integer. */
static readonly i64: Type = new Type(TypeKind.I64, 64);
/** A 32-bit signed size. WASM32 only. */
static readonly isize32: Type = new Type(TypeKind.I32, 32);
/** A 64-bit signed size. WASM64 only. */
static readonly isize64: Type = new Type(TypeKind.I64, 64);
/** An 8-bit unsigned integer. */
static readonly u8: Type = new Type(TypeKind.U8, 8);
/** A 16-bit unsigned integer. */
static readonly u16: Type = new Type(TypeKind.U16, 16);
/** A 32-bit unsigned integer. */
static readonly u32: Type = new Type(TypeKind.U32, 32);
/** A 64-bit unsigned integer. */
static readonly u64: Type = new Type(TypeKind.U64, 64);
/** A 32-bit unsigned size. WASM32 only. */
static readonly usize32: Type = new Type(TypeKind.U32, 32);
/** A 64-bit unsigned size. WASM64 only. */
static readonly usize64: Type = new Type(TypeKind.U64, 64);
/** A 1-bit unsigned integer. */
static readonly bool: Type = new Type(TypeKind.BOOL, 1);
/** A 32-bit float. */
static readonly f32: Type = new Type(TypeKind.F32, 32);
/** A 64-bit float. */
static readonly f64: Type = new Type(TypeKind.F64, 64);
/** No return type. */
static readonly void: Type = new Type(TypeKind.VOID, 0);
static readonly infer: Type = Type.void;
/** Special type used in type inference. Alias of {@link Type.void}. */
static readonly auto: Type = Type.void;
}
/** Converts an array of types to its combined string representation. Usually type arguments. */
export function typesToString(types: Type[], prefix: string = "<", postfix: string = ">"): string {
const k: i32 = types.length;
if (!k)
@ -113,5 +167,5 @@ export function typesToString(types: Type[], prefix: string = "<", postfix: stri
sb.length = 0;
for (let i: i32 = 0; i < k; ++i)
sb[i] = types[i].toString();
return prefix + sb.join(",") + postfix;
return prefix + sb.join(", ") + postfix;
}