mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-24 22:52:13 +00:00
Require exact type in instanceof basicType, fixes #493
This commit is contained in:
parent
6b495f71d0
commit
8d2194f045
@ -6138,24 +6138,32 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// time of implementation, this seemed more useful because dynamic rhs expressions are not
|
||||
// possible in AS anyway.
|
||||
var expr = this.compileExpressionRetainType(expression.expression, this.options.usizeType, WrapMode.NONE);
|
||||
var type = this.currentType;
|
||||
var isType = this.resolver.resolveType(
|
||||
var actualType = this.currentType;
|
||||
var expectedType = this.resolver.resolveType(
|
||||
expression.isType,
|
||||
this.currentFlow.actualFunction
|
||||
);
|
||||
this.currentType = Type.bool;
|
||||
if (!isType) return module.createUnreachable();
|
||||
return type.is(TypeFlags.NULLABLE) && !isType.is(TypeFlags.NULLABLE)
|
||||
? type.nonNullableType.isAssignableTo(isType)
|
||||
? module.createBinary( // not precomputeable
|
||||
type.is(TypeFlags.LONG)
|
||||
? BinaryOp.NeI64
|
||||
: BinaryOp.NeI32,
|
||||
expr,
|
||||
type.toNativeZero(module)
|
||||
)
|
||||
: module.createI32(0)
|
||||
: module.createI32(type.isAssignableTo(isType, true) ? 1 : 0);
|
||||
if (!expectedType) return module.createUnreachable();
|
||||
|
||||
// instanceof <basicType> must be exact
|
||||
if (!expectedType.is(TypeFlags.REFERENCE)) {
|
||||
return module.createI32(actualType == expectedType ? 1 : 0);
|
||||
}
|
||||
// <nullable> instanceof <nonNullable> must be != 0
|
||||
if (
|
||||
actualType.is(TypeFlags.NULLABLE) && !expectedType.is(TypeFlags.NULLABLE) &&
|
||||
actualType.nonNullableType.isAssignableTo(expectedType)
|
||||
) {
|
||||
return module.createBinary(
|
||||
actualType.is(TypeFlags.LONG)
|
||||
? BinaryOp.NeI64
|
||||
: BinaryOp.NeI32,
|
||||
expr,
|
||||
actualType.toNativeZero(module)
|
||||
);
|
||||
}
|
||||
return module.createI32(actualType.isAssignableTo(expectedType) ? 1 : 0);
|
||||
}
|
||||
|
||||
compileLiteralExpression(
|
||||
|
@ -15,7 +15,7 @@
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 43
|
||||
i32.const 68
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
@ -27,7 +27,7 @@
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 46
|
||||
i32.const 71
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
|
@ -4,27 +4,51 @@ class B extends A {}
|
||||
var a: A;
|
||||
var b: B;
|
||||
var i: i32;
|
||||
var I: i64;
|
||||
var f: f32;
|
||||
var F: f64;
|
||||
|
||||
assert( a instanceof A );
|
||||
assert( b instanceof A );
|
||||
assert(!(i instanceof A));
|
||||
assert(!(I instanceof A));
|
||||
assert(!(f instanceof A));
|
||||
assert(!(F instanceof A));
|
||||
|
||||
assert(!(a instanceof B));
|
||||
assert( b instanceof B );
|
||||
assert(!(i instanceof B));
|
||||
assert(!(I instanceof B));
|
||||
assert(!(f instanceof B));
|
||||
assert(!(F instanceof B));
|
||||
|
||||
assert(!(a instanceof i32));
|
||||
assert(!(b instanceof i32));
|
||||
assert( i instanceof i32 );
|
||||
assert(!(I instanceof i32));
|
||||
assert(!(f instanceof i32));
|
||||
assert(!(F instanceof i32));
|
||||
|
||||
assert(!(a instanceof i64));
|
||||
assert(!(b instanceof i64));
|
||||
assert(!(i instanceof i64));
|
||||
assert( I instanceof i64 );
|
||||
assert(!(f instanceof i64));
|
||||
assert(!(F instanceof i64));
|
||||
|
||||
assert(!(a instanceof f32));
|
||||
assert(!(b instanceof f32));
|
||||
assert(!(i instanceof f32));
|
||||
assert(!(I instanceof f32));
|
||||
assert( f instanceof f32 );
|
||||
assert(!(F instanceof f32));
|
||||
|
||||
assert(!(a instanceof f64));
|
||||
assert(!(b instanceof f64));
|
||||
assert(!(i instanceof f64));
|
||||
assert(!(I instanceof f64));
|
||||
assert(!(f instanceof f64));
|
||||
assert( F instanceof f64 );
|
||||
|
||||
function isI32<T>(v: T): bool {
|
||||
// should eliminate non-applicable branches (see fixture)
|
||||
@ -38,13 +62,14 @@ function isI32<T>(v: T): bool {
|
||||
assert( isI32(0));
|
||||
assert(!isI32(0.0));
|
||||
assert(!isI32(<u32>0)); // signedness is relevant
|
||||
assert(!isI32(<u16>0)); // byte size is relevant
|
||||
|
||||
var an: A | null = null;
|
||||
assert(!(an instanceof A)); // TS: null is not an instance of A
|
||||
assert( an instanceof A | null); // AS: null is an instance of A | null
|
||||
assert(!(an instanceof A)); // TS: ==null is not an instance of A
|
||||
assert( an instanceof A | null); // AS: ==null is an instance of A | null
|
||||
an = changetype<A | null>(1);
|
||||
assert( an instanceof A); // TS: non-null is an instance of A
|
||||
assert( an instanceof A | null); // AS: non-null is an instance of A | null
|
||||
assert( an instanceof A); // TS: !=null is an instance of A
|
||||
assert( an instanceof A | null); // AS: !=null is an instance of A | null
|
||||
|
||||
// TODO: keep track of nullability during flows, so this becomes precomputable:
|
||||
// assert(an !== null && an instanceof A);
|
||||
|
@ -11,7 +11,9 @@
|
||||
(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/I (mut i64) (i64.const 0))
|
||||
(global $instanceof/f (mut f32) (f32.const 0))
|
||||
(global $instanceof/F (mut f64) (f64.const 0))
|
||||
(global $instanceof/an (mut i32) (i32.const 0))
|
||||
(global $~lib/memory/HEAP_BASE i32 (i32.const 40))
|
||||
(export "memory" (memory $0))
|
||||
@ -29,29 +31,12 @@
|
||||
i32.const 0
|
||||
return
|
||||
)
|
||||
(func $start:instanceof (; 4 ;) (type $_)
|
||||
i32.const 1
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 9
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 1
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 10
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
(func $instanceof/isI32<u16> (; 4 ;) (type $ii) (param $0 i32) (result i32)
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
return
|
||||
)
|
||||
(func $start:instanceof (; 5 ;) (type $_)
|
||||
i32.const 1
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
@ -61,8 +46,7 @@
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.const 1
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
@ -75,6 +59,17 @@
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 13
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
@ -83,7 +78,8 @@
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 1
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
@ -110,13 +106,12 @@
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 17
|
||||
i32.const 18
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.const 1
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
@ -137,7 +132,8 @@
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 1
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
@ -164,7 +160,7 @@
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 24
|
||||
i32.const 23
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
@ -202,18 +198,104 @@
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
call $instanceof/isI32<i32>
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 38
|
||||
i32.const 28
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
f64.const 0
|
||||
call $instanceof/isI32<f64>
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 29
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 30
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 32
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 33
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 34
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 1
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 35
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 36
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 37
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
@ -225,7 +307,6 @@
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
call $instanceof/isI32<u32>
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
@ -236,6 +317,161 @@
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 41
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 42
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 1
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 43
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 44
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 46
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 47
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 48
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 49
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 50
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 1
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 51
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
call $instanceof/isI32<i32>
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 62
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
f64.const 0
|
||||
call $instanceof/isI32<f64>
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 63
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
call $instanceof/isI32<u32>
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 64
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
i32.const 0
|
||||
call $instanceof/isI32<u16>
|
||||
i32.eqz
|
||||
i32.eqz
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 65
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
global.get $instanceof/an
|
||||
i32.const 0
|
||||
i32.ne
|
||||
@ -244,7 +480,7 @@
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 43
|
||||
i32.const 68
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
@ -254,7 +490,7 @@
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 44
|
||||
i32.const 69
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
@ -268,7 +504,7 @@
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 46
|
||||
i32.const 71
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
@ -278,15 +514,15 @@
|
||||
if
|
||||
i32.const 0
|
||||
i32.const 8
|
||||
i32.const 47
|
||||
i32.const 72
|
||||
i32.const 0
|
||||
call $~lib/env/abort
|
||||
unreachable
|
||||
end
|
||||
)
|
||||
(func $start (; 5 ;) (type $_)
|
||||
(func $start (; 6 ;) (type $_)
|
||||
call $start:instanceof
|
||||
)
|
||||
(func $null (; 6 ;) (type $_)
|
||||
(func $null (; 7 ;) (type $_)
|
||||
)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user