/* ----------------------------------------------------------------------------- Copyright 2020-2021 Kevin P. Barry Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ----------------------------------------------------------------------------- */ // Author: Kevin P. Barry [ta0kira@gmail.com] testcase "reduce to self" { success } unittest test { Value value <- Value.create() scoped { optional Value value2 <- reduce(value) } in if (!present(value2)) { fail("Failed") } } concrete Value { @type create () -> (Value) } define Value { create () { return Value{} } } testcase "reduce to unrelated" { success } unittest test { Value value <- Value.create() scoped { optional String value2 <- reduce(value) } in if (present(value2)) { fail("Failed") } } concrete Value { @type create () -> (Value) } define Value { create () { return Value{} } } testcase "reduce wrong arg type" { error require "String" require "Value" exclude "value2" } unittest test { Value value <- Value.create() optional Value value2 <- reduce(value) } concrete Value { @type create () -> (Value) } define Value { create () { return Value{} } } testcase "reduce wrong return type" { error require "String" require "Value" require "value2" } unittest test { Value value <- Value.create() optional Value value2 <- reduce(value) } concrete Value { @type create () -> (Value) } define Value { create () { return Value{} } } testcase "reduce success with param" { success } unittest test { Value value <- Value.create() scoped { optional Value value2 <- value.attempt() } in if (!present(value2)) { fail("Failed") } } concrete Value<|#x> { @type create () -> (Value<#x>) @value attempt<#y> () -> (optional Value<#y>) } define Value { create () { return Value<#x>{} } attempt () { return reduce,Value<#y>>(self) } } @value interface Type1 {} @value interface Type2 { refines Type1 } testcase "reduce fail with param" { success } unittest test { Value value <- Value.create() scoped { optional Value value2 <- value.attempt() } in if (present(value2)) { fail("Failed") } } concrete Value<|#x> { @type create () -> (Value<#x>) @value attempt<#y> () -> (optional Value<#y>) } define Value { create () { return Value<#x>{} } attempt () { return reduce,Value<#y>>(self) } } @value interface Type1 {} @value interface Type2 { refines Type1 } testcase "reduce success with contra param" { success } unittest test { Value> value <- Value>.create() scoped { optional Value> value2 <- value.attempt>() } in if (!present(value2)) { fail("Failed") } } concrete Value<#x|> { @type create () -> (Value<#x>) @value attempt<#y> () -> (optional Value<#y>) } define Value { create () { return Value<#x>{} } attempt () { return reduce,Value<#y>>(self) } } @value interface Type1 {} @value interface Type2 { refines Type1 } testcase "reduce fail with contra param" { success } unittest test { Value> value <- Value>.create() scoped { optional Value> value2 <- value.attempt>() } in if (present(value2)) { fail("Failed") } } concrete Value<#x|> { @type create () -> (Value<#x>) @value attempt<#y> () -> (optional Value<#y>) } define Value { create () { return Value<#x>{} } attempt () { return reduce,Value<#y>>(self) } } @value interface Type1 {} @value interface Type2 { refines Type1 } testcase "reduce success from union" { success } unittest test { [Value1|Value2] value <- Value1.create() scoped { optional Base value2 <- reduce<[Value1|Value2],Base>(value) } in if (!present(value2)) { fail("Failed") } } @value interface Base {} concrete Value1 { refines Base @type create () -> (Value1) } define Value1 { create () { return Value1{} } } @value interface Value2 { refines Base } testcase "reduce fail from union" { success } unittest test { [Value1|Value2] value <- Value1.create() scoped { optional Value2 value2 <- reduce<[Value1|Value2],Value2>(value) } in if (present(value2)) { fail("Failed") } } @value interface Base {} concrete Value1 { refines Base @type create () -> (Value1) } define Value1 { create () { return Value1{} } } @value interface Value2 { refines Base } testcase "reduce success to intersect" { success } unittest test { Value value <- Value.create() scoped { optional [Base1&Base2] value2 <- reduce(value) } in if (!present(value2)) { fail("Failed") } } @value interface Base1 {} @value interface Base2 {} concrete Value { refines Base1 refines Base2 @type create () -> (Value) } define Value { create () { return Value{} } } testcase "reduce fail to intersect" { success } unittest test { Value value <- Value.create() scoped { optional [Base1&Base2] value2 <- reduce(value) } in if (present(value2)) { fail("Failed") } } @value interface Base1 {} @value interface Base2 {} concrete Value { refines Base1 @type create () -> (Value) } define Value { create () { return Value{} } } testcase "reduce success union to intersect" { success } unittest test { [Value1|Value2] value <- Value2.create() scoped { optional [Base1&Base2] value2 <- reduce<[Value1|Value2],[Base1&Base2]>(value) } in if (!present(value2)) { fail("Failed") } } @value interface Base1 {} @value interface Base2 {} @value interface Value1 { refines Base1 refines Base2 } concrete Value2 { refines Base1 refines Base2 @type create () -> (Value2) } define Value2 { create () { return Value2{} } } testcase "reduce fail union to intersect" { success } unittest test { [Value1|Value2] value <- Value2.create() scoped { optional [Base1&Base2] value2 <- reduce<[Value1|Value2],[Base1&Base2]>(value) } in if (present(value2)) { fail("Failed") } } @value interface Base1 {} @value interface Base2 {} @value interface Value1 { refines Base1 refines Base2 } concrete Value2 { refines Base1 @type create () -> (Value2) } define Value2 { create () { return Value2{} } } testcase "reduce success intersect to union" { success } unittest test { [Value1&Value2] value <- Data.create() scoped { optional [Base1|Base2] value2 <- reduce<[Value1&Value2],[Base1|Base2]>(value) } in if (!present(value2)) { fail("Failed") } } @value interface Base1 {} @value interface Base2 {} @value interface Value1 { refines Base1 } @value interface Value2 {} concrete Data { refines Value1 refines Value2 @type create () -> (Data) } define Data { create () { return Data{} } } testcase "reduce fail intersect to union" { success } unittest test { [Value1&Value2] value <- Data.create() scoped { optional [Base1|Base2] value2 <- reduce<[Value1&Value2],[Base1|Base2]>(value) } in if (present(value2)) { fail("Failed") } } @value interface Base1 {} @value interface Base2 {} @value interface Value1 {} @value interface Value2 {} concrete Data { refines Value1 refines Value2 @type create () -> (Data) } define Data { create () { return Data{} } } testcase "reduce succeeds to covariant any" { success } unittest test { Value value <- Value.create() scoped { optional Value value2 <- reduce,Value>(value) } in if (!present(value2)) { fail("Failed") } } concrete Value<|#x> { @type create () -> (Value<#x>) } define Value { create () { return Value<#x>{} } } testcase "reduce succeeds to contravariant all" { success } unittest test { Value value <- Value.create() scoped { optional Value value2 <- reduce,Value>(value) } in if (!present(value2)) { fail("Failed") } } concrete Value<#x|> { @type create () -> (Value<#x>) } define Value { create () { return Value<#x>{} } } testcase "reduce fails to invariant any" { success } unittest test { Value value <- Value.create() scoped { optional Value value2 <- reduce,Value>(value) } in if (present(value2)) { fail("Failed") } } concrete Value<#x> { @type create () -> (Value<#x>) } define Value { create () { return Value<#x>{} } } testcase "reduce succeeds from covariant all" { success } unittest test { Value value <- Value.create() scoped { optional Value value2 <- reduce,Value>(value) } in if (!present(value2)) { fail("Failed") } } concrete Value<|#x> { @type create () -> (Value<#x>) } define Value { create () { return Value<#x>{} } } testcase "reduce succeeds from contravariant any" { success } unittest test { Value value <- Value.create() scoped { optional Value value2 <- reduce,Value>(value) } in if (!present(value2)) { fail("Failed") } } concrete Value<#x|> { @type create () -> (Value<#x>) } define Value { create () { return Value<#x>{} } } testcase "reduce fails from invariant all" { success } unittest test { Value value <- Value.create() scoped { optional Value value2 <- reduce,Value>(value) } in if (present(value2)) { fail("Failed") } } concrete Value<#x> { @type create () -> (Value<#x>) } define Value { create () { return Value<#x>{} } } testcase "reduce from interface" { success } unittest test { if (!present(reduce(Value.create()))) { fail("Failed") } } @value interface Base0 { } @value interface Base1 { refines Base0 } concrete Value { refines Base1 @type create () -> (Value) } define Value { create () { return Value{ } } } testcase "reduce with internal override" { success } unittest test { if (!present(reduce>(Value.create()))) { fail("Failed") } if (present(reduce>(Value.create()))) { fail("Failed") } } @value interface Base0 {} @value interface Base1 { refines Base0 } @value interface Base2<|#x> {} concrete Value { refines Base2 @type create () -> (Value) } define Value { refines Base2 create () { return Value{ } } } testcase "partial matches in nested types" { success } @value interface A {} @value interface B {} @value interface C {} concrete AB { refines A refines B @type create () -> (AB) } define AB { create () { return AB{ } } } concrete AC { refines A refines C @type create () -> (AC) } define AC { create () { return AC{ } } } unittest leftNestedInRight { \ Testing.checkEquals(present(reduce<[A&B],[[A&B]|C]>(AB.create())),true) } unittest rightNestedInLeft { \ Testing.checkEquals(present(reduce<[[A|B]&C],[A|B]>(AC.create())),true) } unittest unionToUnion { \ Testing.checkEquals(present(reduce<[[A&B]|C],[[A&B]|C]>(AB.create())),true) } unittest intersectToIntersect { \ Testing.checkEquals(present(reduce<[[A|B]&C],[[A|B]&C]>(AC.create())),true) } unittest unionToIntersect { \ Testing.checkEquals(present(reduce<[A|B],[A&B]>(AB.create())),false) }