mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 15:12:12 +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;
|
||||
return expr;
|
||||
}
|
||||
|
||||
abstract serializeAsTree(sb: string[], indent: i32): void;
|
||||
}
|
||||
|
||||
export const enum LiteralKind {
|
||||
@ -384,20 +382,6 @@ export class ArrayLiteralExpression extends LiteralExpression {
|
||||
}
|
||||
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 {
|
||||
@ -424,24 +408,6 @@ export class AssertionExpression extends Expression {
|
||||
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 {
|
||||
@ -458,14 +424,6 @@ export class BinaryExpression extends Expression {
|
||||
sb.push(" ");
|
||||
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 {
|
||||
@ -495,12 +453,6 @@ export class CallExpression extends Expression {
|
||||
}
|
||||
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 {
|
||||
@ -515,15 +467,6 @@ export class ElementAccessExpression extends Expression {
|
||||
this.elementExpression.serialize(sb);
|
||||
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 {
|
||||
@ -534,12 +477,6 @@ export class FloatLiteralExpression extends LiteralExpression {
|
||||
serialize(sb: string[]): void {
|
||||
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 {
|
||||
@ -550,12 +487,6 @@ export class IdentifierExpression extends Expression {
|
||||
serialize(sb: string[]): void {
|
||||
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 {
|
||||
@ -566,12 +497,6 @@ export class IntegerLiteralExpression extends LiteralExpression {
|
||||
serialize(sb: string[]): void {
|
||||
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 {
|
||||
@ -582,12 +507,6 @@ export class NewExpression extends CallExpression {
|
||||
sb.push("new ");
|
||||
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 {
|
||||
@ -605,14 +524,6 @@ export class ParenthesizedExpression extends Expression {
|
||||
this.expression.serialize(sb);
|
||||
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 {
|
||||
@ -626,12 +537,6 @@ export class PropertyAccessExpression extends Expression {
|
||||
sb.push(".");
|
||||
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 {
|
||||
@ -642,12 +547,6 @@ export class RegexpLiteralExpression extends LiteralExpression {
|
||||
serialize(sb: string[]): void {
|
||||
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 {
|
||||
@ -664,16 +563,6 @@ export class SelectExpression extends Expression {
|
||||
sb.push(" : ");
|
||||
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 {
|
||||
@ -684,12 +573,6 @@ export class StringLiteralExpression extends LiteralExpression {
|
||||
serialize(sb: string[]): void {
|
||||
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 {
|
||||
@ -729,17 +612,6 @@ export class UnaryPostfixExpression extends UnaryExpression {
|
||||
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 {
|
||||
@ -750,13 +622,6 @@ export class UnaryPrefixExpression extends UnaryExpression {
|
||||
sb.push(operatorTokenToString(this.operator));
|
||||
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
|
||||
@ -1937,8 +1802,3 @@ function builderEndsWith(sb: string[], code: CharCode): bool {
|
||||
}
|
||||
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 { 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 { CharCode, I64, U64, normalizePath, sb } from "./util";
|
||||
import { Token, Range } from "./tokenizer";
|
||||
@ -77,14 +77,14 @@ import {
|
||||
export enum Target {
|
||||
/** WebAssembly with 32-bit pointers. */
|
||||
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
|
||||
}
|
||||
|
||||
export class Options {
|
||||
/** WebAssembly target. Defaults to {@link 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;
|
||||
/** If true, compiles everything instead of just reachable code. */
|
||||
noTreeShaking: bool = false;
|
||||
@ -92,27 +92,40 @@ export class Options {
|
||||
|
||||
export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
/** Program reference. */
|
||||
program: Program;
|
||||
/** Provided options. */
|
||||
options: Options;
|
||||
/** Module instance being compiled. */
|
||||
module: Module;
|
||||
|
||||
/** Start function being compiled. */
|
||||
startFunction: Function;
|
||||
startFunctionBody: BinaryenExpressionRef[] = new Array();
|
||||
/** Start function expressions. */
|
||||
startFunctionBody: ExpressionRef[] = new Array();
|
||||
|
||||
/** Current type in compilation. */
|
||||
currentType: Type = Type.void;
|
||||
/** Current function in compilation. */
|
||||
currentFunction: Function;
|
||||
/** Marker indicating whether continue statements are allowed in the current break context. */
|
||||
disallowContinue: bool = true;
|
||||
|
||||
/** Counting memory offset. */
|
||||
memoryOffset: U64 = new U64(8, 0); // leave space for (any size of) NULL
|
||||
/** Memory segments being compiled. */
|
||||
memorySegments: MemorySegment[] = new Array();
|
||||
|
||||
/** Already processed file names. */
|
||||
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 {
|
||||
const compiler: Compiler = new Compiler(program, options);
|
||||
return compiler.compile();
|
||||
}
|
||||
|
||||
/** Constructs a new compiler for a {@link Program} using the specified options. */
|
||||
constructor(program: Program, options: Options | null = null) {
|
||||
super(program.diagnostics);
|
||||
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)
|
||||
}
|
||||
|
||||
/** Performs compilation of the underlying {@link Program} to a {@link Module}. */
|
||||
compile(): Module {
|
||||
const program: Program = this.program;
|
||||
|
||||
@ -141,11 +155,11 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// make start function if not empty
|
||||
if (this.startFunctionBody.length) {
|
||||
let typeRef: BinaryenFunctionTypeRef = this.module.getFunctionTypeBySignature(BinaryenType.None, []);
|
||||
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(NativeType.None, []);
|
||||
if (!typeRef)
|
||||
typeRef = this.module.addFunctionType("v", BinaryenType.None, []);
|
||||
typeRef = this.module.addFunctionType("v", NativeType.None, []);
|
||||
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;
|
||||
element.type = type;
|
||||
}
|
||||
const binaryenType: BinaryenType = typeToBinaryenType(<Type>type);
|
||||
let initializer: BinaryenExpressionRef;
|
||||
const nativeType: NativeType = typeToNativeType(<Type>type);
|
||||
let initializer: ExpressionRef;
|
||||
let initializeInStart: bool;
|
||||
if (element.hasConstantValue) {
|
||||
if (type.isLongInteger)
|
||||
@ -304,23 +318,23 @@ export class Compiler extends DiagnosticEmitter {
|
||||
} else
|
||||
initializer = this.module.createI32(element.constantIntegerValue ? element.constantIntegerValue.toI32() : 0);
|
||||
initializeInStart = false;
|
||||
this.module.addGlobal(element.internalName, binaryenType, element.isMutable, initializer);
|
||||
this.module.addGlobal(element.internalName, nativeType, element.isMutable, initializer);
|
||||
} else if (declaration) {
|
||||
if (declaration.initializer) {
|
||||
initializer = this.compileExpression(declaration.initializer, type);
|
||||
initializeInStart = declaration.initializer.kind != NodeKind.LITERAL; // MVP doesn't support complex initializers
|
||||
} else {
|
||||
initializer = typeToBinaryenZero(this.module, type);
|
||||
initializer = typeToNativeZero(this.module, type);
|
||||
initializeInStart = false;
|
||||
}
|
||||
} else
|
||||
throw new Error("unexpected missing declaration or constant value");
|
||||
const internalName: string = element.internalName;
|
||||
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));
|
||||
} else
|
||||
this.module.addGlobal(internalName, BinaryenType.I32, element.isMutable, initializer);
|
||||
this.module.addGlobal(internalName, NativeType.I32, element.isMutable, initializer);
|
||||
return element.compiled = true;
|
||||
}
|
||||
|
||||
@ -340,10 +354,10 @@ export class Compiler extends DiagnosticEmitter {
|
||||
let previousInternalName: string | null = null;
|
||||
for (let [key, val] of element.members) {
|
||||
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) {
|
||||
const declaration: EnumValueDeclaration = val.declaration;
|
||||
let initializer: BinaryenExpressionRef;
|
||||
let initializer: ExpressionRef;
|
||||
let initializeInStart: bool = false;
|
||||
if (declaration.value) {
|
||||
initializer = this.compileExpression(<Expression>declaration.value, Type.i32);
|
||||
@ -353,16 +367,16 @@ export class Compiler extends DiagnosticEmitter {
|
||||
initializeInStart = false;
|
||||
} else {
|
||||
initializer = this.module.createBinary(BinaryOp.AddI32,
|
||||
this.module.createGetGlobal(previousInternalName, BinaryenType.I32),
|
||||
this.module.createGetGlobal(previousInternalName, NativeType.I32),
|
||||
this.module.createI32(1)
|
||||
);
|
||||
initializeInStart = true;
|
||||
}
|
||||
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));
|
||||
} else
|
||||
this.module.addGlobal(val.internalName, BinaryenType.I32, false, initializer);
|
||||
this.module.addGlobal(val.internalName, NativeType.I32, false, initializer);
|
||||
} else
|
||||
throw new Error("unexpected missing declaration or constant value");
|
||||
previousInternalName = val.internalName;
|
||||
@ -403,24 +417,24 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// compile statements
|
||||
const previousFunction: Function = this.currentFunction;
|
||||
this.currentFunction = instance;
|
||||
const stmts: BinaryenExpressionRef[] = this.compileStatements(<Statement[]>declaration.statements);
|
||||
const stmts: ExpressionRef[] = this.compileStatements(<Statement[]>declaration.statements);
|
||||
this.currentFunction = previousFunction;
|
||||
|
||||
// create the function
|
||||
let k: i32 = instance.parameters.length;
|
||||
const binaryenResultType: BinaryenType = typeToBinaryenType(instance.returnType);
|
||||
const binaryenParamTypes: BinaryenType[] = new Array(k);
|
||||
const binaryenResultType: NativeType = typeToNativeType(instance.returnType);
|
||||
const binaryenParamTypes: NativeType[] = new Array(k);
|
||||
const signatureNameParts: string[] = new Array(k + 1);
|
||||
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[k] = typeToSignatureNamePart(instance.returnType);
|
||||
let binaryenTypeRef: BinaryenFunctionTypeRef = this.module.getFunctionTypeBySignature(binaryenResultType, binaryenParamTypes);
|
||||
if (!binaryenTypeRef)
|
||||
binaryenTypeRef = this.module.addFunctionType(signatureNameParts.join(""), binaryenResultType, binaryenParamTypes);
|
||||
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(binaryenResultType, binaryenParamTypes);
|
||||
if (!typeRef)
|
||||
typeRef = this.module.addFunctionType(signatureNameParts.join(""), binaryenResultType, binaryenParamTypes);
|
||||
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)
|
||||
this.module.addExport(internalName, <string>instance.globalExportName);
|
||||
}
|
||||
@ -583,7 +597,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// statements
|
||||
|
||||
compileStatement(statement: Statement): BinaryenExpressionRef {
|
||||
compileStatement(statement: Statement): ExpressionRef {
|
||||
switch (statement.kind) {
|
||||
|
||||
case NodeKind.BLOCK:
|
||||
@ -631,19 +645,19 @@ export class Compiler extends DiagnosticEmitter {
|
||||
throw new Error("unexpected statement kind");
|
||||
}
|
||||
|
||||
compileStatements(statements: Statement[]): BinaryenExpressionRef[] {
|
||||
compileStatements(statements: Statement[]): ExpressionRef[] {
|
||||
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)
|
||||
stmts[i] = this.compileStatement(statements[i]);
|
||||
return stmts;
|
||||
}
|
||||
|
||||
compileBlockStatement(statement: BlockStatement): BinaryenExpressionRef {
|
||||
return this.module.createBlock(null, this.compileStatements(statement.statements), BinaryenType.None);
|
||||
compileBlockStatement(statement: BlockStatement): ExpressionRef {
|
||||
return this.module.createBlock(null, this.compileStatements(statement.statements), NativeType.None);
|
||||
}
|
||||
|
||||
compileBreakStatement(statement: BreakStatement): BinaryenExpressionRef {
|
||||
compileBreakStatement(statement: BreakStatement): ExpressionRef {
|
||||
if (statement.label)
|
||||
throw new Error("not implemented");
|
||||
const context: string | null = this.currentFunction.breakContext;
|
||||
@ -653,7 +667,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
|
||||
compileContinueStatement(statement: ContinueStatement): BinaryenExpressionRef {
|
||||
compileContinueStatement(statement: ContinueStatement): ExpressionRef {
|
||||
if (statement.label)
|
||||
throw new Error("not implemented");
|
||||
const context: string | null = this.currentFunction.breakContext;
|
||||
@ -663,10 +677,10 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
|
||||
compileDoStatement(statement: DoStatement): BinaryenExpressionRef {
|
||||
compileDoStatement(statement: DoStatement): ExpressionRef {
|
||||
const label: string = this.currentFunction.enterBreakContext();
|
||||
const condition: BinaryenExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||
const body: BinaryenExpressionRef = this.compileStatement(statement.statement);
|
||||
const condition: ExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||
const body: ExpressionRef = this.compileStatement(statement.statement);
|
||||
this.currentFunction.leaveBreakContext();
|
||||
const breakLabel: string = "break$" + label;
|
||||
const continueLabel: string = "continue$" + label;
|
||||
@ -675,24 +689,24 @@ export class Compiler extends DiagnosticEmitter {
|
||||
this.module.createBlock(null, [
|
||||
body,
|
||||
this.module.createBreak(continueLabel, condition)
|
||||
], BinaryenType.None))
|
||||
], BinaryenType.None);
|
||||
], NativeType.None))
|
||||
], NativeType.None);
|
||||
}
|
||||
|
||||
compileEmptyStatement(statement: EmptyStatement): BinaryenExpressionRef {
|
||||
compileEmptyStatement(statement: EmptyStatement): ExpressionRef {
|
||||
return this.module.createNop();
|
||||
}
|
||||
|
||||
compileExpressionStatement(statement: ExpressionStatement): BinaryenExpressionRef {
|
||||
compileExpressionStatement(statement: ExpressionStatement): ExpressionRef {
|
||||
return this.compileExpression(statement.expression, Type.void);
|
||||
}
|
||||
|
||||
compileForStatement(statement: ForStatement): BinaryenExpressionRef {
|
||||
compileForStatement(statement: ForStatement): ExpressionRef {
|
||||
const context: string = this.currentFunction.enterBreakContext();
|
||||
const initializer: BinaryenExpressionRef = 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 incrementor: BinaryenExpressionRef = statement.incrementor ? this.compileExpression(<Expression>statement.incrementor, Type.void) : this.module.createNop();
|
||||
const body: BinaryenExpressionRef = this.compileStatement(statement.statement);
|
||||
const initializer: ExpressionRef = statement.initializer ? this.compileStatement(<Statement>statement.initializer) : this.module.createNop();
|
||||
const condition: ExpressionRef = statement.condition ? this.compileExpression(<Expression>statement.condition, Type.i32) : this.module.createI32(1);
|
||||
const incrementor: ExpressionRef = statement.incrementor ? this.compileExpression(<Expression>statement.incrementor, Type.void) : this.module.createNop();
|
||||
const body: ExpressionRef = this.compileStatement(statement.statement);
|
||||
this.currentFunction.leaveBreakContext();
|
||||
const continueLabel: string = "continue$" + context;
|
||||
const breakLabel: string = "break$" + context;
|
||||
@ -703,27 +717,27 @@ export class Compiler extends DiagnosticEmitter {
|
||||
body,
|
||||
incrementor,
|
||||
this.module.createBreak(continueLabel)
|
||||
], BinaryenType.None))
|
||||
], BinaryenType.None))
|
||||
], BinaryenType.None);
|
||||
], NativeType.None))
|
||||
], NativeType.None))
|
||||
], NativeType.None);
|
||||
}
|
||||
|
||||
compileIfStatement(statement: IfStatement): BinaryenExpressionRef {
|
||||
const condition: BinaryenExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||
const ifTrue: BinaryenExpressionRef = this.compileStatement(statement.statement);
|
||||
const ifFalse: BinaryenExpressionRef = statement.elseStatement ? this.compileStatement(<Statement>statement.elseStatement) : 0;
|
||||
compileIfStatement(statement: IfStatement): ExpressionRef {
|
||||
const condition: ExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||
const ifTrue: ExpressionRef = this.compileStatement(statement.statement);
|
||||
const ifFalse: ExpressionRef = statement.elseStatement ? this.compileStatement(<Statement>statement.elseStatement) : 0;
|
||||
return this.module.createIf(condition, ifTrue, ifFalse);
|
||||
}
|
||||
|
||||
compileReturnStatement(statement: ReturnStatement): BinaryenExpressionRef {
|
||||
compileReturnStatement(statement: ReturnStatement): ExpressionRef {
|
||||
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.createUnreachable();
|
||||
}
|
||||
|
||||
compileSwitchStatement(statement: SwitchStatement): BinaryenExpressionRef {
|
||||
compileSwitchStatement(statement: SwitchStatement): ExpressionRef {
|
||||
const context: string = this.currentFunction.enterBreakContext();
|
||||
const previousDisallowContinue: bool = this.disallowContinue;
|
||||
this.disallowContinue = true;
|
||||
@ -733,18 +747,18 @@ export class Compiler extends DiagnosticEmitter {
|
||||
let i: i32, k: i32 = statement.cases.length;
|
||||
|
||||
// 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
|
||||
|
||||
// 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 defaultIndex: i32 = -1;
|
||||
for (i = 0; i < k; ++i) {
|
||||
const case_: SwitchCase = statement.cases[i];
|
||||
if (case_.label) {
|
||||
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)
|
||||
));
|
||||
} else
|
||||
@ -758,18 +772,18 @@ export class Compiler extends DiagnosticEmitter {
|
||||
) + "$" + context);
|
||||
|
||||
// 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) {
|
||||
const case_: SwitchCase = statement.cases[i];
|
||||
const nextLabel: string = i == k - 1
|
||||
? "break$" + context
|
||||
: "case" + (i + 1).toString(10) + "$" + context;
|
||||
const l: i32 = case_.statements.length;
|
||||
const body: BinaryenExpressionRef[] = new Array(1 + l);
|
||||
const body: ExpressionRef[] = new Array(1 + l);
|
||||
body[0] = currentBlock;
|
||||
for (let j: i32 = 0; j < l; ++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.disallowContinue = previousDisallowContinue;
|
||||
@ -777,17 +791,17 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return currentBlock;
|
||||
}
|
||||
|
||||
compileThrowStatement(statement: ThrowStatement): BinaryenExpressionRef {
|
||||
compileThrowStatement(statement: ThrowStatement): ExpressionRef {
|
||||
return this.module.createUnreachable(); // TODO: waiting for exception-handling spec
|
||||
}
|
||||
|
||||
compileTryStatement(statement: TryStatement): BinaryenExpressionRef {
|
||||
compileTryStatement(statement: TryStatement): ExpressionRef {
|
||||
throw new Error("not implemented");
|
||||
// can't yet support something like: try { return ... } finally { ... }
|
||||
// worthwhile to investigate lowering returns to block results (here)?
|
||||
}
|
||||
|
||||
compileVariableStatement(statement: VariableStatement): BinaryenExpressionRef {
|
||||
compileVariableStatement(statement: VariableStatement): ExpressionRef {
|
||||
const declarations: VariableDeclaration[] = statement.declarations;
|
||||
|
||||
// top-level variables become globals
|
||||
@ -798,7 +812,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.module.createNop();
|
||||
}
|
||||
// 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) {
|
||||
const declaration: VariableDeclaration = declarations[i];
|
||||
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 condition: BinaryenExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||
const condition: ExpressionRef = this.compileExpression(statement.condition, Type.i32);
|
||||
const breakLabel: string = "break$" + label;
|
||||
const continueLabel: string = "continue$" + label;
|
||||
const body: BinaryenExpressionRef = this.compileStatement(statement.statement);
|
||||
const body: ExpressionRef = this.compileStatement(statement.statement);
|
||||
this.currentFunction.leaveBreakContext();
|
||||
return this.module.createBlock(breakLabel, [
|
||||
this.module.createLoop(continueLabel,
|
||||
this.module.createIf(condition, this.module.createBlock(null, [
|
||||
body,
|
||||
this.module.createBreak(continueLabel)
|
||||
], BinaryenType.None))
|
||||
], NativeType.None))
|
||||
)
|
||||
], BinaryenType.None);
|
||||
], NativeType.None);
|
||||
}
|
||||
|
||||
// expressions
|
||||
|
||||
compileExpression(expression: Expression, contextualType: Type, convert: bool = true): BinaryenExpressionRef {
|
||||
compileExpression(expression: Expression, contextualType: Type, convert: bool = true): ExpressionRef {
|
||||
this.currentType = contextualType;
|
||||
|
||||
let expr: BinaryenExpressionRef;
|
||||
let expr: ExpressionRef;
|
||||
switch (expression.kind) {
|
||||
|
||||
case NodeKind.ASSERTION:
|
||||
@ -906,7 +920,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return expr;
|
||||
}
|
||||
|
||||
convertExpression(expr: BinaryenExpressionRef, fromType: Type, toType: Type): BinaryenExpressionRef {
|
||||
convertExpression(expr: ExpressionRef, fromType: Type, toType: Type): ExpressionRef {
|
||||
|
||||
// void to any
|
||||
if (fromType.kind == TypeKind.VOID)
|
||||
@ -1059,19 +1073,19 @@ export class Compiler extends DiagnosticEmitter {
|
||||
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
|
||||
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.compileExpression(expression.expression, contextualType);
|
||||
}
|
||||
|
||||
compileBinaryExpression(expression: BinaryExpression, contextualType: Type): BinaryenExpressionRef {
|
||||
compileBinaryExpression(expression: BinaryExpression, contextualType: Type): ExpressionRef {
|
||||
let op: BinaryOp;
|
||||
let left: BinaryenExpressionRef;
|
||||
let right: BinaryenExpressionRef;
|
||||
let left: ExpressionRef;
|
||||
let right: ExpressionRef;
|
||||
let compound: Token = 0;
|
||||
|
||||
switch (expression.operator) {
|
||||
@ -1287,12 +1301,12 @@ export class Compiler extends DiagnosticEmitter {
|
||||
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);
|
||||
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);
|
||||
if (!element)
|
||||
return this.module.createUnreachable();
|
||||
@ -1307,12 +1321,12 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
if (element.kind == ElementKind.GLOBAL && (<Global>element).type) {
|
||||
if (tee) {
|
||||
const globalBinaryenType: BinaryenType = typeToBinaryenType(<Type>(<Global>element).type);
|
||||
const globalNativeType: NativeType = typeToNativeType(<Type>(<Global>element).type);
|
||||
this.currentType = <Type>(<Global>element).type;
|
||||
return this.module.createBlock(null, [ // teeGlobal
|
||||
this.module.createSetGlobal((<Global>element).internalName, valueWithCorrectType),
|
||||
this.module.createGetGlobal((<Global>element).internalName, globalBinaryenType)
|
||||
], globalBinaryenType);
|
||||
this.module.createGetGlobal((<Global>element).internalName, globalNativeType)
|
||||
], globalNativeType);
|
||||
}
|
||||
return this.module.createSetGlobal((<Global>element).internalName, valueWithCorrectType);
|
||||
}
|
||||
@ -1322,7 +1336,17 @@ export class Compiler extends DiagnosticEmitter {
|
||||
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
|
||||
if (!element)
|
||||
return this.module.createUnreachable();
|
||||
@ -1336,40 +1360,57 @@ export class Compiler extends DiagnosticEmitter {
|
||||
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)
|
||||
this.compileFunction(functionInstance);
|
||||
|
||||
// validate and compile arguments
|
||||
const parameters: Parameter[] = functionInstance.parameters;
|
||||
let k: i32 = parameters.length;
|
||||
if (argumentExpressions.length > k) {
|
||||
this.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, k.toString(10), argumentExpressions.length.toString(10));
|
||||
const parameterCount: i32 = parameters.length;
|
||||
const argumentCount: i32 = argumentExpressions.length;
|
||||
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();
|
||||
}
|
||||
const operands: BinaryenExpressionRef[] = new Array(k);
|
||||
for (let i: i32 = 0; i < k; ++i) {
|
||||
const operands: ExpressionRef[] = new Array(parameterCount);
|
||||
for (let i: i32 = 0; i < parameterCount; ++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 {
|
||||
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);
|
||||
} else {
|
||||
this.error(DiagnosticCode.Expected_at_least_0_arguments_but_got_1, reportNode.range, (i + 1).toString(10), argumentExpressions.length.toString(10));
|
||||
} else { // too few arguments
|
||||
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.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
|
||||
if (!element)
|
||||
return this.module.createUnreachable();
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
compileIdentifierExpression(expression: IdentifierExpression, contextualType: Type): BinaryenExpressionRef {
|
||||
compileIdentifierExpression(expression: IdentifierExpression, contextualType: Type): ExpressionRef {
|
||||
|
||||
// null
|
||||
if (expression.kind == NodeKind.NULL) {
|
||||
@ -1397,7 +1438,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
} else if (expression.kind == NodeKind.THIS) {
|
||||
if (this.currentFunction.instanceMethodOf) {
|
||||
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.currentType = this.options.target == Target.WASM64 ? Type.u64 : Type.u32;
|
||||
@ -1431,12 +1472,12 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// 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
|
||||
if (element.kind == ElementKind.GLOBAL)
|
||||
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();
|
||||
|
||||
// field
|
||||
@ -1451,7 +1492,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
|
||||
compileLiteralExpression(expression: LiteralExpression, contextualType: Type): BinaryenExpressionRef {
|
||||
compileLiteralExpression(expression: LiteralExpression, contextualType: Type): ExpressionRef {
|
||||
switch (expression.literalKind) {
|
||||
// case LiteralKind.ARRAY:
|
||||
|
||||
@ -1484,62 +1525,62 @@ export class Compiler extends DiagnosticEmitter {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
compileNewExpression(expression: NewExpression, contextualType: Type): BinaryenExpressionRef {
|
||||
compileNewExpression(expression: NewExpression, contextualType: Type): ExpressionRef {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
compileParenthesizedExpression(expression: ParenthesizedExpression, contextualType: Type): BinaryenExpressionRef {
|
||||
compileParenthesizedExpression(expression: ParenthesizedExpression, contextualType: Type): ExpressionRef {
|
||||
return this.compileExpression(expression.expression, contextualType);
|
||||
}
|
||||
|
||||
compilePropertyAccessExpression(expression: PropertyAccessExpression, contextualType: Type): BinaryenExpressionRef {
|
||||
compilePropertyAccessExpression(expression: PropertyAccessExpression, contextualType: Type): ExpressionRef {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
compileSelectExpression(expression: SelectExpression, contextualType: Type): BinaryenExpressionRef {
|
||||
const condition: BinaryenExpressionRef = this.compileExpression(expression.condition, Type.i32);
|
||||
const ifThen: BinaryenExpressionRef = this.compileExpression(expression.ifThen, contextualType);
|
||||
const ifElse: BinaryenExpressionRef = this.compileExpression(expression.ifElse, contextualType);
|
||||
compileSelectExpression(expression: SelectExpression, contextualType: Type): ExpressionRef {
|
||||
const condition: ExpressionRef = this.compileExpression(expression.condition, Type.i32);
|
||||
const ifThen: ExpressionRef = this.compileExpression(expression.ifThen, contextualType);
|
||||
const ifElse: ExpressionRef = this.compileExpression(expression.ifElse, contextualType);
|
||||
return this.module.createSelect(condition, ifThen, ifElse);
|
||||
}
|
||||
|
||||
compileUnaryPostfixExpression(expression: UnaryPostfixExpression, contextualType: Type): BinaryenExpressionRef {
|
||||
compileUnaryPostfixExpression(expression: UnaryPostfixExpression, contextualType: Type): ExpressionRef {
|
||||
const operator: Token = expression.operator;
|
||||
|
||||
let op: BinaryOp;
|
||||
let binaryenType: BinaryenType;
|
||||
let binaryenOne: BinaryenExpressionRef;
|
||||
let nativeType: NativeType;
|
||||
let nativeOne: ExpressionRef;
|
||||
|
||||
if (contextualType == Type.f32) {
|
||||
op = operator == Token.PLUS_PLUS ? BinaryOp.AddF32 : BinaryOp.SubF32;
|
||||
binaryenType = BinaryenType.F32;
|
||||
binaryenOne = this.module.createF32(1);
|
||||
nativeType = NativeType.F32;
|
||||
nativeOne = this.module.createF32(1);
|
||||
} else if (contextualType == Type.f64) {
|
||||
op = operator == Token.PLUS_PLUS ? BinaryOp.AddF64 : BinaryOp.SubF64;
|
||||
binaryenType = BinaryenType.F64;
|
||||
binaryenOne = this.module.createF64(1);
|
||||
nativeType = NativeType.F64;
|
||||
nativeOne = this.module.createF64(1);
|
||||
} else if (contextualType.isLongInteger) {
|
||||
op = operator == Token.PLUS_PLUS ? BinaryOp.AddI64 : BinaryOp.SubI64;
|
||||
binaryenType = BinaryenType.I64;
|
||||
binaryenOne = this.module.createI64(1, 0);
|
||||
nativeType = NativeType.I64;
|
||||
nativeOne = this.module.createI64(1, 0);
|
||||
} else {
|
||||
op = operator == Token.PLUS_PLUS ? BinaryOp.AddI32 : BinaryOp.SubI32;
|
||||
binaryenType = BinaryenType.I32;
|
||||
binaryenOne = this.module.createI32(1);
|
||||
nativeType = NativeType.I32;
|
||||
nativeOne = this.module.createI32(1);
|
||||
}
|
||||
const getValue: BinaryenExpressionRef = this.compileExpression(expression.expression, contextualType);
|
||||
const setValue: BinaryenExpressionRef = this.compileAssignmentWithValue(expression.expression, this.module.createBinary(op, getValue, binaryenOne), false); // reports
|
||||
const getValue: ExpressionRef = this.compileExpression(expression.expression, contextualType);
|
||||
const setValue: ExpressionRef = this.compileAssignmentWithValue(expression.expression, this.module.createBinary(op, getValue, nativeOne), false); // reports
|
||||
|
||||
return this.module.createBlock(null, [
|
||||
getValue,
|
||||
setValue
|
||||
], binaryenType);
|
||||
], nativeType);
|
||||
}
|
||||
|
||||
compileUnaryPrefixExpression(expression: UnaryPrefixExpression, contextualType: Type): BinaryenExpressionRef {
|
||||
compileUnaryPrefixExpression(expression: UnaryPrefixExpression, contextualType: Type): ExpressionRef {
|
||||
const operandExpression: Expression = expression.expression;
|
||||
|
||||
let operand: BinaryenExpressionRef;
|
||||
let operand: ExpressionRef;
|
||||
let op: UnaryOp;
|
||||
|
||||
switch (expression.operator) {
|
||||
@ -1610,27 +1651,27 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// helpers
|
||||
|
||||
function typeToBinaryenType(type: Type): BinaryenType {
|
||||
function typeToNativeType(type: Type): NativeType {
|
||||
return type.kind == TypeKind.F32
|
||||
? BinaryenType.F32
|
||||
? NativeType.F32
|
||||
: type.kind == TypeKind.F64
|
||||
? BinaryenType.F64
|
||||
? NativeType.F64
|
||||
: type.isLongInteger
|
||||
? BinaryenType.I64
|
||||
? NativeType.I64
|
||||
: type.isAnyInteger || type.kind == TypeKind.BOOL
|
||||
? BinaryenType.I32
|
||||
: BinaryenType.None;
|
||||
? NativeType.I32
|
||||
: NativeType.None;
|
||||
}
|
||||
|
||||
function typesToBinaryenTypes(types: Type[]): BinaryenType[] {
|
||||
function typesToNativeTypes(types: Type[]): NativeType[] {
|
||||
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)
|
||||
ret[i] = typeToBinaryenType(types[i]);
|
||||
ret[i] = typeToNativeType(types[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function typeToBinaryenZero(module: Module, type: Type): BinaryenExpressionRef {
|
||||
function typeToNativeZero(module: Module, type: Type): ExpressionRef {
|
||||
return type.kind == TypeKind.F32
|
||||
? module.createF32(0)
|
||||
: type.kind == TypeKind.F64
|
||||
@ -1640,7 +1681,7 @@ function typeToBinaryenZero(module: Module, type: Type): BinaryenExpressionRef {
|
||||
: module.createI32(0);
|
||||
}
|
||||
|
||||
function typeToBinaryenOne(module: Module, type: Type): BinaryenExpressionRef {
|
||||
function typeToBinaryenOne(module: Module, type: Type): ExpressionRef {
|
||||
return type.kind == TypeKind.F32
|
||||
? module.createF32(1)
|
||||
: type.kind == TypeKind.F64
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
export const PATH_DELIMITER: string = "/";
|
||||
export const PARENT_SUBST: string = "..";
|
||||
export const GETTER_PREFIX: string = "get ";
|
||||
export const SETTER_PREFIX: string = "set ";
|
||||
export const GETTER_PREFIX: string = "get_";
|
||||
export const SETTER_PREFIX: string = "set_";
|
||||
export const INSTANCE_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 _BinaryenNop(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 _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;
|
||||
@ -263,6 +265,12 @@ declare function _BinaryenConstGetValueF64(expr: BinaryenExpressionRef): f64;
|
||||
declare type BinaryenFunctionRef = usize;
|
||||
|
||||
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;
|
||||
|
||||
@ -289,7 +297,7 @@ declare function _BinaryenModulePrint(module: BinaryenModuleRef): void;
|
||||
declare function _BinaryenModulePrintAsmjs(module: BinaryenModuleRef): void;
|
||||
declare function _BinaryenModuleValidate(module: BinaryenModuleRef): i32;
|
||||
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 _BinaryenModuleWrite(module: BinaryenModuleRef, output: CString, outputSize: usize): usize;
|
||||
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 { DiagnosticMessage, DiagnosticCategory } from "./diagnostics";
|
||||
import { Parser } from "./parser";
|
||||
|
@ -1,7 +1,16 @@
|
||||
import { I64, U64 } from "./util";
|
||||
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(),
|
||||
I32 = _BinaryenInt32(),
|
||||
I64 = _BinaryenInt64(),
|
||||
@ -201,11 +210,11 @@ export class MemorySegment {
|
||||
|
||||
export class Module {
|
||||
|
||||
ref: BinaryenModuleRef;
|
||||
ref: ModuleRef;
|
||||
lit: BinaryenLiteral;
|
||||
noEmit: bool;
|
||||
|
||||
static MAX_MEMORY_WASM32: BinaryenIndex = 0xffff;
|
||||
static MAX_MEMORY_WASM32: Index = 0xffff;
|
||||
|
||||
static create(): Module {
|
||||
const module: Module = new Module();
|
||||
@ -240,7 +249,7 @@ export class Module {
|
||||
|
||||
// types
|
||||
|
||||
addFunctionType(name: string, result: Type, paramTypes: Type[]): BinaryenFunctionRef {
|
||||
addFunctionType(name: string, result: NativeType, paramTypes: NativeType[]): FunctionRef {
|
||||
if (this.noEmit) return 0;
|
||||
const cStr: CString = allocString(name);
|
||||
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;
|
||||
const cArr: CArray<i32> = allocI32Array(paramTypes);
|
||||
try {
|
||||
@ -264,63 +273,63 @@ export class Module {
|
||||
|
||||
// expressions
|
||||
|
||||
createI32(value: i32): BinaryenExpressionRef {
|
||||
createI32(value: i32): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
_BinaryenLiteralInt32(this.lit, value);
|
||||
return _BinaryenConst(this.ref, this.lit);
|
||||
}
|
||||
|
||||
createI64(lo: i32, hi: i32): BinaryenExpressionRef {
|
||||
createI64(lo: i32, hi: i32): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
_BinaryenLiteralInt64(this.lit, lo, hi);
|
||||
return _BinaryenConst(this.ref, this.lit);
|
||||
}
|
||||
|
||||
createF32(value: f32): BinaryenExpressionRef {
|
||||
createF32(value: f32): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
_BinaryenLiteralFloat32(this.lit, value);
|
||||
return _BinaryenConst(this.ref, this.lit);
|
||||
}
|
||||
|
||||
createF64(value: f64): BinaryenExpressionRef {
|
||||
createF64(value: f64): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
_BinaryenLiteralFloat64(this.lit, value);
|
||||
return _BinaryenConst(this.ref, this.lit);
|
||||
}
|
||||
|
||||
createUnary(op: UnaryOp, expr: BinaryenExpressionRef): BinaryenExpressionRef {
|
||||
createUnary(op: UnaryOp, expr: ExpressionRef): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
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;
|
||||
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;
|
||||
const cStr: CString = allocString(name);
|
||||
const cArr: CArray<i32> = allocI32Array(operands);
|
||||
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 {
|
||||
_free(cArr);
|
||||
_free(cStr);
|
||||
}
|
||||
}
|
||||
|
||||
createGetLocal(index: i32, type: Type): BinaryenExpressionRef {
|
||||
createGetLocal(index: i32, type: NativeType): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
return _BinaryenGetLocal(this.ref, index, type);
|
||||
}
|
||||
|
||||
createTeeLocal(index: i32, value: BinaryenExpressionRef): BinaryenExpressionRef {
|
||||
createTeeLocal(index: i32, value: ExpressionRef): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
return _BinaryenTeeLocal(this.ref, index, value);
|
||||
}
|
||||
|
||||
createGetGlobal(name: string, type: Type): BinaryenExpressionRef {
|
||||
createGetGlobal(name: string, type: NativeType): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
const cStr: CString = allocString(name);
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
return _BinaryenAtomicWake(this.ref, ptr, wakeCount);
|
||||
}
|
||||
|
||||
// statements
|
||||
|
||||
createSetLocal(index: i32, value: BinaryenExpressionRef): BinaryenExpressionRef {
|
||||
createSetLocal(index: Index, value: ExpressionRef): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
return _BinaryenSetLocal(this.ref, index, value);
|
||||
}
|
||||
|
||||
createSetGlobal(name: string, value: BinaryenExpressionRef): BinaryenExpressionRef {
|
||||
createSetGlobal(name: string, value: ExpressionRef): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
const cStr: CString = allocString(name);
|
||||
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;
|
||||
const cStr: CString = allocString(label);
|
||||
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;
|
||||
const cStr: CString = allocString(label);
|
||||
try {
|
||||
@ -389,12 +418,12 @@ export class Module {
|
||||
}
|
||||
}
|
||||
|
||||
createDrop(expression: BinaryenExpressionRef): BinaryenExpressionRef {
|
||||
createDrop(expression: ExpressionRef): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
return _BinaryenDrop(this.ref, expression);
|
||||
}
|
||||
|
||||
createLoop(label: string | null, body: BinaryenExpressionRef): BinaryenExpressionRef {
|
||||
createLoop(label: string | null, body: ExpressionRef): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
const cStr: CString = allocString(label);
|
||||
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;
|
||||
return _BinaryenIf(this.ref, condition, ifTrue, ifFalse);
|
||||
}
|
||||
|
||||
createNop(): BinaryenExpressionRef {
|
||||
createNop(): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
return _BinaryenNop(this.ref);
|
||||
}
|
||||
|
||||
createReturn(expression: BinaryenExpressionRef = 0): BinaryenExpressionRef {
|
||||
createReturn(expression: ExpressionRef = 0): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
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;
|
||||
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;
|
||||
const strs: CString[] = new Array(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;
|
||||
const cStr: CString = allocString(target);
|
||||
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;
|
||||
const cStr: CString = allocString(target);
|
||||
const cArr: CArray<i32> = allocI32Array(operands);
|
||||
@ -464,14 +493,14 @@ export class Module {
|
||||
}
|
||||
}
|
||||
|
||||
createUnreachable(): BinaryenExpressionRef {
|
||||
createUnreachable(): ExpressionRef {
|
||||
if (this.noEmit) return 0;
|
||||
return _BinaryenUnreachable(this.ref);
|
||||
}
|
||||
|
||||
// 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;
|
||||
const cStr: CString = allocString(name);
|
||||
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;
|
||||
const cStr: CString = allocString(name);
|
||||
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;
|
||||
const cStr1: CString = allocString(internalName);
|
||||
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;
|
||||
const cStr1: CString = allocString(internalName);
|
||||
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;
|
||||
const cStr: CString = allocString(exportName);
|
||||
let i: i32, k: i32 = segments.length;
|
||||
const segs: CArray<u8>[] = new Array(k);
|
||||
const offs: BinaryenExpressionRef[] = new Array(k);
|
||||
const sizs: BinaryenIndex[] = new Array(k);
|
||||
const offs: ExpressionRef[] = new Array(k);
|
||||
const sizs: Index[] = new Array(k);
|
||||
for (i = 0; i < k; ++i) {
|
||||
const buffer: Uint8Array = segments[i].buffer;
|
||||
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;
|
||||
_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);
|
||||
}
|
||||
|
||||
export function getExpressionType(expr: BinaryenExpressionRef): Type {
|
||||
export function getExpressionType(expr: ExpressionRef): NativeType {
|
||||
return _BinaryenExpressionGetType(expr);
|
||||
}
|
||||
|
||||
export function printExpression(expr: BinaryenExpressionRef): void {
|
||||
export function printExpression(expr: ExpressionRef): void {
|
||||
return _BinaryenExpressionPrint(expr);
|
||||
}
|
||||
|
||||
export function getConstValueI32(expr: BinaryenExpressionRef): i32 {
|
||||
export function getConstValueI32(expr: ExpressionRef): i32 {
|
||||
return _BinaryenConstGetValueI32(expr);
|
||||
}
|
||||
|
||||
export function getConstValueI64Low(expr: BinaryenExpressionRef): i32 {
|
||||
export function getConstValueI64Low(expr: ExpressionRef): i32 {
|
||||
return _BinaryenConstGetValueI64Low(expr);
|
||||
}
|
||||
|
||||
export function getConstValueI64High(expr: BinaryenExpressionRef): i32 {
|
||||
export function getConstValueI64High(expr: ExpressionRef): i32 {
|
||||
return _BinaryenConstGetValueI64High(expr);
|
||||
}
|
||||
|
||||
export function getConstValueI64(expr: BinaryenExpressionRef): I64 {
|
||||
export function getConstValueI64(expr: ExpressionRef): I64 {
|
||||
return new I64(
|
||||
_BinaryenConstGetValueI64Low(expr),
|
||||
_BinaryenConstGetValueI64High(expr)
|
||||
);
|
||||
}
|
||||
|
||||
export function getConstValueF32(expr: BinaryenExpressionRef): f32 {
|
||||
export function getConstValueF32(expr: ExpressionRef): f32 {
|
||||
return _BinaryenConstGetValueF32(expr);
|
||||
}
|
||||
|
||||
export function getConstValueF64(expr: BinaryenExpressionRef): f64 {
|
||||
export function getConstValueF64(expr: ExpressionRef): f64 {
|
||||
return _BinaryenConstGetValueF64(expr);
|
||||
}
|
||||
|
||||
@ -658,22 +687,22 @@ export class Relooper {
|
||||
|
||||
private constructor() {}
|
||||
|
||||
addBlock(code: BinaryenExpressionRef): RelooperBlockRef {
|
||||
addBlock(code: ExpressionRef): RelooperBlockRef {
|
||||
if (this.noEmit) return 0;
|
||||
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;
|
||||
_RelooperAddBranch(from, to, condition, code);
|
||||
}
|
||||
|
||||
addBlockWithSwitch(code: BinaryenExpressionRef, condition: BinaryenExpressionRef): RelooperBlockRef {
|
||||
addBlockWithSwitch(code: ExpressionRef, condition: ExpressionRef): RelooperBlockRef {
|
||||
if (this.noEmit) return 0;
|
||||
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;
|
||||
const cArr: CArray<i32> = allocI32Array(indexes);
|
||||
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;
|
||||
return _RelooperRenderAndDispose(this.ref, entry, labelHelper, this.module.ref);
|
||||
}
|
@ -832,7 +832,7 @@ export class Function extends Element {
|
||||
template: FunctionPrototype;
|
||||
/** Concrete type arguments. */
|
||||
typeArguments: Type[];
|
||||
/** Concrete function parameters. */
|
||||
/** Concrete function parameters. Excluding `this` if an instance method. */
|
||||
parameters: Parameter[];
|
||||
/** Concrete return type. */
|
||||
returnType: Type;
|
||||
@ -877,7 +877,7 @@ export class Function extends Element {
|
||||
addLocal(type: Type, name: string | null = null): Local {
|
||||
// if it has a name, check previously as this method will throw otherwise
|
||||
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);
|
||||
if (name) {
|
||||
if (this.locals.has(<string>name))
|
||||
|
@ -20,15 +20,15 @@
|
||||
},
|
||||
"files": [
|
||||
"ast.ts",
|
||||
"binaryen.d.ts",
|
||||
"binaryen.ts",
|
||||
"compiler.ts",
|
||||
"diagnosticMessages.generated.ts",
|
||||
"diagnostics.ts",
|
||||
"evaluator.ts",
|
||||
"glue/binaryen.d.ts",
|
||||
"glue/js.d.ts",
|
||||
"glue/js.ts",
|
||||
"index.ts",
|
||||
"moddule.ts",
|
||||
"parser.ts",
|
||||
"program.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, "");
|
||||
parser.parseFile(text, filename, true);
|
||||
var sb: string[] = [];
|
||||
if (isTree) {
|
||||
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);
|
||||
parser.program.sources[0].serialize(sb);
|
||||
const actual = sb.join("");
|
||||
const expected = isTree ? text : text.replace(/^\s+/mg, "");
|
||||
const diffs = diff.diffLines(expected, actual);
|
||||
|
Loading…
x
Reference in New Issue
Block a user