null checking throughout logical and/or

This commit is contained in:
dcode 2019-04-09 04:25:38 +02:00
parent da4a7751fd
commit cd79376101
4 changed files with 102 additions and 12 deletions

View File

@ -4755,8 +4755,14 @@ export class Compiler extends DiagnosticEmitter {
case Token.AMPERSAND_AMPERSAND: { // left && right
leftExpr = this.compileExpressionRetainType(left, contextualType, WrapMode.NONE);
leftType = this.currentType;
let previousFlow = this.currentFlow;
let rightFlow = previousFlow.fork();
this.currentFlow = rightFlow;
rightFlow.inheritNonnullIf(leftExpr);
rightExpr = this.compileExpression(right, leftType, ConversionKind.IMPLICIT, WrapMode.NONE);
rightType = leftType;
this.currentFlow = previousFlow;
// simplify if only interested in true or false
if (contextualType == Type.bool || contextualType == Type.void) {
@ -4799,8 +4805,14 @@ export class Compiler extends DiagnosticEmitter {
case Token.BAR_BAR: { // left || right
leftExpr = this.compileExpressionRetainType(left, contextualType, WrapMode.NONE);
leftType = this.currentType;
let previousFlow = this.currentFlow;
let rightFlow = previousFlow.fork();
this.currentFlow = rightFlow;
rightFlow.inheritNonnullIfNot(leftExpr);
rightExpr = this.compileExpression(right, leftType, ConversionKind.IMPLICIT, WrapMode.NONE);
rightType = leftType;
this.currentFlow = previousFlow;
// simplify if only interested in true or false
if (contextualType == Type.bool || contextualType == Type.void) {

View File

@ -16,6 +16,10 @@
(export "testWhile" (func $possibly-null/testWhile))
(export "testWhile2" (func $possibly-null/testWhile2))
(export "testWhile3" (func $possibly-null/testWhile3))
(export "testLogicalAnd" (func $possibly-null/testTrue))
(export "testLogicalOr" (func $possibly-null/testTrue))
(export "testLogicalAndMulti" (func $possibly-null/testLogicalAndMulti))
(export "testLogicalOrMulti" (func $possibly-null/testLogicalAndMulti))
(func $possibly-null/testTrue (; 0 ;) (type $FUNCSIG$vi) (param $0 i32)
nop
)
@ -52,7 +56,10 @@
end
end
)
(func $null (; 4 ;) (type $FUNCSIG$v)
(func $possibly-null/testLogicalAndMulti (; 4 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
nop
)
(func $null (; 5 ;) (type $FUNCSIG$v)
nop
)
)

View File

@ -83,16 +83,30 @@ export function testWhile3(a: Ref | null, b: Ref | null): void {
}
}
// TODO:
function requireNonNull(a: Ref): Ref {
return a;
}
// function requireNonNull(a: Ref): Ref {
// return a;
// }
export function testLogicalAnd(a: Ref | null): void {
a && requireNonNull(a);
}
// export function testLogicalAnd(a: Ref | null): void {
// a && requireNonNull(a);
// }
export function testLogicalOr(a: Ref | null): void {
!a || requireNonNull(a) != null;
}
// export function testLogicalOr(a: Ref | null): void {
// !a || requireNonNull(a);
// }
export function testLogicalAndMulti(a: Ref | null, b: Ref | null): void {
if (a && b) {
if (isNullable(a)) ERROR("should be non-nullable");
if (isNullable(b)) ERROR("should be non-nullable");
}
}
export function testLogicalOrMulti(a: Ref | null, b: Ref | null): void {
if (!a || !b) {
// something
} else {
if (isNullable(a)) ERROR("should be non-nullable");
if (isNullable(b)) ERROR("should be non-nullable");
}
}

View File

@ -1,6 +1,7 @@
(module
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$vii (func (param i32 i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$v (func))
(memory $0 0)
(table $0 1 funcref)
@ -18,6 +19,10 @@
(export "testWhile" (func $possibly-null/testWhile))
(export "testWhile2" (func $possibly-null/testWhile2))
(export "testWhile3" (func $possibly-null/testWhile3))
(export "testLogicalAnd" (func $possibly-null/testLogicalAnd))
(export "testLogicalOr" (func $possibly-null/testLogicalOr))
(export "testLogicalAndMulti" (func $possibly-null/testLogicalAndMulti))
(export "testLogicalOrMulti" (func $possibly-null/testLogicalOrMulti))
(func $possibly-null/testTrue (; 0 ;) (type $FUNCSIG$vi) (param $0 i32)
local.get $0
if
@ -128,6 +133,58 @@
end
end
)
(func $null (; 12 ;) (type $FUNCSIG$v)
(func $possibly-null/requireNonNull (; 12 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
)
(func $possibly-null/testLogicalAnd (; 13 ;) (type $FUNCSIG$vi) (param $0 i32)
local.get $0
if (result i32)
local.get $0
call $possibly-null/requireNonNull
else
i32.const 0
end
drop
)
(func $possibly-null/testLogicalOr (; 14 ;) (type $FUNCSIG$vi) (param $0 i32)
local.get $0
i32.eqz
if (result i32)
i32.const 1
else
local.get $0
call $possibly-null/requireNonNull
i32.const 0
i32.ne
end
drop
)
(func $possibly-null/testLogicalAndMulti (; 15 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
local.get $0
if (result i32)
local.get $1
else
i32.const 0
end
if
nop
end
)
(func $possibly-null/testLogicalOrMulti (; 16 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
local.get $0
i32.eqz
if (result i32)
i32.const 1
else
local.get $1
i32.eqz
end
if
nop
else
nop
end
)
(func $null (; 17 ;) (type $FUNCSIG$v)
)
)