mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 23:12:19 +00:00
Cleanup
This commit is contained in:
parent
dc74dd118d
commit
df637164a6
140
src/ast.ts
140
src/ast.ts
@ -351,8 +351,6 @@ export abstract class Expression extends Node {
|
|||||||
(expr.expression = expression).parent = expr;
|
(expr.expression = expression).parent = expr;
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract serializeAsTree(sb: string[], indent: i32): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum LiteralKind {
|
export const enum LiteralKind {
|
||||||
@ -384,20 +382,6 @@ export class ArrayLiteralExpression extends LiteralExpression {
|
|||||||
}
|
}
|
||||||
sb.push("]");
|
sb.push("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent++);
|
|
||||||
sb.push("[\n");
|
|
||||||
for (let i: i32 = 0, k: i32 = this.elementExpressions.length; i < k; ++i) {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
if (i > 0)
|
|
||||||
sb.push(",\n");
|
|
||||||
if (this.elementExpressions[i])
|
|
||||||
(<Expression>this.elementExpressions[i]).serialize(sb);
|
|
||||||
}
|
|
||||||
pushIndent(sb, --indent);
|
|
||||||
sb.push("]");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum AssertionKind {
|
export const enum AssertionKind {
|
||||||
@ -424,24 +408,6 @@ export class AssertionExpression extends Expression {
|
|||||||
this.toType.serialize(sb);
|
this.toType.serialize(sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
if (this.assertionKind == AssertionKind.PREFIX) {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push("<");
|
|
||||||
this.toType.serialize(sb);
|
|
||||||
sb.push(">\n");
|
|
||||||
this.expression.serializeAsTree(sb, indent + 1);
|
|
||||||
} else {
|
|
||||||
this.expression.serializeAsTree(sb, indent + 1);
|
|
||||||
sb.push("\n");
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push("as\n");
|
|
||||||
pushIndent(sb, indent + 1);
|
|
||||||
this.toType.serialize(sb);
|
|
||||||
}
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BinaryExpression extends Expression {
|
export class BinaryExpression extends Expression {
|
||||||
@ -458,14 +424,6 @@ export class BinaryExpression extends Expression {
|
|||||||
sb.push(" ");
|
sb.push(" ");
|
||||||
this.right.serialize(sb);
|
this.right.serialize(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
this.left.serializeAsTree(sb, indent + 1);
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push(operatorTokenToString(this.operator));
|
|
||||||
sb.push("\n");
|
|
||||||
this.right.serializeAsTree(sb, indent + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CallExpression extends Expression {
|
export class CallExpression extends Expression {
|
||||||
@ -495,12 +453,6 @@ export class CallExpression extends Expression {
|
|||||||
}
|
}
|
||||||
sb.push(")");
|
sb.push(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
this.serialize(sb); // not interested in a tree here
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ElementAccessExpression extends Expression {
|
export class ElementAccessExpression extends Expression {
|
||||||
@ -515,15 +467,6 @@ export class ElementAccessExpression extends Expression {
|
|||||||
this.elementExpression.serialize(sb);
|
this.elementExpression.serialize(sb);
|
||||||
sb.push("]");
|
sb.push("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
this.expression.serializeAsTree(sb, indent);
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push("[\n");
|
|
||||||
this.elementExpression.serializeAsTree(sb, indent + 1);
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push("]\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FloatLiteralExpression extends LiteralExpression {
|
export class FloatLiteralExpression extends LiteralExpression {
|
||||||
@ -534,12 +477,6 @@ export class FloatLiteralExpression extends LiteralExpression {
|
|||||||
serialize(sb: string[]): void {
|
serialize(sb: string[]): void {
|
||||||
sb.push(this.value.toString());
|
sb.push(this.value.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
this.serialize(sb);
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IdentifierExpression extends Expression {
|
export class IdentifierExpression extends Expression {
|
||||||
@ -550,12 +487,6 @@ export class IdentifierExpression extends Expression {
|
|||||||
serialize(sb: string[]): void {
|
serialize(sb: string[]): void {
|
||||||
sb.push(this.name);
|
sb.push(this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
this.serialize(sb);
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IntegerLiteralExpression extends LiteralExpression {
|
export class IntegerLiteralExpression extends LiteralExpression {
|
||||||
@ -566,12 +497,6 @@ export class IntegerLiteralExpression extends LiteralExpression {
|
|||||||
serialize(sb: string[]): void {
|
serialize(sb: string[]): void {
|
||||||
sb.push(this.value.toString());
|
sb.push(this.value.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
this.serialize(sb);
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NewExpression extends CallExpression {
|
export class NewExpression extends CallExpression {
|
||||||
@ -582,12 +507,6 @@ export class NewExpression extends CallExpression {
|
|||||||
sb.push("new ");
|
sb.push("new ");
|
||||||
super.serialize(sb);
|
super.serialize(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
this.serialize(sb); // not interested in a tree here
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NullExpression extends IdentifierExpression {
|
export class NullExpression extends IdentifierExpression {
|
||||||
@ -605,14 +524,6 @@ export class ParenthesizedExpression extends Expression {
|
|||||||
this.expression.serialize(sb);
|
this.expression.serialize(sb);
|
||||||
sb.push(")");
|
sb.push(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push("(\n");
|
|
||||||
this.expression.serializeAsTree(sb, indent + 1);
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push(")\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PropertyAccessExpression extends Expression {
|
export class PropertyAccessExpression extends Expression {
|
||||||
@ -626,12 +537,6 @@ export class PropertyAccessExpression extends Expression {
|
|||||||
sb.push(".");
|
sb.push(".");
|
||||||
this.property.serialize(sb);
|
this.property.serialize(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
this.serialize(sb); // not interested in a tree here
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RegexpLiteralExpression extends LiteralExpression {
|
export class RegexpLiteralExpression extends LiteralExpression {
|
||||||
@ -642,12 +547,6 @@ export class RegexpLiteralExpression extends LiteralExpression {
|
|||||||
serialize(sb: string[]): void {
|
serialize(sb: string[]): void {
|
||||||
sb.push(this.value);
|
sb.push(this.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
this.serialize(sb);
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SelectExpression extends Expression {
|
export class SelectExpression extends Expression {
|
||||||
@ -664,16 +563,6 @@ export class SelectExpression extends Expression {
|
|||||||
sb.push(" : ");
|
sb.push(" : ");
|
||||||
this.ifElse.serialize(sb);
|
this.ifElse.serialize(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
this.condition.serializeAsTree(sb, indent + 1);
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push("?\n");
|
|
||||||
this.ifThen.serializeAsTree(sb, indent + 1);
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push(":\n");
|
|
||||||
this.ifElse.serializeAsTree(sb, indent + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StringLiteralExpression extends LiteralExpression {
|
export class StringLiteralExpression extends LiteralExpression {
|
||||||
@ -684,12 +573,6 @@ export class StringLiteralExpression extends LiteralExpression {
|
|||||||
serialize(sb: string[]): void {
|
serialize(sb: string[]): void {
|
||||||
sb.push(JSON.stringify(this.value));
|
sb.push(JSON.stringify(this.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
this.serialize(sb);
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SuperExpression extends IdentifierExpression {
|
export class SuperExpression extends IdentifierExpression {
|
||||||
@ -729,17 +612,6 @@ export class UnaryPostfixExpression extends UnaryExpression {
|
|||||||
default: sb.push("INVALID"); break;
|
default: sb.push("INVALID"); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
this.expression.serializeAsTree(sb, indent + 1);
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
switch (this.operator) {
|
|
||||||
case Token.PLUS_PLUS: sb.push("++"); break;
|
|
||||||
case Token.MINUS_MINUS: sb.push("--"); break;
|
|
||||||
default: sb.push("INVALID"); break;
|
|
||||||
}
|
|
||||||
sb.push("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UnaryPrefixExpression extends UnaryExpression {
|
export class UnaryPrefixExpression extends UnaryExpression {
|
||||||
@ -750,13 +622,6 @@ export class UnaryPrefixExpression extends UnaryExpression {
|
|||||||
sb.push(operatorTokenToString(this.operator));
|
sb.push(operatorTokenToString(this.operator));
|
||||||
this.expression.serialize(sb);
|
this.expression.serialize(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeAsTree(sb: string[], indent: i32 = 0): void {
|
|
||||||
pushIndent(sb, indent);
|
|
||||||
sb.push(operatorTokenToString(this.operator));
|
|
||||||
sb.push("\n");
|
|
||||||
this.expression.serializeAsTree(sb, indent + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// statements
|
// statements
|
||||||
@ -1937,8 +1802,3 @@ function builderEndsWith(sb: string[], code: CharCode): bool {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pushIndent(sb: string[], indent: i32): void {
|
|
||||||
for (let i: i32 = 0; i < indent; ++i)
|
|
||||||
sb.push(" ");
|
|
||||||
}
|
|
||||||
|
313
src/compiler.ts
313
src/compiler.ts
@ -1,6 +1,6 @@
|
|||||||
import { Module, MemorySegment, UnaryOp, BinaryOp, HostOp, Type as BinaryenType, Relooper } from "./binaryen";
|
|
||||||
import { PATH_DELIMITER } from "./constants";
|
import { PATH_DELIMITER } from "./constants";
|
||||||
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter } from "./diagnostics";
|
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter } from "./diagnostics";
|
||||||
|
import { Module, ModuleRef, MemorySegment, ExpressionRef, UnaryOp, BinaryOp, HostOp, NativeType, FunctionTypeRef, FunctionRef, ImportRef, ExportRef, GlobalRef, Relooper } from "./module";
|
||||||
import { Program, ClassPrototype, Class, Element, ElementKind, Enum, FunctionPrototype, Function, Global, Local, Namespace, Parameter } from "./program";
|
import { Program, ClassPrototype, Class, Element, ElementKind, Enum, FunctionPrototype, Function, Global, Local, Namespace, Parameter } from "./program";
|
||||||
import { CharCode, I64, U64, normalizePath, sb } from "./util";
|
import { CharCode, I64, U64, normalizePath, sb } from "./util";
|
||||||
import { Token, Range } from "./tokenizer";
|
import { Token, Range } from "./tokenizer";
|
||||||
@ -77,14 +77,14 @@ import {
|
|||||||
export enum Target {
|
export enum Target {
|
||||||
/** WebAssembly with 32-bit pointers. */
|
/** WebAssembly with 32-bit pointers. */
|
||||||
WASM32,
|
WASM32,
|
||||||
/** WebAssembly with 64-bit pointers. Experimental / not supported by any runtime yet. */
|
/** WebAssembly with 64-bit pointers. Experimental and not supported by any runtime yet. */
|
||||||
WASM64
|
WASM64
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Options {
|
export class Options {
|
||||||
/** WebAssembly target. Defaults to {@link Target.WASM32}. */
|
/** WebAssembly target. Defaults to {@link Target.WASM32}. */
|
||||||
target: Target = Target.WASM32;
|
target: Target = Target.WASM32;
|
||||||
/** If true, performs compilation as usual but doesn't produce any output (all calls to Binaryen become nops). */
|
/** If true, performs compilation as usual but doesn't produce any output (all calls to module become nops). */
|
||||||
noEmit: bool = false;
|
noEmit: bool = false;
|
||||||
/** If true, compiles everything instead of just reachable code. */
|
/** If true, compiles everything instead of just reachable code. */
|
||||||
noTreeShaking: bool = false;
|
noTreeShaking: bool = false;
|
||||||
@ -92,27 +92,40 @@ export class Options {
|
|||||||
|
|
||||||
export class Compiler extends DiagnosticEmitter {
|
export class Compiler extends DiagnosticEmitter {
|
||||||
|
|
||||||
|
/** Program reference. */
|
||||||
program: Program;
|
program: Program;
|
||||||
|
/** Provided options. */
|
||||||
options: Options;
|
options: Options;
|
||||||
|
/** Module instance being compiled. */
|
||||||
module: Module;
|
module: Module;
|
||||||
|
|
||||||
|
/** Start function being compiled. */
|
||||||
startFunction: Function;
|
startFunction: Function;
|
||||||
startFunctionBody: BinaryenExpressionRef[] = new Array();
|
/** Start function expressions. */
|
||||||
|
startFunctionBody: ExpressionRef[] = new Array();
|
||||||
|
|
||||||
|
/** Current type in compilation. */
|
||||||
currentType: Type = Type.void;
|
currentType: Type = Type.void;
|
||||||
|
/** Current function in compilation. */
|
||||||
currentFunction: Function;
|
currentFunction: Function;
|
||||||
|
/** Marker indicating whether continue statements are allowed in the current break context. */
|
||||||
disallowContinue: bool = true;
|
disallowContinue: bool = true;
|
||||||
|
|
||||||
|
/** Counting memory offset. */
|
||||||
memoryOffset: U64 = new U64(8, 0); // leave space for (any size of) NULL
|
memoryOffset: U64 = new U64(8, 0); // leave space for (any size of) NULL
|
||||||
|
/** Memory segments being compiled. */
|
||||||
memorySegments: MemorySegment[] = new Array();
|
memorySegments: MemorySegment[] = new Array();
|
||||||
|
|
||||||
|
/** Already processed file names. */
|
||||||
files: Set<string> = new Set();
|
files: Set<string> = new Set();
|
||||||
|
|
||||||
|
/** Compiles a {@link Program} to a {@link Module} using the specified options. */
|
||||||
static compile(program: Program, options: Options | null = null): Module {
|
static compile(program: Program, options: Options | null = null): Module {
|
||||||
const compiler: Compiler = new Compiler(program, options);
|
const compiler: Compiler = new Compiler(program, options);
|
||||||
return compiler.compile();
|
return compiler.compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Constructs a new compiler for a {@link Program} using the specified options. */
|
||||||
constructor(program: Program, options: Options | null = null) {
|
constructor(program: Program, options: Options | null = null) {
|
||||||
super(program.diagnostics);
|
super(program.diagnostics);
|
||||||
this.program = program;
|
this.program = program;
|
||||||
@ -124,6 +137,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
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(2 * (this.options.target == Target.WASM64 ? 8 : 4), 0); // leave space for `null` and heapStart (both of usize type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Performs compilation of the underlying {@link Program} to a {@link Module}. */
|
||||||
compile(): Module {
|
compile(): Module {
|
||||||
const program: Program = this.program;
|
const program: Program = this.program;
|
||||||
|
|
||||||
@ -141,11 +155,11 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// make start function if not empty
|
// make start function if not empty
|
||||||
if (this.startFunctionBody.length) {
|
if (this.startFunctionBody.length) {
|
||||||
let typeRef: BinaryenFunctionTypeRef = this.module.getFunctionTypeBySignature(BinaryenType.None, []);
|
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(NativeType.None, []);
|
||||||
if (!typeRef)
|
if (!typeRef)
|
||||||
typeRef = this.module.addFunctionType("v", BinaryenType.None, []);
|
typeRef = this.module.addFunctionType("v", NativeType.None, []);
|
||||||
this.module.setStart(
|
this.module.setStart(
|
||||||
this.module.addFunction(this.startFunction.template.internalName, typeRef, typesToBinaryenTypes(this.startFunction.additionalLocals), this.module.createBlock(null, this.startFunctionBody))
|
this.module.addFunction(this.startFunction.template.internalName, typeRef, typesToNativeTypes(this.startFunction.additionalLocals), this.module.createBlock(null, this.startFunctionBody))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,8 +299,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return false;
|
return false;
|
||||||
element.type = type;
|
element.type = type;
|
||||||
}
|
}
|
||||||
const binaryenType: BinaryenType = typeToBinaryenType(<Type>type);
|
const nativeType: NativeType = typeToNativeType(<Type>type);
|
||||||
let initializer: BinaryenExpressionRef;
|
let initializer: ExpressionRef;
|
||||||
let initializeInStart: bool;
|
let initializeInStart: bool;
|
||||||
if (element.hasConstantValue) {
|
if (element.hasConstantValue) {
|
||||||
if (type.isLongInteger)
|
if (type.isLongInteger)
|
||||||
@ -304,23 +318,23 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
} else
|
} else
|
||||||
initializer = this.module.createI32(element.constantIntegerValue ? element.constantIntegerValue.toI32() : 0);
|
initializer = this.module.createI32(element.constantIntegerValue ? element.constantIntegerValue.toI32() : 0);
|
||||||
initializeInStart = false;
|
initializeInStart = false;
|
||||||
this.module.addGlobal(element.internalName, binaryenType, element.isMutable, initializer);
|
this.module.addGlobal(element.internalName, nativeType, element.isMutable, initializer);
|
||||||
} else if (declaration) {
|
} else if (declaration) {
|
||||||
if (declaration.initializer) {
|
if (declaration.initializer) {
|
||||||
initializer = this.compileExpression(declaration.initializer, type);
|
initializer = this.compileExpression(declaration.initializer, type);
|
||||||
initializeInStart = declaration.initializer.kind != NodeKind.LITERAL; // MVP doesn't support complex initializers
|
initializeInStart = declaration.initializer.kind != NodeKind.LITERAL; // MVP doesn't support complex initializers
|
||||||
} else {
|
} else {
|
||||||
initializer = typeToBinaryenZero(this.module, type);
|
initializer = typeToNativeZero(this.module, type);
|
||||||
initializeInStart = false;
|
initializeInStart = false;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
throw new Error("unexpected missing declaration or constant value");
|
throw new Error("unexpected missing declaration or constant value");
|
||||||
const internalName: string = element.internalName;
|
const internalName: string = element.internalName;
|
||||||
if (initializeInStart) {
|
if (initializeInStart) {
|
||||||
this.module.addGlobal(internalName, BinaryenType.I32, true, this.module.createI32(-1));
|
this.module.addGlobal(internalName, NativeType.I32, true, this.module.createI32(-1));
|
||||||
this.startFunctionBody.push(this.module.createSetGlobal(internalName, initializer));
|
this.startFunctionBody.push(this.module.createSetGlobal(internalName, initializer));
|
||||||
} else
|
} else
|
||||||
this.module.addGlobal(internalName, BinaryenType.I32, element.isMutable, initializer);
|
this.module.addGlobal(internalName, NativeType.I32, element.isMutable, initializer);
|
||||||
return element.compiled = true;
|
return element.compiled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,10 +354,10 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let previousInternalName: string | null = null;
|
let previousInternalName: string | null = null;
|
||||||
for (let [key, val] of element.members) {
|
for (let [key, val] of element.members) {
|
||||||
if (val.hasConstantValue) {
|
if (val.hasConstantValue) {
|
||||||
this.module.addGlobal(val.internalName, BinaryenType.I32, false, this.module.createI32(val.constantValue));
|
this.module.addGlobal(val.internalName, NativeType.I32, false, this.module.createI32(val.constantValue));
|
||||||
} else if (val.declaration) {
|
} else if (val.declaration) {
|
||||||
const declaration: EnumValueDeclaration = val.declaration;
|
const declaration: EnumValueDeclaration = val.declaration;
|
||||||
let initializer: BinaryenExpressionRef;
|
let initializer: ExpressionRef;
|
||||||
let initializeInStart: bool = false;
|
let initializeInStart: bool = false;
|
||||||
if (declaration.value) {
|
if (declaration.value) {
|
||||||
initializer = this.compileExpression(<Expression>declaration.value, Type.i32);
|
initializer = this.compileExpression(<Expression>declaration.value, Type.i32);
|
||||||
@ -353,16 +367,16 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
initializeInStart = false;
|
initializeInStart = false;
|
||||||
} else {
|
} else {
|
||||||
initializer = this.module.createBinary(BinaryOp.AddI32,
|
initializer = this.module.createBinary(BinaryOp.AddI32,
|
||||||
this.module.createGetGlobal(previousInternalName, BinaryenType.I32),
|
this.module.createGetGlobal(previousInternalName, NativeType.I32),
|
||||||
this.module.createI32(1)
|
this.module.createI32(1)
|
||||||
);
|
);
|
||||||
initializeInStart = true;
|
initializeInStart = true;
|
||||||
}
|
}
|
||||||
if (initializeInStart) {
|
if (initializeInStart) {
|
||||||
this.module.addGlobal(val.internalName, BinaryenType.I32, true, this.module.createI32(-1));
|
this.module.addGlobal(val.internalName, NativeType.I32, true, this.module.createI32(-1));
|
||||||
this.startFunctionBody.push(this.module.createSetGlobal(val.internalName, initializer));
|
this.startFunctionBody.push(this.module.createSetGlobal(val.internalName, initializer));
|
||||||
} else
|
} else
|
||||||
this.module.addGlobal(val.internalName, BinaryenType.I32, false, initializer);
|
this.module.addGlobal(val.internalName, NativeType.I32, false, initializer);
|
||||||
} else
|
} else
|
||||||
throw new Error("unexpected missing declaration or constant value");
|
throw new Error("unexpected missing declaration or constant value");
|
||||||
previousInternalName = val.internalName;
|
previousInternalName = val.internalName;
|
||||||
@ -403,24 +417,24 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// compile statements
|
// compile statements
|
||||||
const previousFunction: Function = this.currentFunction;
|
const previousFunction: Function = this.currentFunction;
|
||||||
this.currentFunction = instance;
|
this.currentFunction = instance;
|
||||||
const stmts: BinaryenExpressionRef[] = this.compileStatements(<Statement[]>declaration.statements);
|
const stmts: ExpressionRef[] = this.compileStatements(<Statement[]>declaration.statements);
|
||||||
this.currentFunction = previousFunction;
|
this.currentFunction = previousFunction;
|
||||||
|
|
||||||
// create the function
|
// create the function
|
||||||
let k: i32 = instance.parameters.length;
|
let k: i32 = instance.parameters.length;
|
||||||
const binaryenResultType: BinaryenType = typeToBinaryenType(instance.returnType);
|
const binaryenResultType: NativeType = typeToNativeType(instance.returnType);
|
||||||
const binaryenParamTypes: BinaryenType[] = new Array(k);
|
const binaryenParamTypes: NativeType[] = new Array(k);
|
||||||
const signatureNameParts: string[] = new Array(k + 1);
|
const signatureNameParts: string[] = new Array(k + 1);
|
||||||
for (let i: i32 = 0; i < k; ++i) {
|
for (let i: i32 = 0; i < k; ++i) {
|
||||||
binaryenParamTypes[i] = typeToBinaryenType(instance.parameters[i].type);
|
binaryenParamTypes[i] = typeToNativeType(instance.parameters[i].type);
|
||||||
signatureNameParts[i] = typeToSignatureNamePart(instance.parameters[i].type);
|
signatureNameParts[i] = typeToSignatureNamePart(instance.parameters[i].type);
|
||||||
}
|
}
|
||||||
signatureNameParts[k] = typeToSignatureNamePart(instance.returnType);
|
signatureNameParts[k] = typeToSignatureNamePart(instance.returnType);
|
||||||
let binaryenTypeRef: BinaryenFunctionTypeRef = this.module.getFunctionTypeBySignature(binaryenResultType, binaryenParamTypes);
|
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(binaryenResultType, binaryenParamTypes);
|
||||||
if (!binaryenTypeRef)
|
if (!typeRef)
|
||||||
binaryenTypeRef = this.module.addFunctionType(signatureNameParts.join(""), binaryenResultType, binaryenParamTypes);
|
typeRef = this.module.addFunctionType(signatureNameParts.join(""), binaryenResultType, binaryenParamTypes);
|
||||||
const internalName: string = instance.internalName;
|
const internalName: string = instance.internalName;
|
||||||
this.module.addFunction(internalName, binaryenTypeRef, typesToBinaryenTypes(instance.additionalLocals), this.module.createBlock(null, stmts, BinaryenType.None));
|
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, stmts, NativeType.None));
|
||||||
if (instance.globalExportName != null)
|
if (instance.globalExportName != null)
|
||||||
this.module.addExport(internalName, <string>instance.globalExportName);
|
this.module.addExport(internalName, <string>instance.globalExportName);
|
||||||
}
|
}
|
||||||
@ -583,7 +597,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// statements
|
// statements
|
||||||
|
|
||||||
compileStatement(statement: Statement): BinaryenExpressionRef {
|
compileStatement(statement: Statement): ExpressionRef {
|
||||||
switch (statement.kind) {
|
switch (statement.kind) {
|
||||||
|
|
||||||
case NodeKind.BLOCK:
|
case NodeKind.BLOCK:
|
||||||
@ -631,19 +645,19 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
throw new Error("unexpected statement kind");
|
throw new Error("unexpected statement kind");
|
||||||
}
|
}
|
||||||
|
|
||||||
compileStatements(statements: Statement[]): BinaryenExpressionRef[] {
|
compileStatements(statements: Statement[]): ExpressionRef[] {
|
||||||
const k: i32 = statements.length;
|
const k: i32 = statements.length;
|
||||||
const stmts: BinaryenExpressionRef[] = new Array(k);
|
const stmts: ExpressionRef[] = new Array(k);
|
||||||
for (let i: i32 = 0; i < k; ++i)
|
for (let i: i32 = 0; i < k; ++i)
|
||||||
stmts[i] = this.compileStatement(statements[i]);
|
stmts[i] = this.compileStatement(statements[i]);
|
||||||
return stmts;
|
return stmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileBlockStatement(statement: BlockStatement): BinaryenExpressionRef {
|
compileBlockStatement(statement: BlockStatement): ExpressionRef {
|
||||||
return this.module.createBlock(null, this.compileStatements(statement.statements), BinaryenType.None);
|
return this.module.createBlock(null, this.compileStatements(statement.statements), NativeType.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileBreakStatement(statement: BreakStatement): BinaryenExpressionRef {
|
compileBreakStatement(statement: BreakStatement): ExpressionRef {
|
||||||
if (statement.label)
|
if (statement.label)
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
const context: string | null = this.currentFunction.breakContext;
|
const context: string | null = this.currentFunction.breakContext;
|
||||||
@ -653,7 +667,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
compileContinueStatement(statement: ContinueStatement): BinaryenExpressionRef {
|
compileContinueStatement(statement: ContinueStatement): ExpressionRef {
|
||||||
if (statement.label)
|
if (statement.label)
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
const context: string | null = this.currentFunction.breakContext;
|
const context: string | null = this.currentFunction.breakContext;
|
||||||
@ -663,10 +677,10 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
compileDoStatement(statement: DoStatement): BinaryenExpressionRef {
|
compileDoStatement(statement: DoStatement): ExpressionRef {
|
||||||
const label: string = this.currentFunction.enterBreakContext();
|
const label: string = this.currentFunction.enterBreakContext();
|
||||||
const condition: BinaryenExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
const condition: ExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||||
const body: BinaryenExpressionRef = this.compileStatement(statement.statement);
|
const body: ExpressionRef = this.compileStatement(statement.statement);
|
||||||
this.currentFunction.leaveBreakContext();
|
this.currentFunction.leaveBreakContext();
|
||||||
const breakLabel: string = "break$" + label;
|
const breakLabel: string = "break$" + label;
|
||||||
const continueLabel: string = "continue$" + label;
|
const continueLabel: string = "continue$" + label;
|
||||||
@ -675,24 +689,24 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
this.module.createBlock(null, [
|
this.module.createBlock(null, [
|
||||||
body,
|
body,
|
||||||
this.module.createBreak(continueLabel, condition)
|
this.module.createBreak(continueLabel, condition)
|
||||||
], BinaryenType.None))
|
], NativeType.None))
|
||||||
], BinaryenType.None);
|
], NativeType.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileEmptyStatement(statement: EmptyStatement): BinaryenExpressionRef {
|
compileEmptyStatement(statement: EmptyStatement): ExpressionRef {
|
||||||
return this.module.createNop();
|
return this.module.createNop();
|
||||||
}
|
}
|
||||||
|
|
||||||
compileExpressionStatement(statement: ExpressionStatement): BinaryenExpressionRef {
|
compileExpressionStatement(statement: ExpressionStatement): ExpressionRef {
|
||||||
return this.compileExpression(statement.expression, Type.void);
|
return this.compileExpression(statement.expression, Type.void);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileForStatement(statement: ForStatement): BinaryenExpressionRef {
|
compileForStatement(statement: ForStatement): ExpressionRef {
|
||||||
const context: string = this.currentFunction.enterBreakContext();
|
const context: string = this.currentFunction.enterBreakContext();
|
||||||
const initializer: BinaryenExpressionRef = statement.initializer ? this.compileStatement(<Statement>statement.initializer) : this.module.createNop();
|
const initializer: ExpressionRef = statement.initializer ? this.compileStatement(<Statement>statement.initializer) : this.module.createNop();
|
||||||
const condition: BinaryenExpressionRef = statement.condition ? this.compileExpression(<Expression>statement.condition, Type.i32) : this.module.createI32(1);
|
const condition: ExpressionRef = statement.condition ? this.compileExpression(<Expression>statement.condition, Type.i32) : this.module.createI32(1);
|
||||||
const incrementor: BinaryenExpressionRef = statement.incrementor ? this.compileExpression(<Expression>statement.incrementor, Type.void) : this.module.createNop();
|
const incrementor: ExpressionRef = statement.incrementor ? this.compileExpression(<Expression>statement.incrementor, Type.void) : this.module.createNop();
|
||||||
const body: BinaryenExpressionRef = this.compileStatement(statement.statement);
|
const body: ExpressionRef = this.compileStatement(statement.statement);
|
||||||
this.currentFunction.leaveBreakContext();
|
this.currentFunction.leaveBreakContext();
|
||||||
const continueLabel: string = "continue$" + context;
|
const continueLabel: string = "continue$" + context;
|
||||||
const breakLabel: string = "break$" + context;
|
const breakLabel: string = "break$" + context;
|
||||||
@ -703,27 +717,27 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
body,
|
body,
|
||||||
incrementor,
|
incrementor,
|
||||||
this.module.createBreak(continueLabel)
|
this.module.createBreak(continueLabel)
|
||||||
], BinaryenType.None))
|
], NativeType.None))
|
||||||
], BinaryenType.None))
|
], NativeType.None))
|
||||||
], BinaryenType.None);
|
], NativeType.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileIfStatement(statement: IfStatement): BinaryenExpressionRef {
|
compileIfStatement(statement: IfStatement): ExpressionRef {
|
||||||
const condition: BinaryenExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
const condition: ExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||||
const ifTrue: BinaryenExpressionRef = this.compileStatement(statement.statement);
|
const ifTrue: ExpressionRef = this.compileStatement(statement.statement);
|
||||||
const ifFalse: BinaryenExpressionRef = statement.elseStatement ? this.compileStatement(<Statement>statement.elseStatement) : 0;
|
const ifFalse: ExpressionRef = statement.elseStatement ? this.compileStatement(<Statement>statement.elseStatement) : 0;
|
||||||
return this.module.createIf(condition, ifTrue, ifFalse);
|
return this.module.createIf(condition, ifTrue, ifFalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileReturnStatement(statement: ReturnStatement): BinaryenExpressionRef {
|
compileReturnStatement(statement: ReturnStatement): ExpressionRef {
|
||||||
if (this.currentFunction) {
|
if (this.currentFunction) {
|
||||||
const expression: BinaryenExpressionRef = statement.expression ? this.compileExpression(<Expression>statement.expression, this.currentFunction.returnType) : 0;
|
const expression: ExpressionRef = statement.expression ? this.compileExpression(<Expression>statement.expression, this.currentFunction.returnType) : 0;
|
||||||
return this.module.createReturn(expression);
|
return this.module.createReturn(expression);
|
||||||
}
|
}
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
compileSwitchStatement(statement: SwitchStatement): BinaryenExpressionRef {
|
compileSwitchStatement(statement: SwitchStatement): ExpressionRef {
|
||||||
const context: string = this.currentFunction.enterBreakContext();
|
const context: string = this.currentFunction.enterBreakContext();
|
||||||
const previousDisallowContinue: bool = this.disallowContinue;
|
const previousDisallowContinue: bool = this.disallowContinue;
|
||||||
this.disallowContinue = true;
|
this.disallowContinue = true;
|
||||||
@ -733,18 +747,18 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let i: i32, k: i32 = statement.cases.length;
|
let i: i32, k: i32 = statement.cases.length;
|
||||||
|
|
||||||
// prepend initializer to inner block
|
// prepend initializer to inner block
|
||||||
const breaks: BinaryenExpressionRef[] = new Array(1 + k);
|
const breaks: ExpressionRef[] = new Array(1 + k);
|
||||||
breaks[0] = this.module.createSetLocal(local.index, this.compileExpression(statement.expression, Type.i32)); // initializer
|
breaks[0] = this.module.createSetLocal(local.index, this.compileExpression(statement.expression, Type.i32)); // initializer
|
||||||
|
|
||||||
// make one br_if per (possibly dynamic) labeled case
|
// make one br_if per (possibly dynamic) labeled case
|
||||||
// TODO: take advantage of br_table where labels are known to be (sequential) constant (ideally Binaryen's optimizer would)
|
// TODO: take advantage of br_table where labels are known to be (sequential) constant (ideally the optimizer would)
|
||||||
let breakIndex: i32 = 1;
|
let breakIndex: i32 = 1;
|
||||||
let defaultIndex: i32 = -1;
|
let defaultIndex: i32 = -1;
|
||||||
for (i = 0; i < k; ++i) {
|
for (i = 0; i < k; ++i) {
|
||||||
const case_: SwitchCase = statement.cases[i];
|
const case_: SwitchCase = statement.cases[i];
|
||||||
if (case_.label) {
|
if (case_.label) {
|
||||||
breaks[breakIndex++] = this.module.createBreak("case" + i.toString(10) + "$" + context, this.module.createBinary(BinaryOp.EqI32,
|
breaks[breakIndex++] = this.module.createBreak("case" + i.toString(10) + "$" + context, this.module.createBinary(BinaryOp.EqI32,
|
||||||
this.module.createGetLocal(local.index, BinaryenType.I32),
|
this.module.createGetLocal(local.index, NativeType.I32),
|
||||||
this.compileExpression(case_.label, Type.i32)
|
this.compileExpression(case_.label, Type.i32)
|
||||||
));
|
));
|
||||||
} else
|
} else
|
||||||
@ -758,18 +772,18 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
) + "$" + context);
|
) + "$" + context);
|
||||||
|
|
||||||
// nest blocks in order
|
// nest blocks in order
|
||||||
let currentBlock: BinaryenExpressionRef = this.module.createBlock("case0$" + context, breaks, BinaryenType.None);
|
let currentBlock: ExpressionRef = this.module.createBlock("case0$" + context, breaks, NativeType.None);
|
||||||
for (i = 0; i < k; ++i) {
|
for (i = 0; i < k; ++i) {
|
||||||
const case_: SwitchCase = statement.cases[i];
|
const case_: SwitchCase = statement.cases[i];
|
||||||
const nextLabel: string = i == k - 1
|
const nextLabel: string = i == k - 1
|
||||||
? "break$" + context
|
? "break$" + context
|
||||||
: "case" + (i + 1).toString(10) + "$" + context;
|
: "case" + (i + 1).toString(10) + "$" + context;
|
||||||
const l: i32 = case_.statements.length;
|
const l: i32 = case_.statements.length;
|
||||||
const body: BinaryenExpressionRef[] = new Array(1 + l);
|
const body: ExpressionRef[] = new Array(1 + l);
|
||||||
body[0] = currentBlock;
|
body[0] = currentBlock;
|
||||||
for (let j: i32 = 0; j < l; ++j)
|
for (let j: i32 = 0; j < l; ++j)
|
||||||
body[j + 1] = this.compileStatement(case_.statements[j]);
|
body[j + 1] = this.compileStatement(case_.statements[j]);
|
||||||
currentBlock = this.module.createBlock(nextLabel, body, BinaryenType.None);
|
currentBlock = this.module.createBlock(nextLabel, body, NativeType.None);
|
||||||
}
|
}
|
||||||
this.currentFunction.leaveBreakContext();
|
this.currentFunction.leaveBreakContext();
|
||||||
this.disallowContinue = previousDisallowContinue;
|
this.disallowContinue = previousDisallowContinue;
|
||||||
@ -777,17 +791,17 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return currentBlock;
|
return currentBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileThrowStatement(statement: ThrowStatement): BinaryenExpressionRef {
|
compileThrowStatement(statement: ThrowStatement): ExpressionRef {
|
||||||
return this.module.createUnreachable(); // TODO: waiting for exception-handling spec
|
return this.module.createUnreachable(); // TODO: waiting for exception-handling spec
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTryStatement(statement: TryStatement): BinaryenExpressionRef {
|
compileTryStatement(statement: TryStatement): ExpressionRef {
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
// can't yet support something like: try { return ... } finally { ... }
|
// can't yet support something like: try { return ... } finally { ... }
|
||||||
// worthwhile to investigate lowering returns to block results (here)?
|
// worthwhile to investigate lowering returns to block results (here)?
|
||||||
}
|
}
|
||||||
|
|
||||||
compileVariableStatement(statement: VariableStatement): BinaryenExpressionRef {
|
compileVariableStatement(statement: VariableStatement): ExpressionRef {
|
||||||
const declarations: VariableDeclaration[] = statement.declarations;
|
const declarations: VariableDeclaration[] = statement.declarations;
|
||||||
|
|
||||||
// top-level variables become globals
|
// top-level variables become globals
|
||||||
@ -798,7 +812,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createNop();
|
return this.module.createNop();
|
||||||
}
|
}
|
||||||
// other variables become locals
|
// other variables become locals
|
||||||
const initializers: BinaryenExpressionRef[] = new Array();
|
const initializers: ExpressionRef[] = new Array();
|
||||||
for (let i: i32 = 0, k = declarations.length; i < k; ++i) {
|
for (let i: i32 = 0, k = declarations.length; i < k; ++i) {
|
||||||
const declaration: VariableDeclaration = declarations[i];
|
const declaration: VariableDeclaration = declarations[i];
|
||||||
if (declaration.type) {
|
if (declaration.type) {
|
||||||
@ -814,32 +828,32 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return initializers.length ? this.module.createBlock(null, initializers, BinaryenType.None) : this.module.createNop();
|
return initializers.length ? this.module.createBlock(null, initializers, NativeType.None) : this.module.createNop();
|
||||||
}
|
}
|
||||||
|
|
||||||
compileWhileStatement(statement: WhileStatement): BinaryenExpressionRef {
|
compileWhileStatement(statement: WhileStatement): ExpressionRef {
|
||||||
const label: string = this.currentFunction.enterBreakContext();
|
const label: string = this.currentFunction.enterBreakContext();
|
||||||
const condition: BinaryenExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
const condition: ExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||||
const breakLabel: string = "break$" + label;
|
const breakLabel: string = "break$" + label;
|
||||||
const continueLabel: string = "continue$" + label;
|
const continueLabel: string = "continue$" + label;
|
||||||
const body: BinaryenExpressionRef = this.compileStatement(statement.statement);
|
const body: ExpressionRef = this.compileStatement(statement.statement);
|
||||||
this.currentFunction.leaveBreakContext();
|
this.currentFunction.leaveBreakContext();
|
||||||
return this.module.createBlock(breakLabel, [
|
return this.module.createBlock(breakLabel, [
|
||||||
this.module.createLoop(continueLabel,
|
this.module.createLoop(continueLabel,
|
||||||
this.module.createIf(condition, this.module.createBlock(null, [
|
this.module.createIf(condition, this.module.createBlock(null, [
|
||||||
body,
|
body,
|
||||||
this.module.createBreak(continueLabel)
|
this.module.createBreak(continueLabel)
|
||||||
], BinaryenType.None))
|
], NativeType.None))
|
||||||
)
|
)
|
||||||
], BinaryenType.None);
|
], NativeType.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// expressions
|
// expressions
|
||||||
|
|
||||||
compileExpression(expression: Expression, contextualType: Type, convert: bool = true): BinaryenExpressionRef {
|
compileExpression(expression: Expression, contextualType: Type, convert: bool = true): ExpressionRef {
|
||||||
this.currentType = contextualType;
|
this.currentType = contextualType;
|
||||||
|
|
||||||
let expr: BinaryenExpressionRef;
|
let expr: ExpressionRef;
|
||||||
switch (expression.kind) {
|
switch (expression.kind) {
|
||||||
|
|
||||||
case NodeKind.ASSERTION:
|
case NodeKind.ASSERTION:
|
||||||
@ -906,7 +920,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
convertExpression(expr: BinaryenExpressionRef, fromType: Type, toType: Type): BinaryenExpressionRef {
|
convertExpression(expr: ExpressionRef, fromType: Type, toType: Type): ExpressionRef {
|
||||||
|
|
||||||
// void to any
|
// void to any
|
||||||
if (fromType.kind == TypeKind.VOID)
|
if (fromType.kind == TypeKind.VOID)
|
||||||
@ -1059,19 +1073,19 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileAssertionExpression(expression: AssertionExpression, contextualType: Type): BinaryenExpressionRef {
|
compileAssertionExpression(expression: AssertionExpression, contextualType: Type): ExpressionRef {
|
||||||
const toType: Type | null = this.program.resolveType(expression.toType, this.currentFunction.contextualTypeArguments); // reports
|
const toType: Type | null = this.program.resolveType(expression.toType, this.currentFunction.contextualTypeArguments); // reports
|
||||||
if (toType && toType != contextualType) {
|
if (toType && toType != contextualType) {
|
||||||
const expr: BinaryenExpressionRef = this.compileExpression(expression.expression, <Type>toType, false);
|
const expr: ExpressionRef = this.compileExpression(expression.expression, <Type>toType, false);
|
||||||
return this.convertExpression(expr, this.currentType, <Type>toType);
|
return this.convertExpression(expr, this.currentType, <Type>toType);
|
||||||
}
|
}
|
||||||
return this.compileExpression(expression.expression, contextualType);
|
return this.compileExpression(expression.expression, contextualType);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileBinaryExpression(expression: BinaryExpression, contextualType: Type): BinaryenExpressionRef {
|
compileBinaryExpression(expression: BinaryExpression, contextualType: Type): ExpressionRef {
|
||||||
let op: BinaryOp;
|
let op: BinaryOp;
|
||||||
let left: BinaryenExpressionRef;
|
let left: ExpressionRef;
|
||||||
let right: BinaryenExpressionRef;
|
let right: ExpressionRef;
|
||||||
let compound: Token = 0;
|
let compound: Token = 0;
|
||||||
|
|
||||||
switch (expression.operator) {
|
switch (expression.operator) {
|
||||||
@ -1287,12 +1301,12 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createBinary(op, left, right);
|
return this.module.createBinary(op, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileAssignment(expression: Expression, valueExpression: Expression, contextualType: Type): BinaryenExpressionRef {
|
compileAssignment(expression: Expression, valueExpression: Expression, contextualType: Type): ExpressionRef {
|
||||||
this.currentType = this.determineExpressionType(expression, contextualType);
|
this.currentType = this.determineExpressionType(expression, contextualType);
|
||||||
return this.compileAssignmentWithValue(expression, this.compileExpression(valueExpression, this.currentType), contextualType != Type.void);
|
return this.compileAssignmentWithValue(expression, this.compileExpression(valueExpression, this.currentType), contextualType != Type.void);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileAssignmentWithValue(expression: Expression, valueWithCorrectType: BinaryenExpressionRef, tee: bool = false): BinaryenExpressionRef {
|
compileAssignmentWithValue(expression: Expression, valueWithCorrectType: ExpressionRef, tee: bool = false): ExpressionRef {
|
||||||
const element: Element | null = this.program.resolveElement(expression, this.currentFunction);
|
const element: Element | null = this.program.resolveElement(expression, this.currentFunction);
|
||||||
if (!element)
|
if (!element)
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
@ -1307,12 +1321,12 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
if (element.kind == ElementKind.GLOBAL && (<Global>element).type) {
|
if (element.kind == ElementKind.GLOBAL && (<Global>element).type) {
|
||||||
if (tee) {
|
if (tee) {
|
||||||
const globalBinaryenType: BinaryenType = typeToBinaryenType(<Type>(<Global>element).type);
|
const globalNativeType: NativeType = typeToNativeType(<Type>(<Global>element).type);
|
||||||
this.currentType = <Type>(<Global>element).type;
|
this.currentType = <Type>(<Global>element).type;
|
||||||
return this.module.createBlock(null, [ // teeGlobal
|
return this.module.createBlock(null, [ // teeGlobal
|
||||||
this.module.createSetGlobal((<Global>element).internalName, valueWithCorrectType),
|
this.module.createSetGlobal((<Global>element).internalName, valueWithCorrectType),
|
||||||
this.module.createGetGlobal((<Global>element).internalName, globalBinaryenType)
|
this.module.createGetGlobal((<Global>element).internalName, globalNativeType)
|
||||||
], globalBinaryenType);
|
], globalNativeType);
|
||||||
}
|
}
|
||||||
return this.module.createSetGlobal((<Global>element).internalName, valueWithCorrectType);
|
return this.module.createSetGlobal((<Global>element).internalName, valueWithCorrectType);
|
||||||
}
|
}
|
||||||
@ -1322,7 +1336,17 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
compileCallExpression(expression: CallExpression, contextualType: Type): BinaryenExpressionRef {
|
compileCallExpression(expression: CallExpression, contextualType: Type): ExpressionRef {
|
||||||
|
// TODO
|
||||||
|
/* const callee: Expression = expression.expression;
|
||||||
|
switch (callee.kind) {
|
||||||
|
case NodeKind.THIS:
|
||||||
|
// use current class
|
||||||
|
case NodeKind.PROPERTYACCESS:
|
||||||
|
// compile, use class in currentType?
|
||||||
|
case NodeKind.IDENTIFIER:
|
||||||
|
// lookup identifier?
|
||||||
|
} */
|
||||||
const element: Element | null = this.program.resolveElement(expression.expression, this.currentFunction); // reports
|
const element: Element | null = this.program.resolveElement(expression.expression, this.currentFunction); // reports
|
||||||
if (!element)
|
if (!element)
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
@ -1336,40 +1360,57 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
compileCall(functionInstance: Function, argumentExpressions: Expression[], reportNode: Node): BinaryenExpressionRef {
|
/** Compiles a call to a function. If an instance method, `this` is the first element in `argumentExpressions`. */
|
||||||
|
compileCall(functionInstance: Function, argumentExpressions: Expression[], reportNode: Node): ExpressionRef {
|
||||||
|
// when called, the function is considered reachable -> compile
|
||||||
if (!functionInstance.compiled)
|
if (!functionInstance.compiled)
|
||||||
this.compileFunction(functionInstance);
|
this.compileFunction(functionInstance);
|
||||||
|
|
||||||
|
// validate and compile arguments
|
||||||
const parameters: Parameter[] = functionInstance.parameters;
|
const parameters: Parameter[] = functionInstance.parameters;
|
||||||
let k: i32 = parameters.length;
|
const parameterCount: i32 = parameters.length;
|
||||||
if (argumentExpressions.length > k) {
|
const argumentCount: i32 = argumentExpressions.length;
|
||||||
this.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, k.toString(10), argumentExpressions.length.toString(10));
|
if (argumentExpressions.length > parameterCount) { // too many arguments
|
||||||
|
this.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range,
|
||||||
|
(functionInstance.isInstance ? parameterCount - 1 : parameterCount).toString(10),
|
||||||
|
(functionInstance.isInstance ? argumentCount - 1 : argumentCount).toString(10)
|
||||||
|
);
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
const operands: BinaryenExpressionRef[] = new Array(k);
|
const operands: ExpressionRef[] = new Array(parameterCount);
|
||||||
for (let i: i32 = 0; i < k; ++i) {
|
for (let i: i32 = 0; i < parameterCount; ++i) {
|
||||||
if (argumentExpressions.length > i) {
|
if (argumentExpressions.length > i) {
|
||||||
operands[i] = this.compileExpression(argumentExpressions[i], parameters[i].type);
|
operands[i] = this.compileExpression(argumentExpressions[i], parameters[i].type, true);
|
||||||
} else {
|
} else {
|
||||||
const initializer: Expression | null = parameters[i].initializer;
|
const initializer: Expression | null = parameters[i].initializer;
|
||||||
if (initializer) {
|
if (initializer) { // omitted, uses initializer
|
||||||
|
// FIXME: here, the initializer is compiled in the caller's scope.
|
||||||
|
// a solution could be to use a stub for each possible overload, calling the
|
||||||
|
// full function with optional arguments being part of the stub's body.
|
||||||
operands[i] = this.compileExpression(initializer, parameters[i].type);
|
operands[i] = this.compileExpression(initializer, parameters[i].type);
|
||||||
} else {
|
} else { // too few arguments
|
||||||
this.error(DiagnosticCode.Expected_at_least_0_arguments_but_got_1, reportNode.range, (i + 1).toString(10), argumentExpressions.length.toString(10));
|
this.error(DiagnosticCode.Expected_at_least_0_arguments_but_got_1, reportNode.range,
|
||||||
|
(functionInstance.isInstance ? i : i + 1).toString(10),
|
||||||
|
(functionInstance.isInstance ? argumentCount - 1 : argumentCount).toString(10)
|
||||||
|
);
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.module.createCall(functionInstance.internalName, operands, typeToBinaryenType(functionInstance.returnType));
|
|
||||||
|
// finally compile the call
|
||||||
|
this.currentType = functionInstance.returnType;
|
||||||
|
return this.module.createCall(functionInstance.internalName, operands, typeToNativeType(functionInstance.returnType));
|
||||||
}
|
}
|
||||||
|
|
||||||
compileElementAccessExpression(expression: ElementAccessExpression, contextualType: Type): BinaryenExpressionRef {
|
compileElementAccessExpression(expression: ElementAccessExpression, contextualType: Type): ExpressionRef {
|
||||||
const element: Element | null = this.program.resolveElement(expression.expression, this.currentFunction); // reports
|
const element: Element | null = this.program.resolveElement(expression.expression, this.currentFunction); // reports
|
||||||
if (!element)
|
if (!element)
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
compileIdentifierExpression(expression: IdentifierExpression, contextualType: Type): BinaryenExpressionRef {
|
compileIdentifierExpression(expression: IdentifierExpression, contextualType: Type): ExpressionRef {
|
||||||
|
|
||||||
// null
|
// null
|
||||||
if (expression.kind == NodeKind.NULL) {
|
if (expression.kind == NodeKind.NULL) {
|
||||||
@ -1397,7 +1438,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
} else if (expression.kind == NodeKind.THIS) {
|
} else if (expression.kind == NodeKind.THIS) {
|
||||||
if (this.currentFunction.instanceMethodOf) {
|
if (this.currentFunction.instanceMethodOf) {
|
||||||
this.currentType = this.currentFunction.instanceMethodOf.type;
|
this.currentType = this.currentFunction.instanceMethodOf.type;
|
||||||
return this.module.createGetLocal(0, typeToBinaryenType(this.currentType));
|
return this.module.createGetLocal(0, typeToNativeType(this.currentType));
|
||||||
}
|
}
|
||||||
this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range);
|
this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range);
|
||||||
this.currentType = this.options.target == Target.WASM64 ? Type.u64 : Type.u32;
|
this.currentType = this.options.target == Target.WASM64 ? Type.u64 : Type.u32;
|
||||||
@ -1431,12 +1472,12 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// local
|
// local
|
||||||
if (element.kind == ElementKind.LOCAL)
|
if (element.kind == ElementKind.LOCAL)
|
||||||
return this.module.createGetLocal((<Local>element).index, typeToBinaryenType(this.currentType = (<Local>element).type));
|
return this.module.createGetLocal((<Local>element).index, typeToNativeType(this.currentType = (<Local>element).type));
|
||||||
|
|
||||||
// global
|
// global
|
||||||
if (element.kind == ElementKind.GLOBAL)
|
if (element.kind == ElementKind.GLOBAL)
|
||||||
return this.compileGlobal(<Global>element) // reports
|
return this.compileGlobal(<Global>element) // reports
|
||||||
? this.module.createGetGlobal((<Global>element).internalName, typeToBinaryenType(this.currentType = <Type>(<Global>element).type))
|
? this.module.createGetGlobal((<Global>element).internalName, typeToNativeType(this.currentType = <Type>(<Global>element).type))
|
||||||
: this.module.createUnreachable();
|
: this.module.createUnreachable();
|
||||||
|
|
||||||
// field
|
// field
|
||||||
@ -1451,7 +1492,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
compileLiteralExpression(expression: LiteralExpression, contextualType: Type): BinaryenExpressionRef {
|
compileLiteralExpression(expression: LiteralExpression, contextualType: Type): ExpressionRef {
|
||||||
switch (expression.literalKind) {
|
switch (expression.literalKind) {
|
||||||
// case LiteralKind.ARRAY:
|
// case LiteralKind.ARRAY:
|
||||||
|
|
||||||
@ -1484,62 +1525,62 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
compileNewExpression(expression: NewExpression, contextualType: Type): BinaryenExpressionRef {
|
compileNewExpression(expression: NewExpression, contextualType: Type): ExpressionRef {
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
compileParenthesizedExpression(expression: ParenthesizedExpression, contextualType: Type): BinaryenExpressionRef {
|
compileParenthesizedExpression(expression: ParenthesizedExpression, contextualType: Type): ExpressionRef {
|
||||||
return this.compileExpression(expression.expression, contextualType);
|
return this.compileExpression(expression.expression, contextualType);
|
||||||
}
|
}
|
||||||
|
|
||||||
compilePropertyAccessExpression(expression: PropertyAccessExpression, contextualType: Type): BinaryenExpressionRef {
|
compilePropertyAccessExpression(expression: PropertyAccessExpression, contextualType: Type): ExpressionRef {
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
compileSelectExpression(expression: SelectExpression, contextualType: Type): BinaryenExpressionRef {
|
compileSelectExpression(expression: SelectExpression, contextualType: Type): ExpressionRef {
|
||||||
const condition: BinaryenExpressionRef = this.compileExpression(expression.condition, Type.i32);
|
const condition: ExpressionRef = this.compileExpression(expression.condition, Type.i32);
|
||||||
const ifThen: BinaryenExpressionRef = this.compileExpression(expression.ifThen, contextualType);
|
const ifThen: ExpressionRef = this.compileExpression(expression.ifThen, contextualType);
|
||||||
const ifElse: BinaryenExpressionRef = this.compileExpression(expression.ifElse, contextualType);
|
const ifElse: ExpressionRef = this.compileExpression(expression.ifElse, contextualType);
|
||||||
return this.module.createSelect(condition, ifThen, ifElse);
|
return this.module.createSelect(condition, ifThen, ifElse);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileUnaryPostfixExpression(expression: UnaryPostfixExpression, contextualType: Type): BinaryenExpressionRef {
|
compileUnaryPostfixExpression(expression: UnaryPostfixExpression, contextualType: Type): ExpressionRef {
|
||||||
const operator: Token = expression.operator;
|
const operator: Token = expression.operator;
|
||||||
|
|
||||||
let op: BinaryOp;
|
let op: BinaryOp;
|
||||||
let binaryenType: BinaryenType;
|
let nativeType: NativeType;
|
||||||
let binaryenOne: BinaryenExpressionRef;
|
let nativeOne: ExpressionRef;
|
||||||
|
|
||||||
if (contextualType == Type.f32) {
|
if (contextualType == Type.f32) {
|
||||||
op = operator == Token.PLUS_PLUS ? BinaryOp.AddF32 : BinaryOp.SubF32;
|
op = operator == Token.PLUS_PLUS ? BinaryOp.AddF32 : BinaryOp.SubF32;
|
||||||
binaryenType = BinaryenType.F32;
|
nativeType = NativeType.F32;
|
||||||
binaryenOne = this.module.createF32(1);
|
nativeOne = this.module.createF32(1);
|
||||||
} else if (contextualType == Type.f64) {
|
} else if (contextualType == Type.f64) {
|
||||||
op = operator == Token.PLUS_PLUS ? BinaryOp.AddF64 : BinaryOp.SubF64;
|
op = operator == Token.PLUS_PLUS ? BinaryOp.AddF64 : BinaryOp.SubF64;
|
||||||
binaryenType = BinaryenType.F64;
|
nativeType = NativeType.F64;
|
||||||
binaryenOne = this.module.createF64(1);
|
nativeOne = this.module.createF64(1);
|
||||||
} else if (contextualType.isLongInteger) {
|
} else if (contextualType.isLongInteger) {
|
||||||
op = operator == Token.PLUS_PLUS ? BinaryOp.AddI64 : BinaryOp.SubI64;
|
op = operator == Token.PLUS_PLUS ? BinaryOp.AddI64 : BinaryOp.SubI64;
|
||||||
binaryenType = BinaryenType.I64;
|
nativeType = NativeType.I64;
|
||||||
binaryenOne = this.module.createI64(1, 0);
|
nativeOne = this.module.createI64(1, 0);
|
||||||
} else {
|
} else {
|
||||||
op = operator == Token.PLUS_PLUS ? BinaryOp.AddI32 : BinaryOp.SubI32;
|
op = operator == Token.PLUS_PLUS ? BinaryOp.AddI32 : BinaryOp.SubI32;
|
||||||
binaryenType = BinaryenType.I32;
|
nativeType = NativeType.I32;
|
||||||
binaryenOne = this.module.createI32(1);
|
nativeOne = this.module.createI32(1);
|
||||||
}
|
}
|
||||||
const getValue: BinaryenExpressionRef = this.compileExpression(expression.expression, contextualType);
|
const getValue: ExpressionRef = this.compileExpression(expression.expression, contextualType);
|
||||||
const setValue: BinaryenExpressionRef = this.compileAssignmentWithValue(expression.expression, this.module.createBinary(op, getValue, binaryenOne), false); // reports
|
const setValue: ExpressionRef = this.compileAssignmentWithValue(expression.expression, this.module.createBinary(op, getValue, nativeOne), false); // reports
|
||||||
|
|
||||||
return this.module.createBlock(null, [
|
return this.module.createBlock(null, [
|
||||||
getValue,
|
getValue,
|
||||||
setValue
|
setValue
|
||||||
], binaryenType);
|
], nativeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileUnaryPrefixExpression(expression: UnaryPrefixExpression, contextualType: Type): BinaryenExpressionRef {
|
compileUnaryPrefixExpression(expression: UnaryPrefixExpression, contextualType: Type): ExpressionRef {
|
||||||
const operandExpression: Expression = expression.expression;
|
const operandExpression: Expression = expression.expression;
|
||||||
|
|
||||||
let operand: BinaryenExpressionRef;
|
let operand: ExpressionRef;
|
||||||
let op: UnaryOp;
|
let op: UnaryOp;
|
||||||
|
|
||||||
switch (expression.operator) {
|
switch (expression.operator) {
|
||||||
@ -1610,27 +1651,27 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
|
|
||||||
function typeToBinaryenType(type: Type): BinaryenType {
|
function typeToNativeType(type: Type): NativeType {
|
||||||
return type.kind == TypeKind.F32
|
return type.kind == TypeKind.F32
|
||||||
? BinaryenType.F32
|
? NativeType.F32
|
||||||
: type.kind == TypeKind.F64
|
: type.kind == TypeKind.F64
|
||||||
? BinaryenType.F64
|
? NativeType.F64
|
||||||
: type.isLongInteger
|
: type.isLongInteger
|
||||||
? BinaryenType.I64
|
? NativeType.I64
|
||||||
: type.isAnyInteger || type.kind == TypeKind.BOOL
|
: type.isAnyInteger || type.kind == TypeKind.BOOL
|
||||||
? BinaryenType.I32
|
? NativeType.I32
|
||||||
: BinaryenType.None;
|
: NativeType.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
function typesToBinaryenTypes(types: Type[]): BinaryenType[] {
|
function typesToNativeTypes(types: Type[]): NativeType[] {
|
||||||
const k: i32 = types.length;
|
const k: i32 = types.length;
|
||||||
const ret: BinaryenType[] = new Array(k);
|
const ret: NativeType[] = new Array(k);
|
||||||
for (let i: i32 = 0; i < k; ++i)
|
for (let i: i32 = 0; i < k; ++i)
|
||||||
ret[i] = typeToBinaryenType(types[i]);
|
ret[i] = typeToNativeType(types[i]);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
function typeToBinaryenZero(module: Module, type: Type): BinaryenExpressionRef {
|
function typeToNativeZero(module: Module, type: Type): ExpressionRef {
|
||||||
return type.kind == TypeKind.F32
|
return type.kind == TypeKind.F32
|
||||||
? module.createF32(0)
|
? module.createF32(0)
|
||||||
: type.kind == TypeKind.F64
|
: type.kind == TypeKind.F64
|
||||||
@ -1640,7 +1681,7 @@ function typeToBinaryenZero(module: Module, type: Type): BinaryenExpressionRef {
|
|||||||
: module.createI32(0);
|
: module.createI32(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function typeToBinaryenOne(module: Module, type: Type): BinaryenExpressionRef {
|
function typeToBinaryenOne(module: Module, type: Type): ExpressionRef {
|
||||||
return type.kind == TypeKind.F32
|
return type.kind == TypeKind.F32
|
||||||
? module.createF32(1)
|
? module.createF32(1)
|
||||||
: type.kind == TypeKind.F64
|
: type.kind == TypeKind.F64
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
export const PATH_DELIMITER: string = "/";
|
export const PATH_DELIMITER: string = "/";
|
||||||
export const PARENT_SUBST: string = "..";
|
export const PARENT_SUBST: string = "..";
|
||||||
export const GETTER_PREFIX: string = "get ";
|
export const GETTER_PREFIX: string = "get_";
|
||||||
export const SETTER_PREFIX: string = "set ";
|
export const SETTER_PREFIX: string = "set_";
|
||||||
export const INSTANCE_DELIMITER: string = "#";
|
export const INSTANCE_DELIMITER: string = "#";
|
||||||
export const STATIC_DELIMITER: string = ".";
|
export const STATIC_DELIMITER: string = ".";
|
||||||
|
10
src/binaryen.d.ts → src/glue/binaryen.d.ts
vendored
10
src/binaryen.d.ts → src/glue/binaryen.d.ts
vendored
@ -246,6 +246,8 @@ declare function _BinaryenReturn(module: BinaryenModuleRef, value: BinaryenExpre
|
|||||||
declare function _BinaryenHost(module: BinaryenModuleRef, op: BinaryenOp, name: CString | 0, operands: CArray<BinaryenExpressionRef>, numOperands: BinaryenIndex): BinaryenExpressionRef;
|
declare function _BinaryenHost(module: BinaryenModuleRef, op: BinaryenOp, name: CString | 0, operands: CArray<BinaryenExpressionRef>, numOperands: BinaryenIndex): BinaryenExpressionRef;
|
||||||
declare function _BinaryenNop(module: BinaryenModuleRef): BinaryenExpressionRef;
|
declare function _BinaryenNop(module: BinaryenModuleRef): BinaryenExpressionRef;
|
||||||
declare function _BinaryenUnreachable(module: BinaryenModuleRef): BinaryenExpressionRef;
|
declare function _BinaryenUnreachable(module: BinaryenModuleRef): BinaryenExpressionRef;
|
||||||
|
declare function _BinaryenAtomicLoad(module: BinaryenModuleRef, bytes: BinaryenIndex, offset: BinaryenIndex, type: BinaryenType, ptr: BinaryenExpressionRef): BinaryenExpressionRef;
|
||||||
|
declare function _BinaryenAtomicStore(module: BinaryenModuleRef, bytes: BinaryenIndex, offset: BinaryenIndex, ptr: BinaryenExpressionRef, value: BinaryenExpressionRef, type: BinaryenType): BinaryenExpressionRef;
|
||||||
declare function _BinaryenAtomicRMW(module: BinaryenModuleRef, op: BinaryenAtomicRMWOp, bytes: i32, offset: i32, ptr: BinaryenExpressionRef, value: BinaryenExpressionRef, type: BinaryenType): BinaryenExpressionRef;
|
declare function _BinaryenAtomicRMW(module: BinaryenModuleRef, op: BinaryenAtomicRMWOp, bytes: i32, offset: i32, ptr: BinaryenExpressionRef, value: BinaryenExpressionRef, type: BinaryenType): BinaryenExpressionRef;
|
||||||
declare function _BinaryenAtomicCmpxchg(module: BinaryenModuleRef, bytes: i32, offset: i32, ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, replacement: BinaryenExpressionRef, type: BinaryenType): BinaryenExpressionRef;
|
declare function _BinaryenAtomicCmpxchg(module: BinaryenModuleRef, bytes: i32, offset: i32, ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, replacement: BinaryenExpressionRef, type: BinaryenType): BinaryenExpressionRef;
|
||||||
declare function _BinaryenAtomicWait(module: BinaryenModuleRef, ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, timeout: BinaryenExpressionRef, expectedType: BinaryenType): BinaryenExpressionRef;
|
declare function _BinaryenAtomicWait(module: BinaryenModuleRef, ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, timeout: BinaryenExpressionRef, expectedType: BinaryenType): BinaryenExpressionRef;
|
||||||
@ -263,6 +265,12 @@ declare function _BinaryenConstGetValueF64(expr: BinaryenExpressionRef): f64;
|
|||||||
declare type BinaryenFunctionRef = usize;
|
declare type BinaryenFunctionRef = usize;
|
||||||
|
|
||||||
declare function _BinaryenAddFunction(module: BinaryenModuleRef, name: CString, type: BinaryenFunctionTypeRef, varTypes: CArray<BinaryenType>, numVarTypes: BinaryenIndex, body: BinaryenExpressionRef): BinaryenFunctionRef;
|
declare function _BinaryenAddFunction(module: BinaryenModuleRef, name: CString, type: BinaryenFunctionTypeRef, varTypes: CArray<BinaryenType>, numVarTypes: BinaryenIndex, body: BinaryenExpressionRef): BinaryenFunctionRef;
|
||||||
|
declare function _BinaryenGetFunction(module: BinaryenModuleRef, name: CString): BinaryenFunctionRef;
|
||||||
|
declare function _BinaryenRemoveFunction(module: BinaryenModuleRef, name: CString): void;
|
||||||
|
|
||||||
|
declare function _BinaryenFunctionGetBody(func: BinaryenFunctionRef): BinaryenExpressionRef;
|
||||||
|
declare function _BinaryenFunctionOptimize(func: BinaryenFunctionRef, module: BinaryenModuleRef): void;
|
||||||
|
declare function _BinaryenFunctionRunPasses(func: BinaryenFunctionRef, module: BinaryenModuleRef, passes: CArray<CString>, numPasses: BinaryenIndex): void;
|
||||||
|
|
||||||
declare type BinaryenImportRef = usize;
|
declare type BinaryenImportRef = usize;
|
||||||
|
|
||||||
@ -289,7 +297,7 @@ declare function _BinaryenModulePrint(module: BinaryenModuleRef): void;
|
|||||||
declare function _BinaryenModulePrintAsmjs(module: BinaryenModuleRef): void;
|
declare function _BinaryenModulePrintAsmjs(module: BinaryenModuleRef): void;
|
||||||
declare function _BinaryenModuleValidate(module: BinaryenModuleRef): i32;
|
declare function _BinaryenModuleValidate(module: BinaryenModuleRef): i32;
|
||||||
declare function _BinaryenModuleOptimize(module: BinaryenModuleRef): void;
|
declare function _BinaryenModuleOptimize(module: BinaryenModuleRef): void;
|
||||||
declare function _BinaryenModuleRunPasses(module: BinaryenModuleRef, passes: string[]): void;
|
declare function _BinaryenModuleRunPasses(module: BinaryenModuleRef, passes: CArray<CString>, numPasses: BinaryenIndex): void;
|
||||||
declare function _BinaryenModuleAutoDrop(module: BinaryenModuleRef): void;
|
declare function _BinaryenModuleAutoDrop(module: BinaryenModuleRef): void;
|
||||||
declare function _BinaryenModuleWrite(module: BinaryenModuleRef, output: CString, outputSize: usize): usize;
|
declare function _BinaryenModuleWrite(module: BinaryenModuleRef, output: CString, outputSize: usize): usize;
|
||||||
declare function _BinaryenModuleRead(input: CString, inputSize: usize): BinaryenModuleRef;
|
declare function _BinaryenModuleRead(input: CString, inputSize: usize): BinaryenModuleRef;
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Module } from "./binaryen";
|
import { Module } from "./module";
|
||||||
import { Compiler } from "./compiler";
|
import { Compiler } from "./compiler";
|
||||||
import { DiagnosticMessage, DiagnosticCategory } from "./diagnostics";
|
import { DiagnosticMessage, DiagnosticCategory } from "./diagnostics";
|
||||||
import { Parser } from "./parser";
|
import { Parser } from "./parser";
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
import { I64, U64 } from "./util";
|
import { I64, U64 } from "./util";
|
||||||
import { Target } from "./compiler";
|
import { Target } from "./compiler";
|
||||||
|
|
||||||
export enum Type {
|
export type ModuleRef = BinaryenModuleRef;
|
||||||
|
export type FunctionTypeRef = BinaryenFunctionTypeRef;
|
||||||
|
export type FunctionRef = BinaryenFunctionRef;
|
||||||
|
export type ExpressionRef = BinaryenExpressionRef;
|
||||||
|
export type GlobalRef = BinaryenGlobalRef;
|
||||||
|
export type ImportRef = BinaryenImportRef;
|
||||||
|
export type ExportRef = BinaryenExportRef;
|
||||||
|
export type Index = BinaryenIndex;
|
||||||
|
|
||||||
|
export enum NativeType {
|
||||||
None = _BinaryenNone(),
|
None = _BinaryenNone(),
|
||||||
I32 = _BinaryenInt32(),
|
I32 = _BinaryenInt32(),
|
||||||
I64 = _BinaryenInt64(),
|
I64 = _BinaryenInt64(),
|
||||||
@ -201,11 +210,11 @@ export class MemorySegment {
|
|||||||
|
|
||||||
export class Module {
|
export class Module {
|
||||||
|
|
||||||
ref: BinaryenModuleRef;
|
ref: ModuleRef;
|
||||||
lit: BinaryenLiteral;
|
lit: BinaryenLiteral;
|
||||||
noEmit: bool;
|
noEmit: bool;
|
||||||
|
|
||||||
static MAX_MEMORY_WASM32: BinaryenIndex = 0xffff;
|
static MAX_MEMORY_WASM32: Index = 0xffff;
|
||||||
|
|
||||||
static create(): Module {
|
static create(): Module {
|
||||||
const module: Module = new Module();
|
const module: Module = new Module();
|
||||||
@ -240,7 +249,7 @@ export class Module {
|
|||||||
|
|
||||||
// types
|
// types
|
||||||
|
|
||||||
addFunctionType(name: string, result: Type, paramTypes: Type[]): BinaryenFunctionRef {
|
addFunctionType(name: string, result: NativeType, paramTypes: NativeType[]): FunctionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(name);
|
const cStr: CString = allocString(name);
|
||||||
const cArr: CArray<i32> = allocI32Array(paramTypes);
|
const cArr: CArray<i32> = allocI32Array(paramTypes);
|
||||||
@ -252,7 +261,7 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getFunctionTypeBySignature(result: Type, paramTypes: Type[]): BinaryenFunctionTypeRef {
|
getFunctionTypeBySignature(result: NativeType, paramTypes: NativeType[]): FunctionTypeRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cArr: CArray<i32> = allocI32Array(paramTypes);
|
const cArr: CArray<i32> = allocI32Array(paramTypes);
|
||||||
try {
|
try {
|
||||||
@ -264,63 +273,63 @@ export class Module {
|
|||||||
|
|
||||||
// expressions
|
// expressions
|
||||||
|
|
||||||
createI32(value: i32): BinaryenExpressionRef {
|
createI32(value: i32): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
_BinaryenLiteralInt32(this.lit, value);
|
_BinaryenLiteralInt32(this.lit, value);
|
||||||
return _BinaryenConst(this.ref, this.lit);
|
return _BinaryenConst(this.ref, this.lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
createI64(lo: i32, hi: i32): BinaryenExpressionRef {
|
createI64(lo: i32, hi: i32): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
_BinaryenLiteralInt64(this.lit, lo, hi);
|
_BinaryenLiteralInt64(this.lit, lo, hi);
|
||||||
return _BinaryenConst(this.ref, this.lit);
|
return _BinaryenConst(this.ref, this.lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
createF32(value: f32): BinaryenExpressionRef {
|
createF32(value: f32): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
_BinaryenLiteralFloat32(this.lit, value);
|
_BinaryenLiteralFloat32(this.lit, value);
|
||||||
return _BinaryenConst(this.ref, this.lit);
|
return _BinaryenConst(this.ref, this.lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
createF64(value: f64): BinaryenExpressionRef {
|
createF64(value: f64): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
_BinaryenLiteralFloat64(this.lit, value);
|
_BinaryenLiteralFloat64(this.lit, value);
|
||||||
return _BinaryenConst(this.ref, this.lit);
|
return _BinaryenConst(this.ref, this.lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
createUnary(op: UnaryOp, expr: BinaryenExpressionRef): BinaryenExpressionRef {
|
createUnary(op: UnaryOp, expr: ExpressionRef): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenUnary(this.ref, op, expr);
|
return _BinaryenUnary(this.ref, op, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
createBinary(op: BinaryOp, left: BinaryenExpressionRef, right: BinaryenExpressionRef): BinaryenExpressionRef {
|
createBinary(op: BinaryOp, left: ExpressionRef, right: ExpressionRef): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenBinary(this.ref, op, left, right);
|
return _BinaryenBinary(this.ref, op, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
createHost(op: HostOp, name: string | null = null, operands: BinaryenExpressionRef[] | null = null): BinaryenExpressionRef {
|
createHost(op: HostOp, name: string | null = null, operands: ExpressionRef[] | null = null): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(name);
|
const cStr: CString = allocString(name);
|
||||||
const cArr: CArray<i32> = allocI32Array(operands);
|
const cArr: CArray<i32> = allocI32Array(operands);
|
||||||
try {
|
try {
|
||||||
return _BinaryenHost(this.ref, op, cStr, cArr, operands ? (<BinaryenExpressionRef[]>operands).length : 0);
|
return _BinaryenHost(this.ref, op, cStr, cArr, operands ? (<ExpressionRef[]>operands).length : 0);
|
||||||
} finally {
|
} finally {
|
||||||
_free(cArr);
|
_free(cArr);
|
||||||
_free(cStr);
|
_free(cStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createGetLocal(index: i32, type: Type): BinaryenExpressionRef {
|
createGetLocal(index: i32, type: NativeType): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenGetLocal(this.ref, index, type);
|
return _BinaryenGetLocal(this.ref, index, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
createTeeLocal(index: i32, value: BinaryenExpressionRef): BinaryenExpressionRef {
|
createTeeLocal(index: i32, value: ExpressionRef): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenTeeLocal(this.ref, index, value);
|
return _BinaryenTeeLocal(this.ref, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
createGetGlobal(name: string, type: Type): BinaryenExpressionRef {
|
createGetGlobal(name: string, type: NativeType): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(name);
|
const cStr: CString = allocString(name);
|
||||||
try {
|
try {
|
||||||
@ -330,34 +339,54 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createAtomicRMW(op: AtomicRMWOp, bytes: i32, offset: i32, ptr: BinaryenExpressionRef, value: BinaryenExpressionRef, type: Type): BinaryenExpressionRef {
|
createLoad(bytes: Index, signed: bool, ptr: ExpressionRef, type: NativeType, offset: Index = 0): ExpressionRef {
|
||||||
|
if (this.noEmit) return 0;
|
||||||
|
return _BinaryenLoad(this.ref, bytes, signed ? 1 : 0, offset, /* always aligned */ bytes, type, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
createStore(bytes: Index, ptr: ExpressionRef, value: ExpressionRef, type: NativeType, offset: Index = 0): ExpressionRef {
|
||||||
|
if (this.noEmit) return 0;
|
||||||
|
return _BinaryenStore(this.ref, bytes, offset, /* always aligned */ bytes, ptr, value, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAtomicLoad(bytes: Index, ptr: ExpressionRef, type: NativeType, offset: Index = 0): ExpressionRef {
|
||||||
|
if (this.noEmit) return 0;
|
||||||
|
return _BinaryenAtomicLoad(this.ref, bytes, offset, type, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAtomicStore(bytes: Index, ptr: ExpressionRef, value: ExpressionRef, type: NativeType, offset: Index = 0): ExpressionRef {
|
||||||
|
if (this.noEmit) return 0;
|
||||||
|
return _BinaryenAtomicStore(this.ref, bytes, offset, ptr, value, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAtomicRMW(op: AtomicRMWOp, bytes: Index, offset: Index, ptr: ExpressionRef, value: ExpressionRef, type: NativeType): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenAtomicRMW(this.ref, op, bytes, offset, ptr, value, type);
|
return _BinaryenAtomicRMW(this.ref, op, bytes, offset, ptr, value, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
createAtomicCmpxchg(bytes: i32, offset: i32, ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, replacement: BinaryenExpressionRef, type: Type): BinaryenExpressionRef {
|
createAtomicCmpxchg(bytes: Index, offset: Index, ptr: ExpressionRef, expected: ExpressionRef, replacement: ExpressionRef, type: NativeType): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenAtomicCmpxchg(this.ref, bytes, offset, ptr, expected, replacement, type);
|
return _BinaryenAtomicCmpxchg(this.ref, bytes, offset, ptr, expected, replacement, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
createAtomicWait(ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, timeout: BinaryenExpressionRef, expectedType: BinaryenType): BinaryenExpressionRef {
|
createAtomicWait(ptr: ExpressionRef, expected: ExpressionRef, timeout: ExpressionRef, expectedType: NativeType): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenAtomicWait(this.ref, ptr, expected, timeout, expectedType);
|
return _BinaryenAtomicWait(this.ref, ptr, expected, timeout, expectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
createAtomicWake(ptr: BinaryenExpressionRef, wakeCount: BinaryenExpressionRef): BinaryenExpressionRef {
|
createAtomicWake(ptr: ExpressionRef, wakeCount: ExpressionRef): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenAtomicWake(this.ref, ptr, wakeCount);
|
return _BinaryenAtomicWake(this.ref, ptr, wakeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// statements
|
// statements
|
||||||
|
|
||||||
createSetLocal(index: i32, value: BinaryenExpressionRef): BinaryenExpressionRef {
|
createSetLocal(index: Index, value: ExpressionRef): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenSetLocal(this.ref, index, value);
|
return _BinaryenSetLocal(this.ref, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
createSetGlobal(name: string, value: BinaryenExpressionRef): BinaryenExpressionRef {
|
createSetGlobal(name: string, value: ExpressionRef): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(name);
|
const cStr: CString = allocString(name);
|
||||||
try {
|
try {
|
||||||
@ -367,7 +396,7 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createBlock(label: string | null, children: BinaryenExpressionRef[], type: Type = Type.Undefined): BinaryenExpressionRef {
|
createBlock(label: string | null, children: ExpressionRef[], type: NativeType = NativeType.Undefined): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(label);
|
const cStr: CString = allocString(label);
|
||||||
const cArr: CArray<i32> = allocI32Array(children);
|
const cArr: CArray<i32> = allocI32Array(children);
|
||||||
@ -379,7 +408,7 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createBreak(label: string | null, condition: BinaryenExpressionRef = 0, value: BinaryenExpressionRef = 0): BinaryenExpressionRef {
|
createBreak(label: string | null, condition: ExpressionRef = 0, value: ExpressionRef = 0): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(label);
|
const cStr: CString = allocString(label);
|
||||||
try {
|
try {
|
||||||
@ -389,12 +418,12 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createDrop(expression: BinaryenExpressionRef): BinaryenExpressionRef {
|
createDrop(expression: ExpressionRef): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenDrop(this.ref, expression);
|
return _BinaryenDrop(this.ref, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
createLoop(label: string | null, body: BinaryenExpressionRef): BinaryenExpressionRef {
|
createLoop(label: string | null, body: ExpressionRef): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(label);
|
const cStr: CString = allocString(label);
|
||||||
try {
|
try {
|
||||||
@ -404,27 +433,27 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createIf(condition: BinaryenExpressionRef, ifTrue: BinaryenExpressionRef, ifFalse: BinaryenExpressionRef = 0): BinaryenExpressionRef {
|
createIf(condition: ExpressionRef, ifTrue: ExpressionRef, ifFalse: ExpressionRef = 0): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenIf(this.ref, condition, ifTrue, ifFalse);
|
return _BinaryenIf(this.ref, condition, ifTrue, ifFalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
createNop(): BinaryenExpressionRef {
|
createNop(): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenNop(this.ref);
|
return _BinaryenNop(this.ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
createReturn(expression: BinaryenExpressionRef = 0): BinaryenExpressionRef {
|
createReturn(expression: ExpressionRef = 0): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenReturn(this.ref, expression);
|
return _BinaryenReturn(this.ref, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
createSelect(condition: BinaryenExpressionRef, ifTrue: BinaryenExpressionRef, ifFalse: BinaryenExpressionRef): BinaryenExpressionRef {
|
createSelect(condition: ExpressionRef, ifTrue: ExpressionRef, ifFalse: ExpressionRef): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenSelect(this.ref, condition, ifTrue, ifFalse);
|
return _BinaryenSelect(this.ref, condition, ifTrue, ifFalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
createSwitch(names: string[], defaultName: string | null, condition: BinaryenExpressionRef, value: BinaryenExpressionRef = 0): BinaryenExpressionRef {
|
createSwitch(names: string[], defaultName: string | null, condition: ExpressionRef, value: ExpressionRef = 0): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const strs: CString[] = new Array(names.length);
|
const strs: CString[] = new Array(names.length);
|
||||||
let i: i32, k: i32 = names.length;
|
let i: i32, k: i32 = names.length;
|
||||||
@ -440,7 +469,7 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createCall(target: string, operands: BinaryenExpressionRef[], returnType: Type): BinaryenExpressionRef {
|
createCall(target: string, operands: ExpressionRef[], returnType: NativeType): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(target);
|
const cStr: CString = allocString(target);
|
||||||
const cArr: CArray<i32> = allocI32Array(operands);
|
const cArr: CArray<i32> = allocI32Array(operands);
|
||||||
@ -452,7 +481,7 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createCallImport(target: string, operands: BinaryenExpressionRef[], returnType: Type): BinaryenExpressionRef {
|
createCallImport(target: string, operands: ExpressionRef[], returnType: NativeType): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(target);
|
const cStr: CString = allocString(target);
|
||||||
const cArr: CArray<i32> = allocI32Array(operands);
|
const cArr: CArray<i32> = allocI32Array(operands);
|
||||||
@ -464,14 +493,14 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createUnreachable(): BinaryenExpressionRef {
|
createUnreachable(): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _BinaryenUnreachable(this.ref);
|
return _BinaryenUnreachable(this.ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
// meta
|
// meta
|
||||||
|
|
||||||
addGlobal(name: string, type: Type, mutable: bool, initializer: BinaryenExpressionRef): BinaryenGlobalRef {
|
addGlobal(name: string, type: NativeType, mutable: bool, initializer: ExpressionRef): GlobalRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(name);
|
const cStr: CString = allocString(name);
|
||||||
try {
|
try {
|
||||||
@ -481,7 +510,7 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addFunction(name: string, type: BinaryenFunctionTypeRef, varTypes: Type[], body: BinaryenExpressionRef): BinaryenFunctionRef {
|
addFunction(name: string, type: FunctionTypeRef, varTypes: NativeType[], body: ExpressionRef): FunctionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(name);
|
const cStr: CString = allocString(name);
|
||||||
const cArr: CArray<i32> = allocI32Array(varTypes);
|
const cArr: CArray<i32> = allocI32Array(varTypes);
|
||||||
@ -493,7 +522,7 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addExport(internalName: string, externalName: string): BinaryenExportRef {
|
addExport(internalName: string, externalName: string): ExportRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr1: CString = allocString(internalName);
|
const cStr1: CString = allocString(internalName);
|
||||||
const cStr2: CString = allocString(externalName);
|
const cStr2: CString = allocString(externalName);
|
||||||
@ -515,7 +544,7 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addImport(internalName: string, externalModuleName: string, externalBaseName: string, type: BinaryenFunctionTypeRef): BinaryenImportRef {
|
addImport(internalName: string, externalModuleName: string, externalBaseName: string, type: FunctionTypeRef): ImportRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr1: CString = allocString(internalName);
|
const cStr1: CString = allocString(internalName);
|
||||||
const cStr2: CString = allocString(externalModuleName);
|
const cStr2: CString = allocString(externalModuleName);
|
||||||
@ -539,13 +568,13 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setMemory(initial: BinaryenIndex, maximum: BinaryenIndex, segments: MemorySegment[], target: Target, exportName: string | null = null): void {
|
setMemory(initial: Index, maximum: Index, segments: MemorySegment[], target: Target, exportName: string | null = null): void {
|
||||||
if (this.noEmit) return;
|
if (this.noEmit) return;
|
||||||
const cStr: CString = allocString(exportName);
|
const cStr: CString = allocString(exportName);
|
||||||
let i: i32, k: i32 = segments.length;
|
let i: i32, k: i32 = segments.length;
|
||||||
const segs: CArray<u8>[] = new Array(k);
|
const segs: CArray<u8>[] = new Array(k);
|
||||||
const offs: BinaryenExpressionRef[] = new Array(k);
|
const offs: ExpressionRef[] = new Array(k);
|
||||||
const sizs: BinaryenIndex[] = new Array(k);
|
const sizs: Index[] = new Array(k);
|
||||||
for (i = 0; i < k; ++i) {
|
for (i = 0; i < k; ++i) {
|
||||||
const buffer: Uint8Array = segments[i].buffer;
|
const buffer: Uint8Array = segments[i].buffer;
|
||||||
const offset: U64 = segments[i].offset;
|
const offset: U64 = segments[i].offset;
|
||||||
@ -569,7 +598,7 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setStart(func: BinaryenFunctionRef): void {
|
setStart(func: FunctionRef): void {
|
||||||
if (this.noEmit) return;
|
if (this.noEmit) return;
|
||||||
_BinaryenSetStart(this.ref, func);
|
_BinaryenSetStart(this.ref, func);
|
||||||
}
|
}
|
||||||
@ -595,42 +624,42 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getExpressionId(expr: BinaryenExpressionRef): ExpressionId {
|
export function getExpressionId(expr: ExpressionRef): ExpressionId {
|
||||||
return _BinaryenExpressionGetId(expr);
|
return _BinaryenExpressionGetId(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getExpressionType(expr: BinaryenExpressionRef): Type {
|
export function getExpressionType(expr: ExpressionRef): NativeType {
|
||||||
return _BinaryenExpressionGetType(expr);
|
return _BinaryenExpressionGetType(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function printExpression(expr: BinaryenExpressionRef): void {
|
export function printExpression(expr: ExpressionRef): void {
|
||||||
return _BinaryenExpressionPrint(expr);
|
return _BinaryenExpressionPrint(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getConstValueI32(expr: BinaryenExpressionRef): i32 {
|
export function getConstValueI32(expr: ExpressionRef): i32 {
|
||||||
return _BinaryenConstGetValueI32(expr);
|
return _BinaryenConstGetValueI32(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getConstValueI64Low(expr: BinaryenExpressionRef): i32 {
|
export function getConstValueI64Low(expr: ExpressionRef): i32 {
|
||||||
return _BinaryenConstGetValueI64Low(expr);
|
return _BinaryenConstGetValueI64Low(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getConstValueI64High(expr: BinaryenExpressionRef): i32 {
|
export function getConstValueI64High(expr: ExpressionRef): i32 {
|
||||||
return _BinaryenConstGetValueI64High(expr);
|
return _BinaryenConstGetValueI64High(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getConstValueI64(expr: BinaryenExpressionRef): I64 {
|
export function getConstValueI64(expr: ExpressionRef): I64 {
|
||||||
return new I64(
|
return new I64(
|
||||||
_BinaryenConstGetValueI64Low(expr),
|
_BinaryenConstGetValueI64Low(expr),
|
||||||
_BinaryenConstGetValueI64High(expr)
|
_BinaryenConstGetValueI64High(expr)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getConstValueF32(expr: BinaryenExpressionRef): f32 {
|
export function getConstValueF32(expr: ExpressionRef): f32 {
|
||||||
return _BinaryenConstGetValueF32(expr);
|
return _BinaryenConstGetValueF32(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getConstValueF64(expr: BinaryenExpressionRef): f64 {
|
export function getConstValueF64(expr: ExpressionRef): f64 {
|
||||||
return _BinaryenConstGetValueF64(expr);
|
return _BinaryenConstGetValueF64(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,22 +687,22 @@ export class Relooper {
|
|||||||
|
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
addBlock(code: BinaryenExpressionRef): RelooperBlockRef {
|
addBlock(code: ExpressionRef): RelooperBlockRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _RelooperAddBlock(this.ref, code);
|
return _RelooperAddBlock(this.ref, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
addBranch(from: RelooperBlockRef, to: RelooperBlockRef, condition: BinaryenExpressionRef = 0, code: BinaryenExpressionRef = 0): void {
|
addBranch(from: RelooperBlockRef, to: RelooperBlockRef, condition: ExpressionRef = 0, code: ExpressionRef = 0): void {
|
||||||
if (this.noEmit) return;
|
if (this.noEmit) return;
|
||||||
_RelooperAddBranch(from, to, condition, code);
|
_RelooperAddBranch(from, to, condition, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
addBlockWithSwitch(code: BinaryenExpressionRef, condition: BinaryenExpressionRef): RelooperBlockRef {
|
addBlockWithSwitch(code: ExpressionRef, condition: ExpressionRef): RelooperBlockRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _RelooperAddBlockWithSwitch(this.ref, code, condition);
|
return _RelooperAddBlockWithSwitch(this.ref, code, condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
addBranchForSwitch(from: RelooperBlockRef, to: RelooperBlockRef, indexes: i32[], code: BinaryenExpressionRef = 0): void {
|
addBranchForSwitch(from: RelooperBlockRef, to: RelooperBlockRef, indexes: i32[], code: ExpressionRef = 0): void {
|
||||||
if (this.noEmit) return;
|
if (this.noEmit) return;
|
||||||
const cArr: CArray<i32> = allocI32Array(indexes);
|
const cArr: CArray<i32> = allocI32Array(indexes);
|
||||||
try {
|
try {
|
||||||
@ -683,7 +712,7 @@ export class Relooper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderAndDispose(entry: RelooperBlockRef, labelHelper: BinaryenIndex): BinaryenExpressionRef {
|
renderAndDispose(entry: RelooperBlockRef, labelHelper: Index): ExpressionRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
return _RelooperRenderAndDispose(this.ref, entry, labelHelper, this.module.ref);
|
return _RelooperRenderAndDispose(this.ref, entry, labelHelper, this.module.ref);
|
||||||
}
|
}
|
@ -832,7 +832,7 @@ export class Function extends Element {
|
|||||||
template: FunctionPrototype;
|
template: FunctionPrototype;
|
||||||
/** Concrete type arguments. */
|
/** Concrete type arguments. */
|
||||||
typeArguments: Type[];
|
typeArguments: Type[];
|
||||||
/** Concrete function parameters. */
|
/** Concrete function parameters. Excluding `this` if an instance method. */
|
||||||
parameters: Parameter[];
|
parameters: Parameter[];
|
||||||
/** Concrete return type. */
|
/** Concrete return type. */
|
||||||
returnType: Type;
|
returnType: Type;
|
||||||
@ -877,7 +877,7 @@ export class Function extends Element {
|
|||||||
addLocal(type: Type, name: string | null = null): Local {
|
addLocal(type: Type, name: string | null = null): Local {
|
||||||
// if it has a name, check previously as this method will throw otherwise
|
// if it has a name, check previously as this method will throw otherwise
|
||||||
let localIndex = this.parameters.length + this.additionalLocals.length;
|
let localIndex = this.parameters.length + this.additionalLocals.length;
|
||||||
if (this.instanceMethodOf) localIndex++; // plus 'this'
|
if (this.isInstance) localIndex++; // plus 'this'
|
||||||
const local: Local = new Local(this.template.program, name ? name : "anonymous$" + localIndex.toString(10), localIndex, type);
|
const local: Local = new Local(this.template.program, name ? name : "anonymous$" + localIndex.toString(10), localIndex, type);
|
||||||
if (name) {
|
if (name) {
|
||||||
if (this.locals.has(<string>name))
|
if (this.locals.has(<string>name))
|
||||||
|
@ -20,15 +20,15 @@
|
|||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"ast.ts",
|
"ast.ts",
|
||||||
"binaryen.d.ts",
|
|
||||||
"binaryen.ts",
|
|
||||||
"compiler.ts",
|
"compiler.ts",
|
||||||
"diagnosticMessages.generated.ts",
|
"diagnosticMessages.generated.ts",
|
||||||
"diagnostics.ts",
|
"diagnostics.ts",
|
||||||
"evaluator.ts",
|
"evaluator.ts",
|
||||||
|
"glue/binaryen.d.ts",
|
||||||
"glue/js.d.ts",
|
"glue/js.d.ts",
|
||||||
"glue/js.ts",
|
"glue/js.ts",
|
||||||
"index.ts",
|
"index.ts",
|
||||||
|
"moddule.ts",
|
||||||
"parser.ts",
|
"parser.ts",
|
||||||
"program.ts",
|
"program.ts",
|
||||||
"tokenizer.ts",
|
"tokenizer.ts",
|
||||||
|
@ -1,171 +0,0 @@
|
|||||||
// incrementing precedence
|
|
||||||
a
|
|
||||||
=
|
|
||||||
b
|
|
||||||
?
|
|
||||||
X
|
|
||||||
:
|
|
||||||
c
|
|
||||||
||
|
|
||||||
d
|
|
||||||
&&
|
|
||||||
e
|
|
||||||
|
|
|
||||||
f
|
|
||||||
^
|
|
||||||
g
|
|
||||||
&
|
|
||||||
h
|
|
||||||
==
|
|
||||||
i
|
|
||||||
<
|
|
||||||
j
|
|
||||||
<<
|
|
||||||
k
|
|
||||||
+
|
|
||||||
l
|
|
||||||
/
|
|
||||||
++
|
|
||||||
m
|
|
||||||
++
|
|
||||||
;
|
|
||||||
// decrementing precedence
|
|
||||||
++
|
|
||||||
a
|
|
||||||
++
|
|
||||||
/
|
|
||||||
b
|
|
||||||
+
|
|
||||||
c
|
|
||||||
<<
|
|
||||||
d
|
|
||||||
<
|
|
||||||
e
|
|
||||||
==
|
|
||||||
f
|
|
||||||
&
|
|
||||||
g
|
|
||||||
^
|
|
||||||
h
|
|
||||||
|
|
|
||||||
i
|
|
||||||
&&
|
|
||||||
j
|
|
||||||
||
|
|
||||||
k
|
|
||||||
?
|
|
||||||
X
|
|
||||||
:
|
|
||||||
y
|
|
||||||
=
|
|
||||||
l
|
|
||||||
;
|
|
||||||
// assignment (right-to-left)
|
|
||||||
a
|
|
||||||
=
|
|
||||||
b
|
|
||||||
+=
|
|
||||||
c
|
|
||||||
-=
|
|
||||||
d
|
|
||||||
**=
|
|
||||||
e
|
|
||||||
*=
|
|
||||||
f
|
|
||||||
/=
|
|
||||||
g
|
|
||||||
%=
|
|
||||||
h
|
|
||||||
<<=
|
|
||||||
i
|
|
||||||
>>=
|
|
||||||
j
|
|
||||||
>>>=
|
|
||||||
k
|
|
||||||
&=
|
|
||||||
l
|
|
||||||
^=
|
|
||||||
m
|
|
||||||
|=
|
|
||||||
n
|
|
||||||
;
|
|
||||||
// equality (left-to-right)
|
|
||||||
a
|
|
||||||
==
|
|
||||||
b
|
|
||||||
!=
|
|
||||||
c
|
|
||||||
===
|
|
||||||
d
|
|
||||||
!==
|
|
||||||
e
|
|
||||||
;
|
|
||||||
// relational (left-to-right)
|
|
||||||
a
|
|
||||||
<
|
|
||||||
b
|
|
||||||
<=
|
|
||||||
c
|
|
||||||
>
|
|
||||||
d
|
|
||||||
>=
|
|
||||||
e
|
|
||||||
;
|
|
||||||
// bitwise shift (left-to-right)
|
|
||||||
a
|
|
||||||
<<
|
|
||||||
b
|
|
||||||
>>
|
|
||||||
c
|
|
||||||
>>>
|
|
||||||
d
|
|
||||||
;
|
|
||||||
// addition (left-to-right)
|
|
||||||
a
|
|
||||||
+
|
|
||||||
b
|
|
||||||
-
|
|
||||||
c
|
|
||||||
;
|
|
||||||
// exponentiation (right-to-left), multiplication (left-to-right)
|
|
||||||
a
|
|
||||||
**
|
|
||||||
b
|
|
||||||
*
|
|
||||||
c
|
|
||||||
/
|
|
||||||
d
|
|
||||||
%
|
|
||||||
e
|
|
||||||
**
|
|
||||||
f
|
|
||||||
*
|
|
||||||
g
|
|
||||||
;
|
|
||||||
// prefix (right-to-left)
|
|
||||||
delete
|
|
||||||
void
|
|
||||||
typeof
|
|
||||||
--
|
|
||||||
++
|
|
||||||
-
|
|
||||||
+
|
|
||||||
~
|
|
||||||
!
|
|
||||||
a
|
|
||||||
;
|
|
||||||
// parenthesized
|
|
||||||
(
|
|
||||||
a
|
|
||||||
+
|
|
||||||
(
|
|
||||||
b
|
|
||||||
/
|
|
||||||
c
|
|
||||||
)
|
|
||||||
-
|
|
||||||
d
|
|
||||||
)
|
|
||||||
*
|
|
||||||
e
|
|
||||||
;
|
|
@ -14,15 +14,7 @@ files.forEach(filename => {
|
|||||||
const text = fs.readFileSync(__dirname + "/fixtures/" + filename, { encoding: "utf8" }).replace(/\r?\n/g, "\n").replace(/^\/\/.*\r?\n/mg, "");
|
const text = fs.readFileSync(__dirname + "/fixtures/" + filename, { encoding: "utf8" }).replace(/\r?\n/g, "\n").replace(/^\/\/.*\r?\n/mg, "");
|
||||||
parser.parseFile(text, filename, true);
|
parser.parseFile(text, filename, true);
|
||||||
var sb: string[] = [];
|
var sb: string[] = [];
|
||||||
if (isTree) {
|
parser.program.sources[0].serialize(sb);
|
||||||
const statements = parser.program.sources[0].statements;
|
|
||||||
statements.forEach(stmt => {
|
|
||||||
if (stmt.kind != NodeKind.EXPRESSION) return;
|
|
||||||
(<ExpressionStatement>stmt).expression.serializeAsTree(sb, 0);
|
|
||||||
sb.push(";\n");
|
|
||||||
});
|
|
||||||
} else
|
|
||||||
parser.program.sources[0].serialize(sb);
|
|
||||||
const actual = sb.join("");
|
const actual = sb.join("");
|
||||||
const expected = isTree ? text : text.replace(/^\s+/mg, "");
|
const expected = isTree ? text : text.replace(/^\s+/mg, "");
|
||||||
const diffs = diff.diffLines(expected, actual);
|
const diffs = diff.diffLines(expected, actual);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user