mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 07:02:13 +00:00
More tests and fixes (unary, binary, globals)
This commit is contained in:
parent
ef859937a8
commit
b9edfb5185
@ -925,12 +925,13 @@ export abstract class Statement extends Node {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static createVariableDeclaration(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, range: Range): VariableDeclaration {
|
||||
static createVariableDeclaration(identifier: IdentifierExpression, type: TypeNode | null, initializer: Expression | null, modifiers: Modifier[] | null, range: Range): VariableDeclaration {
|
||||
const elem: VariableDeclaration = new VariableDeclaration();
|
||||
elem.range = range;
|
||||
(elem.identifier = identifier).parent = elem;
|
||||
if (elem.type = type) (<TypeNode>type).parent = elem;
|
||||
if (elem.initializer = initializer) (<Expression>initializer).parent = elem;
|
||||
elem.modifiers = modifiers;
|
||||
return elem;
|
||||
}
|
||||
|
||||
@ -1681,7 +1682,7 @@ export class TryStatement extends Statement {
|
||||
export class VariableDeclaration extends VariableLikeDeclarationStatement {
|
||||
|
||||
kind = NodeKind.VARIABLEDECLARATION;
|
||||
modifiers = null;
|
||||
modifiers: Modifier[] | null;
|
||||
|
||||
serialize(sb: string[]): void {
|
||||
this.identifier.serialize(sb);
|
||||
|
172
src/compiler.ts
172
src/compiler.ts
@ -90,6 +90,15 @@ export class Options {
|
||||
noTreeShaking: bool = false;
|
||||
}
|
||||
|
||||
const enum ConversionKind {
|
||||
/** No conversion. */
|
||||
NONE,
|
||||
/** Implicit conversion. */
|
||||
IMPLICIT,
|
||||
/** Explicit conversion. */
|
||||
EXPLICIT
|
||||
}
|
||||
|
||||
export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
/** Program reference. */
|
||||
@ -141,7 +150,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
compile(): Module {
|
||||
const program: Program = this.program;
|
||||
|
||||
// initialize lookup maps
|
||||
// initialize lookup maps, builtins, imports, exports, etc.
|
||||
program.initialize(this.options.target);
|
||||
|
||||
// compile entry file (exactly one, usually)
|
||||
@ -181,7 +190,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
heapStartBuffer[7] = (initial.hi >>> 24) as u8;
|
||||
} else {
|
||||
if (!initial.fitsInU32)
|
||||
throw new Error("memory size overflow");
|
||||
throw new Error("static memory size overflows 32 bits");
|
||||
heapStartBuffer = new Uint8Array(4);
|
||||
heapStartOffset = 4;
|
||||
heapStartBuffer[0] = (initial.lo ) as u8;
|
||||
@ -299,6 +308,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return false;
|
||||
element.type = type;
|
||||
}
|
||||
if (this.module.noEmit)
|
||||
return true;
|
||||
const nativeType: NativeType = typeToNativeType(<Type>type);
|
||||
let initializer: ExpressionRef;
|
||||
let initializeInStart: bool;
|
||||
@ -331,10 +342,10 @@ export class Compiler extends DiagnosticEmitter {
|
||||
throw new Error("unexpected missing declaration or constant value");
|
||||
const internalName: string = element.internalName;
|
||||
if (initializeInStart) {
|
||||
this.module.addGlobal(internalName, NativeType.I32, true, this.module.createI32(-1));
|
||||
this.module.addGlobal(internalName, nativeType, true, this.module.createI32(-1));
|
||||
this.startFunctionBody.push(this.module.createSetGlobal(internalName, initializer));
|
||||
} else
|
||||
this.module.addGlobal(internalName, NativeType.I32, element.isMutable, initializer);
|
||||
this.module.addGlobal(internalName, nativeType, element.isMutable, initializer);
|
||||
return element.isCompiled = true;
|
||||
}
|
||||
|
||||
@ -350,7 +361,6 @@ export class Compiler extends DiagnosticEmitter {
|
||||
compileEnum(element: Enum): void {
|
||||
if (element.isCompiled)
|
||||
return;
|
||||
element.isCompiled = true;
|
||||
let previousInternalName: string | null = null;
|
||||
for (let [key, val] of element.members) {
|
||||
if (val.hasConstantValue) {
|
||||
@ -381,6 +391,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
throw new Error("unexpected missing declaration or constant value");
|
||||
previousInternalName = val.internalName;
|
||||
}
|
||||
element.isCompiled = true;
|
||||
}
|
||||
|
||||
// functions
|
||||
@ -405,8 +416,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return;
|
||||
|
||||
const declaration: FunctionDeclaration | null = instance.template.declaration;
|
||||
if (!declaration) // TODO: compile builtins
|
||||
throw new Error("not implemented");
|
||||
if (!declaration)
|
||||
throw new Error("unexpected missing declaration");
|
||||
|
||||
if (!declaration.statements) {
|
||||
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.identifier.range);
|
||||
@ -588,7 +599,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
const previousType: Type = this.currentType;
|
||||
const previousNoEmit: bool = this.module.noEmit;
|
||||
this.module.noEmit = true;
|
||||
this.compileExpression(expression, contextualType, false); // now performs a dry run
|
||||
this.compileExpression(expression, contextualType, ConversionKind.NONE); // now performs a dry run
|
||||
const type: Type = this.currentType;
|
||||
this.currentType = previousType;
|
||||
this.module.noEmit = previousNoEmit;
|
||||
@ -698,7 +709,12 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
compileExpressionStatement(statement: ExpressionStatement): ExpressionRef {
|
||||
return this.compileExpression(statement.expression, Type.void);
|
||||
let expr: ExpressionRef = this.compileExpression(statement.expression, Type.void, ConversionKind.NONE);
|
||||
if (this.currentType != Type.void) {
|
||||
expr = this.module.createDrop(expr);
|
||||
this.currentType = Type.void;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
compileForStatement(statement: ForStatement): ExpressionRef {
|
||||
@ -850,7 +866,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// expressions
|
||||
|
||||
compileExpression(expression: Expression, contextualType: Type, convert: bool = true): ExpressionRef {
|
||||
compileExpression(expression: Expression, contextualType: Type, conversionKind: ConversionKind = ConversionKind.IMPLICIT): ExpressionRef {
|
||||
this.currentType = contextualType;
|
||||
|
||||
let expr: ExpressionRef;
|
||||
@ -912,19 +928,22 @@ export class Compiler extends DiagnosticEmitter {
|
||||
throw new Error("unexpected expression kind");
|
||||
}
|
||||
|
||||
if (convert && this.currentType != contextualType) {
|
||||
expr = this.convertExpression(expr, this.currentType, contextualType);
|
||||
if (conversionKind != ConversionKind.NONE) {
|
||||
expr = this.convertExpression(expr, this.currentType, contextualType, conversionKind, expression);
|
||||
this.currentType = contextualType;
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
convertExpression(expr: ExpressionRef, fromType: Type, toType: Type): ExpressionRef {
|
||||
convertExpression(expr: ExpressionRef, fromType: Type, toType: Type, conversionKind: ConversionKind, reportNode: Node): ExpressionRef {
|
||||
if (conversionKind == ConversionKind.NONE)
|
||||
return expr;
|
||||
|
||||
// void to any
|
||||
if (fromType.kind == TypeKind.VOID)
|
||||
if (fromType.kind == TypeKind.VOID) {
|
||||
this.error(DiagnosticCode.Operation_not_supported, reportNode.range);
|
||||
throw new Error("unexpected conversion from void");
|
||||
}
|
||||
|
||||
// any to void
|
||||
if (toType.kind == TypeKind.VOID)
|
||||
@ -1070,16 +1089,17 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
if (losesInformation && conversionKind == ConversionKind.IMPLICIT)
|
||||
this.error(DiagnosticCode.Conversion_from_type_0_to_1_requires_an_explicit_cast, reportNode.range, fromType.toString(), toType.toString());
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
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: ExpressionRef = this.compileExpression(expression.expression, <Type>toType, false);
|
||||
return this.convertExpression(expr, this.currentType, <Type>toType);
|
||||
}
|
||||
return this.compileExpression(expression.expression, contextualType);
|
||||
return toType && toType != contextualType
|
||||
? this.compileExpression(expression.expression, <Type>toType, ConversionKind.EXPLICIT)
|
||||
: this.compileExpression(expression.expression, contextualType);
|
||||
}
|
||||
|
||||
compileBinaryExpression(expression: BinaryExpression, contextualType: Type): ExpressionRef {
|
||||
@ -1091,7 +1111,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
switch (expression.operator) {
|
||||
|
||||
case Token.LESSTHAN:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType == Type.f32
|
||||
? BinaryOp.LtF32
|
||||
@ -1104,7 +1124,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
break;
|
||||
|
||||
case Token.GREATERTHAN:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType == Type.f32
|
||||
? BinaryOp.GtF32
|
||||
@ -1117,7 +1137,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
break;
|
||||
|
||||
case Token.LESSTHAN_EQUALS:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType == Type.f32
|
||||
? BinaryOp.LeF32
|
||||
@ -1130,7 +1150,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
break;
|
||||
|
||||
case Token.GREATERTHAN_EQUALS:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType == Type.f32
|
||||
? BinaryOp.GeF32
|
||||
@ -1144,7 +1164,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
case Token.EQUALS_EQUALS:
|
||||
case Token.EQUALS_EQUALS_EQUALS:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType == Type.f32
|
||||
? BinaryOp.EqF32
|
||||
@ -1162,7 +1182,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.PLUS_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.PLUS:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType == Type.f32
|
||||
? BinaryOp.AddF32
|
||||
@ -1176,7 +1196,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.MINUS_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.MINUS:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType == Type.f32
|
||||
? BinaryOp.SubF32
|
||||
@ -1190,7 +1210,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.ASTERISK_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.ASTERISK:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType == Type.f32
|
||||
? BinaryOp.MulF32
|
||||
@ -1204,7 +1224,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.SLASH_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.SLASH:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType == Type.f32
|
||||
? BinaryOp.DivF32
|
||||
@ -1218,7 +1238,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.PERCENT_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.PERCENT:
|
||||
left = this.compileExpression(expression.left, contextualType, false);
|
||||
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
if (this.currentType.isAnyFloat)
|
||||
throw new Error("not implemented"); // TODO: internal fmod, possibly simply imported from JS
|
||||
@ -1230,7 +1250,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.LESSTHAN_LESSTHAN_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.LESSTHAN_LESSTHAN:
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType);
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType.isLongInteger
|
||||
? BinaryOp.ShlI64
|
||||
@ -1240,7 +1260,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.GREATERTHAN_GREATERTHAN_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.GREATERTHAN_GREATERTHAN:
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType);
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType.isSignedInteger
|
||||
? this.currentType.isLongInteger
|
||||
@ -1254,7 +1274,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN:
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.u64 : contextualType);
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.u64 : contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType.isLongInteger
|
||||
? BinaryOp.ShrU64
|
||||
@ -1264,7 +1284,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.AMPERSAND_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.AMPERSAND:
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType);
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType.isLongInteger
|
||||
? BinaryOp.AndI64
|
||||
@ -1274,7 +1294,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.BAR_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.BAR:
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType);
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType.isLongInteger
|
||||
? BinaryOp.OrI64
|
||||
@ -1284,7 +1304,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case Token.CARET_EQUALS:
|
||||
compound = Token.EQUALS;
|
||||
case Token.CARET:
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType);
|
||||
left = this.compileExpression(expression.left, contextualType.isAnyFloat ? Type.i64 : contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
right = this.compileExpression(expression.right, this.currentType);
|
||||
op = this.currentType.isLongInteger
|
||||
? BinaryOp.XorI64
|
||||
@ -1316,11 +1336,17 @@ export class Compiler extends DiagnosticEmitter {
|
||||
this.currentType = (<Local>element).type;
|
||||
return this.module.createTeeLocal((<Local>element).index, valueWithCorrectType);
|
||||
}
|
||||
this.currentType = Type.void;
|
||||
return this.module.createSetLocal((<Local>element).index, valueWithCorrectType);
|
||||
}
|
||||
|
||||
if (element.kind == ElementKind.GLOBAL && (<Global>element).type) {
|
||||
if (element.kind == ElementKind.GLOBAL) {
|
||||
this.compileGlobal(<Global>element);
|
||||
if (!(<Global>element).isMutable)
|
||||
this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, element.internalName);
|
||||
if (tee) {
|
||||
if (!(<Global>element).type)
|
||||
return this.module.createUnreachable();
|
||||
const globalNativeType: NativeType = typeToNativeType(<Type>(<Global>element).type);
|
||||
this.currentType = <Type>(<Global>element).type;
|
||||
return this.module.createBlock(null, [ // teeGlobal
|
||||
@ -1328,6 +1354,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
this.module.createGetGlobal((<Global>element).internalName, globalNativeType)
|
||||
], globalNativeType);
|
||||
}
|
||||
this.currentType = Type.void;
|
||||
return this.module.createSetGlobal((<Global>element).internalName, valueWithCorrectType);
|
||||
}
|
||||
|
||||
@ -1384,7 +1411,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
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, true);
|
||||
operands[i] = this.compileExpression(argumentExpressions[i], parameters[i].type);
|
||||
} else {
|
||||
const initializer: Expression | null = parameters[i].initializer;
|
||||
if (initializer) { // omitted, uses initializer
|
||||
@ -1621,47 +1648,52 @@ 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, typeToNativeType(this.currentType));
|
||||
return this.module.createGetLocal(0, this.options.target == Target.WASM64 ? NativeType.I64 : NativeType.I32);
|
||||
}
|
||||
this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range);
|
||||
this.currentType = this.options.target == Target.WASM64 ? Type.u64 : Type.u32;
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
|
||||
const element: Element | null = this.program.resolveElement(expression, this.currentFunction); // reports
|
||||
if (!element) {
|
||||
if (expression.kind == NodeKind.IDENTIFIER) {
|
||||
if (expression.kind == NodeKind.IDENTIFIER) {
|
||||
|
||||
// NaN
|
||||
if ((<IdentifierExpression>expression).name == "NaN")
|
||||
if (this.currentType.kind == TypeKind.F32)
|
||||
return this.module.createF32(NaN);
|
||||
else {
|
||||
this.currentType = Type.f64;
|
||||
return this.module.createF64(NaN);
|
||||
}
|
||||
// NaN
|
||||
if ((<IdentifierExpression>expression).name == "NaN")
|
||||
if (this.currentType.kind == TypeKind.F32)
|
||||
return this.module.createF32(NaN);
|
||||
else {
|
||||
this.currentType = Type.f64;
|
||||
return this.module.createF64(NaN);
|
||||
}
|
||||
|
||||
// Infinity
|
||||
if ((<IdentifierExpression>expression).name == "Infinity")
|
||||
if (this.currentType.kind == TypeKind.F32)
|
||||
return this.module.createF32(Infinity);
|
||||
else {
|
||||
this.currentType = Type.f64;
|
||||
return this.module.createF64(Infinity);
|
||||
}
|
||||
}
|
||||
return this.module.createUnreachable();
|
||||
// Infinity
|
||||
if ((<IdentifierExpression>expression).name == "Infinity")
|
||||
if (this.currentType.kind == TypeKind.F32)
|
||||
return this.module.createF32(Infinity);
|
||||
else {
|
||||
this.currentType = Type.f64;
|
||||
return this.module.createF64(Infinity);
|
||||
}
|
||||
}
|
||||
|
||||
const element: Element | null = this.program.resolveElement(expression, this.currentFunction); // reports
|
||||
if (!element)
|
||||
return this.module.createUnreachable();
|
||||
|
||||
// local
|
||||
if (element.kind == ElementKind.LOCAL)
|
||||
if (element.kind == ElementKind.LOCAL) {
|
||||
this.currentType = (<Local>element).type;
|
||||
return this.module.createGetLocal((<Local>element).index, typeToNativeType(this.currentType = (<Local>element).type));
|
||||
}
|
||||
|
||||
// global
|
||||
if (element.kind == ElementKind.GLOBAL)
|
||||
if (element.kind == ElementKind.GLOBAL) {
|
||||
if ((<Global>element).type)
|
||||
this.currentType = <Type>(<Global>element).type;
|
||||
return this.compileGlobal(<Global>element) // reports
|
||||
? this.module.createGetGlobal((<Global>element).internalName, typeToNativeType(this.currentType = <Type>(<Global>element).type))
|
||||
: this.module.createUnreachable();
|
||||
}
|
||||
|
||||
// field
|
||||
// if (element.kind == ElementKind.FIELD)
|
||||
@ -1691,6 +1723,10 @@ export class Compiler extends DiagnosticEmitter {
|
||||
const intValue: I64 = (<IntegerLiteralExpression>expression).value;
|
||||
if (contextualType == Type.bool && (intValue.isZero || intValue.isOne))
|
||||
return this.module.createI32(intValue.isZero ? 0 : 1);
|
||||
if (contextualType == Type.f64)
|
||||
return this.module.createF64((<f64>intValue.lo) + (<f64>intValue.hi) * 0xffffffff);
|
||||
if (contextualType == Type.f32)
|
||||
return this.module.createF32((<f32>intValue.lo) + (<f32>intValue.hi) * 0xffffffff);
|
||||
if (contextualType.isLongInteger)
|
||||
return this.module.createI64(intValue.lo, intValue.hi);
|
||||
if (!intValue.fitsInI32) {
|
||||
@ -1769,10 +1805,10 @@ export class Compiler extends DiagnosticEmitter {
|
||||
switch (expression.operator) {
|
||||
|
||||
case Token.PLUS:
|
||||
return this.compileExpression(operandExpression, contextualType);
|
||||
return this.compileExpression(operandExpression, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
|
||||
case Token.MINUS:
|
||||
operand = this.compileExpression(operandExpression, contextualType);
|
||||
operand = this.compileExpression(operandExpression, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
if (this.currentType == Type.f32)
|
||||
op = UnaryOp.NegF32;
|
||||
else if (this.currentType == Type.f64)
|
||||
@ -1784,7 +1820,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
break;
|
||||
|
||||
case Token.PLUS_PLUS:
|
||||
operand = this.compileExpression(operandExpression, contextualType);
|
||||
operand = this.compileExpression(operandExpression, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
return this.currentType == Type.f32
|
||||
? this.compileAssignmentWithValue(operandExpression, this.module.createBinary(BinaryOp.AddF32, operand, this.module.createF32(1)), contextualType != Type.void)
|
||||
: this.currentType == Type.f64
|
||||
@ -1794,7 +1830,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
: this.compileAssignmentWithValue(operandExpression, this.module.createBinary(BinaryOp.AddI32, operand, this.module.createI32(1)), contextualType != Type.void);
|
||||
|
||||
case Token.MINUS_MINUS:
|
||||
operand = this.compileExpression(operandExpression, contextualType);
|
||||
operand = this.compileExpression(operandExpression, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
return this.currentType == Type.f32
|
||||
? this.compileAssignmentWithValue(operandExpression, this.module.createBinary(BinaryOp.SubF32, operand, this.module.createF32(1)), contextualType != Type.void)
|
||||
: this.currentType == Type.f64
|
||||
@ -1804,7 +1840,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
: this.compileAssignmentWithValue(operandExpression, this.module.createBinary(BinaryOp.SubI32, operand, this.module.createI32(1)), contextualType != Type.void);
|
||||
|
||||
case Token.EXCLAMATION:
|
||||
operand = this.compileExpression(operandExpression, Type.bool, false);
|
||||
operand = this.compileExpression(operandExpression, Type.bool, ConversionKind.NONE);
|
||||
if (this.currentType == Type.f32) {
|
||||
this.currentType = Type.bool;
|
||||
return this.module.createBinary(BinaryOp.EqF32, operand, this.module.createF32(0));
|
||||
@ -1820,7 +1856,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
break;
|
||||
|
||||
case Token.TILDE:
|
||||
operand = this.compileExpression(operandExpression, contextualType.isAnyFloat ? Type.i64 : contextualType);
|
||||
operand = this.compileExpression(operandExpression, contextualType.isAnyFloat ? Type.i64 : contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT);
|
||||
return this.currentType.isLongInteger
|
||||
? this.module.createBinary(BinaryOp.XorI64, operand, this.module.createI64(-1, -1))
|
||||
: this.module.createBinary(BinaryOp.XorI32, operand, this.module.createI32(-1));
|
||||
|
@ -60,6 +60,7 @@ export enum DiagnosticCode {
|
||||
Function_implementation_is_missing_or_not_immediately_following_the_declaration = 2391,
|
||||
Duplicate_function_implementation = 2393,
|
||||
Export_declaration_conflicts_with_exported_declaration_of_0 = 2484,
|
||||
Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property = 2540,
|
||||
The_target_of_an_assignment_must_be_a_variable_or_a_property_access = 2541,
|
||||
Expected_0_arguments_but_got_1 = 2554,
|
||||
Expected_at_least_0_arguments_but_got_1 = 2555,
|
||||
@ -128,6 +129,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 2391: return "Function implementation is missing or not immediately following the declaration.";
|
||||
case 2393: return "Duplicate function implementation.";
|
||||
case 2484: return "Export declaration conflicts with exported declaration of '{0}'.";
|
||||
case 2540: return "Cannot assign to '{0}' because it is a constant or a read-only property.";
|
||||
case 2541: return "The target of an assignment must be a variable or a property access.";
|
||||
case 2554: return "Expected {0} arguments, but got {1}.";
|
||||
case 2555: return "Expected at least {0} arguments, but got {1}.";
|
||||
|
@ -60,6 +60,7 @@
|
||||
"Function implementation is missing or not immediately following the declaration.": 2391,
|
||||
"Duplicate function implementation.": 2393,
|
||||
"Export declaration conflicts with exported declaration of '{0}'.": 2484,
|
||||
"Cannot assign to '{0}' because it is a constant or a read-only property.": 2540,
|
||||
"The target of an assignment must be a variable or a property access.": 2541,
|
||||
"Expected {0} arguments, but got {1}.": 2554,
|
||||
"Expected at least {0} arguments, but got {1}.": 2555,
|
||||
|
@ -350,7 +350,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
const members: VariableDeclaration[] = new Array();
|
||||
const isDeclare = hasModifier(ModifierKind.DECLARE, modifiers);
|
||||
do {
|
||||
const member: VariableDeclaration | null = this.parseVariableDeclaration(tn, isDeclare);
|
||||
const member: VariableDeclaration | null = this.parseVariableDeclaration(tn, isDeclare, modifiers);
|
||||
if (!member)
|
||||
return null;
|
||||
members.push(<VariableDeclaration>member);
|
||||
@ -361,7 +361,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
return ret;
|
||||
}
|
||||
|
||||
parseVariableDeclaration(tn: Tokenizer, isDeclare: bool = false): VariableDeclaration | null {
|
||||
parseVariableDeclaration(tn: Tokenizer, isDeclare: bool = false, parentModifiers: Modifier[]): VariableDeclaration | null {
|
||||
// Identifier (':' Type)? ('=' Expression)?
|
||||
if (!tn.skip(Token.IDENTIFIER)) {
|
||||
this.error(DiagnosticCode.Identifier_expected, tn.range());
|
||||
@ -383,7 +383,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
if (!initializer)
|
||||
return null;
|
||||
}
|
||||
return Statement.createVariableDeclaration(identifier, type, initializer, Range.join(identifier.range, tn.range()));
|
||||
return Statement.createVariableDeclaration(identifier, type, initializer, parentModifiers, Range.join(identifier.range, tn.range()));
|
||||
}
|
||||
|
||||
parseEnum(tn: Tokenizer, modifiers: Modifier[]): EnumDeclaration | null {
|
||||
|
@ -764,7 +764,7 @@ export class Global extends Element {
|
||||
|
||||
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't exports */ false; }
|
||||
get isGlobalExport(): bool { return this.globalExportName != null; }
|
||||
get isMutable(): bool { return this.declaration ? hasModifier(ModifierKind.CONST, this.declaration.modifiers) : /* internals are immutable */ false; }
|
||||
get isMutable(): bool { return this.declaration ? !hasModifier(ModifierKind.CONST, this.declaration.modifiers) : /* internals are immutable */ false; }
|
||||
}
|
||||
|
||||
/** A function parameter. */
|
||||
|
@ -49,9 +49,12 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => {
|
||||
const actual = module.toText() + "(;\n[program.elements]\n " + iterate(program.elements.keys()).join("\n ") + "\n[program.exports]\n " + iterate(program.exports.keys()).join("\n ") + "\n;)\n";
|
||||
const fixture = path.basename(filename, ".ts") + ".wast";
|
||||
|
||||
if (module.validate())
|
||||
console.log("Validates");
|
||||
|
||||
if (isCreate) {
|
||||
fs.writeFileSync(__dirname + "/compiler/" + fixture, actual, { encoding: "utf8" });
|
||||
console.log("Created\n");
|
||||
console.log("Created");
|
||||
} else {
|
||||
const expected = fs.readFileSync(__dirname + "/compiler/" + fixture, { encoding: "utf8" });
|
||||
const diffs = diff("compiler/" + fixture, expected, actual);
|
||||
@ -59,9 +62,11 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => {
|
||||
process.exitCode = 1;
|
||||
console.log(diffs);
|
||||
} else {
|
||||
console.log("No changes\n");
|
||||
console.log("No changes");
|
||||
}
|
||||
}
|
||||
|
||||
console.log();
|
||||
});
|
||||
|
||||
function iterate<T>(it: IterableIterator<T>): T[] {
|
||||
|
161
tests/compiler/binary.ts
Normal file
161
tests/compiler/binary.ts
Normal file
@ -0,0 +1,161 @@
|
||||
let b: bool = false;
|
||||
|
||||
let i: i32 = 0;
|
||||
|
||||
i < 1;
|
||||
i > 1;
|
||||
i <= 1;
|
||||
i >= 1;
|
||||
i == 1;
|
||||
i === 1;
|
||||
i + 1;
|
||||
i - 1;
|
||||
i * 1;
|
||||
i / 1;
|
||||
i % 1;
|
||||
i << 1;
|
||||
i >> 1;
|
||||
i >>> 1;
|
||||
i & 1;
|
||||
i | 1;
|
||||
i ^ 1;
|
||||
|
||||
b = i < 1;
|
||||
b = i > 1;
|
||||
b = i <= 1;
|
||||
b = i >= 1;
|
||||
b = i == 1;
|
||||
b = i === 1;
|
||||
i = i + 1;
|
||||
i = i - 1;
|
||||
i = i * 1;
|
||||
i = i / 1;
|
||||
i = i % 1;
|
||||
i = i << 1;
|
||||
i = i >> 1;
|
||||
i = i >>> 1;
|
||||
i = i & 1;
|
||||
i = i | 1;
|
||||
i = i ^ 1;
|
||||
|
||||
i += 1;
|
||||
i -= 1;
|
||||
i *= 1;
|
||||
i %= 1;
|
||||
i <<= 1;
|
||||
i >>= 1;
|
||||
i >>>= 1;
|
||||
i &= 1;
|
||||
i |= 1;
|
||||
i ^= 1;
|
||||
|
||||
let I: i64 = 0;
|
||||
|
||||
I < 1;
|
||||
I > 1;
|
||||
I <= 1;
|
||||
I >= 1;
|
||||
I == 1;
|
||||
I === 1;
|
||||
I + 1;
|
||||
I - 1;
|
||||
I * 1;
|
||||
I / 1;
|
||||
I % 1;
|
||||
I << 1;
|
||||
I >> 1;
|
||||
I >>> 1;
|
||||
I & 1;
|
||||
I | 1;
|
||||
I ^ 1;
|
||||
|
||||
b = I < 1;
|
||||
b = I > 1;
|
||||
b = I <= 1;
|
||||
b = I >= 1;
|
||||
b = I == 1;
|
||||
b = I === 1;
|
||||
I = I + 1;
|
||||
I = I - 1;
|
||||
I = I * 1;
|
||||
I = I / 1;
|
||||
I = I % 1;
|
||||
I = I << 1;
|
||||
I = I >> 1;
|
||||
I = I >>> 1;
|
||||
I = I & 1;
|
||||
I = I | 1;
|
||||
I = I ^ 1;
|
||||
|
||||
I += 1;
|
||||
I -= 1;
|
||||
I *= 1;
|
||||
I %= 1;
|
||||
I <<= 1;
|
||||
I >>= 1;
|
||||
I >>>= 1;
|
||||
I &= 1;
|
||||
I |= 1;
|
||||
I ^= 1;
|
||||
|
||||
let f: f32 = 0;
|
||||
|
||||
f < 1;
|
||||
f > 1;
|
||||
f <= 1;
|
||||
f >= 1;
|
||||
f == 1;
|
||||
f === 1;
|
||||
f + 1;
|
||||
f - 1;
|
||||
f * 1;
|
||||
f / 1;
|
||||
// f % 1;
|
||||
|
||||
b = f < 1;
|
||||
b = f > 1;
|
||||
b = f <= 1;
|
||||
b = f >= 1;
|
||||
b = f == 1;
|
||||
b = f === 1;
|
||||
f = f + 1;
|
||||
f = f - 1;
|
||||
f = f * 1;
|
||||
f = f / 1;
|
||||
// f = f % 1;
|
||||
|
||||
f += 1;
|
||||
f -= 1;
|
||||
f *= 1;
|
||||
// f %= 1;
|
||||
|
||||
let F: f64 = 0;
|
||||
|
||||
F < 1;
|
||||
F > 1;
|
||||
F <= 1;
|
||||
F >= 1;
|
||||
F == 1;
|
||||
F === 1;
|
||||
F + 1;
|
||||
F - 1;
|
||||
F * 1;
|
||||
F / 1;
|
||||
// f % 1;
|
||||
|
||||
b = F < 1;
|
||||
b = F > 1;
|
||||
b = F <= 1;
|
||||
b = F >= 1;
|
||||
b = F == 1;
|
||||
b = F === 1;
|
||||
F = F + 1;
|
||||
F = F - 1;
|
||||
F = F * 1;
|
||||
F = F / 1;
|
||||
// F = F % 1;
|
||||
|
||||
F += 1;
|
||||
F -= 1;
|
||||
F *= 1;
|
||||
// F %= 1;
|
847
tests/compiler/binary.wast
Normal file
847
tests/compiler/binary.wast
Normal file
@ -0,0 +1,847 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(global $binary/i (mut i32) (i32.const 0))
|
||||
(global $binary/b (mut i32) (i32.const -1))
|
||||
(global $binary/I (mut i64) (i64.const 0))
|
||||
(global $binary/f (mut f32) (f32.const 0))
|
||||
(global $binary/F (mut f64) (f64.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
(drop
|
||||
(i32.lt_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.gt_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.le_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.ge_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.eq
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.eq
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.add
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.sub
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.mul
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.div_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.rem_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.shl
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.shr_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.shr_u
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.and
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.or
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.xor
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i32.const 0)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i32.lt_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i32.gt_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i32.le_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i32.ge_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i32.eq
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i32.eq
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.add
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.sub
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.mul
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.div_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.rem_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.shl
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.shr_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.shr_u
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.and
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.or
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.xor
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.add
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.sub
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.mul
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.rem_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.shl
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.shr_s
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.shr_u
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.and
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.or
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/i
|
||||
(i32.xor
|
||||
(get_global $binary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.lt_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.gt_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.le_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.ge_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.eq
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.eq
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.add
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.sub
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.mul
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.div_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.rem_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.shl
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.shr_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.shr_u
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.and
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.or
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.xor
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i64.lt_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i64.gt_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i64.le_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i64.ge_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i64.eq
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(i64.eq
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.add
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.sub
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.mul
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.div_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.rem_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.shl
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.shr_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.shr_u
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.and
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.or
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.xor
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.add
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.sub
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.mul
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.rem_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.shl
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.shr_s
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.shr_u
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.and
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.or
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/I
|
||||
(i64.xor
|
||||
(get_global $binary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.lt
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.gt
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.le
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.ge
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.eq
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.eq
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.add
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.sub
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.mul
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.div
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f32.lt
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f32.gt
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f32.le
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f32.ge
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f32.eq
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f32.eq
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/f
|
||||
(f32.add
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/f
|
||||
(f32.sub
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/f
|
||||
(f32.mul
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/f
|
||||
(f32.div
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/f
|
||||
(f32.add
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/f
|
||||
(f32.sub
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/f
|
||||
(f32.mul
|
||||
(get_global $binary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.lt
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.gt
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.le
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.ge
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.eq
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.eq
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.add
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.sub
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.mul
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.div
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f64.lt
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f64.gt
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f64.le
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f64.ge
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f64.eq
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/b
|
||||
(f64.eq
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/F
|
||||
(f64.add
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/F
|
||||
(f64.sub
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/F
|
||||
(f64.mul
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/F
|
||||
(f64.div
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/F
|
||||
(f64.add
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/F
|
||||
(f64.sub
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $binary/F
|
||||
(f64.mul
|
||||
(get_global $binary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
clz
|
||||
ctz
|
||||
popcnt
|
||||
rotl
|
||||
rotr
|
||||
abs
|
||||
ceil
|
||||
copysign
|
||||
floor
|
||||
max
|
||||
min
|
||||
nearest
|
||||
sqrt
|
||||
trunc
|
||||
isNaN
|
||||
isFinite
|
||||
binary/b
|
||||
binary/i
|
||||
binary/I
|
||||
binary/f
|
||||
binary/F
|
||||
[program.exports]
|
||||
|
||||
;)
|
14
tests/compiler/do.ts
Normal file
14
tests/compiler/do.ts
Normal file
@ -0,0 +1,14 @@
|
||||
export function loopDo(n: i32): void {
|
||||
do {
|
||||
n = n - 1;
|
||||
} while (n);
|
||||
}
|
||||
|
||||
export function loopDoInDo(n: i32): void {
|
||||
do {
|
||||
n = n - 1;
|
||||
do {
|
||||
n = n - 1;
|
||||
} while (n);
|
||||
} while (n);
|
||||
}
|
79
tests/compiler/do.wast
Normal file
79
tests/compiler/do.wast
Normal file
@ -0,0 +1,79 @@
|
||||
(module
|
||||
(type $iv (func (param i32)))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(func $do/loopDo (; 0 ;) (type $iv) (param $0 i32)
|
||||
(block $break$1.1
|
||||
(loop $continue$1.1
|
||||
(block
|
||||
(set_local $0
|
||||
(i32.sub
|
||||
(get_local $0)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br_if $continue$1.1
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $do/loopDoInDo (; 1 ;) (type $iv) (param $0 i32)
|
||||
(block $break$1.1
|
||||
(loop $continue$1.1
|
||||
(block
|
||||
(set_local $0
|
||||
(i32.sub
|
||||
(get_local $0)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(block $break$1.2
|
||||
(loop $continue$1.2
|
||||
(block
|
||||
(set_local $0
|
||||
(i32.sub
|
||||
(get_local $0)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br_if $continue$1.2
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br_if $continue$1.1
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
clz
|
||||
ctz
|
||||
popcnt
|
||||
rotl
|
||||
rotr
|
||||
abs
|
||||
ceil
|
||||
copysign
|
||||
floor
|
||||
max
|
||||
min
|
||||
nearest
|
||||
sqrt
|
||||
trunc
|
||||
isNaN
|
||||
isFinite
|
||||
do/loopDo
|
||||
do/loopDoInDo
|
||||
[program.exports]
|
||||
do/loopDo
|
||||
do/loopDoInDo
|
||||
;)
|
@ -1,7 +1,7 @@
|
||||
(module
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(global $export/a i32 (i32.const 1))
|
||||
(global $export/b i32 (i32.const 2))
|
||||
(global $export/a (mut i32) (i32.const 1))
|
||||
(global $export/b (mut i32) (i32.const 2))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
|
22
tests/compiler/if.ts
Normal file
22
tests/compiler/if.ts
Normal file
@ -0,0 +1,22 @@
|
||||
export function ifThenElse(n: i32): bool {
|
||||
if (n)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
export function ifThen(n: i32): bool {
|
||||
if (n)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
export function ifThenElseBlock(n: i32): bool {
|
||||
if (n) {
|
||||
; // nop
|
||||
return true;
|
||||
} else {
|
||||
; // nop
|
||||
return false;
|
||||
}
|
||||
}
|
71
tests/compiler/if.wast
Normal file
71
tests/compiler/if.wast
Normal file
@ -0,0 +1,71 @@
|
||||
(module
|
||||
(type $ii (func (param i32) (result i32)))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(func $if/ifThenElse (; 0 ;) (type $ii) (param $0 i32) (result i32)
|
||||
(if
|
||||
(get_local $0)
|
||||
(return
|
||||
(i32.const 1)
|
||||
)
|
||||
(return
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $if/ifThen (; 1 ;) (type $ii) (param $0 i32) (result i32)
|
||||
(if
|
||||
(get_local $0)
|
||||
(return
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
(func $if/ifThenElseBlock (; 2 ;) (type $ii) (param $0 i32) (result i32)
|
||||
(if
|
||||
(get_local $0)
|
||||
(block
|
||||
(nop)
|
||||
(return
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(nop)
|
||||
(return
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
clz
|
||||
ctz
|
||||
popcnt
|
||||
rotl
|
||||
rotr
|
||||
abs
|
||||
ceil
|
||||
copysign
|
||||
floor
|
||||
max
|
||||
min
|
||||
nearest
|
||||
sqrt
|
||||
trunc
|
||||
isNaN
|
||||
isFinite
|
||||
if/ifThenElse
|
||||
if/ifThen
|
||||
if/ifThenElseBlock
|
||||
[program.exports]
|
||||
if/ifThenElse
|
||||
if/ifThen
|
||||
if/ifThenElseBlock
|
||||
;)
|
@ -1,8 +1,8 @@
|
||||
(module
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(type $v (func))
|
||||
(global $export/a i32 (i32.const 1))
|
||||
(global $export/b i32 (i32.const 2))
|
||||
(global $export/a (mut i32) (i32.const 1))
|
||||
(global $export/b (mut i32) (i32.const 2))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
|
46
tests/compiler/literals.ts
Normal file
46
tests/compiler/literals.ts
Normal file
@ -0,0 +1,46 @@
|
||||
0;
|
||||
1;
|
||||
2;
|
||||
3;
|
||||
4;
|
||||
5;
|
||||
6;
|
||||
7;
|
||||
8;
|
||||
9;
|
||||
0x0;
|
||||
0x1;
|
||||
0x2;
|
||||
0x3;
|
||||
0x4;
|
||||
0x5;
|
||||
0x6;
|
||||
0x7;
|
||||
0x8;
|
||||
0x9;
|
||||
0xA;
|
||||
0xB;
|
||||
0xC;
|
||||
0xD;
|
||||
0xE;
|
||||
0xF;
|
||||
0xa;
|
||||
0xb;
|
||||
0xc;
|
||||
0xd;
|
||||
0xe;
|
||||
0xf;
|
||||
0o0;
|
||||
0o1;
|
||||
0o2;
|
||||
0o3;
|
||||
0o4;
|
||||
0o5;
|
||||
0o6;
|
||||
0o7;
|
||||
0b0;
|
||||
0b1;
|
||||
true;
|
||||
false;
|
||||
NaN;
|
||||
Infinity;
|
168
tests/compiler/literals.wast
Normal file
168
tests/compiler/literals.wast
Normal file
@ -0,0 +1,168 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
(drop
|
||||
(i32.const 0)
|
||||
)
|
||||
(drop
|
||||
(i32.const 1)
|
||||
)
|
||||
(drop
|
||||
(i32.const 2)
|
||||
)
|
||||
(drop
|
||||
(i32.const 3)
|
||||
)
|
||||
(drop
|
||||
(i32.const 4)
|
||||
)
|
||||
(drop
|
||||
(i32.const 5)
|
||||
)
|
||||
(drop
|
||||
(i32.const 6)
|
||||
)
|
||||
(drop
|
||||
(i32.const 7)
|
||||
)
|
||||
(drop
|
||||
(i32.const 8)
|
||||
)
|
||||
(drop
|
||||
(i32.const 9)
|
||||
)
|
||||
(drop
|
||||
(i32.const 0)
|
||||
)
|
||||
(drop
|
||||
(i32.const 1)
|
||||
)
|
||||
(drop
|
||||
(i32.const 2)
|
||||
)
|
||||
(drop
|
||||
(i32.const 3)
|
||||
)
|
||||
(drop
|
||||
(i32.const 4)
|
||||
)
|
||||
(drop
|
||||
(i32.const 5)
|
||||
)
|
||||
(drop
|
||||
(i32.const 6)
|
||||
)
|
||||
(drop
|
||||
(i32.const 7)
|
||||
)
|
||||
(drop
|
||||
(i32.const 8)
|
||||
)
|
||||
(drop
|
||||
(i32.const 9)
|
||||
)
|
||||
(drop
|
||||
(i32.const 10)
|
||||
)
|
||||
(drop
|
||||
(i32.const 11)
|
||||
)
|
||||
(drop
|
||||
(i32.const 12)
|
||||
)
|
||||
(drop
|
||||
(i32.const 13)
|
||||
)
|
||||
(drop
|
||||
(i32.const 14)
|
||||
)
|
||||
(drop
|
||||
(i32.const 15)
|
||||
)
|
||||
(drop
|
||||
(i32.const 10)
|
||||
)
|
||||
(drop
|
||||
(i32.const 11)
|
||||
)
|
||||
(drop
|
||||
(i32.const 12)
|
||||
)
|
||||
(drop
|
||||
(i32.const 13)
|
||||
)
|
||||
(drop
|
||||
(i32.const 14)
|
||||
)
|
||||
(drop
|
||||
(i32.const 15)
|
||||
)
|
||||
(drop
|
||||
(i32.const 0)
|
||||
)
|
||||
(drop
|
||||
(i32.const 1)
|
||||
)
|
||||
(drop
|
||||
(i32.const 2)
|
||||
)
|
||||
(drop
|
||||
(i32.const 3)
|
||||
)
|
||||
(drop
|
||||
(i32.const 4)
|
||||
)
|
||||
(drop
|
||||
(i32.const 5)
|
||||
)
|
||||
(drop
|
||||
(i32.const 6)
|
||||
)
|
||||
(drop
|
||||
(i32.const 7)
|
||||
)
|
||||
(drop
|
||||
(i32.const 0)
|
||||
)
|
||||
(drop
|
||||
(i32.const 1)
|
||||
)
|
||||
(drop
|
||||
(i32.const 1)
|
||||
)
|
||||
(drop
|
||||
(i32.const 0)
|
||||
)
|
||||
(drop
|
||||
(f64.const nan:0x8000000000000)
|
||||
)
|
||||
(drop
|
||||
(f64.const inf)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
clz
|
||||
ctz
|
||||
popcnt
|
||||
rotl
|
||||
rotr
|
||||
abs
|
||||
ceil
|
||||
copysign
|
||||
floor
|
||||
max
|
||||
min
|
||||
nearest
|
||||
sqrt
|
||||
trunc
|
||||
isNaN
|
||||
isFinite
|
||||
[program.exports]
|
||||
|
||||
;)
|
88
tests/compiler/unary.ts
Normal file
88
tests/compiler/unary.ts
Normal file
@ -0,0 +1,88 @@
|
||||
+1;
|
||||
-1;
|
||||
!1;
|
||||
~1;
|
||||
+1.25;
|
||||
-1.25;
|
||||
!1.25;
|
||||
// ~1.25;
|
||||
|
||||
let i: i32 = 0;
|
||||
|
||||
+i;
|
||||
-i;
|
||||
!i;
|
||||
~i;
|
||||
++i;
|
||||
--i;
|
||||
|
||||
i = +1;
|
||||
i = -1;
|
||||
i = !1;
|
||||
i = ~1;
|
||||
i = +i;
|
||||
i = -i;
|
||||
i = !i;
|
||||
i = ~i;
|
||||
i = ++i;
|
||||
i = --i;
|
||||
|
||||
let I: i64 = 0;
|
||||
|
||||
+I;
|
||||
-I;
|
||||
!I;
|
||||
~I;
|
||||
++I;
|
||||
--I;
|
||||
|
||||
I = +1;
|
||||
I = -1;
|
||||
I = !1;
|
||||
I = ~1;
|
||||
I = +I;
|
||||
I = -I;
|
||||
I = !I;
|
||||
I = ~I;
|
||||
I = ++I;
|
||||
I = --I;
|
||||
|
||||
let f: f32 = 0;
|
||||
|
||||
+f;
|
||||
-f;
|
||||
!f;
|
||||
// ~f;
|
||||
++f;
|
||||
--f;
|
||||
|
||||
f = +1.25;
|
||||
f = -1.25;
|
||||
i = !1.25;
|
||||
// i = ~1.25;
|
||||
f = +f;
|
||||
f = -f;
|
||||
i = !f;
|
||||
// i = ~f;
|
||||
f = ++f;
|
||||
f = --f;
|
||||
|
||||
let F: f64 = 0;
|
||||
|
||||
+F;
|
||||
-F;
|
||||
!F;
|
||||
// ~F;
|
||||
++F;
|
||||
--F;
|
||||
|
||||
F = +1.25;
|
||||
F = -1.25;
|
||||
I = !1.25;
|
||||
// I = ~1.25;
|
||||
F = +F;
|
||||
F = -F;
|
||||
I = !F;
|
||||
// I = ~F;
|
||||
F = ++F;
|
||||
F = --F;
|
420
tests/compiler/unary.wast
Normal file
420
tests/compiler/unary.wast
Normal file
@ -0,0 +1,420 @@
|
||||
(module
|
||||
(type $v (func))
|
||||
(global $unary/i (mut i32) (i32.const 0))
|
||||
(global $unary/I (mut i64) (i64.const 0))
|
||||
(global $unary/f (mut f32) (f32.const 0))
|
||||
(global $unary/F (mut f64) (f64.const 0))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $start (; 0 ;) (type $v)
|
||||
(drop
|
||||
(i32.const 1)
|
||||
)
|
||||
(drop
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.eqz
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.xor
|
||||
(i32.const 1)
|
||||
(i32.const -1)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.const 1.25)
|
||||
)
|
||||
(drop
|
||||
(f64.neg
|
||||
(f64.const 1.25)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.eq
|
||||
(f64.const 1.25)
|
||||
(f64.const 0)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(get_global $unary/i)
|
||||
)
|
||||
(drop
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(get_global $unary/i)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.eqz
|
||||
(get_global $unary/i)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i32.xor
|
||||
(get_global $unary/i)
|
||||
(i32.const -1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(i32.add
|
||||
(get_global $unary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(i32.sub
|
||||
(get_global $unary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(i32.const 1)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(i32.eqz
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(i32.xor
|
||||
(i32.const 1)
|
||||
(i32.const -1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(get_global $unary/i)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(get_global $unary/i)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(i32.eqz
|
||||
(get_global $unary/i)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(i32.xor
|
||||
(get_global $unary/i)
|
||||
(i32.const -1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(block (result i32)
|
||||
(set_global $unary/i
|
||||
(i32.add
|
||||
(get_global $unary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_global $unary/i)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(block (result i32)
|
||||
(set_global $unary/i
|
||||
(i32.sub
|
||||
(get_global $unary/i)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_global $unary/i)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(get_global $unary/I)
|
||||
)
|
||||
(drop
|
||||
(i64.sub
|
||||
(i64.const 0)
|
||||
(get_global $unary/I)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.eqz
|
||||
(get_global $unary/I)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(i64.xor
|
||||
(get_global $unary/I)
|
||||
(i64.const -1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.add
|
||||
(get_global $unary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.sub
|
||||
(get_global $unary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.const 1)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.sub
|
||||
(i64.const 0)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.extend_s/i32
|
||||
(i32.eqz
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.xor
|
||||
(i64.const 1)
|
||||
(i64.const -1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(get_global $unary/I)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.sub
|
||||
(i64.const 0)
|
||||
(get_global $unary/I)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.extend_s/i32
|
||||
(i64.eqz
|
||||
(get_global $unary/I)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.xor
|
||||
(get_global $unary/I)
|
||||
(i64.const -1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(block (result i64)
|
||||
(set_global $unary/I
|
||||
(i64.add
|
||||
(get_global $unary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(get_global $unary/I)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(block (result i64)
|
||||
(set_global $unary/I
|
||||
(i64.sub
|
||||
(get_global $unary/I)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(get_global $unary/I)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(get_global $unary/f)
|
||||
)
|
||||
(drop
|
||||
(f32.neg
|
||||
(get_global $unary/f)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f32.eq
|
||||
(get_global $unary/f)
|
||||
(f32.const 0)
|
||||
)
|
||||
)
|
||||
(set_global $unary/f
|
||||
(f32.add
|
||||
(get_global $unary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/f
|
||||
(f32.sub
|
||||
(get_global $unary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/f
|
||||
(f32.const 1.25)
|
||||
)
|
||||
(set_global $unary/f
|
||||
(f32.neg
|
||||
(f32.const 1.25)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(f64.eq
|
||||
(f64.const 1.25)
|
||||
(f64.const 0)
|
||||
)
|
||||
)
|
||||
(set_global $unary/f
|
||||
(get_global $unary/f)
|
||||
)
|
||||
(set_global $unary/f
|
||||
(f32.neg
|
||||
(get_global $unary/f)
|
||||
)
|
||||
)
|
||||
(set_global $unary/i
|
||||
(f32.eq
|
||||
(get_global $unary/f)
|
||||
(f32.const 0)
|
||||
)
|
||||
)
|
||||
(set_global $unary/f
|
||||
(block (result f32)
|
||||
(set_global $unary/f
|
||||
(f32.add
|
||||
(get_global $unary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(get_global $unary/f)
|
||||
)
|
||||
)
|
||||
(set_global $unary/f
|
||||
(block (result f32)
|
||||
(set_global $unary/f
|
||||
(f32.sub
|
||||
(get_global $unary/f)
|
||||
(f32.const 1)
|
||||
)
|
||||
)
|
||||
(get_global $unary/f)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(get_global $unary/F)
|
||||
)
|
||||
(drop
|
||||
(f64.neg
|
||||
(get_global $unary/F)
|
||||
)
|
||||
)
|
||||
(drop
|
||||
(f64.eq
|
||||
(get_global $unary/F)
|
||||
(f64.const 0)
|
||||
)
|
||||
)
|
||||
(set_global $unary/F
|
||||
(f64.add
|
||||
(get_global $unary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/F
|
||||
(f64.sub
|
||||
(get_global $unary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(set_global $unary/F
|
||||
(f64.const 1.25)
|
||||
)
|
||||
(set_global $unary/F
|
||||
(f64.neg
|
||||
(f64.const 1.25)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.extend_s/i32
|
||||
(f64.eq
|
||||
(f64.const 1.25)
|
||||
(f64.const 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_global $unary/F
|
||||
(get_global $unary/F)
|
||||
)
|
||||
(set_global $unary/F
|
||||
(f64.neg
|
||||
(get_global $unary/F)
|
||||
)
|
||||
)
|
||||
(set_global $unary/I
|
||||
(i64.extend_s/i32
|
||||
(f64.eq
|
||||
(get_global $unary/F)
|
||||
(f64.const 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_global $unary/F
|
||||
(block (result f64)
|
||||
(set_global $unary/F
|
||||
(f64.add
|
||||
(get_global $unary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(get_global $unary/F)
|
||||
)
|
||||
)
|
||||
(set_global $unary/F
|
||||
(block (result f64)
|
||||
(set_global $unary/F
|
||||
(f64.sub
|
||||
(get_global $unary/F)
|
||||
(f64.const 1)
|
||||
)
|
||||
)
|
||||
(get_global $unary/F)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
clz
|
||||
ctz
|
||||
popcnt
|
||||
rotl
|
||||
rotr
|
||||
abs
|
||||
ceil
|
||||
copysign
|
||||
floor
|
||||
max
|
||||
min
|
||||
nearest
|
||||
sqrt
|
||||
trunc
|
||||
isNaN
|
||||
isFinite
|
||||
unary/i
|
||||
unary/I
|
||||
unary/f
|
||||
unary/F
|
||||
[program.exports]
|
||||
|
||||
;)
|
14
tests/compiler/while.ts
Normal file
14
tests/compiler/while.ts
Normal file
@ -0,0 +1,14 @@
|
||||
export function loopWhile(n: i32): void {
|
||||
while (n) {
|
||||
n = n - 1;
|
||||
}
|
||||
}
|
||||
|
||||
export function loopWhileInWhile(n: i32): void {
|
||||
while (n) {
|
||||
n = n - 1;
|
||||
while (n) {
|
||||
n = n - 1;
|
||||
}
|
||||
}
|
||||
}
|
88
tests/compiler/while.wast
Normal file
88
tests/compiler/while.wast
Normal file
@ -0,0 +1,88 @@
|
||||
(module
|
||||
(type $iv (func (param i32)))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\08\00\00\00")
|
||||
(export "memory" (memory $0))
|
||||
(func $while/loopWhile (; 0 ;) (type $iv) (param $0 i32)
|
||||
(block $break$1.1
|
||||
(loop $continue$1.1
|
||||
(if
|
||||
(get_local $0)
|
||||
(block
|
||||
(block
|
||||
(set_local $0
|
||||
(i32.sub
|
||||
(get_local $0)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue$1.1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $while/loopWhileInWhile (; 1 ;) (type $iv) (param $0 i32)
|
||||
(block $break$1.1
|
||||
(loop $continue$1.1
|
||||
(if
|
||||
(get_local $0)
|
||||
(block
|
||||
(block
|
||||
(set_local $0
|
||||
(i32.sub
|
||||
(get_local $0)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(block $break$1.2
|
||||
(loop $continue$1.2
|
||||
(if
|
||||
(get_local $0)
|
||||
(block
|
||||
(block
|
||||
(set_local $0
|
||||
(i32.sub
|
||||
(get_local $0)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue$1.2)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue$1.1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
clz
|
||||
ctz
|
||||
popcnt
|
||||
rotl
|
||||
rotr
|
||||
abs
|
||||
ceil
|
||||
copysign
|
||||
floor
|
||||
max
|
||||
min
|
||||
nearest
|
||||
sqrt
|
||||
trunc
|
||||
isNaN
|
||||
isFinite
|
||||
while/loopWhile
|
||||
while/loopWhileInWhile
|
||||
[program.exports]
|
||||
while/loopWhile
|
||||
while/loopWhileInWhile
|
||||
;)
|
16
tests/set_global-immutable.js
Normal file
16
tests/set_global-immutable.js
Normal file
@ -0,0 +1,16 @@
|
||||
var binaryen = require("binaryen");
|
||||
|
||||
// "It is a validation error for a set_global to index an immutable global variable."
|
||||
|
||||
var mod = new binaryen.Module();
|
||||
mod.addGlobal("a", binaryen.i32, false, mod.i32.const(0));
|
||||
|
||||
var funcType = mod.addFunctionType("v", binaryen.none, []);
|
||||
var func = mod.addFunction("start", funcType, [], mod.block("", [
|
||||
mod.setGlobal("a", mod.i32.const(1))
|
||||
]));
|
||||
mod.setStart(func);
|
||||
|
||||
console.log(mod.emitText());
|
||||
if (mod.validate())
|
||||
console.log("-> validates");
|
Loading…
x
Reference in New Issue
Block a user