""" The `dynamic` type crossed with operators. """ class Test def main .testDynamic .testNilableDynamic .testNilableAndNotDynamic .testMixedDynamic .testNumericPromotion .testNumericSmallInts .testEquality .testComparison1 .testComparison2 .testBinaryArithmetic .testUnaryArithmetic .testAugmentedAssignment .testBoolOps .testConcat .testIn def add(x, y) as dynamic return x + y def testDynamic x as dynamic = 2 y as dynamic = 4 assert x * y == 8 x = 'aoeu' y = 'aoeu' assert x + y == 'aoeuaoeu' def testNilableDynamic x as dynamic? = 2 y as dynamic? = 4 assert x * y == 8 x = 'aoeu' y = 'aoeu' assert x + y == 'aoeuaoeu' def testNilableAndNotDynamic x as dynamic? = 2 y as dynamic = 4 assert x * y == 8 x = 'aoeu' y = 'aoeu' assert x + y == 'aoeuaoeu' def testMixedDynamic x as dynamic? = 2 y as dynamic = 2 assert x * 4 == 8 assert 4 * x == 8 assert y * 4 == 8 assert 4 * y == 8 x = 'aoeu' y = 'aoeu' assert x + 'aoeu' == 'aoeuaoeu' assert 'aoeu' + y == 'aoeuaoeu' def testNumericPromotion x as dynamic? y as dynamic? x, y = 1, 2.3d assert x + y == 3.3d x, y = 2.3d, 1 assert x + y == 3.3d x, y = 1, 2.3f assert x + y == 3.3f x, y = 2.3f, 1 assert x + y == 3.3f def testNumericSmallInts x16 as int16 = 9 y16 as int16 = 10 assert .add(x16, y16) == 19 x8 as int8 = 3 y8 as int8 = 5 assert .add(x8, y8) == 8 xu16 as uint16 = 9 yu16 as uint16 = 10 assert .add(xu16, yu16) == 19 xu8 as uint8 = 3 yu8 as uint8 = 5 assert .add(xu8, yu8) == 8 def testEquality x as dynamic = 2 y as dynamic = 2 assert x == y y = 4 assert x <> y assert not x == y x = 'aoeu' y = 'AOEU'.toLower assert x == y y = 'AOUE' assert x <> y assert not x == y x = 'aoeu' y = 2 assert x <> y assert not x == y def testComparison1 x as dynamic = 2 y as dynamic = 4 assert x < y assert y > x assert x <= y assert y >= x assert not x > y assert not y < x x = 3.0f assert x > 0 x = 3.0d assert x > 0 # int vs. number x = 0 y = -0.1 assert x >= y assert not (x <= y) def testComparison2 i = 5 d = 'aoeu' to dynamic expect CannotCompareException, print d < MyStruct() expect CannotCompareException, print i < d expect CannotCompareException, print i > d # Cobra does not allow `3 < '4'` at compile-time # It is not allowed at run-time either. d = '20' expect CannotCompareException, print i < d expect CannotCompareException, print i > d def testBinaryArithmetic x as dynamic? y as dynamic? x = 2 y = 4 assert x + y == 6 assert x - y == -2 assert y - x == 2 assert x * y == 8 assert x / y == 0.5 assert y / x == 2.0 assert y / x == 2 assert x // y == 0 assert y // x == 2 assert x % y == 2 assert y % x == 0 def testUnaryArithmetic x as dynamic = 2 assert x == 2 x = -x assert x == -2 x = -x assert x == 2 x = 2.0 x = -x x = 2.0f x = -x x = +x # TODO warning. same assert x == -2 x = -2 x = +x # TODO warning. same assert x == -2 def testAugmentedAssignment x as dynamic = 1 x += 1 assert x == 2 x *= 4 assert x == 8 x /= 2 assert x == 4.0 x -= 4 assert x == 0 x = 'a' x += 'b' assert x == 'ab' def testBoolOps x as dynamic = 0 y as dynamic = 1 assert not (x and y) assert x or y x = 1 assert x and y assert x or y x = 0 y = 'aoeu' assert not (x and y) assert x or y x = 'aoeu' assert x and y assert x or y xq as dynamic? = nil yq as dynamic? = 1 assert not (xq and yq) assert xq or yq xq = 1 assert xq and yq assert xq or yq xq = 0 yq = 'aoeu' assert not (xq and yq) assert xq or yq xq = 'aoeu' assert xq and yq assert xq or yq x = 0 assert not x x = 'aoeu' assert not not x xq = nil assert not xq xq = 'aoeu' assert not not xq t as dynamic = [1, 2, 3] assert all t assert any t t.add(0) assert not all t assert any t t = [0] assert not all t assert not any t t.clear assert all t assert not any t def testConcat a = 'a' to dynamic b = 'b' to dynamic assert a + b == 'ab' assert a == 'a' and b == 'b' a += 'c' assert a == 'ac' a, b = 1, 2 assert a + b == 3 def testIn .testIn1 .testIn2 .testIn3 .testIn4 .testCustomIn def testIn1 s = List() s.add(5) assert 5 in s x = 5 to Object assert x in s xq = 5 to Object? assert xq in s def testIn2 s = Set() s.add(5) assert 5 in s x = 5 to Object assert x in s xq = 5 to Object? # TODO: # assert xq in s ... error: Argument 1 of method "contains" expects a non-nilable type (dynamic), but the call is supplying a nilable type (Object?). # ... interesting issue. this likely comes from the use of NotNull on arguments in Cobra-based libraries CobraCore.noOp(xq) def testIn3 pass # x = 5 to dynamic # t = [1, 3, 5] # to-do: the following fails because Cobra perceives List.contains to have an arg type of "T?" due to their not being a NotNull attribute on it. So then it thinks the List contains int32?, it casts the dynamic var to int32? and then C# appropriately chokes because it's really a list of int32. # assert x in t # x = 2 # assert x not in t # assert not (x in t) # TODO: xq def testIn4 assert 'ao' in 'aoeu' s = 'aoeu' assert 'ao' in s t = 'aoeu' to dynamic assert 'ao' in t # <--- string lit `in` dynamic which is a string def testCustomIn c = MyContainer(3, 5) assert 3 in c assert 4 in c assert 1 not in c assert not (1 in c) assert c.invokeContainsCount == 4 and c.invokeEnumerateCount == 0 class MyContainer implements IEnumerable cue init(min as int, max as int) base.init _min, _max = min, max get invokeContainsCount from var as int get invokeEnumerateCount from var as int get min from var as int get max from var as int # TODO: # cue enumerate as int* # _invokeEnumerateCount += 1 # for i in min : max, yield i def getEnumerator as IEnumerator _invokeEnumerateCount += 1 for i in .min : .max, yield i def getEnumerator as System.Collections.IEnumerator implements System.Collections.IEnumerable return .getEnumerator def contains(i as int) as bool _invokeContainsCount += 1 return i >= .min and i < .max struct MyStruct pass