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

88
std/assembly.d.ts vendored
View File

@ -157,8 +157,8 @@ declare function unreachable(): any; // sic
declare const NaN: f32 | f64;
/** Positive infinity as a 32-bit or 64-bit float depending on context. */
declare const Infinity: f32 | f64;
/** Heap start offset. */
declare const HEAP_START: usize;
/** Heap base offset. */
declare const HEAP_BASE: usize;
/** Determines the byte size of the specified core or class type. Compiles to a constant. */
declare function sizeof<T>(): usize;
/** Changes the type of a value to another one. Useful for casting class instances to their pointer values and vice-versa. */
@ -174,18 +174,72 @@ declare function parseInt(str: string, radix?: i32): f64;
/** Parses a string to a 64-bit float. */
declare function parseFloat(str: string): f64;
// Internal decorators (not yet implemented)
/** Annotates an element being part of the global namespace. */
declare function global(): any;
/** Annotates a function being always inlined. */
declare function inline(): any;
/** Annotates a class using a C-style memory layout. */
declare function struct(): any;
// Standard library (not yet implemented)
interface Array<T> {}
/** Class representing a sequence of values of type `T`. */
declare class Array<T> {
/** Current maximum capacity of the array. */
readonly capacity: i32;
/** Current length of the array. */
length: i32;
/** Constructs a new array. */
constructor(capacity?: i32);
}
/** Class representing a sequence of characters. */
declare class String {
static fromCharCode(ls: i32, hs?: i32): string;
static fromCharCodes(arr: u16[]): string;
static fromCodePoint(cp: i32): string;
static fromCodePoints(arr: i32[]): string;
}
/** Class for representing a runtime error. Base class of all errors. */
declare class Error {
/** Error name. */
name: string;
/** Message provided on construction. */
message: string;
/** Stack trace. */
stack: string;
/** Constructs a new error, optionally with a message. */
constructor(message?: string);
}
/** Class for indicating an error when a value is not in the set or range of allowed values. */
declare class RangeError extends Error { }
/** A static class representing the heap. */
declare class Heap {
/** Gets the amount of used heap space, in bytes. */
static readonly used: usize;
/** Gets the amount of free heap space, in bytes. */
static readonly free: usize;
/** Gets the size of the heap, in bytes. */
static readonly size: usize;
/** Allocates a chunk of memory and returns a pointer to it. */
static allocate(size: usize): usize;
/** Disposes a chunk of memory by its pointer. */
static dispose(ptr: usize): void;
/** Copies a chunk of memory from one location to another. */
static copy(dest: usize, src: usize, n: usize): usize;
private constructor();
}
interface Boolean {}
interface Function {}
interface IArguments {}
@ -193,9 +247,7 @@ interface Number {}
interface Object {}
interface RegExp {}
declare class String {
static fromCharCode(ls: i32, hs?: i32): string;
static fromCharCodes(arr: u16[]): string;
static fromCodePoint(cp: i32): string;
static fromCodePoints(arr: i32[]): string;
}
// Internal decorators (not yet implemented)
/** Annotates an element being part of the global namespace. */
declare function global(): any;

View File

@ -1,25 +1,13 @@
// Multiple options:
// 1. C-like with no 'length' or 'push'
// 2. Descriptors that can be constructed from lower level arrays
@global()
class Array<T> {
export class Array<T> {
readonly capacity: i32;
length: i32;
ptr: usize;
static fromPtr<T>(ptr: usize, capacity: i32): Array<T> {
assert(capacity >= 0);
const arr: Array<T> = new Array(0);
store<i32>(changetype<Array<T>, usize>(arr), capacity);
arr.length = ptr;
arr.ptr = ptr;
return arr;
}
constructor(capacity: i32 = 0) {
assert(capacity >= 0);
if (capacity < 0)
throw new RangeError("invalid array length");
this.capacity = this.length = capacity;
if (capacity > 0) {
this.ptr = Heap.allocate(<usize>capacity);
@ -35,5 +23,5 @@ class Array<T> {
Heap.dispose(changetype<this,usize>(this));
}
static test(): void {}
// TODO
}

16
std/assembly/error.ts Normal file
View File

@ -0,0 +1,16 @@
@global()
export class Error {
name: string = "Error";
message: string;
stack: string = ""; // TODO
constructor(message: string = "") {
this.message = message;
}
}
@global()
export class RangeError extends Error {
name: string = "RangeError";
}

View File

@ -2,10 +2,16 @@ const ALIGN_LOG2: usize = 3;
const ALIGN_SIZE: usize = 1 << ALIGN_LOG2;
const ALIGN_MASK: usize = ALIGN_SIZE - 1;
let HEAP_OFFSET: usize = HEAP_START; // HEAP_START is a constant generated by the compiler
let HEAP_OFFSET: usize = HEAP_BASE; // HEAP_BASE is a constant generated by the compiler
// TODO: maybe tlsf
@global()
class Heap {
export class Heap {
static get used(): usize { return HEAP_OFFSET - HEAP_BASE; }
static get free(): usize { return (<usize>current_memory() << 16) - HEAP_OFFSET; }
static get size(): usize { return (<usize>current_memory() << 16) - HEAP_BASE; }
static allocate(size: usize): usize {
if (!size) return 0;
@ -23,20 +29,8 @@ class Heap {
// just a big chunk of non-disposable memory for now
}
static get used(): usize {
return HEAP_OFFSET - HEAP_START;
}
static get free(): usize {
return (<usize>current_memory() << 16) - HEAP_OFFSET;
}
static get size(): usize {
return (<usize>current_memory() << 16) - HEAP_START;
}
static copy(dest: usize, src: usize, n: usize): usize {
assert(dest >= HEAP_START);
assert(dest >= HEAP_BASE);
// the following is based on musl's implementation of memcpy
let dst: usize = dest;
@ -179,4 +173,6 @@ class Heap {
}
return dest;
}
private constructor() {}
}

4
std/assembly/map.ts Normal file
View File

@ -0,0 +1,4 @@
@global()
export class Map<K,V> {
// TODO
}

4
std/assembly/set.ts Normal file
View File

@ -0,0 +1,4 @@
@global()
export class Set<T> {
// TODO
}

4
std/assembly/string.ts Normal file
View File

@ -0,0 +1,4 @@
@global()
export class String {
// TODO
}

View File

@ -37,7 +37,7 @@ Object.defineProperties(
"MAX_VALUE": { value: 4294967295, writable: false }
});
Object.defineProperties(
globalScope["bool"] = function bool(value) { return Boolean(value); }
globalScope["bool"] = function bool(value) { return !!value; }
, {
"MIN_VALUE": { value: 0, writable: false },
"MAX_VALUE": { value: 1, writable: false }

View File

@ -15,4 +15,7 @@ declare class Heap {
/** Gets the size of the heap, in bytes. */
static readonly size: usize;
/** Copies a chunk of memory from one location to another. */
static copy(dest: usize, src: usize, n: usize): usize;
}

View File

@ -1,6 +1,6 @@
(module
(type $v (func))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -58,7 +58,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
[program.exports]
;)

View File

@ -5,7 +5,7 @@
(global $binary/I (mut i64) (i64.const 0))
(global $binary/f (mut f32) (f32.const 0))
(global $binary/F (mut f64) (f64.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -861,7 +861,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
binary/b
binary/i
binary/I

View File

@ -6,7 +6,7 @@
(global $builtins/b (mut i32) (i32.const 0))
(global $builtins/F (mut f64) (f64.const 0))
(global $builtins/s (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -1078,7 +1078,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
builtins/b
builtins/i
builtins/I

View File

@ -3,7 +3,7 @@
(type $fff (func (param f32 f32) (result f32)))
(type $v (func))
(global $class/Animal.MAX (mut i32) (i32.const 1))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -86,7 +86,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
class/Animal
class/Animal.MAX
class/Animal.add

View File

@ -1,7 +1,7 @@
(module
(type $v (func))
(import "env" "external" (func $declare/external))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "external" (func $declare/external))
(export "memory" (memory $0))
@ -51,7 +51,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
declare/external
[program.exports]
declare/external

View File

@ -1,6 +1,6 @@
(module
(type $iv (func (param i32)))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "loopDo" (func $do/loopDo))
(export "loopDoInDo" (func $do/loopDoInDo))
@ -96,7 +96,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
do/loopDo
do/loopDoInDo
[program.exports]

View File

@ -15,7 +15,7 @@
(global $enum/Mixed.FOUR i32 (i32.const 4))
(global $enum/NonConstant.ZERO (mut i32) (i32.const 0))
(global $enum/NonConstant.ONE (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -81,7 +81,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
enum/Implicit
enum/Explicit
enum/Mixed

View File

@ -3,7 +3,7 @@
(type $v (func))
(global $export/a i32 (i32.const 1))
(global $export/b i32 (i32.const 2))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "add" (func $export/add))
(export "renamed_sub" (func $export/sub))
@ -75,7 +75,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
export/add
export/sub
export/a

View File

@ -1,7 +1,7 @@
(module
(type $v (func))
(global $for/i (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -192,7 +192,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
for/i
[program.exports]

View File

@ -4,7 +4,7 @@
(global $../../examples/game-of-life/assembly/game-of-life/w (mut i32) (i32.const 0))
(global $../../examples/game-of-life/assembly/game-of-life/h (mut i32) (i32.const 0))
(global $../../examples/game-of-life/assembly/game-of-life/s (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "init" (func $../../examples/game-of-life/assembly/game-of-life/init))
(export "step" (func $../../examples/game-of-life/assembly/game-of-life/step))
@ -353,7 +353,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
../../examples/game-of-life/assembly/game-of-life/w
../../examples/game-of-life/assembly/game-of-life/h
../../examples/game-of-life/assembly/game-of-life/s

View File

@ -4,7 +4,7 @@
(type $iiiiv (func (param i32 i32 i32 i32)))
(global $../../examples/i64-polyfill/assembly/i64/hi (mut i32) (i32.const 0))
(global $../../examples/i64-polyfill/assembly/i64/lo (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "getHi" (func $../../examples/i64-polyfill/assembly/i64/getHi))
(export "getLo" (func $../../examples/i64-polyfill/assembly/i64/getLo))
@ -1234,7 +1234,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
../../examples/i64-polyfill/assembly/i64/lo
../../examples/i64-polyfill/assembly/i64/hi
../../examples/i64-polyfill/assembly/i64/getLo

View File

@ -1,6 +1,6 @@
(module
(type $ii (func (param i32) (result i32)))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "ifThenElse" (func $if/ifThenElse))
(export "ifThen" (func $if/ifThen))
@ -91,7 +91,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
if/ifThenElse
if/ifThen
if/ifThenElseBlock

View File

@ -3,7 +3,7 @@
(type $v (func))
(global $export/a i32 (i32.const 1))
(global $export/b i32 (i32.const 2))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -86,7 +86,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
export/add
export/sub
export/a

View File

@ -22,7 +22,7 @@
(global $f32.MAX_SAFE_INTEGER f32 (f32.const 16777215))
(global $f64.MIN_SAFE_INTEGER f64 (f64.const -9007199254740991))
(global $f64.MAX_SAFE_INTEGER f64 (f64.const 9007199254740991))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -152,7 +152,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
[program.exports]
;)

View File

@ -1,6 +1,6 @@
(module
(type $v (func))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -184,7 +184,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
[program.exports]
;)

View File

@ -4,7 +4,7 @@
(global $logical/I (mut i64) (i64.const 0))
(global $logical/f (mut f32) (f32.const 0))
(global $logical/F (mut f64) (f64.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -300,7 +300,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
logical/i
logical/I
logical/f

View File

@ -3,7 +3,7 @@
(type $v (func))
(global $memcpy/base i32 (i32.const 8))
(global $memcpy/dest (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memcpy" (func $memcpy/memcpy))
(export "memory" (memory $0))
@ -2098,7 +2098,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
memcpy/memcpy
memcpy/base
memcpy/dest

View File

@ -1,7 +1,7 @@
(module
(type $v (func))
(global $namespace/Outer.Inner.aVar (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "test" (func $namespace/test))
(export "memory" (memory $0))
@ -62,7 +62,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
namespace/Outer
namespace/Outer.Inner
namespace/Outer.Inner.aVar

View File

@ -4,7 +4,7 @@
(global $portable-conversions/I (mut i64) (i64.const 0))
(global $portable-conversions/f (mut f32) (f32.const 0))
(global $portable-conversions/F (mut f64) (f64.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -374,7 +374,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
portable-conversions/i
portable-conversions/I
portable-conversions/f

View File

@ -3,7 +3,7 @@
(type $v (func))
(global $export/a i32 (i32.const 1))
(global $export/b i32 (i32.const 2))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "add" (func $export/add))
(export "renamed_sub" (func $export/sub))
@ -91,7 +91,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
export/add
export/sub
export/a

View File

@ -1,11 +0,0 @@
(module
(type $v (func))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
(func $start (; 0 ;) (type $v)
(block $__inlined_func$Array.test
(nop)
)
)
)

View File

@ -1,12 +1,4 @@
(module
(type $v (func))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
(func $Array.test (; 0 ;) (type $v)
(nop)
)
(func $start (; 1 ;) (type $v)
(call $Array.test)
)
)

View File

@ -1,2 +1 @@
// Array.fromPtr<i32>(1);
Array.test();

View File

@ -1,14 +1,7 @@
(module
(type $v (func))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
(func $Array.test (; 0 ;) (type $v)
)
(func $start (; 1 ;) (type $v)
(call $Array.test)
)
)
(;
[program.elements]
@ -55,21 +48,30 @@
f64
isize
usize
HEAP_START
HEAP_BASE
Array
Array.fromPtr
Array.test
Error
RangeError
heap/ALIGN_LOG2
heap/ALIGN_SIZE
heap/ALIGN_MASK
heap/HEAP_OFFSET
Heap
Heap.allocate
Heap.dispose
Heap.get_used
Heap.get_free
Heap.get_size
Heap.allocate
Heap.dispose
Heap.copy
Map
Set
String
[program.exports]
Array
Error
RangeError
Heap
Map
Set
String
;)

View File

@ -4,7 +4,7 @@
(type $v (func))
(global $heap/HEAP_OFFSET (mut i32) (i32.const 0))
(global $std/heap/ptr (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -100,7 +100,7 @@
(func $start (; 1 ;) (type $v)
(local $0 i32)
(set_global $heap/HEAP_OFFSET
(get_global $HEAP_START)
(get_global $HEAP_BASE)
)
(set_global $std/heap/ptr
(call $Heap.allocate

View File

@ -4,7 +4,7 @@
(type $v (func))
(global $heap/HEAP_OFFSET (mut i32) (i32.const 0))
(global $std/heap/ptr (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -102,7 +102,7 @@
)
(func $start (; 2 ;) (type $v)
(set_global $heap/HEAP_OFFSET
(get_global $HEAP_START)
(get_global $HEAP_BASE)
)
(set_global $std/heap/ptr
(call $Heap.allocate

View File

@ -8,7 +8,7 @@
(global $heap/ALIGN_SIZE i32 (i32.const 8))
(global $heap/ALIGN_MASK i32 (i32.const 7))
(global $std/heap/ptr (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -113,7 +113,7 @@
)
(func $start (; 2 ;) (type $v)
(set_global $heap/HEAP_OFFSET
(get_global $HEAP_START)
(get_global $HEAP_BASE)
)
(set_global $std/heap/ptr
(call $Heap.allocate
@ -170,22 +170,31 @@
f64
isize
usize
HEAP_START
HEAP_BASE
Array
Array.fromPtr
Array.test
Error
RangeError
heap/ALIGN_LOG2
heap/ALIGN_SIZE
heap/ALIGN_MASK
heap/HEAP_OFFSET
Heap
Heap.allocate
Heap.dispose
Heap.get_used
Heap.get_free
Heap.get_size
Heap.allocate
Heap.dispose
Heap.copy
Map
Set
String
std/heap/ptr
[program.exports]
Array
Error
RangeError
Heap
Map
Set
String
;)

View File

@ -1,6 +1,6 @@
(module
(type $ii (func (param i32) (result i32)))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "doSwitch" (func $switch/doSwitch))
(export "doSwitchDefaultFirst" (func $switch/doSwitchDefaultFirst))
@ -190,7 +190,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
switch/doSwitch
switch/doSwitchDefaultFirst
switch/doSwitchDefaultOmitted

View File

@ -1,7 +1,7 @@
(module
(type $v (func))
(global $ternary/a (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -78,7 +78,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
ternary/a
[program.exports]

View File

@ -21,7 +21,7 @@
(global $tlsf/CONTROL$SL_BITMAP_OFFSET i32 (i32.const 20))
(global $tlsf/SL_INDEX_COUNT i32 (i32.const 32))
(global $tlsf/CONTROL$BLOCKS_OFFSET i32 (i32.const 112))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "control$construct" (func $tlsf/control$construct))
(export "memory" (memory $0))
@ -373,7 +373,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
tlsf/fls
tlsf/ffs
tlsf/ALIGN_SIZE_LOG2

View File

@ -4,7 +4,7 @@
(global $unary/I (mut i64) (i64.const 0))
(global $unary/f (mut f32) (f32.const 0))
(global $unary/F (mut f64) (f64.const 0))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -666,7 +666,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
unary/i
unary/I
unary/f

View File

@ -1,6 +1,6 @@
(module
(type $iv (func (param i32)))
(global $HEAP_START i32 (i32.const 4))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "loopWhile" (func $while/loopWhile))
(export "loopWhileInWhile" (func $while/loopWhileInWhile))
@ -105,7 +105,7 @@
f64
isize
usize
HEAP_START
HEAP_BASE
while/loopWhile
while/loopWhileInWhile
[program.exports]