diff --git a/src/ast.ts b/src/ast.ts index 7aba0ca6..305e0f97 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -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 "); - (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) (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) (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 = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; + if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (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 = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; + if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (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 = (modifiers).length; i < k; ++i) (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 ? 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) (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 ? 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) (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 = (modifiers).length; i < k; ++i) (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) (type).parent = stmt; + if (stmt.initializer = initializer) (initializer).parent = stmt; + if (stmt.modifiers = modifiers) for (i = 0, k = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; + if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (initializer).parent = stmt; + if (stmt.condition = condition) (condition).parent = stmt; + if (stmt.incrementor = incrementor) (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) (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) (type).parent = elem; + if (elem.initializer = initializer) (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) (returnType).parent = stmt; + if (stmt.statements = statements) for (i = 0, k = (statements).length; i < k; ++i) (statements)[i].parent = stmt; + if (stmt.modifiers = modifiers) for (i = 0, k = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; + if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (returnType).parent = stmt;; + if (stmt.statements = statements) for (i = 0, k = (statements).length; i < k; ++i) (statements)[i].parent = stmt; + if (stmt.modifiers = modifiers) for (i = 0, k = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; + if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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 = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; + if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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).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) (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) (catchVariable).parent = stmt; + if (stmt.catchStatements = catchStatements) for (i = 0, k = (catchStatements).length; i < k; ++i) (catchStatements)[i].parent = stmt; + if (stmt.finallyStatements = finallyStatements) for (i = 0, k = (finallyStatements).length; i < k; ++i) (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 = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; + if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (type).parent = elem; + if (elem.initializer = initializer) (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 "); + (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) (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) (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 = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; - if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (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 = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; - if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (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 = (modifiers).length; i < k; ++i) (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 ? 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) (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 ? 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) (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 = (modifiers).length; i < k; ++i) (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) (type).parent = stmt; - if (stmt.initializer = initializer) (initializer).parent = stmt; - if (stmt.modifiers = modifiers) for (i = 0, k = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; - if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (initializer).parent = stmt; - if (stmt.condition = condition) (condition).parent = stmt; - if (stmt.incrementor = incrementor) (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) (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) (type).parent = elem; - if (elem.initializer = initializer) (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) (returnType).parent = stmt; - if (stmt.statements = statements) for (i = 0, k = (statements).length; i < k; ++i) (statements)[i].parent = stmt; - if (stmt.modifiers = modifiers) for (i = 0, k = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; - if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (returnType).parent = stmt;; - if (stmt.statements = statements) for (i = 0, k = (statements).length; i < k; ++i) (statements)[i].parent = stmt; - if (stmt.modifiers = modifiers) for (i = 0, k = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; - if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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 = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; - if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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).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) (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) (catchVariable).parent = stmt; - if (stmt.catchStatements = catchStatements) for (i = 0, k = (catchStatements).length; i < k; ++i) (catchStatements)[i].parent = stmt; - if (stmt.finallyStatements = finallyStatements) for (i = 0, k = (finallyStatements).length; i < k; ++i) (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 = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; - if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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) (type).parent = elem; - if (elem.initializer = initializer) (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 && (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"; } } } diff --git a/src/builtins.ts b/src/builtins.ts index 460af549..1989adee 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -99,11 +99,11 @@ export function initialize(program: Program): void { if (program.target == Target.WASM64) { program.elements.set("isize", program.elements.get("i64")); program.elements.set("usize", program.elements.get("u64")); - addConstant(program, "HEAP_START", Type.usize64); + addConstant(program, "HEAP_BASE", Type.usize64); } else { program.elements.set("isize", program.elements.get("i32")); program.elements.set("usize", 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(global.type)); + case "HEAP_BASE": // constant, but never inlined + return compiler.module.createGetGlobal("HEAP_BASE", typeToNativeType(compiler.currentType = 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) { diff --git a/src/compiler.ts b/src/compiler.ts index a2073fa1..fd843e60 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -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(); diff --git a/src/parser.ts b/src/parser.ts index 486fc64e..4d1f06d2 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -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, args, tn.range(startPos, tn.pos)); + return Node.createDecorator(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(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(startRange, tn.range())); + return Node.createParameter(identifier, type, initializer, multiple, Range.join(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, parameters, returnType, statements, modifiers, decorators, tn.range(startPos, tn.pos)); + const ret: FunctionDeclaration = Node.createFunction(identifier, typeParameters, 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(member); } while (!tn.skip(Token.CLOSEBRACE)); } - return Statement.createClass(identifier, typeParameters, extendsType, implementsTypes, members, modifiers, decorators, tn.range(startPos, tn.pos)); + return Node.createClass(identifier, 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, typeParameters, parameters, returnType, statements, modifiers, decorators, Range.join(startRange, tn.range())); + const ret: MethodDeclaration = Node.createMethod(identifier, typeParameters, 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(ret.normalizedPath)) { this.backlog.push(ret.normalizedPath); this.seenlog.add(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, condition, tn.range(startPos, tn.pos)); + const ret: DoStatement = Node.createDo(statement, 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(condition, statement, elseStatement, Range.join(startRange, tn.range())); + return Node.createIf(condition, 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(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); } - return Statement.createSwitchCase(label, statements, tn.range(startPos, tn.pos)); + return Node.createSwitchCase(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); } - 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, tn.range(startPos, tn.pos)); + const ret: ThrowStatement = Node.createThrow(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, statement, Range.join(startRange, tn.range())); + const ret: WhileStatement = Node.createWhile(expression, 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((operand).expression, (operand).typeArguments, (operand).arguments, tn.range(startPos, tn.pos)); + return Node.createNew((operand).expression, (operand).typeArguments, (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 ((operand).kind != NodeKind.IDENTIFIER && (operand).kind != NodeKind.ELEMENTACCESS && (operand).kind != NodeKind.PROPERTYACCESS) this.error(DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, (operand).range); - return Expression.createUnaryPrefix(token, operand, tn.range(startPos, tn.pos)); + return Node.createUnaryPrefix(token, 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, expr, toType, tn.range(startPos, tn.pos)); + return Node.createAssertion(AssertionKind.PREFIX, expr, 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, (typeArguments ? typeArguments : []), args, tn.range(startPos, tn.pos)); + expr = Node.createCall(expr, (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(expr, next, tn.range(startPos, tn.pos)); + expr = Node.createElementAccess(expr, 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(expr, ifThen, ifElse, tn.range(startPos, tn.pos)); + expr = Node.createTernary(expr, ifThen, 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(expr, next, tn.range(startPos, tn.pos)); + expr = Node.createPropertyAccess(expr, next, tn.range(startPos, tn.pos)); } else if (next.kind == NodeKind.CALL) { // amend let propertyCall: CallExpression = next; if (propertyCall.expression.kind == NodeKind.IDENTIFIER) { - propertyCall.expression = Expression.createPropertyAccess(expr, propertyCall.expression, tn.range(startPos, tn.pos)); + propertyCall.expression = Node.createPropertyAccess(expr, 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, expr, next, tn.range(startPos, tn.pos)); + expr = Node.createBinary(token, expr, next, tn.range(startPos, tn.pos)); } } return expr; diff --git a/src/program.ts b/src/program.ts index 056f1c92..0a4c7963 100644 --- a/src/program.ts +++ b/src/program.ts @@ -672,10 +672,10 @@ export class Program extends DiagnosticEmitter { resolveType(node: TypeNode, contextualTypeArguments: Map | 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] = 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 { diff --git a/src/types.ts b/src/types.ts index fb367dc2..01c927b3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -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 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; } diff --git a/std/assembly.d.ts b/std/assembly.d.ts index 4096cbf5..cd0e7fc8 100644 --- a/std/assembly.d.ts +++ b/std/assembly.d.ts @@ -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(): 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 {} +/** Class representing a sequence of values of type `T`. */ +declare class Array { + + /** 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; diff --git a/std/assembly/array.ts b/std/assembly/array.ts index 47e84bda..e57a7a64 100644 --- a/std/assembly/array.ts +++ b/std/assembly/array.ts @@ -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 { +export class Array { readonly capacity: i32; length: i32; ptr: usize; - static fromPtr(ptr: usize, capacity: i32): Array { - assert(capacity >= 0); - const arr: Array = new Array(0); - store(changetype, 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(capacity); @@ -35,5 +23,5 @@ class Array { Heap.dispose(changetype(this)); } - static test(): void {} + // TODO } diff --git a/std/assembly/error.ts b/std/assembly/error.ts new file mode 100644 index 00000000..097a6944 --- /dev/null +++ b/std/assembly/error.ts @@ -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"; +} diff --git a/std/assembly/heap.ts b/std/assembly/heap.ts index 922d6df9..f6c0a1ec 100644 --- a/std/assembly/heap.ts +++ b/std/assembly/heap.ts @@ -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 (current_memory() << 16) - HEAP_OFFSET; } + static get size(): usize { return (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 (current_memory() << 16) - HEAP_OFFSET; - } - - static get size(): usize { - return (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() {} } diff --git a/std/assembly/map.ts b/std/assembly/map.ts new file mode 100644 index 00000000..926a7bcb --- /dev/null +++ b/std/assembly/map.ts @@ -0,0 +1,4 @@ +@global() +export class Map { + // TODO +} diff --git a/std/assembly/set.ts b/std/assembly/set.ts new file mode 100644 index 00000000..691ad76c --- /dev/null +++ b/std/assembly/set.ts @@ -0,0 +1,4 @@ +@global() +export class Set { + // TODO +} diff --git a/std/assembly/string.ts b/std/assembly/string.ts new file mode 100644 index 00000000..ecd560a4 --- /dev/null +++ b/std/assembly/string.ts @@ -0,0 +1,4 @@ +@global() +export class String { + // TODO +} diff --git a/std/portable.js b/std/portable.js index bf37aa9e..65969003 100644 --- a/std/portable.js +++ b/std/portable.js @@ -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 } diff --git a/std/portable/heap.d.ts b/std/portable/heap.d.ts index f402cca8..9e20526d 100644 --- a/std/portable/heap.d.ts +++ b/std/portable/heap.d.ts @@ -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; } diff --git a/tests/compiler/assert.wast b/tests/compiler/assert.wast index a959a787..d84b8b6d 100644 --- a/tests/compiler/assert.wast +++ b/tests/compiler/assert.wast @@ -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] ;) diff --git a/tests/compiler/binary.wast b/tests/compiler/binary.wast index f4b2b421..6089b36c 100644 --- a/tests/compiler/binary.wast +++ b/tests/compiler/binary.wast @@ -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 diff --git a/tests/compiler/builtins.wast b/tests/compiler/builtins.wast index 38afc425..4a5662da 100644 --- a/tests/compiler/builtins.wast +++ b/tests/compiler/builtins.wast @@ -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 diff --git a/tests/compiler/class.wast b/tests/compiler/class.wast index ec74a3cd..f2e6d071 100644 --- a/tests/compiler/class.wast +++ b/tests/compiler/class.wast @@ -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 diff --git a/tests/compiler/declare.wast b/tests/compiler/declare.wast index 2354477e..6f16b73b 100644 --- a/tests/compiler/declare.wast +++ b/tests/compiler/declare.wast @@ -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 diff --git a/tests/compiler/do.wast b/tests/compiler/do.wast index 49a1b858..4647d394 100644 --- a/tests/compiler/do.wast +++ b/tests/compiler/do.wast @@ -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] diff --git a/tests/compiler/enum.wast b/tests/compiler/enum.wast index d505dfd4..37e4f386 100644 --- a/tests/compiler/enum.wast +++ b/tests/compiler/enum.wast @@ -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 diff --git a/tests/compiler/export.wast b/tests/compiler/export.wast index 3718d942..9f203840 100644 --- a/tests/compiler/export.wast +++ b/tests/compiler/export.wast @@ -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 diff --git a/tests/compiler/for.wast b/tests/compiler/for.wast index 92e932a5..f4321ba8 100644 --- a/tests/compiler/for.wast +++ b/tests/compiler/for.wast @@ -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] diff --git a/tests/compiler/game-of-life.wast b/tests/compiler/game-of-life.wast index ddcef671..74624a88 100644 --- a/tests/compiler/game-of-life.wast +++ b/tests/compiler/game-of-life.wast @@ -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 diff --git a/tests/compiler/i64.wast b/tests/compiler/i64.wast index 38fe6b57..26e672d6 100644 --- a/tests/compiler/i64.wast +++ b/tests/compiler/i64.wast @@ -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 diff --git a/tests/compiler/if.wast b/tests/compiler/if.wast index 79868217..4a1efe0a 100644 --- a/tests/compiler/if.wast +++ b/tests/compiler/if.wast @@ -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 diff --git a/tests/compiler/import.wast b/tests/compiler/import.wast index ccf4daaf..55342210 100644 --- a/tests/compiler/import.wast +++ b/tests/compiler/import.wast @@ -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 diff --git a/tests/compiler/limits.wast b/tests/compiler/limits.wast index 3f3f09c9..6623c2ee 100644 --- a/tests/compiler/limits.wast +++ b/tests/compiler/limits.wast @@ -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] ;) diff --git a/tests/compiler/literals.wast b/tests/compiler/literals.wast index 53cebd9c..3317e936 100644 --- a/tests/compiler/literals.wast +++ b/tests/compiler/literals.wast @@ -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] ;) diff --git a/tests/compiler/logical.wast b/tests/compiler/logical.wast index 713e91f8..6b57728b 100644 --- a/tests/compiler/logical.wast +++ b/tests/compiler/logical.wast @@ -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 diff --git a/tests/compiler/memcpy.wast b/tests/compiler/memcpy.wast index 44a26d63..0093e7c2 100644 --- a/tests/compiler/memcpy.wast +++ b/tests/compiler/memcpy.wast @@ -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 diff --git a/tests/compiler/namespace.wast b/tests/compiler/namespace.wast index 9d396baf..bf8989df 100644 --- a/tests/compiler/namespace.wast +++ b/tests/compiler/namespace.wast @@ -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 diff --git a/tests/compiler/portable-conversions.wast b/tests/compiler/portable-conversions.wast index 0953b5d7..8cb5f849 100644 --- a/tests/compiler/portable-conversions.wast +++ b/tests/compiler/portable-conversions.wast @@ -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 diff --git a/tests/compiler/reexport.wast b/tests/compiler/reexport.wast index 2157b4e4..35dce4a8 100644 --- a/tests/compiler/reexport.wast +++ b/tests/compiler/reexport.wast @@ -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 diff --git a/tests/compiler/std/array.optimized-inlined.wast b/tests/compiler/std/array.optimized-inlined.wast deleted file mode 100644 index 251eb50c..00000000 --- a/tests/compiler/std/array.optimized-inlined.wast +++ /dev/null @@ -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) - ) - ) -) diff --git a/tests/compiler/std/array.optimized.wast b/tests/compiler/std/array.optimized.wast index 4a67c92e..7a4e7940 100644 --- a/tests/compiler/std/array.optimized.wast +++ b/tests/compiler/std/array.optimized.wast @@ -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) - ) ) diff --git a/tests/compiler/std/array.ts b/tests/compiler/std/array.ts index 212326cc..7c464175 100644 --- a/tests/compiler/std/array.ts +++ b/tests/compiler/std/array.ts @@ -1,2 +1 @@ // Array.fromPtr(1); -Array.test(); diff --git a/tests/compiler/std/array.wast b/tests/compiler/std/array.wast index e4a63150..56df39cc 100644 --- a/tests/compiler/std/array.wast +++ b/tests/compiler/std/array.wast @@ -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 ;) diff --git a/tests/compiler/std/heap.optimized-inlined.wast b/tests/compiler/std/heap.optimized-inlined.wast index ac80cca8..131a40fc 100644 --- a/tests/compiler/std/heap.optimized-inlined.wast +++ b/tests/compiler/std/heap.optimized-inlined.wast @@ -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 diff --git a/tests/compiler/std/heap.optimized.wast b/tests/compiler/std/heap.optimized.wast index a0f927b9..d9bf10eb 100644 --- a/tests/compiler/std/heap.optimized.wast +++ b/tests/compiler/std/heap.optimized.wast @@ -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 diff --git a/tests/compiler/std/heap.wast b/tests/compiler/std/heap.wast index 0f35338f..290afa40 100644 --- a/tests/compiler/std/heap.wast +++ b/tests/compiler/std/heap.wast @@ -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 ;) diff --git a/tests/compiler/switch.wast b/tests/compiler/switch.wast index e8bc50a4..b4b75914 100644 --- a/tests/compiler/switch.wast +++ b/tests/compiler/switch.wast @@ -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 diff --git a/tests/compiler/ternary.wast b/tests/compiler/ternary.wast index 2fd3720d..723f3af0 100644 --- a/tests/compiler/ternary.wast +++ b/tests/compiler/ternary.wast @@ -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] diff --git a/tests/compiler/tlsf.wast b/tests/compiler/tlsf.wast index 3287a353..0c0f71df 100644 --- a/tests/compiler/tlsf.wast +++ b/tests/compiler/tlsf.wast @@ -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 diff --git a/tests/compiler/unary.wast b/tests/compiler/unary.wast index 58d72974..84b4af81 100644 --- a/tests/compiler/unary.wast +++ b/tests/compiler/unary.wast @@ -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 diff --git a/tests/compiler/while.wast b/tests/compiler/while.wast index 4ae0b3f1..8ae47a8d 100644 --- a/tests/compiler/while.wast +++ b/tests/compiler/while.wast @@ -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]