mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 07:02:13 +00:00
changetype builtin; some namespace parsing; more stdlib ideas; compiler options for asc
This commit is contained in:
parent
59dafc8d22
commit
bbb57baecb
9
assembly.d.ts
vendored
9
assembly.d.ts
vendored
@ -27,7 +27,7 @@ declare type f32 = number;
|
||||
/** A 64-bit float. */
|
||||
declare type f64 = number;
|
||||
|
||||
// builtins
|
||||
// built-ins
|
||||
|
||||
/** Performs the sign-agnostic count leading zero bits operation on a 32-bit or 64-bit integer. All zero bits are considered leading if the value is zero. */
|
||||
declare function clz<T = i32 | i64>(value: T): T;
|
||||
@ -78,6 +78,8 @@ declare const NaN: f32 | f64;
|
||||
declare const Infinity: f32 | f64;
|
||||
/** Determines the byte size of the specified core or class type. Compiles to a constant. */
|
||||
declare function sizeof<T>(): usize;
|
||||
/** Changes the type of a value to another one. Useful for casting class instances to their pointer values and vice-versa. */
|
||||
declare function changetype<T1,T2>(value: T1): T2;
|
||||
/** Tests if a 32-bit or 64-bit float is NaN. */
|
||||
declare function isNaN<T = f32 | f64>(value: T): bool;
|
||||
/** Tests if a 32-bit or 64-bit float is finite, that is not NaN or +/-Infinity. */
|
||||
@ -87,10 +89,15 @@ declare function assert(isTrue: bool): void;
|
||||
|
||||
// internal decorators
|
||||
|
||||
/** 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
|
||||
|
||||
/// <reference path="./std/carray.d.ts" />
|
||||
/// <reference path="./std/cstring.d.ts" />
|
||||
/// <reference path="./std/heap.d.ts" />
|
||||
|
@ -110,7 +110,12 @@ while ((diagnostic = assemblyscript.nextDiagnostic(parser)) != null) {
|
||||
if (hasErrors)
|
||||
process.exit(1);
|
||||
|
||||
var module = assemblyscript.compile(parser);
|
||||
var options = assemblyscript.createOptions();
|
||||
assemblyscript.setTarget(options, 0);
|
||||
assemblyscript.setNoTreeShaking(options, args.noTreeShaking);
|
||||
assemblyscript.setNoDebug(options, args.noDebug);
|
||||
|
||||
var module = assemblyscript.compile(parser, options);
|
||||
|
||||
hasErrors = false;
|
||||
while ((diagnostic = assemblyscript.nextDiagnostic(parser)) != null) {
|
||||
|
20
bin/asc.json
20
bin/asc.json
@ -1,29 +1,37 @@
|
||||
{
|
||||
"version": {
|
||||
"desc": "Print the compiler's version.",
|
||||
"desc": "Prints the compiler's version.",
|
||||
"type": "boolean",
|
||||
"aliases": [ "v" ]
|
||||
},
|
||||
"help": {
|
||||
"desc": "Print this message.",
|
||||
"desc": "Prints this message.",
|
||||
"type": "boolean",
|
||||
"aliases": [ "h" ]
|
||||
},
|
||||
"optimize": {
|
||||
"desc": "Optimize the module.",
|
||||
"desc": "Optimizes the module.",
|
||||
"type": "boolean",
|
||||
"aliases": [ "O" ]
|
||||
},
|
||||
"validate": {
|
||||
"desc": "Validate the module.",
|
||||
"desc": "Validates the module.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"outFile": {
|
||||
"desc": "Specify the output file (binary format).",
|
||||
"desc": "Specifies the output file (binary format).",
|
||||
"type": "string"
|
||||
},
|
||||
"textFile": {
|
||||
"desc": "Specify the output file (text format).",
|
||||
"desc": "Specifies the output file (text format).",
|
||||
"type": "string"
|
||||
},
|
||||
"noTreeShaking": {
|
||||
"desc": "Disables built-in tree-shaking.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"noDebug": {
|
||||
"desc": "Replaces assertions with nops.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
|
121
src/ast.ts
121
src/ast.ts
@ -657,17 +657,17 @@ export abstract class Statement extends Node {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createClass(modifiers: Modifier[], identifier: IdentifierExpression, typeParameters: TypeParameter[], extendsType: TypeNode | null, implementsTypes: TypeNode[], members: DeclarationStatement[], decorators: DecoratorStatement[], range: Range): ClassDeclaration {
|
||||
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;
|
||||
for (i = 0, k = (stmt.modifiers = modifiers).length; i < k; ++i) modifiers[i].parent = stmt;
|
||||
(stmt.identifier = identifier).parent = stmt;
|
||||
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
|
||||
if (stmt.extendsType = extendsType) (<TypeNode>extendsType).parent = stmt;
|
||||
for (i = 0, k = (stmt.implementsTypes = implementsTypes).length; i < k; ++i) implementsTypes[i].parent = stmt;
|
||||
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
|
||||
for (i = 0, k = (stmt.decorators = decorators).length; i < k; ++i) decorators[i].parent = stmt;
|
||||
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
|
||||
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@ -678,8 +678,8 @@ export abstract class Statement extends Node {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createDecorator(expression: Expression, args: Expression[], range: Range): DecoratorStatement {
|
||||
const stmt: DecoratorStatement = new DecoratorStatement();
|
||||
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;
|
||||
@ -700,13 +700,14 @@ export abstract class Statement extends Node {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createEnum(modifiers: Modifier[], identifier: IdentifierExpression, members: EnumValueDeclaration[], range: Range): EnumDeclaration {
|
||||
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;
|
||||
for (i = 0, k = (stmt.modifiers = modifiers).length; i < k; ++i) modifiers[i].parent = stmt;
|
||||
(stmt.identifier = identifier).parent = stmt;
|
||||
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
|
||||
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
|
||||
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@ -718,15 +719,15 @@ export abstract class Statement extends Node {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createExport(modifiers: Modifier[], members: ExportMember[], path: StringLiteralExpression | null, range: Range): ExportStatement {
|
||||
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.modifiers = modifiers).length; i < k; ++i) modifiers[i].parent = stmt;
|
||||
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
|
||||
stmt.path = path;
|
||||
stmt.normalizedPath = path ? resolvePath(normalizePath(path.value), range.source.normalizedPath) : null;
|
||||
stmt.internalPath = stmt.normalizedPath ? mangleInternalPath(stmt.normalizedPath) : null;
|
||||
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@ -780,25 +781,26 @@ export abstract class Statement extends Node {
|
||||
return elem;
|
||||
}
|
||||
|
||||
static createInterface(modifiers: Modifier[], extendsType: TypeNode | null, members: DeclarationStatement[], range: Range): InterfaceDeclaration {
|
||||
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;
|
||||
for (i = 0, k = (stmt.modifiers = modifiers).length; i < k; ++i) modifiers[i].parent = stmt;
|
||||
(stmt.identifier = identifier).parent = stmt;
|
||||
if (stmt.extendsType = extendsType) (<TypeNode>extendsType).parent = stmt;
|
||||
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
|
||||
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createField(modifiers: Modifier[], identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, decorators: DecoratorStatement[], range: Range): FieldDeclaration {
|
||||
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;
|
||||
for (i = 0, k = (stmt.modifiers = modifiers).length; i < k; ++i) modifiers[i].parent = stmt;
|
||||
(stmt.identifier = identifier).parent = stmt;
|
||||
if (stmt.type = type) (<TypeNode>type).parent = stmt;
|
||||
if (stmt.initializer = initializer) (<Expression>initializer).parent = stmt;
|
||||
for (i = 0, k = (stmt.decorators = decorators).length; i < k; ++i) decorators[i].parent = stmt;
|
||||
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
|
||||
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@ -830,31 +832,31 @@ export abstract class Statement extends Node {
|
||||
return elem;
|
||||
}
|
||||
|
||||
static createFunction(modifiers: Modifier[], identifier: IdentifierExpression, typeParameters: TypeParameter[], parameters: Parameter[], returnType: TypeNode | null, statements: Statement[] | null, decorators: DecoratorStatement[], range: Range): FunctionDeclaration {
|
||||
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;
|
||||
for (i = 0, k = (stmt.modifiers = modifiers).length; i < k; ++i) modifiers[i].parent = stmt;
|
||||
(stmt.identifier = identifier).parent = stmt;
|
||||
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
|
||||
for (i = 0, k = (stmt.parameters = parameters).length; i < k; ++i) parameters[i].parent = stmt;
|
||||
if (stmt.returnType = returnType) (<TypeNode>returnType).parent = stmt;
|
||||
if (stmt.statements = statements) for (i = 0, k = (<Statement[]>statements).length; i < k; ++i) (<Statement[]>statements)[i].parent = stmt;
|
||||
for (i = 0, k = (stmt.decorators = decorators).length; i < k; ++i) decorators[i].parent = stmt;
|
||||
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
|
||||
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createMethod(modifiers: Modifier[], identifier: IdentifierExpression, typeParameters: TypeParameter[], parameters: Parameter[], returnType: TypeNode | null, statements: Statement[] | null, decorators: DecoratorStatement[], range: Range): MethodDeclaration {
|
||||
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;
|
||||
for (i = 0, k = (stmt.modifiers = modifiers).length; i < k; ++i) modifiers[i].parent = stmt;
|
||||
(stmt.identifier = identifier).parent = stmt;
|
||||
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
|
||||
for (i = 0, k = (stmt.parameters = parameters).length; i < k; ++i) parameters[i].parent = stmt;
|
||||
if (stmt.returnType = returnType) (<TypeNode>returnType).parent = stmt;;
|
||||
if (stmt.statements = statements) for (i = 0, k = (<Statement[]>statements).length; i < k; ++i) (<Statement[]>statements)[i].parent = stmt;
|
||||
for (i = 0, k = (stmt.decorators = decorators).length; i < k; ++i) decorators[i].parent = stmt;
|
||||
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
|
||||
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@ -865,13 +867,14 @@ export abstract class Statement extends Node {
|
||||
return elem;
|
||||
}
|
||||
|
||||
static createNamespace(modifiers: Modifier[], identifier: IdentifierExpression, members: DeclarationStatement[], range: Range): NamespaceDeclaration {
|
||||
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;
|
||||
for (i = 0, k = (stmt.modifiers = modifiers).length; i < k; ++i) modifiers[i].parent = stmt;
|
||||
(stmt.identifier = identifier).parent = stmt;
|
||||
for (i = 0, k = (stmt.members = members).length; i < k; ++i) members[i].parent = stmt;
|
||||
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
|
||||
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@ -916,22 +919,24 @@ export abstract class Statement extends Node {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createVariable(modifiers: Modifier[], declarations: VariableDeclaration[], range: Range): VariableStatement {
|
||||
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.modifiers = modifiers).length; i < k; ++i) modifiers[i].parent = stmt;
|
||||
for (i = 0, k = (stmt.declarations = declarations).length; i < k; ++i) declarations[i].parent = stmt;
|
||||
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
|
||||
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createVariableDeclaration(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, modifiers: Modifier[] | null, range: Range): VariableDeclaration {
|
||||
static createVariableDeclaration(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, modifiers: Modifier[] | null, decorators: Decorator[] | null, range: Range): VariableDeclaration {
|
||||
const elem: VariableDeclaration = new VariableDeclaration();
|
||||
elem.range = range;
|
||||
(elem.identifier = identifier).parent = elem;
|
||||
if (elem.type = type) (<TypeNode>type).parent = elem;
|
||||
if (elem.initializer = initializer) (<Expression>initializer).parent = elem;
|
||||
elem.modifiers = modifiers;
|
||||
elem.decorators = decorators;
|
||||
return elem;
|
||||
}
|
||||
|
||||
@ -987,6 +992,7 @@ export abstract class DeclarationStatement extends Statement {
|
||||
|
||||
identifier: IdentifierExpression;
|
||||
modifiers: Modifier[] | null;
|
||||
decorators: Decorator[] | null = null;
|
||||
|
||||
protected _cachedInternalName: string | null = null;
|
||||
|
||||
@ -1037,12 +1043,11 @@ export class ClassDeclaration extends DeclarationStatement {
|
||||
extendsType: TypeNode | null;
|
||||
implementsTypes: TypeNode[];
|
||||
members: DeclarationStatement[];
|
||||
decorators: DecoratorStatement[];
|
||||
|
||||
get internalName(): string {
|
||||
if (this._cachedInternalName !== null)
|
||||
return this._cachedInternalName;
|
||||
const globalDecorator: DecoratorStatement | null = getDecoratorByName("global", this.decorators);
|
||||
const globalDecorator: Decorator | null = this.decorators ? getDecoratorByName("global", this.decorators) : null;
|
||||
if (globalDecorator && globalDecorator.expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>globalDecorator.expression).name == "global")
|
||||
return this._cachedInternalName = this.identifier.name;
|
||||
else
|
||||
@ -1051,10 +1056,11 @@ export class ClassDeclaration extends DeclarationStatement {
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
let i: i32, k: i32;
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.decorators)
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.modifiers)
|
||||
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
||||
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
||||
@ -1109,7 +1115,7 @@ export class ContinueStatement extends Statement {
|
||||
}
|
||||
}
|
||||
|
||||
export class DecoratorStatement extends Statement {
|
||||
export class Decorator extends Statement {
|
||||
|
||||
kind = NodeKind.DECORATOR;
|
||||
expression: Expression;
|
||||
@ -1264,14 +1270,14 @@ export class ExpressionStatement extends Statement {
|
||||
export class FieldDeclaration extends VariableLikeDeclarationStatement {
|
||||
|
||||
kind = NodeKind.FIELD;
|
||||
decorators: DecoratorStatement[];
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
let i: i32, k: i32;
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.decorators)
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.modifiers)
|
||||
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
||||
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
||||
@ -1323,12 +1329,11 @@ export class FunctionDeclaration extends DeclarationStatement {
|
||||
parameters: Parameter[];
|
||||
returnType: TypeNode | null;
|
||||
statements: Statement[] | null;
|
||||
decorators: DecoratorStatement[];
|
||||
|
||||
get internalName(): string {
|
||||
if (this._cachedInternalName !== null)
|
||||
return this._cachedInternalName;
|
||||
const globalDecorator: DecoratorStatement | null = getDecoratorByName("global", this.decorators);
|
||||
const globalDecorator: Decorator | null = this.decorators ? getDecoratorByName("global", this.decorators) : null;
|
||||
if (globalDecorator && globalDecorator.expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>globalDecorator.expression).name == "global")
|
||||
return this._cachedInternalName = this.identifier.name;
|
||||
else
|
||||
@ -1337,10 +1342,11 @@ export class FunctionDeclaration extends DeclarationStatement {
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
let i: i32, k: i32;
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.decorators)
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.modifiers)
|
||||
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
||||
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
||||
@ -1453,6 +1459,11 @@ export class InterfaceDeclaration extends ClassDeclaration {
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
let i: i32, k: i32;
|
||||
if (this.decorators)
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.modifiers)
|
||||
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
||||
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
||||
@ -1491,10 +1502,11 @@ export class MethodDeclaration extends FunctionDeclaration {
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
let i: i32, k: i32;
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.decorators)
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.modifiers)
|
||||
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
||||
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
||||
@ -1511,6 +1523,11 @@ export class NamespaceDeclaration extends DeclarationStatement {
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
let i: i32, k: i32;
|
||||
if (this.decorators)
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.modifiers)
|
||||
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
||||
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
||||
@ -1701,11 +1718,17 @@ export class VariableStatement extends Statement {
|
||||
|
||||
kind = NodeKind.VARIABLE;
|
||||
modifiers: Modifier[] | null;
|
||||
decorators: Decorator[] | null;
|
||||
declarations: VariableDeclaration[];
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
let isConst: bool = false;
|
||||
let i: i32, k: i32;
|
||||
if (this.decorators)
|
||||
for (i = 0, k = this.decorators.length; i < k; ++i) {
|
||||
this.decorators[i].serialize(sb);
|
||||
sb.push("\n");
|
||||
}
|
||||
if (this.modifiers)
|
||||
for (i = 0, k = (<Modifier[]>this.modifiers).length; i < k; ++i) {
|
||||
(<Modifier[]>this.modifiers)[i].serialize(sb);
|
||||
@ -1745,9 +1768,9 @@ export function hasModifier(kind: ModifierKind, modifiers: Modifier[] | null): b
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getDecoratorByName(name: string, decorators: DecoratorStatement[]): DecoratorStatement | null {
|
||||
export function getDecoratorByName(name: string, decorators: Decorator[]): Decorator | null {
|
||||
for (let i: i32 = 0, k: i32 = decorators.length; i < k; ++i) {
|
||||
const decorator: DecoratorStatement = decorators[i];
|
||||
const decorator: Decorator = decorators[i];
|
||||
const expression: Expression = decorator.expression;
|
||||
if (expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>expression).name == name)
|
||||
return decorator;
|
||||
|
326
src/builtins.ts
326
src/builtins.ts
@ -2,7 +2,7 @@ import { Compiler, Target, typeToNativeType, typeToNativeOne } from "./compiler"
|
||||
import { DiagnosticCode } from "./diagnostics";
|
||||
import { Node, Expression } from "./ast";
|
||||
import { Type } from "./types";
|
||||
import { ExpressionRef, UnaryOp, BinaryOp, HostOp, NativeType } from "./module";
|
||||
import { Module, ExpressionRef, UnaryOp, BinaryOp, HostOp, NativeType } from "./module";
|
||||
import { Program, FunctionPrototype, Local } from "./program";
|
||||
|
||||
/** Initializes the specified program with built-in functions. */
|
||||
@ -29,6 +29,7 @@ export function initialize(program: Program): void {
|
||||
addFunction(program, "reinterpret", true);
|
||||
addFunction(program, "select", true);
|
||||
addFunction(program, "sizeof", true);
|
||||
addFunction(program, "changetype", true);
|
||||
addFunction(program, "isNaN", true);
|
||||
addFunction(program, "isFinite", true);
|
||||
addFunction(program, "assert");
|
||||
@ -47,6 +48,7 @@ function addFunction(program: Program, name: string, isGeneric: bool = false, is
|
||||
|
||||
/** Compiles a call to a built-in function. */
|
||||
export function compileCall(compiler: Compiler, internalName: string, typeArguments: Type[], operands: Expression[], reportNode: Node): ExpressionRef {
|
||||
const module: Module = compiler.module;
|
||||
const usizeType: Type = select<Type>(Type.usize64, Type.usize32, compiler.options.target == Target.WASM64);
|
||||
|
||||
let arg0: ExpressionRef,
|
||||
@ -55,126 +57,127 @@ export function compileCall(compiler: Compiler, internalName: string, typeArgume
|
||||
|
||||
let tempLocal0: Local;
|
||||
let tempLocal1: Local;
|
||||
let nativeType: NativeType;
|
||||
|
||||
let type: Type;
|
||||
|
||||
switch (internalName) {
|
||||
|
||||
case "clz": // clz<T>(value: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
||||
? compiler.module.createUnary(UnaryOp.ClzI64, arg0)
|
||||
? module.createUnary(UnaryOp.ClzI64, arg0)
|
||||
: typeArguments[0].isSmallInteger
|
||||
? compiler.module.createBinary(BinaryOp.AndI32,
|
||||
compiler.module.createUnary(UnaryOp.ClzI32, arg0),
|
||||
compiler.module.createI32(typeArguments[0].smallIntegerMask)
|
||||
? module.createBinary(BinaryOp.AndI32,
|
||||
module.createUnary(UnaryOp.ClzI32, arg0),
|
||||
module.createI32(typeArguments[0].smallIntegerMask)
|
||||
)
|
||||
: compiler.module.createUnary(UnaryOp.ClzI32, arg0);
|
||||
: module.createUnary(UnaryOp.ClzI32, arg0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "ctz": // ctz<T>(value: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
||||
? compiler.module.createUnary(UnaryOp.CtzI64, arg0)
|
||||
? module.createUnary(UnaryOp.CtzI64, arg0)
|
||||
: typeArguments[0].isSmallInteger
|
||||
? compiler.module.createBinary(BinaryOp.AndI32,
|
||||
compiler.module.createUnary(UnaryOp.CtzI32, arg0),
|
||||
compiler.module.createI32(typeArguments[0].smallIntegerMask)
|
||||
? module.createBinary(BinaryOp.AndI32,
|
||||
module.createUnary(UnaryOp.CtzI32, arg0),
|
||||
module.createI32(typeArguments[0].smallIntegerMask)
|
||||
)
|
||||
: compiler.module.createUnary(UnaryOp.CtzI32, arg0);
|
||||
: module.createUnary(UnaryOp.CtzI32, arg0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "popcnt": // popcnt<T>(value: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
||||
? compiler.module.createUnary(UnaryOp.PopcntI64, arg0)
|
||||
? module.createUnary(UnaryOp.PopcntI64, arg0)
|
||||
: typeArguments[0].isSmallInteger
|
||||
? compiler.module.createBinary(BinaryOp.AndI32,
|
||||
compiler.module.createUnary(UnaryOp.PopcntI32, arg0),
|
||||
compiler.module.createI32(typeArguments[0].smallIntegerMask)
|
||||
? module.createBinary(BinaryOp.AndI32,
|
||||
module.createUnary(UnaryOp.PopcntI32, arg0),
|
||||
module.createI32(typeArguments[0].smallIntegerMask)
|
||||
)
|
||||
: compiler.module.createUnary(UnaryOp.PopcntI32, arg0);
|
||||
: module.createUnary(UnaryOp.PopcntI32, arg0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "rotl": // rotl<T>(value: T, shift: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
||||
? compiler.module.createBinary(BinaryOp.RotlI64, arg0, arg1)
|
||||
? module.createBinary(BinaryOp.RotlI64, arg0, arg1)
|
||||
: typeArguments[0].isSmallInteger
|
||||
? compiler.module.createBinary(BinaryOp.AndI32,
|
||||
compiler.module.createBinary(BinaryOp.RotlI32, arg0, arg1),
|
||||
compiler.module.createI32(typeArguments[0].smallIntegerMask)
|
||||
? module.createBinary(BinaryOp.AndI32,
|
||||
module.createBinary(BinaryOp.RotlI32, arg0, arg1),
|
||||
module.createI32(typeArguments[0].smallIntegerMask)
|
||||
)
|
||||
: compiler.module.createBinary(BinaryOp.RotlI32, arg0, arg1);
|
||||
: module.createBinary(BinaryOp.RotlI32, arg0, arg1);
|
||||
}
|
||||
break;
|
||||
|
||||
case "rotr": // rotr<T>(value: T, shift: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
||||
? compiler.module.createBinary(BinaryOp.RotrI64, arg0, arg1)
|
||||
? module.createBinary(BinaryOp.RotrI64, arg0, arg1)
|
||||
: typeArguments[0].isSmallInteger
|
||||
? compiler.module.createBinary(BinaryOp.AndI32,
|
||||
compiler.module.createBinary(BinaryOp.RotrI32, arg0, arg1),
|
||||
compiler.module.createI32(typeArguments[0].smallIntegerMask)
|
||||
? module.createBinary(BinaryOp.AndI32,
|
||||
module.createBinary(BinaryOp.RotrI32, arg0, arg1),
|
||||
module.createI32(typeArguments[0].smallIntegerMask)
|
||||
)
|
||||
: compiler.module.createBinary(BinaryOp.RotrI32, arg0, arg1);
|
||||
: module.createBinary(BinaryOp.RotrI32, arg0, arg1);
|
||||
}
|
||||
break;
|
||||
|
||||
case "abs": // abs<T>(value: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]) != Type.void) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) // sic
|
||||
return typeArguments[0] == Type.f32
|
||||
? compiler.module.createUnary(UnaryOp.AbsF32, arg0)
|
||||
: compiler.module.createUnary(UnaryOp.AbsF64, arg0);
|
||||
? module.createUnary(UnaryOp.AbsF32, arg0)
|
||||
: module.createUnary(UnaryOp.AbsF64, arg0);
|
||||
if (typeArguments[0].isAnyInteger) {
|
||||
if (typeArguments[0].isSignedInteger) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
if (typeArguments[0].isLongInteger)
|
||||
return compiler.module.createSelect(
|
||||
compiler.module.createBinary(BinaryOp.SubI64,
|
||||
compiler.module.createI64(0, 0),
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0)
|
||||
return module.createSelect(
|
||||
module.createBinary(BinaryOp.SubI64,
|
||||
module.createI64(0, 0),
|
||||
module.createTeeLocal(tempLocal0.index, arg0)
|
||||
),
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||
compiler.module.createBinary(BinaryOp.LtI64,
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||
compiler.module.createI64(0, 0)
|
||||
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||
module.createBinary(BinaryOp.LtI64,
|
||||
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||
module.createI64(0, 0)
|
||||
)
|
||||
);
|
||||
else
|
||||
return compiler.module.createSelect(
|
||||
compiler.module.createBinary(BinaryOp.SubI32,
|
||||
compiler.module.createI32(0),
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0)
|
||||
return module.createSelect(
|
||||
module.createBinary(BinaryOp.SubI32,
|
||||
module.createI32(0),
|
||||
module.createTeeLocal(tempLocal0.index, arg0)
|
||||
),
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||
compiler.module.createBinary(BinaryOp.LtI32,
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||
compiler.module.createI32(0)
|
||||
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||
module.createBinary(BinaryOp.LtI32,
|
||||
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||
module.createI32(0)
|
||||
)
|
||||
);
|
||||
} else
|
||||
@ -185,33 +188,33 @@ export function compileCall(compiler: Compiler, internalName: string, typeArgume
|
||||
|
||||
case "max": // max<T>(left: T, right: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]) != Type.void) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) // sic
|
||||
return typeArguments[0] == Type.f32
|
||||
? compiler.module.createBinary(BinaryOp.MaxF32, arg0, arg1)
|
||||
: compiler.module.createBinary(BinaryOp.MaxF64, arg0, arg1);
|
||||
? module.createBinary(BinaryOp.MaxF32, arg0, arg1)
|
||||
: module.createBinary(BinaryOp.MaxF64, arg0, arg1);
|
||||
if (typeArguments[0].isAnyInteger) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
tempLocal1 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
if (typeArguments[0].isLongInteger)
|
||||
return compiler.module.createSelect(
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0),
|
||||
compiler.module.createTeeLocal(tempLocal1.index, arg1),
|
||||
compiler.module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.GtI64 : BinaryOp.GtU64,
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||
compiler.module.createGetLocal(tempLocal1.index, NativeType.I64)
|
||||
return module.createSelect(
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
module.createTeeLocal(tempLocal1.index, arg1),
|
||||
module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.GtI64 : BinaryOp.GtU64,
|
||||
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
||||
)
|
||||
);
|
||||
else
|
||||
return compiler.module.createSelect(
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0),
|
||||
compiler.module.createTeeLocal(tempLocal1.index, arg1),
|
||||
compiler.module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.GtI32 : BinaryOp.GtU32,
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||
compiler.module.createGetLocal(tempLocal1.index, NativeType.I32)
|
||||
return module.createSelect(
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
module.createTeeLocal(tempLocal1.index, arg1),
|
||||
module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.GtI32 : BinaryOp.GtU32,
|
||||
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -220,33 +223,33 @@ export function compileCall(compiler: Compiler, internalName: string, typeArgume
|
||||
|
||||
case "min": // min<T>(left: T, right: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]) != Type.void) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) // sic
|
||||
return typeArguments[0] == Type.f32
|
||||
? compiler.module.createBinary(BinaryOp.MinF32, arg0, arg1)
|
||||
: compiler.module.createBinary(BinaryOp.MinF64, arg0, arg1);
|
||||
? module.createBinary(BinaryOp.MinF32, arg0, arg1)
|
||||
: module.createBinary(BinaryOp.MinF64, arg0, arg1);
|
||||
if (typeArguments[0].isAnyInteger) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
tempLocal1 = compiler.currentFunction.addLocal(typeArguments[0]);
|
||||
if (typeArguments[0].isLongInteger)
|
||||
return compiler.module.createSelect(
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0),
|
||||
compiler.module.createTeeLocal(tempLocal1.index, arg1),
|
||||
compiler.module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.LtI64 : BinaryOp.LtU64,
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||
compiler.module.createGetLocal(tempLocal1.index, NativeType.I64)
|
||||
return module.createSelect(
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
module.createTeeLocal(tempLocal1.index, arg1),
|
||||
module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.LtI64 : BinaryOp.LtU64,
|
||||
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
||||
)
|
||||
);
|
||||
else
|
||||
return compiler.module.createSelect(
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0),
|
||||
compiler.module.createTeeLocal(tempLocal1.index, arg1),
|
||||
compiler.module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.LtI32 : BinaryOp.LtU32,
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||
compiler.module.createGetLocal(tempLocal1.index, NativeType.I32)
|
||||
return module.createSelect(
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
module.createTeeLocal(tempLocal1.index, arg1),
|
||||
module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.LtI32 : BinaryOp.LtU32,
|
||||
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -255,174 +258,185 @@ export function compileCall(compiler: Compiler, internalName: string, typeArgume
|
||||
|
||||
case "ceil": // ceil<T>(value: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
||||
? compiler.module.createUnary(UnaryOp.CeilF32, arg0)
|
||||
: compiler.module.createUnary(UnaryOp.CeilF64, arg0);
|
||||
? module.createUnary(UnaryOp.CeilF32, arg0)
|
||||
: module.createUnary(UnaryOp.CeilF64, arg0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "floor": // floor<T>(value: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
||||
? compiler.module.createUnary(UnaryOp.FloorF32, arg0)
|
||||
: compiler.module.createUnary(UnaryOp.FloorF64, arg0);
|
||||
? module.createUnary(UnaryOp.FloorF32, arg0)
|
||||
: module.createUnary(UnaryOp.FloorF64, arg0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "copysign": // copysign<T>(left: T, right: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
||||
? compiler.module.createBinary(BinaryOp.CopysignF32, arg0, arg1)
|
||||
: compiler.module.createBinary(BinaryOp.CopysignF64, arg0, arg1);
|
||||
? module.createBinary(BinaryOp.CopysignF32, arg0, arg1)
|
||||
: module.createBinary(BinaryOp.CopysignF64, arg0, arg1);
|
||||
}
|
||||
break;
|
||||
|
||||
case "nearest": // nearest<T>(value: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
||||
? compiler.module.createUnary(UnaryOp.NearestF32, arg0)
|
||||
: compiler.module.createUnary(UnaryOp.NearestF64, arg0);
|
||||
? module.createUnary(UnaryOp.NearestF32, arg0)
|
||||
: module.createUnary(UnaryOp.NearestF64, arg0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "sqrt": // sqrt<T>(value: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
||||
? compiler.module.createUnary(UnaryOp.SqrtF32, arg0)
|
||||
: compiler.module.createUnary(UnaryOp.SqrtF64, arg0);
|
||||
? module.createUnary(UnaryOp.SqrtF32, arg0)
|
||||
: module.createUnary(UnaryOp.SqrtF64, arg0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "trunc": // trunc<T>(value: T) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
||||
? compiler.module.createUnary(UnaryOp.TruncF32, arg0)
|
||||
: compiler.module.createUnary(UnaryOp.TruncF64, arg0);
|
||||
? module.createUnary(UnaryOp.TruncF32, arg0)
|
||||
: module.createUnary(UnaryOp.TruncF64, arg0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "sizeof": // sizeof<T>() -> usize
|
||||
compiler.currentType = usizeType;
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 0, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return usizeType.isLongInteger
|
||||
? compiler.module.createI64(typeArguments[0].byteSize, 0)
|
||||
: compiler.module.createI32(typeArguments[0].byteSize);
|
||||
|
||||
case "load": // load<T>(offset: usize) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
arg0 = compiler.compileExpression(operands[0], usizeType); // reports
|
||||
if ((compiler.currentType = typeArguments[0]) != Type.void)
|
||||
return compiler.module.createLoad(typeArguments[0].byteSize, typeArguments[0].isSignedInteger, arg0, typeToNativeType(typeArguments[0]));
|
||||
return module.createLoad(typeArguments[0].byteSize, typeArguments[0].isSignedInteger, arg0, typeToNativeType(typeArguments[0]));
|
||||
break;
|
||||
|
||||
case "store": // store<T>(offset: usize, value: T) -> void
|
||||
compiler.currentType = Type.void;
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
arg0 = compiler.compileExpression(operands[0], usizeType); // reports
|
||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]); // reports
|
||||
compiler.currentType = Type.void;
|
||||
if (typeArguments[0] != Type.void)
|
||||
return compiler.module.createStore(typeArguments[0].byteSize, arg0, arg1, typeToNativeType(typeArguments[0]));
|
||||
return module.createStore(typeArguments[0].byteSize, arg0, arg1, typeToNativeType(typeArguments[0]));
|
||||
break;
|
||||
|
||||
case "reinterpret": // reinterpret<T1,T2>(value: T1) -> T2
|
||||
if (!validateCall(compiler, typeArguments, 2, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
compiler.currentType = typeArguments[1];
|
||||
if (typeArguments[0].isLongInteger && typeArguments[1] == Type.f64) {
|
||||
arg0 = compiler.compileExpression(operands[0], Type.i64); // reports
|
||||
compiler.currentType = Type.f64;
|
||||
return compiler.module.createUnary(UnaryOp.ReinterpretI64, arg0);
|
||||
return module.createUnary(UnaryOp.ReinterpretI64, arg0);
|
||||
}
|
||||
if (typeArguments[0].isAnyInteger && typeArguments[0].byteSize == 4 && typeArguments[1] == Type.f32) {
|
||||
arg0 = compiler.compileExpression(operands[0], Type.i32); // reports
|
||||
compiler.currentType = Type.f32;
|
||||
return compiler.module.createUnary(UnaryOp.ReinterpretI32, arg0);
|
||||
return module.createUnary(UnaryOp.ReinterpretI32, arg0);
|
||||
}
|
||||
if (typeArguments[0] == Type.f64 && typeArguments[1].isLongInteger) {
|
||||
arg0 = compiler.compileExpression(operands[0], Type.f64); // reports
|
||||
compiler.currentType = typeArguments[1];
|
||||
return compiler.module.createUnary(UnaryOp.ReinterpretF64, arg0);
|
||||
return module.createUnary(UnaryOp.ReinterpretF64, arg0);
|
||||
}
|
||||
if (typeArguments[0] == Type.f32 && typeArguments[1].isAnyInteger && typeArguments[1].byteSize == 4) {
|
||||
arg0 = compiler.compileExpression(operands[0], Type.f32); // reports
|
||||
compiler.currentType = typeArguments[1];
|
||||
return compiler.module.createUnary(UnaryOp.ReinterpretF32, arg0);
|
||||
return module.createUnary(UnaryOp.ReinterpretF32, arg0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "select": // select<T>(ifTrue: T, ifFalse: T, condition: bool) -> T
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 3, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if (typeArguments[0] != Type.void) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]); // reports
|
||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]); // reports
|
||||
arg2 = compiler.compileExpression(operands[2], Type.i32); // reports
|
||||
compiler.currentType = typeArguments[0];
|
||||
return compiler.module.createSelect(arg0, arg1, arg2);
|
||||
return module.createSelect(arg0, arg1, arg2);
|
||||
}
|
||||
break;
|
||||
|
||||
case "current_memory": // current_memory() -> i32
|
||||
compiler.currentType = Type.i32;
|
||||
if (!validateCall(compiler, typeArguments, 0, operands, 0, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return compiler.module.createHost(HostOp.CurrentMemory);
|
||||
return module.createUnreachable();
|
||||
return module.createHost(HostOp.CurrentMemory);
|
||||
|
||||
case "grow_memory": // grow_memory(pages: i32) -> i32
|
||||
compiler.currentType = Type.i32;
|
||||
if (!validateCall(compiler, typeArguments, 0, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
arg0 = compiler.compileExpression(operands[0], Type.i32);
|
||||
return compiler.module.createHost(HostOp.GrowMemory, null, [ arg0 ]);
|
||||
return module.createHost(HostOp.GrowMemory, null, [ arg0 ]);
|
||||
|
||||
case "unreachable": // unreachable() -> *
|
||||
// does not modify currentType
|
||||
validateCall(compiler, typeArguments, 0, operands, 0, reportNode);
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
|
||||
case "sizeof": // sizeof<T>() -> usize
|
||||
compiler.currentType = usizeType;
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 0, reportNode))
|
||||
return module.createUnreachable();
|
||||
return usizeType.isLongInteger
|
||||
? module.createI64(typeArguments[0].byteSize, 0)
|
||||
: module.createI32(typeArguments[0].byteSize);
|
||||
|
||||
case "changetype": // changetype<T1,T2>(value: T1) -> T2
|
||||
if (!validateCall(compiler, typeArguments, 2, operands, 1, reportNode))
|
||||
return module.createUnreachable();
|
||||
if ((typeArguments[0] == usizeType && typeArguments[1].classType) || (typeArguments[0].classType && typeArguments[1] == usizeType)) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
||||
compiler.currentType = typeArguments[1];
|
||||
return arg0;
|
||||
}
|
||||
compiler.error(DiagnosticCode.Type_0_cannot_be_changed_to_type_1, reportNode.range, typeArguments[0].toString(), typeArguments[1].toString());
|
||||
return module.createUnreachable();
|
||||
|
||||
case "isNaN": // isNaN<T>(value: T) -> bool
|
||||
compiler.currentType = Type.bool;
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if (typeArguments[0].isAnyInteger)
|
||||
return compiler.module.createI32(0);
|
||||
return module.createI32(0);
|
||||
if (typeArguments[0].isAnyFloat) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]); // reports
|
||||
compiler.currentType = Type.bool;
|
||||
if (typeArguments[0] == Type.f32) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(Type.f32);
|
||||
return compiler.module.createBinary(BinaryOp.NeF32,
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0),
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.F32)
|
||||
return module.createBinary(BinaryOp.NeF32,
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
module.createGetLocal(tempLocal0.index, NativeType.F32)
|
||||
);
|
||||
} else {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(Type.f64);
|
||||
return compiler.module.createBinary(BinaryOp.NeF64,
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0),
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.F64)
|
||||
return module.createBinary(BinaryOp.NeF64,
|
||||
module.createTeeLocal(tempLocal0.index, arg0),
|
||||
module.createGetLocal(tempLocal0.index, NativeType.F64)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -431,40 +445,40 @@ export function compileCall(compiler: Compiler, internalName: string, typeArgume
|
||||
case "isFinite": // isFinite<T>(value: T) -> bool
|
||||
compiler.currentType = Type.bool;
|
||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
if (typeArguments[0].isAnyInteger)
|
||||
return compiler.module.createI32(1);
|
||||
return module.createI32(1);
|
||||
if (typeArguments[0].isAnyFloat) {
|
||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]); // reports
|
||||
compiler.currentType = Type.bool;
|
||||
if (typeArguments[0] == Type.f32) {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(Type.f32);
|
||||
return compiler.module.createSelect(
|
||||
compiler.module.createBinary(BinaryOp.NeF32,
|
||||
compiler.module.createUnary(UnaryOp.AbsF32,
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0)
|
||||
return module.createSelect(
|
||||
module.createBinary(BinaryOp.NeF32,
|
||||
module.createUnary(UnaryOp.AbsF32,
|
||||
module.createTeeLocal(tempLocal0.index, arg0)
|
||||
),
|
||||
compiler.module.createF32(Infinity)
|
||||
module.createF32(Infinity)
|
||||
),
|
||||
compiler.module.createI32(0),
|
||||
compiler.module.createBinary(BinaryOp.EqF32,
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.F32),
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.F32)
|
||||
module.createI32(0),
|
||||
module.createBinary(BinaryOp.EqF32,
|
||||
module.createGetLocal(tempLocal0.index, NativeType.F32),
|
||||
module.createGetLocal(tempLocal0.index, NativeType.F32)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
tempLocal0 = compiler.currentFunction.addLocal(Type.f64);
|
||||
return compiler.module.createSelect(
|
||||
compiler.module.createBinary(BinaryOp.NeF64,
|
||||
compiler.module.createUnary(UnaryOp.AbsF64,
|
||||
compiler.module.createTeeLocal(tempLocal0.index, arg0)
|
||||
return module.createSelect(
|
||||
module.createBinary(BinaryOp.NeF64,
|
||||
module.createUnary(UnaryOp.AbsF64,
|
||||
module.createTeeLocal(tempLocal0.index, arg0)
|
||||
),
|
||||
compiler.module.createF64(Infinity)
|
||||
module.createF64(Infinity)
|
||||
),
|
||||
compiler.module.createI32(0),
|
||||
compiler.module.createBinary(BinaryOp.EqF64,
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.F64),
|
||||
compiler.module.createGetLocal(tempLocal0.index, NativeType.F64)
|
||||
module.createI32(0),
|
||||
module.createBinary(BinaryOp.EqF64,
|
||||
module.createGetLocal(tempLocal0.index, NativeType.F64),
|
||||
module.createGetLocal(tempLocal0.index, NativeType.F64)
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -474,14 +488,14 @@ export function compileCall(compiler: Compiler, internalName: string, typeArgume
|
||||
case "assert": // assert(isTrue: bool) -> void
|
||||
compiler.currentType = Type.void;
|
||||
if (!validateCall(compiler, typeArguments, 0, operands, 1, reportNode))
|
||||
return compiler.module.createUnreachable();
|
||||
return module.createUnreachable();
|
||||
arg0 = compiler.compileExpression(operands[0], Type.i32); // reports
|
||||
compiler.currentType = Type.void;
|
||||
return compiler.options.noDebug
|
||||
? compiler.module.createNop()
|
||||
: compiler.module.createIf(
|
||||
compiler.module.createUnary(UnaryOp.EqzI32, arg0),
|
||||
compiler.module.createUnreachable()
|
||||
? module.createNop()
|
||||
: module.createIf(
|
||||
module.createUnary(UnaryOp.EqzI32, arg0),
|
||||
module.createUnreachable()
|
||||
);
|
||||
|
||||
// case "fmod":
|
||||
|
@ -148,7 +148,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
const startFunctionTemplate: FunctionPrototype = new FunctionPrototype(program, "start", null);
|
||||
const startFunctionInstance: Function = new Function(startFunctionTemplate, startFunctionTemplate.internalName, [], [], Type.void, null);
|
||||
this.currentFunction = this.startFunction = startFunctionInstance;
|
||||
this.memoryOffset = new U64(2 * (this.options.target == Target.WASM64 ? 8 : 4), 0); // leave space for `null` and heapStart (both of usize type)
|
||||
this.memoryOffset = new U64(this.options.target == Target.WASM64 ? 8 : 4, 0); // leave space for `null`
|
||||
}
|
||||
|
||||
/** Performs compilation of the underlying {@link Program} to a {@link Module}. */
|
||||
@ -178,32 +178,12 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
// set up memory
|
||||
// store heapStart at `sizeof<usize>()` (that is right after `null`) as an usize
|
||||
const initial: U64 = this.memoryOffset.clone();
|
||||
let heapStartBuffer: Uint8Array;
|
||||
let heapStartOffset: i32;
|
||||
if (this.options.target == Target.WASM64) {
|
||||
heapStartBuffer = new Uint8Array(8);
|
||||
heapStartOffset = 8;
|
||||
heapStartBuffer[0] = (initial.lo ) as u8;
|
||||
heapStartBuffer[1] = (initial.lo >>> 8) as u8;
|
||||
heapStartBuffer[2] = (initial.lo >>> 16) as u8;
|
||||
heapStartBuffer[3] = (initial.lo >>> 24) as u8;
|
||||
heapStartBuffer[4] = (initial.hi ) as u8;
|
||||
heapStartBuffer[5] = (initial.hi >>> 8) as u8;
|
||||
heapStartBuffer[6] = (initial.hi >>> 16) as u8;
|
||||
heapStartBuffer[7] = (initial.hi >>> 24) as u8;
|
||||
} else {
|
||||
if (!initial.fitsInU32)
|
||||
throw new Error("static memory size overflows 32 bits");
|
||||
heapStartBuffer = new Uint8Array(4);
|
||||
heapStartOffset = 4;
|
||||
heapStartBuffer[0] = (initial.lo ) as u8;
|
||||
heapStartBuffer[1] = (initial.lo >>> 8) as u8;
|
||||
heapStartBuffer[2] = (initial.lo >>> 16) as u8;
|
||||
heapStartBuffer[3] = (initial.lo >>> 24) as u8;
|
||||
}
|
||||
this.memorySegments.push(MemorySegment.create(heapStartBuffer, new U64(heapStartOffset, 0))); // TODO: use a global instead?
|
||||
if (this.options.target == Target.WASM64)
|
||||
this.module.addGlobal("HEAP_START", NativeType.I64, false, this.module.createI64(initial.lo, initial.hi));
|
||||
else
|
||||
this.module.addGlobal("HEAP_START", NativeType.I32, false, this.module.createI32(initial.lo));
|
||||
|
||||
// determine initial page size
|
||||
const initialOverlaps: U64 = initial.clone();
|
||||
initialOverlaps.and32(0xffff);
|
||||
@ -663,7 +643,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// memory
|
||||
|
||||
addMemorySegment(buffer: Uint8Array): MemorySegment {
|
||||
if (this.memoryOffset.lo & 7) { // align to 8 bytes so any possible data type is aligned here
|
||||
if (this.memoryOffset.lo & 7) { // align to 8 bytes so any native data type is aligned here
|
||||
this.memoryOffset.or32(7);
|
||||
this.memoryOffset.add32(1);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ export enum DiagnosticCode {
|
||||
Operation_is_unsafe = 103,
|
||||
Cannot_export_a_mutable_global = 104,
|
||||
Compiling_constant_global_with_non_constant_initializer_as_mutable = 105,
|
||||
Type_0_cannot_be_changed_to_type_1 = 106,
|
||||
Unterminated_string_literal = 1002,
|
||||
Identifier_expected = 1003,
|
||||
_0_expected = 1005,
|
||||
@ -79,6 +80,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 103: return "Operation is unsafe.";
|
||||
case 104: return "Cannot export a mutable global.";
|
||||
case 105: return "Compiling constant global with non-constant initializer as mutable.";
|
||||
case 106: return "Type '{0}' cannot be changed to type '{1}'.";
|
||||
case 1002: return "Unterminated string literal.";
|
||||
case 1003: return "Identifier expected.";
|
||||
case 1005: return "'{0}' expected.";
|
||||
|
@ -5,6 +5,7 @@
|
||||
"Operation is unsafe.": 103,
|
||||
"Cannot export a mutable global.": 104,
|
||||
"Compiling constant global with non-constant initializer as mutable.": 105,
|
||||
"Type '{0}' cannot be changed to type '{1}'.": 106,
|
||||
|
||||
"Unterminated string literal.": 1002,
|
||||
"Identifier expected.": 1003,
|
||||
|
51
src/index.ts
51
src/index.ts
@ -20,11 +20,12 @@
|
||||
*/
|
||||
|
||||
import { Module } from "./module";
|
||||
import { Compiler } from "./compiler";
|
||||
import { DiagnosticMessage, DiagnosticCategory } from "./diagnostics";
|
||||
import { Compiler, Options, Target } from "./compiler";
|
||||
import { DiagnosticMessage, DiagnosticCategory, formatDiagnosticMessage } from "./diagnostics";
|
||||
import { Parser } from "./parser";
|
||||
import { Program } from "./program";
|
||||
|
||||
/** Parses a single source file. If `parser` has been omitted a new one is created. */
|
||||
export function parseFile(text: string, path: string, parser: Parser | null = null): Parser {
|
||||
let isEntry: bool = false;
|
||||
if (!parser) {
|
||||
@ -35,10 +36,12 @@ export function parseFile(text: string, path: string, parser: Parser | null = nu
|
||||
return parser;
|
||||
}
|
||||
|
||||
/** Obtains the path to the next file required by the parser. Returns `null` once complete. */
|
||||
export function nextFile(parser: Parser): string | null {
|
||||
return parser.nextFile();
|
||||
}
|
||||
|
||||
/** Obtains the next diagnostic message. Returns `null` once there are no more messages. */
|
||||
export function nextDiagnostic(parser: Parser): DiagnosticMessage | null {
|
||||
const program: Program = parser.program;
|
||||
if (program.diagnosticsOffset < program.diagnostics.length)
|
||||
@ -46,13 +49,49 @@ export function nextDiagnostic(parser: Parser): DiagnosticMessage | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Formats a diagnostic message to a string. */
|
||||
export function formatDiagnostic(message: DiagnosticMessage, useColors: bool, showContext: bool): string {
|
||||
return formatDiagnosticMessage(message, useColors, showContext);
|
||||
}
|
||||
|
||||
/** Tests whether a diagnostic is informatory. */
|
||||
export function isInfo(message: DiagnosticMessage): bool {
|
||||
return message.category == DiagnosticCategory.INFO;
|
||||
}
|
||||
|
||||
/** Tests whether a diagnostic is a warning. */
|
||||
export function isWarning(message: DiagnosticMessage): bool {
|
||||
return message.category == DiagnosticCategory.WARNING;
|
||||
}
|
||||
|
||||
/** Tests whether a diagnostic is an error. */
|
||||
export function isError(message: DiagnosticMessage): bool {
|
||||
return message.category == DiagnosticCategory.ERROR;
|
||||
}
|
||||
|
||||
export function compile(parser: Parser): Module {
|
||||
const program: Program = parser.finish();
|
||||
return Compiler.compile(program);
|
||||
/** Creates a new set of compiler options. */
|
||||
export function createOptions(): Options {
|
||||
return new Options();
|
||||
}
|
||||
|
||||
export { DiagnosticMessage, formatDiagnosticMessage as formatDiagnostic } from "./diagnostics";
|
||||
/** Sets the `target` option. */
|
||||
export function setTarget(options: Options, target: Target): void {
|
||||
options.target = target;
|
||||
}
|
||||
|
||||
/** Sets the `noTreeShaking` option. */
|
||||
export function setNoTreeShaking(options: Options, noTreeShaking: bool): void {
|
||||
options.noTreeShaking = noTreeShaking;
|
||||
}
|
||||
|
||||
/** Sets the `noDebug` option. */
|
||||
export function setNoDebug(options: Options, noDebug: bool): void {
|
||||
options.noDebug = noDebug;
|
||||
}
|
||||
|
||||
/** Compiles the sources computed by the parser to a module. */
|
||||
export function compile(parser: Parser, options: Options | null = null): Module {
|
||||
const program: Program = parser.finish();
|
||||
const compiler: Compiler = new Compiler(program, options);
|
||||
return compiler.compile();
|
||||
}
|
||||
|
296
src/parser.ts
296
src/parser.ts
@ -13,6 +13,7 @@ import { DiagnosticCode, DiagnosticEmitter } from "./diagnostics";
|
||||
import { normalizePath, I64 } from "./util";
|
||||
import {
|
||||
|
||||
Node,
|
||||
NodeKind,
|
||||
Source,
|
||||
|
||||
@ -30,7 +31,7 @@ import {
|
||||
BreakStatement,
|
||||
ClassDeclaration,
|
||||
ContinueStatement,
|
||||
DecoratorStatement,
|
||||
Decorator,
|
||||
DoStatement,
|
||||
EnumDeclaration,
|
||||
EnumValueDeclaration,
|
||||
@ -60,7 +61,8 @@ import {
|
||||
VariableDeclaration,
|
||||
WhileStatement,
|
||||
|
||||
hasModifier
|
||||
hasModifier,
|
||||
NamespaceDeclaration
|
||||
|
||||
} from "./ast";
|
||||
|
||||
@ -89,102 +91,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
source.tokenizer = tn;
|
||||
|
||||
while (!tn.skip(Token.ENDOFFILE)) {
|
||||
|
||||
let decorators: DecoratorStatement[] | null = null;
|
||||
|
||||
while (tn.skip(Token.AT)) {
|
||||
const decorator: DecoratorStatement | null = this.parseDecorator(tn);
|
||||
if (!decorator)
|
||||
break;
|
||||
if (!decorators)
|
||||
decorators = new Array();
|
||||
(<DecoratorStatement[]>decorators).push(<DecoratorStatement>decorator);
|
||||
}
|
||||
|
||||
let modifiers: Modifier[] | null = null;
|
||||
|
||||
if (tn.skip(Token.EXPORT))
|
||||
modifiers = addModifier(Statement.createModifier(ModifierKind.EXPORT, tn.range()), modifiers);
|
||||
|
||||
if (tn.skip(Token.DECLARE)) {
|
||||
modifiers = addModifier(Statement.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
|
||||
}
|
||||
|
||||
tn.mark();
|
||||
|
||||
let statement: Statement | null = null;
|
||||
switch (tn.next()) {
|
||||
|
||||
case Token.CONST:
|
||||
modifiers = addModifier(Statement.createModifier(ModifierKind.CONST, tn.range()), modifiers);
|
||||
|
||||
if (tn.skip(Token.ENUM)) {
|
||||
statement = this.parseEnum(tn, modifiers ? <Modifier[]>modifiers : createModifiers());
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
|
||||
case Token.VAR:
|
||||
case Token.LET:
|
||||
statement = this.parseVariable(tn, modifiers ? <Modifier[]>modifiers : createModifiers());
|
||||
break;
|
||||
|
||||
case Token.ENUM:
|
||||
statement = this.parseEnum(tn, modifiers ? <Modifier[]>modifiers : createModifiers());
|
||||
break;
|
||||
|
||||
case Token.FUNCTION:
|
||||
statement = this.parseFunction(tn, modifiers ? <Modifier[]>modifiers : createModifiers(), decorators);
|
||||
decorators = null;
|
||||
break;
|
||||
|
||||
case Token.ABSTRACT:
|
||||
if (!tn.skip(Token.CLASS)) {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(tn.pos), "class");
|
||||
break;
|
||||
}
|
||||
modifiers = addModifier(Statement.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers);
|
||||
// fall through
|
||||
|
||||
case Token.CLASS:
|
||||
statement = this.parseClass(tn, modifiers ? <Modifier[]>modifiers : createModifiers(), decorators);
|
||||
decorators = null;
|
||||
break;
|
||||
|
||||
case Token.IMPORT:
|
||||
if (hasModifier(ModifierKind.EXPORT, modifiers)) {
|
||||
statement = this.parseExportImport(tn, getModifier(ModifierKind.EXPORT, <Modifier[]>modifiers).range);
|
||||
} else
|
||||
statement = this.parseImport(tn);
|
||||
if (modifiers)
|
||||
reusableModifiers = modifiers;
|
||||
break;
|
||||
|
||||
case Token.TYPE:
|
||||
// TODO
|
||||
|
||||
default:
|
||||
if (hasModifier(ModifierKind.EXPORT, modifiers)) {
|
||||
tn.reset();
|
||||
statement = this.parseExport(tn, modifiers ? <Modifier[]>modifiers : createModifiers());
|
||||
} else {
|
||||
if (modifiers) {
|
||||
if (hasModifier(ModifierKind.DECLARE, modifiers))
|
||||
this.error(DiagnosticCode._0_modifier_cannot_be_used_here, getModifier(ModifierKind.DECLARE, <Modifier[]>modifiers).range, "declare"); // recoverable
|
||||
reusableModifiers = modifiers;
|
||||
}
|
||||
tn.reset();
|
||||
statement = this.parseStatement(tn, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (decorators)
|
||||
for (let i: i32 = 0, k: i32 = (<DecoratorStatement[]>decorators).length; i < k; ++i)
|
||||
this.error(DiagnosticCode.Decorators_are_not_valid_here, (<DecoratorStatement[]>decorators)[i].range);
|
||||
const statement: Statement | null = this.parseTopLevelStatement(tn);
|
||||
if (!statement)
|
||||
return;
|
||||
statement.parent = source;
|
||||
@ -193,6 +100,114 @@ export class Parser extends DiagnosticEmitter {
|
||||
reusableModifiers = null;
|
||||
}
|
||||
|
||||
parseTopLevelStatement(tn: Tokenizer, isNamespaceMember: bool = false): Statement | null {
|
||||
let decorators: Decorator[] | null = null;
|
||||
|
||||
while (tn.skip(Token.AT)) {
|
||||
const decorator: Decorator | null = this.parseDecorator(tn);
|
||||
if (!decorator)
|
||||
break;
|
||||
if (!decorators)
|
||||
decorators = new Array();
|
||||
(<Decorator[]>decorators).push(<Decorator>decorator);
|
||||
}
|
||||
|
||||
let modifiers: Modifier[] | null = null;
|
||||
|
||||
if (tn.skip(Token.EXPORT))
|
||||
modifiers = addModifier(Statement.createModifier(ModifierKind.EXPORT, tn.range()), modifiers);
|
||||
|
||||
if (tn.skip(Token.DECLARE)) {
|
||||
modifiers = addModifier(Statement.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
|
||||
}
|
||||
|
||||
tn.mark();
|
||||
|
||||
let statement: Statement | null = null;
|
||||
switch (tn.next()) {
|
||||
|
||||
case Token.CONST:
|
||||
modifiers = addModifier(Statement.createModifier(ModifierKind.CONST, tn.range()), modifiers);
|
||||
|
||||
if (tn.skip(Token.ENUM)) {
|
||||
statement = this.parseEnum(tn, modifiers, decorators);
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
|
||||
case Token.VAR:
|
||||
case Token.LET:
|
||||
statement = this.parseVariable(tn, modifiers, decorators);
|
||||
decorators = null;
|
||||
break;
|
||||
|
||||
case Token.ENUM:
|
||||
statement = this.parseEnum(tn, modifiers, decorators);
|
||||
decorators = null;
|
||||
break;
|
||||
|
||||
case Token.FUNCTION:
|
||||
statement = this.parseFunction(tn, modifiers, decorators);
|
||||
decorators = null;
|
||||
break;
|
||||
|
||||
case Token.ABSTRACT:
|
||||
if (!tn.skip(Token.CLASS)) {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(tn.pos), "class");
|
||||
break;
|
||||
}
|
||||
modifiers = addModifier(Statement.createModifier(ModifierKind.ABSTRACT, tn.range()), modifiers);
|
||||
// fall through
|
||||
|
||||
case Token.CLASS:
|
||||
statement = this.parseClass(tn, modifiers, decorators);
|
||||
decorators = null;
|
||||
break;
|
||||
|
||||
case Token.NAMESPACE:
|
||||
statement = this.parseNamespace(tn, modifiers, decorators);
|
||||
decorators = null;
|
||||
break;
|
||||
|
||||
case Token.IMPORT:
|
||||
if (hasModifier(ModifierKind.EXPORT, modifiers)) {
|
||||
statement = this.parseExportImport(tn, getModifier(ModifierKind.EXPORT, <Modifier[]>modifiers).range);
|
||||
} else
|
||||
statement = this.parseImport(tn);
|
||||
if (modifiers)
|
||||
reusableModifiers = modifiers;
|
||||
break;
|
||||
|
||||
case Token.TYPE:
|
||||
// TODO
|
||||
|
||||
default:
|
||||
if (hasModifier(ModifierKind.EXPORT, modifiers)) {
|
||||
tn.reset();
|
||||
statement = this.parseExport(tn, modifiers); // TODO: why exactly does this have modifiers again?
|
||||
} else {
|
||||
if (modifiers) {
|
||||
if (hasModifier(ModifierKind.DECLARE, modifiers))
|
||||
this.error(DiagnosticCode._0_modifier_cannot_be_used_here, getModifier(ModifierKind.DECLARE, modifiers).range, "declare"); // recoverable
|
||||
reusableModifiers = modifiers;
|
||||
}
|
||||
tn.reset();
|
||||
if (!isNamespaceMember)
|
||||
statement = this.parseStatement(tn, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (decorators /* not consumed */)
|
||||
for (let i: i32 = 0, k: i32 = (<Decorator[]>decorators).length; i < k; ++i)
|
||||
this.error(DiagnosticCode.Decorators_are_not_valid_here, (<Decorator[]>decorators)[i].range);
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
nextFile(): string | null {
|
||||
if (this.backlog.length) {
|
||||
const filename: string = this.backlog[0];
|
||||
@ -318,7 +333,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
|
||||
// statements
|
||||
|
||||
parseDecorator(tn: Tokenizer): DecoratorStatement | null {
|
||||
parseDecorator(tn: Tokenizer): Decorator | null {
|
||||
// at '@': Identifier ('.' Identifier)* '(' Arguments
|
||||
const startPos: i32 = tn.tokenPos;
|
||||
if (tn.skip(Token.IDENTIFIER)) {
|
||||
@ -344,24 +359,24 @@ export class Parser extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
|
||||
parseVariable(tn: Tokenizer, modifiers: Modifier[]): VariableStatement | null {
|
||||
parseVariable(tn: Tokenizer, modifiers: Modifier[] | null, decorators: Decorator[] | null): VariableStatement | null {
|
||||
// at ('const' | 'let' | 'var'): VariableDeclaration (',' VariableDeclaration)* ';'?
|
||||
const startPos: i32 = modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
||||
const startPos: i32 = modifiers && modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
||||
const members: VariableDeclaration[] = new Array();
|
||||
const isDeclare = hasModifier(ModifierKind.DECLARE, modifiers);
|
||||
do {
|
||||
const member: VariableDeclaration | null = this.parseVariableDeclaration(tn, isDeclare, modifiers);
|
||||
const member: VariableDeclaration | null = this.parseVariableDeclaration(tn, isDeclare, modifiers, decorators);
|
||||
if (!member)
|
||||
return null;
|
||||
members.push(<VariableDeclaration>member);
|
||||
} while (tn.skip(Token.COMMA));
|
||||
|
||||
const ret: VariableStatement = Statement.createVariable(modifiers, members, tn.range(startPos, tn.pos));
|
||||
const ret: VariableStatement = Statement.createVariable(members, modifiers, decorators, tn.range(startPos, tn.pos));
|
||||
tn.skip(Token.SEMICOLON);
|
||||
return ret;
|
||||
}
|
||||
|
||||
parseVariableDeclaration(tn: Tokenizer, isDeclare: bool = false, parentModifiers: Modifier[]): VariableDeclaration | null {
|
||||
parseVariableDeclaration(tn: Tokenizer, isDeclare: bool = false, parentModifiers: Modifier[] | null, parentDecorators: Decorator[] | null): VariableDeclaration | null {
|
||||
// Identifier (':' Type)? ('=' Expression)?
|
||||
if (!tn.skip(Token.IDENTIFIER)) {
|
||||
this.error(DiagnosticCode.Identifier_expected, tn.range());
|
||||
@ -383,12 +398,12 @@ export class Parser extends DiagnosticEmitter {
|
||||
if (!initializer)
|
||||
return null;
|
||||
}
|
||||
return Statement.createVariableDeclaration(identifier, type, initializer, parentModifiers, Range.join(identifier.range, tn.range()));
|
||||
return Statement.createVariableDeclaration(identifier, type, initializer, parentModifiers, parentDecorators, Range.join(identifier.range, tn.range()));
|
||||
}
|
||||
|
||||
parseEnum(tn: Tokenizer, modifiers: Modifier[]): EnumDeclaration | null {
|
||||
parseEnum(tn: Tokenizer, modifiers: Modifier[] | null, decorators: Decorator[] | null): EnumDeclaration | null {
|
||||
// at 'enum': Identifier '{' (EnumValueDeclaration (',' EnumValueDeclaration )*)? '}' ';'?
|
||||
const startPos: i32 = modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
||||
const startPos: i32 = modifiers && modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
||||
if (tn.next() != Token.IDENTIFIER) {
|
||||
this.error(DiagnosticCode.Identifier_expected, tn.range());
|
||||
return null;
|
||||
@ -411,7 +426,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
const ret: EnumDeclaration = Statement.createEnum(modifiers, identifier, members, tn.range(startPos, tn.pos));
|
||||
const ret: EnumDeclaration = Statement.createEnum(identifier, members, modifiers, decorators, tn.range(startPos, tn.pos));
|
||||
tn.skip(Token.SEMICOLON);
|
||||
return ret;
|
||||
}
|
||||
@ -528,13 +543,9 @@ export class Parser extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
|
||||
parseFunction(tn: Tokenizer, modifiers: Modifier[], decorators: DecoratorStatement[] | null): FunctionDeclaration | null {
|
||||
parseFunction(tn: Tokenizer, modifiers: Modifier[] | null, decorators: Decorator[] | null): FunctionDeclaration | null {
|
||||
// at 'function': Identifier ('<' TypeParameters)? '(' Parameters (':' Type)? '{' Statement* '}' ';'?
|
||||
const startPos: i32 = decorators && (<DecoratorStatement[]>decorators).length
|
||||
? (<DecoratorStatement[]>decorators)[0].range.start
|
||||
: modifiers.length
|
||||
? modifiers[0].range.start
|
||||
: tn.tokenPos;
|
||||
const startPos: i32 = modifiers && modifiers.length ? modifiers[0].range.start : tn.tokenPos;
|
||||
|
||||
if (!tn.skip(Token.IDENTIFIER)) {
|
||||
this.error(DiagnosticCode.Identifier_expected, tn.range(tn.pos));
|
||||
@ -576,16 +587,16 @@ 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(modifiers, identifier, typeParameters, <Parameter[]>parameters, returnType, statements, decorators ? <DecoratorStatement[]>decorators : [], tn.range(startPos, tn.pos));
|
||||
const ret: FunctionDeclaration = Statement.createFunction(identifier, typeParameters, <Parameter[]>parameters, returnType, statements, modifiers, decorators, tn.range(startPos, tn.pos));
|
||||
tn.skip(Token.SEMICOLON);
|
||||
return ret;
|
||||
}
|
||||
|
||||
parseClass(tn: Tokenizer, modifiers: Modifier[], decorators: DecoratorStatement[] | null): ClassDeclaration | null {
|
||||
parseClass(tn: Tokenizer, modifiers: Modifier[] | null, decorators: Decorator[] | null): ClassDeclaration | null {
|
||||
// at 'class': Identifier ('<' TypeParameters)? ('extends' Type)? ('implements' Type (',' Type)*)? '{' ClassMember* '}'
|
||||
const startPos: i32 = decorators && (<DecoratorStatement[]>decorators).length
|
||||
? (<DecoratorStatement[]>decorators)[0].range.start
|
||||
: modifiers.length
|
||||
const startPos: i32 = decorators && decorators.length
|
||||
? decorators[0].range.start
|
||||
: modifiers && modifiers.length
|
||||
? modifiers[0].range.start
|
||||
: tn.tokenPos;
|
||||
|
||||
@ -628,7 +639,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
members.push(<DeclarationStatement>member);
|
||||
} while (!tn.skip(Token.CLOSEBRACE));
|
||||
}
|
||||
return Statement.createClass(modifiers, identifier, <TypeParameter[]>typeParameters, extendsType, implementsTypes, members, decorators ? <DecoratorStatement[]>decorators : [], tn.range(startPos, tn.pos));
|
||||
return Statement.createClass(identifier, <TypeParameter[]>typeParameters, extendsType, implementsTypes, members, modifiers, decorators, tn.range(startPos, tn.pos));
|
||||
} else
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), "{");
|
||||
} else
|
||||
@ -640,13 +651,13 @@ export class Parser extends DiagnosticEmitter {
|
||||
// ('public' | 'private' | 'protected')? ('static' | 'abstract')? ('get' | 'set')? Identifier ...
|
||||
const startRange: Range = tn.range();
|
||||
|
||||
let decorators: DecoratorStatement[] = new Array();
|
||||
let decorators: Decorator[] = new Array();
|
||||
|
||||
while (tn.skip(Token.AT)) {
|
||||
const decorator: DecoratorStatement | null = this.parseDecorator(tn);
|
||||
const decorator: Decorator | null = this.parseDecorator(tn);
|
||||
if (!decorator)
|
||||
break;
|
||||
decorators.push(<DecoratorStatement>decorator);
|
||||
decorators.push(<Decorator>decorator);
|
||||
}
|
||||
|
||||
let modifiers: Modifier[] | null = null;
|
||||
@ -706,7 +717,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(modifiers ? modifiers : createModifiers(), identifier, <TypeParameter[]>typeParameters, <Parameter[]>parameters, returnType, statements, decorators, Range.join(startRange, tn.range()));
|
||||
const ret: MethodDeclaration = Statement.createMethod(identifier, <TypeParameter[]>typeParameters, <Parameter[]>parameters, returnType, statements, modifiers, decorators, Range.join(startRange, tn.range()));
|
||||
tn.skip(Token.SEMICOLON);
|
||||
return ret;
|
||||
|
||||
@ -731,7 +742,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
if (!initializer)
|
||||
return null;
|
||||
}
|
||||
const ret: FieldDeclaration = Statement.createField(modifiers ? modifiers : createModifiers(), identifier, type, initializer, decorators, Range.join(startRange, tn.range()));
|
||||
const ret: FieldDeclaration = Statement.createField(identifier, type, initializer, modifiers, decorators, Range.join(startRange, tn.range()));
|
||||
tn.skip(Token.SEMICOLON);
|
||||
return ret;
|
||||
}
|
||||
@ -740,9 +751,32 @@ export class Parser extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
|
||||
parseExport(tn: Tokenizer, modifiers: Modifier[]): ExportStatement | null {
|
||||
parseNamespace(tn: Tokenizer, modifiers: Modifier[] | null, decorators: Decorator[] | null): NamespaceDeclaration | null {
|
||||
// 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());
|
||||
if (tn.skip(Token.OPENBRACE)) {
|
||||
const members: Statement[] = new Array();
|
||||
while (!tn.skip(Token.CLOSEBRACE)) {
|
||||
const member: Statement | null = this.parseTopLevelStatement(tn, true);
|
||||
if (!member)
|
||||
return null;
|
||||
members.push(member);
|
||||
}
|
||||
const ret: NamespaceDeclaration = Statement.createNamespace(identifier, members, modifiers, decorators, Range.join(startRange, tn.range()));
|
||||
tn.skip(Token.SEMICOLON);
|
||||
return ret;
|
||||
} else
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), "{");
|
||||
} else
|
||||
this.error(DiagnosticCode.Identifier_expected, tn.range());
|
||||
return null;
|
||||
}
|
||||
|
||||
parseExport(tn: Tokenizer, modifiers: Modifier[] | null): ExportStatement | null {
|
||||
// at 'export': '{' ExportMember (',' ExportMember)* }' ('from' StringLiteral)? ';'?
|
||||
const startRange: Range = modifiers.length ? modifiers[0].range : tn.range();
|
||||
const startRange: Range = modifiers && modifiers.length ? modifiers[0].range : tn.range();
|
||||
if (tn.skip(Token.OPENBRACE)) {
|
||||
const members: ExportMember[] = new Array();
|
||||
if (!tn.skip(Token.CLOSEBRACE)) {
|
||||
@ -766,7 +800,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
const ret: ExportStatement = Statement.createExport(modifiers, members, path, Range.join(startRange, tn.range()));
|
||||
const ret: ExportStatement = Statement.createExport(members, path, modifiers, Range.join(startRange, tn.range()));
|
||||
if (ret.normalizedPath && !this.seenlog.has(<string>ret.normalizedPath)) {
|
||||
this.backlog.push(<string>ret.normalizedPath);
|
||||
this.seenlog.add(<string>ret.normalizedPath);
|
||||
@ -881,7 +915,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
return this.parseBreak(tn);
|
||||
|
||||
case Token.CONST:
|
||||
return this.parseVariable(tn, [ Statement.createModifier(ModifierKind.CONST, tn.range()) ]);
|
||||
return this.parseVariable(tn, [ Statement.createModifier(ModifierKind.CONST, tn.range()) ], null);
|
||||
|
||||
case Token.CONTINUE:
|
||||
return this.parseContinue(tn);
|
||||
@ -897,7 +931,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
|
||||
case Token.LET:
|
||||
case Token.VAR:
|
||||
return this.parseVariable(tn, []);
|
||||
return this.parseVariable(tn, null, null);
|
||||
|
||||
case Token.OPENBRACE:
|
||||
return this.parseBlockStatement(tn, topLevel);
|
||||
@ -1007,7 +1041,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
if (tn.skip(Token.OPENPAREN)) {
|
||||
let initializer: Statement | null = null;
|
||||
if (tn.skip(Token.LET) || tn.skip(Token.CONST) || tn.skip(Token.VAR)) {
|
||||
initializer = this.parseVariable(tn, /* TODO */ createModifiers());
|
||||
initializer = this.parseVariable(tn, null, null);
|
||||
} else if (!tn.skip(Token.SEMICOLON)) {
|
||||
initializer = this.parseExpressionStatement(tn);
|
||||
if (!initializer)
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
|
||||
ClassDeclaration,
|
||||
DeclarationStatement,
|
||||
DecoratorStatement,
|
||||
Decorator,
|
||||
EnumDeclaration,
|
||||
EnumValueDeclaration,
|
||||
ExportMember,
|
||||
@ -665,9 +665,9 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
function checkGlobalDecorator(decorators: DecoratorStatement[]): string | null {
|
||||
function checkGlobalDecorator(decorators: Decorator[]): string | null {
|
||||
for (let i: i32 = 0, k: i32 = decorators.length; i < k; ++i) {
|
||||
const decorator: DecoratorStatement = decorators[i];
|
||||
const decorator: Decorator = decorators[i];
|
||||
const expression: Expression = decorator.expression;
|
||||
const args: Expression[] = decorator.arguments;
|
||||
if (expression.kind == NodeKind.IDENTIFIER && args.length <= 1 && (<IdentifierExpression>expression).name == "global") {
|
||||
|
6
std/carray.d.ts
vendored
6
std/carray.d.ts
vendored
@ -1,6 +1,12 @@
|
||||
/// <reference path="../assembly.d.ts" />
|
||||
|
||||
/** A C-compatible array class. */
|
||||
declare class CArray<T> {
|
||||
[key: number]: T;
|
||||
|
||||
/** Constructs a new C-Array of the specified capacity. */
|
||||
constructor(capacity: usize);
|
||||
|
||||
/** Disposes this instance and the memory associated with it. */
|
||||
dispose(): void;
|
||||
}
|
||||
|
11
std/cstring.d.ts
vendored
11
std/cstring.d.ts
vendored
@ -1,5 +1,12 @@
|
||||
/// <reference path="../assembly.d.ts" />
|
||||
|
||||
declare class CString extends CArray<u8> {
|
||||
constructor(text: string);
|
||||
/** A C-compatible string class. */
|
||||
declare class CString {
|
||||
readonly [key: number]: u8;
|
||||
|
||||
/** Constructs a new C-String from a standard string. */
|
||||
constructor(string: string);
|
||||
|
||||
/** Disposes this instance and the memory associated with it. */
|
||||
dispose(): void;
|
||||
}
|
||||
|
20
std/heap.ts
Normal file
20
std/heap.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/// <reference path="../assembly.d.ts" />
|
||||
|
||||
/** A static class representing the heap. */
|
||||
declare class Heap {
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Gets the amount of used heap space, in bytes. */
|
||||
static get used(): usize;
|
||||
|
||||
/** Gets the amount of free heap space, in bytes. */
|
||||
static get free(): usize;
|
||||
|
||||
/** Gets the size of the heap, in bytes. */
|
||||
static get size(): usize;
|
||||
}
|
@ -1,29 +1,25 @@
|
||||
/// <reference path="../../assembly.d.ts" />
|
||||
|
||||
/** A C-compatible Array class. */
|
||||
@global()
|
||||
@struct()
|
||||
class CArray<T> {
|
||||
|
||||
/** Constructs a new C-Array of the specified capacity. */
|
||||
constructor(capacity: usize) {
|
||||
return unsafe_cast<usize,this>(Memory.allocate(capacity * sizeof<T>()));
|
||||
return changetype<usize, this>(Heap.allocate(capacity * sizeof<T>()));
|
||||
}
|
||||
|
||||
/** Gets the element at the specified index using bracket notation. */
|
||||
@inline()
|
||||
"[]"(index: usize): T {
|
||||
return load<T>(unsafe_cast<this,usize>(this) + index * sizeof<T>());
|
||||
return load<T>(changetype<this, usize>(this) + index * sizeof<T>());
|
||||
}
|
||||
|
||||
/** Sets the element at the specified index using bracket notation. */
|
||||
@inline()
|
||||
"[]="(index: usize, value: T): T {
|
||||
store<T>(unsafe_cast<this,usize>(this) + index * sizeof<T>(), value);
|
||||
store<T>(changetype<this, usize>(this) + index * sizeof<T>(), value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Disposes this instance and the memory associated with it. */
|
||||
dispose(): void {
|
||||
Memory.dispose(unsafe_cast<this,usize>(this));
|
||||
Heap.dispose(changetype<this, usize>(this));
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,16 @@
|
||||
/// <reference path="../../assembly.d.ts" />
|
||||
|
||||
/** A C-compatible string class. */
|
||||
@global()
|
||||
class CString extends CArray<u8> {
|
||||
@struct()
|
||||
class CString {
|
||||
|
||||
/** Constructs a new C-String from a String. */
|
||||
constructor(text: string) {
|
||||
super(text.length * 2 + 1);
|
||||
let idx: usize = unsafe_cast<this,usize>(this);
|
||||
for (let i: usize = 0, k: usize = (<string>str).length; i < k; ++i) {
|
||||
let u: i32 = text.charCodeAt(i);
|
||||
constructor(string: string) {
|
||||
const ptr: usize = Heap.allocate(<usize>string.length * 2 + 1);
|
||||
let idx: usize = ptr;
|
||||
for (let i: usize = 0, k: usize = <usize>(<string>str).length; i < k; ++i) {
|
||||
let u: i32 = string.charCodeAt(i);
|
||||
if (u >= 0xD800 && u <= 0xDFFF && i + 1 < k)
|
||||
u = 0x10000 + ((u & 0x3FF) << 10) | (text.charCodeAt(++i) & 0x3FF);
|
||||
u = 0x10000 + ((u & 0x3FF) << 10) | (string.charCodeAt(++i) & 0x3FF);
|
||||
if (u <= 0x7F)
|
||||
store<u8>(idx++, u as u8);
|
||||
else if (u <= 0x7FF) {
|
||||
@ -43,5 +42,17 @@ class CString extends CArray<u8> {
|
||||
}
|
||||
}
|
||||
store<u8>(idx, 0);
|
||||
return changetype<usize, this>(ptr);
|
||||
}
|
||||
|
||||
@inline()
|
||||
"[]"(index: usize): u8 {
|
||||
return load<u8>(changetype<this, usize>(this) + index /* * sizeof<u8>() */);
|
||||
}
|
||||
|
||||
// read-only
|
||||
|
||||
dispose(): void {
|
||||
Heap.dispose(changetype<this, usize>(this));
|
||||
}
|
||||
}
|
||||
|
38
std/impl/heap.ts
Normal file
38
std/impl/heap.ts
Normal file
@ -0,0 +1,38 @@
|
||||
/// <reference path="../../assembly.d.ts" />
|
||||
|
||||
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
|
||||
|
||||
@global()
|
||||
@struct()
|
||||
class Heap {
|
||||
|
||||
static allocate(size: usize): usize {
|
||||
const ptr: usize = HEAP_OFFSET;
|
||||
assert(ptr + size <= (<usize>current_memory() << 16));
|
||||
if (((HEAP_OFFSET += size) & ALIGN_MASK) != 0) // align next offset
|
||||
HEAP_OFFSET = (HEAP_OFFSET | ALIGN_MASK) + 1;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static dispose(ptr: usize): void {
|
||||
// just a big chunk of non-disposable memory for now
|
||||
}
|
||||
|
||||
static get used(): usize {
|
||||
return HEAP_OFFSET - HEAP_START;
|
||||
}
|
||||
|
||||
static get free(): usize {
|
||||
return (<usize>current_memory() << 16) - HEAP_OFFSET;
|
||||
}
|
||||
|
||||
static get size(): usize {
|
||||
return (<usize>current_memory() << 16) - HEAP_START;
|
||||
}
|
||||
|
||||
private constructor() {}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/// <reference path="../../assembly.d.ts" />
|
||||
|
||||
const MEMORY_ALIGN_LOG2: usize = 3;
|
||||
const MEMORY_ALIGN_SIZE: usize = 1 << MEMORY_ALIGN_LOG2;
|
||||
const MEMORY_ALIGN_MASK: usize = MEMORY_ALIGN_SIZE - 1;
|
||||
|
||||
@global()
|
||||
class Memory {
|
||||
|
||||
static allocate(size: usize): usize {
|
||||
const ptr: usize = HEAP_OFFSET;
|
||||
HEAP_OFFSET += size;
|
||||
if ((HEAP_OFFSET & MEMORY_ALIGN_MASK) != 0)
|
||||
HEAP_OFFSET = (HEAP_OFFSET | MEMORY_ALIGN_MASK) + 1;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static dispose(ptr: usize): void {
|
||||
// just a big chunk of non-disposable memory for now
|
||||
}
|
||||
}
|
@ -6,6 +6,6 @@
|
||||
"files": [
|
||||
"carray.ts",
|
||||
"cstring.ts",
|
||||
"memory.ts"
|
||||
"heap.ts"
|
||||
]
|
||||
}
|
6
std/memory.d.ts
vendored
6
std/memory.d.ts
vendored
@ -1,6 +0,0 @@
|
||||
/// <reference path="../assembly.d.ts" />
|
||||
|
||||
declare class Memory {
|
||||
static allocate(size: usize): usize;
|
||||
static dispose(ptr: usize): void;
|
||||
}
|
@ -6,6 +6,6 @@
|
||||
"files": [
|
||||
"carray.d.ts",
|
||||
"cstring.d.ts",
|
||||
"memory.d.ts"
|
||||
"heap.d.ts"
|
||||
]
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -1,7 +1,7 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
@ -37,6 +37,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -6,7 +6,6 @@
|
||||
(global $binary/f (mut f32) (f32.const 0))
|
||||
(global $binary/F (mut f64) (f64.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -5,8 +5,8 @@
|
||||
(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))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
@ -840,6 +840,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -7,7 +7,6 @@
|
||||
(global $builtins/F (mut f64) (f64.const 0))
|
||||
(global $builtins/s (mut i32) (i32.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -6,8 +6,8 @@
|
||||
(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))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
@ -1083,6 +1083,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -1,8 +1,8 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(import "env" "external" (func $declare/external))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "external" (func $declare/external))
|
||||
(export "memory" (memory $0))
|
||||
)
|
||||
@ -30,6 +30,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -1,7 +1,6 @@
|
||||
(module
|
||||
(type $iv (func (param i32)))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "loopDo" (func $do/loopDo))
|
||||
(export "loopDoInDo" (func $do/loopDoInDo))
|
||||
(export "memory" (memory $0))
|
||||
|
@ -1,7 +1,7 @@
|
||||
(module
|
||||
(type $iv (func (param i32)))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "loopDo" (func $do/loopDo))
|
||||
(export "loopDoInDo" (func $do/loopDoInDo))
|
||||
(export "memory" (memory $0))
|
||||
@ -75,6 +75,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -4,7 +4,6 @@
|
||||
(global $enum/NonConstant.ZERO (mut i32) (i32.const 0))
|
||||
(global $enum/NonConstant.ONE (mut i32) (i32.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -4,7 +4,6 @@
|
||||
(global $enum/NonConstant.ZERO (mut i32) (i32.const 0))
|
||||
(global $enum/NonConstant.ONE (mut i32) (i32.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $enum/getZero (; 0 ;) (type $i) (result i32)
|
||||
|
@ -15,8 +15,8 @@
|
||||
(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))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $enum/getZero (; 0 ;) (type $i) (result i32)
|
||||
@ -60,6 +60,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -3,7 +3,6 @@
|
||||
(global $export/a i32 (i32.const 1))
|
||||
(global $export/b i32 (i32.const 2))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "add" (func $export/add))
|
||||
(export "renamed_sub" (func $export/sub))
|
||||
(export "a" (global $export/a))
|
||||
|
@ -13,3 +13,8 @@ export const a: i32 = 1;
|
||||
const b: i32 = 2;
|
||||
|
||||
export { b as renamed_b };
|
||||
|
||||
/* export namespace ns {
|
||||
function one(): void {}
|
||||
export function two(): void {}
|
||||
} */
|
||||
|
@ -2,8 +2,8 @@
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(global $export/a i32 (i32.const 1))
|
||||
(global $export/b i32 (i32.const 2))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "add" (func $export/add))
|
||||
(export "renamed_sub" (func $export/sub))
|
||||
(export "a" (global $export/a))
|
||||
@ -50,6 +50,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -2,7 +2,6 @@
|
||||
(type $v (func))
|
||||
(global $for/i (mut i32) (i32.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -1,8 +1,8 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(global $for/i (mut i32) (i32.const 0))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
@ -171,6 +171,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -5,7 +5,6 @@
|
||||
(global $game-of-life/h (mut i32) (i32.const 0))
|
||||
(global $game-of-life/s (mut i32) (i32.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "init" (func $game-of-life/init))
|
||||
(export "step" (func $game-of-life/step))
|
||||
(export "memory" (memory $0))
|
||||
|
@ -4,8 +4,8 @@
|
||||
(global $game-of-life/w (mut i32) (i32.const 0))
|
||||
(global $game-of-life/h (mut i32) (i32.const 0))
|
||||
(global $game-of-life/s (mut i32) (i32.const 0))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "init" (func $game-of-life/init))
|
||||
(export "step" (func $game-of-life/step))
|
||||
(export "memory" (memory $0))
|
||||
@ -332,6 +332,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -1,7 +1,6 @@
|
||||
(module
|
||||
(type $ii (func (param i32) (result i32)))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "ifThenElse" (func $if/ifThenElse))
|
||||
(export "ifThen" (func $if/ifThen))
|
||||
(export "ifThenElseBlock" (func $if/ifThenElse))
|
||||
|
@ -1,7 +1,7 @@
|
||||
(module
|
||||
(type $ii (func (param i32) (result i32)))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "ifThenElse" (func $if/ifThenElse))
|
||||
(export "ifThen" (func $if/ifThen))
|
||||
(export "ifThenElseBlock" (func $if/ifThenElseBlock))
|
||||
@ -70,6 +70,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -2,7 +2,6 @@
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(type $v (func))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -2,7 +2,6 @@
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(type $v (func))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
|
@ -3,8 +3,8 @@
|
||||
(type $v (func))
|
||||
(global $export/a i32 (i32.const 1))
|
||||
(global $export/b i32 (i32.const 2))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
@ -62,6 +62,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -1,7 +1,6 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -1,7 +1,7 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
@ -163,6 +163,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -5,7 +5,6 @@
|
||||
(global $logical/f (mut f32) (f32.const 0))
|
||||
(global $logical/F (mut f64) (f64.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -4,8 +4,8 @@
|
||||
(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))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
@ -291,6 +291,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -4,7 +4,6 @@
|
||||
(global $export/a i32 (i32.const 1))
|
||||
(global $export/b i32 (i32.const 2))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "add" (func $export/add))
|
||||
(export "renamed_sub" (func $export/sub))
|
||||
(export "renamed_a" (global $export/a))
|
||||
|
@ -3,8 +3,8 @@
|
||||
(type $v (func))
|
||||
(global $export/a i32 (i32.const 1))
|
||||
(global $export/b i32 (i32.const 2))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "add" (func $export/add))
|
||||
(export "renamed_sub" (func $export/sub))
|
||||
(export "renamed_a" (global $export/a))
|
||||
@ -68,6 +68,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -1,7 +1,6 @@
|
||||
(module
|
||||
(type $ii (func (param i32) (result i32)))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "doSwitch" (func $switch/doSwitch))
|
||||
(export "doSwitchDefaultFirst" (func $switch/doSwitchDefaultFirst))
|
||||
(export "doSwitchDefaultOmitted" (func $switch/doSwitchDefaultOmitted))
|
||||
|
@ -1,7 +1,7 @@
|
||||
(module
|
||||
(type $ii (func (param i32) (result i32)))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "doSwitch" (func $switch/doSwitch))
|
||||
(export "doSwitchDefaultFirst" (func $switch/doSwitchDefaultFirst))
|
||||
(export "doSwitchDefaultOmitted" (func $switch/doSwitchDefaultOmitted))
|
||||
@ -169,6 +169,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -2,7 +2,6 @@
|
||||
(type $v (func))
|
||||
(global $ternary/a (mut i32) (i32.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -1,8 +1,8 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(global $ternary/a (mut i32) (i32.const 0))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
@ -57,6 +57,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -6,7 +6,6 @@
|
||||
(type $iv (func (param i32)))
|
||||
(type $v (func))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "control$construct" (func $tlsf/control$construct))
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
|
@ -6,7 +6,6 @@
|
||||
(type $iv (func (param i32)))
|
||||
(type $v (func))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "control$construct" (func $tlsf/control$construct))
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
|
@ -21,8 +21,8 @@
|
||||
(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))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "control$construct" (func $tlsf/control$construct))
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
@ -352,6 +352,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -5,7 +5,6 @@
|
||||
(global $unary/f (mut f32) (f32.const 0))
|
||||
(global $unary/F (mut f64) (f64.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
|
@ -4,8 +4,8 @@
|
||||
(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))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
@ -657,6 +657,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
@ -1,7 +1,6 @@
|
||||
(module
|
||||
(type $iv (func (param i32)))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08")
|
||||
(export "loopWhile" (func $while/loopWhile))
|
||||
(export "loopWhileInWhile" (func $while/loopWhileInWhile))
|
||||
(export "memory" (memory $0))
|
||||
|
@ -1,7 +1,7 @@
|
||||
(module
|
||||
(type $iv (func (param i32)))
|
||||
(global $HEAP_START i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "loopWhile" (func $while/loopWhile))
|
||||
(export "loopWhileInWhile" (func $while/loopWhileInWhile))
|
||||
(export "memory" (memory $0))
|
||||
@ -84,6 +84,7 @@
|
||||
reinterpret
|
||||
select
|
||||
sizeof
|
||||
changetype
|
||||
isNaN
|
||||
isFinite
|
||||
assert
|
||||
|
Loading…
x
Reference in New Issue
Block a user