mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-05-03 10:52:15 +00:00
Initial implementation of 'instanceof'
Works like an assignability check for now / does not yet honor nullables.
This commit is contained in:
parent
cea69a6de1
commit
7478c8a0d3
2
dist/assemblyscript.js
vendored
2
dist/assemblyscript.js
vendored
File diff suppressed because one or more lines are too long
2
dist/assemblyscript.js.map
vendored
2
dist/assemblyscript.js.map
vendored
File diff suppressed because one or more lines are too long
23
src/ast.ts
23
src/ast.ts
@ -45,6 +45,7 @@ export enum NodeKind {
|
|||||||
ELEMENTACCESS,
|
ELEMENTACCESS,
|
||||||
FALSE,
|
FALSE,
|
||||||
FUNCTION,
|
FUNCTION,
|
||||||
|
INSTANCEOF,
|
||||||
LITERAL,
|
LITERAL,
|
||||||
NEW,
|
NEW,
|
||||||
NULL,
|
NULL,
|
||||||
@ -346,6 +347,18 @@ export abstract class Node {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static createInstanceOfExpression(
|
||||||
|
expression: Expression,
|
||||||
|
isType: CommonTypeNode,
|
||||||
|
range: Range
|
||||||
|
): InstanceOfExpression {
|
||||||
|
var expr = new InstanceOfExpression();
|
||||||
|
expr.range = range;
|
||||||
|
expr.expression = expression; expression.parent = expr;
|
||||||
|
expr.isType = isType; isType.parent = expr;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
static createIntegerLiteralExpression(
|
static createIntegerLiteralExpression(
|
||||||
value: I64,
|
value: I64,
|
||||||
range: Range
|
range: Range
|
||||||
@ -1267,6 +1280,16 @@ export class FunctionExpression extends Expression {
|
|||||||
declaration: FunctionDeclaration;
|
declaration: FunctionDeclaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Represents an `instanceof` expression. */
|
||||||
|
export class InstanceOfExpression extends Expression {
|
||||||
|
kind = NodeKind.INSTANCEOF;
|
||||||
|
|
||||||
|
/** Expression being asserted. */
|
||||||
|
expression: Expression;
|
||||||
|
/** Type to test for. */
|
||||||
|
isType: CommonTypeNode;
|
||||||
|
}
|
||||||
|
|
||||||
/** Represents an integer literal expression. */
|
/** Represents an integer literal expression. */
|
||||||
export class IntegerLiteralExpression extends LiteralExpression {
|
export class IntegerLiteralExpression extends LiteralExpression {
|
||||||
literalKind = LiteralKind.INTEGER;
|
literalKind = LiteralKind.INTEGER;
|
||||||
|
@ -94,6 +94,7 @@ import {
|
|||||||
ForStatement,
|
ForStatement,
|
||||||
IfStatement,
|
IfStatement,
|
||||||
ImportStatement,
|
ImportStatement,
|
||||||
|
InstanceOfExpression,
|
||||||
InterfaceDeclaration,
|
InterfaceDeclaration,
|
||||||
NamespaceDeclaration,
|
NamespaceDeclaration,
|
||||||
ReturnStatement,
|
ReturnStatement,
|
||||||
@ -2263,6 +2264,10 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NodeKind.INSTANCEOF: {
|
||||||
|
expr = this.compileInstanceOfExpression(<InstanceOfExpression>expression, contextualType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NodeKind.LITERAL: {
|
case NodeKind.LITERAL: {
|
||||||
expr = this.compileLiteralExpression(<LiteralExpression>expression, contextualType);
|
expr = this.compileLiteralExpression(<LiteralExpression>expression, contextualType);
|
||||||
break;
|
break;
|
||||||
@ -5873,6 +5878,18 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileInstanceOfExpression(
|
||||||
|
expression: InstanceOfExpression,
|
||||||
|
contextualType: Type
|
||||||
|
): ExpressionRef {
|
||||||
|
this.compileExpressionRetainType(expression.expression, this.options.usizeType, WrapMode.NONE);
|
||||||
|
var type = this.currentType;
|
||||||
|
var isType = this.program.resolveType(expression.isType);
|
||||||
|
this.currentType = Type.bool;
|
||||||
|
if (!isType) return this.module.createUnreachable();
|
||||||
|
return this.module.createI32(type.isAssignableTo(isType, false) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
compileLiteralExpression(
|
compileLiteralExpression(
|
||||||
expression: LiteralExpression,
|
expression: LiteralExpression,
|
||||||
contextualType: Type,
|
contextualType: Type,
|
||||||
|
@ -52,6 +52,7 @@ import {
|
|||||||
ForStatement,
|
ForStatement,
|
||||||
IfStatement,
|
IfStatement,
|
||||||
ImportStatement,
|
ImportStatement,
|
||||||
|
InstanceOfExpression,
|
||||||
ReturnStatement,
|
ReturnStatement,
|
||||||
SwitchStatement,
|
SwitchStatement,
|
||||||
ThrowStatement,
|
ThrowStatement,
|
||||||
@ -160,6 +161,10 @@ export class ASTBuilder {
|
|||||||
this.visitFunctionExpression(<FunctionExpression>node);
|
this.visitFunctionExpression(<FunctionExpression>node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NodeKind.INSTANCEOF: {
|
||||||
|
this.visitInstanceOfExpression(<InstanceOfExpression>node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NodeKind.LITERAL: {
|
case NodeKind.LITERAL: {
|
||||||
this.visitLiteralExpression(<LiteralExpression>node);
|
this.visitLiteralExpression(<LiteralExpression>node);
|
||||||
break;
|
break;
|
||||||
@ -544,6 +549,12 @@ export class ASTBuilder {
|
|||||||
this.sb.push(node.value.toString(10));
|
this.sb.push(node.value.toString(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
visitInstanceOfExpression(node: InstanceOfExpression): void {
|
||||||
|
this.visitNode(node.expression);
|
||||||
|
this.sb.push(" instanceof ");
|
||||||
|
this.visitTypeNode(node.isType);
|
||||||
|
}
|
||||||
|
|
||||||
visitIntegerLiteralExpression(node: IntegerLiteralExpression): void {
|
visitIntegerLiteralExpression(node: IntegerLiteralExpression): void {
|
||||||
this.sb.push(i64_to_string(node.value));
|
this.sb.push(i64_to_string(node.value));
|
||||||
}
|
}
|
||||||
|
@ -3108,7 +3108,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
switch (token) {
|
switch (token) {
|
||||||
// AssertionExpression
|
// AssertionExpression
|
||||||
case Token.AS: {
|
case Token.AS: {
|
||||||
let toType = this.parseType(tn);
|
let toType = this.parseType(tn); // reports
|
||||||
if (!toType) return null;
|
if (!toType) return null;
|
||||||
expr = Node.createAssertionExpression(
|
expr = Node.createAssertionExpression(
|
||||||
AssertionKind.AS,
|
AssertionKind.AS,
|
||||||
@ -3118,9 +3118,20 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// InstanceOfExpression
|
||||||
|
case Token.INSTANCEOF: {
|
||||||
|
let isType = this.parseType(tn); // reports
|
||||||
|
if (!isType) return null;
|
||||||
|
expr = Node.createInstanceOfExpression(
|
||||||
|
expr,
|
||||||
|
isType,
|
||||||
|
tn.range(startPos, tn.pos)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
// ElementAccessExpression
|
// ElementAccessExpression
|
||||||
case Token.OPENBRACKET: {
|
case Token.OPENBRACKET: {
|
||||||
next = this.parseExpression(tn);
|
next = this.parseExpression(tn); // reports
|
||||||
if (!next) return null;
|
if (!next) return null;
|
||||||
if (!tn.skip(Token.CLOSEBRACKET)) {
|
if (!tn.skip(Token.CLOSEBRACKET)) {
|
||||||
this.error(
|
this.error(
|
||||||
|
49
tests/compiler/instanceof.optimized.wat
Normal file
49
tests/compiler/instanceof.optimized.wat
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
(module
|
||||||
|
(type $iiiiv (func (param i32 i32 i32 i32)))
|
||||||
|
(type $ii (func (param i32) (result i32)))
|
||||||
|
(type $Fi (func (param f64) (result i32)))
|
||||||
|
(type $v (func))
|
||||||
|
(import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32)))
|
||||||
|
(memory $0 1)
|
||||||
|
(data (i32.const 8) "\0d\00\00\00i\00n\00s\00t\00a\00n\00c\00e\00o\00f\00.\00t\00s")
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $instanceof/isI32<i32> (; 1 ;) (type $ii) (param $0 i32) (result i32)
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(func $instanceof/isI32<f64> (; 2 ;) (type $Fi) (param $0 f64) (result i32)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(func $start (; 3 ;) (type $v)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(call $instanceof/isI32<i32>
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 38)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(call $instanceof/isI32<f64>
|
||||||
|
(f64.const 0)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 39)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
49
tests/compiler/instanceof.ts
Normal file
49
tests/compiler/instanceof.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
class A {}
|
||||||
|
class B extends A {}
|
||||||
|
|
||||||
|
var a: A;
|
||||||
|
var b: B;
|
||||||
|
var i: i32;
|
||||||
|
var f: f32;
|
||||||
|
|
||||||
|
assert( a instanceof A );
|
||||||
|
assert( b instanceof A );
|
||||||
|
assert(!(i instanceof A));
|
||||||
|
assert(!(f instanceof A));
|
||||||
|
|
||||||
|
assert(!(a instanceof B));
|
||||||
|
assert( b instanceof B );
|
||||||
|
assert(!(i instanceof B));
|
||||||
|
assert(!(f instanceof B));
|
||||||
|
|
||||||
|
assert(!(a instanceof i32));
|
||||||
|
assert(!(b instanceof i32));
|
||||||
|
assert( i instanceof i32 );
|
||||||
|
assert(!(f instanceof i32));
|
||||||
|
|
||||||
|
assert(!(a instanceof f32));
|
||||||
|
assert(!(b instanceof f32));
|
||||||
|
assert(!(i instanceof f32));
|
||||||
|
assert( f instanceof f32 );
|
||||||
|
|
||||||
|
function isI32<T>(v: T): bool {
|
||||||
|
// should eliminate non-applicable branches (see fixture)
|
||||||
|
if (v instanceof i32) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( isI32(0));
|
||||||
|
assert(!isI32(0.0));
|
||||||
|
|
||||||
|
// TODO: what about nullables?
|
||||||
|
// var an: A | null;
|
||||||
|
// var bn: B | null;
|
||||||
|
//
|
||||||
|
// assert(an instanceof A);
|
||||||
|
// assert(bn instanceof A);
|
||||||
|
//
|
||||||
|
// assert(!(an instanceof B));
|
||||||
|
// assert(bn instanceof B);
|
308
tests/compiler/instanceof.untouched.wat
Normal file
308
tests/compiler/instanceof.untouched.wat
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
(module
|
||||||
|
(type $iiiiv (func (param i32 i32 i32 i32)))
|
||||||
|
(type $ii (func (param i32) (result i32)))
|
||||||
|
(type $Fi (func (param f64) (result i32)))
|
||||||
|
(type $v (func))
|
||||||
|
(import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32)))
|
||||||
|
(global $instanceof/a (mut i32) (i32.const 0))
|
||||||
|
(global $instanceof/b (mut i32) (i32.const 0))
|
||||||
|
(global $instanceof/i (mut i32) (i32.const 0))
|
||||||
|
(global $instanceof/f (mut f32) (f32.const 0))
|
||||||
|
(global $HEAP_BASE i32 (i32.const 40))
|
||||||
|
(memory $0 1)
|
||||||
|
(data (i32.const 8) "\0d\00\00\00i\00n\00s\00t\00a\00n\00c\00e\00o\00f\00.\00t\00s\00")
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $instanceof/isI32<i32> (; 1 ;) (type $ii) (param $0 i32) (result i32)
|
||||||
|
(return
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $instanceof/isI32<f64> (; 2 ;) (type $Fi) (param $0 f64) (result i32)
|
||||||
|
(return
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start (; 3 ;) (type $v)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 9)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 10)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 11)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 12)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 14)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 15)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 16)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 17)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 19)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 20)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 21)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 22)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 24)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 25)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 26)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 27)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(call $instanceof/isI32<i32>
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 38)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eqz
|
||||||
|
(call $instanceof/isI32<f64>
|
||||||
|
(f64.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(call $~lib/env/abort
|
||||||
|
(i32.const 0)
|
||||||
|
(i32.const 8)
|
||||||
|
(i32.const 39)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user