|
| 1 | +#! nqp |
| 2 | + |
| 3 | +plan(10); |
| 4 | + |
| 5 | +# Counter to make sure parameterization interning works right. |
| 6 | +my int $num_parameterizations := 0; |
| 7 | + |
| 8 | +# A coercion type HOW, as far as needed to test parameterization. |
| 9 | +class SimpleCoerceHOW { |
| 10 | + method new_type() { |
| 11 | + my $type := nqp::newtype(self.new(), 'Uninstantiable'); |
| 12 | + nqp::setparameterizer($type, -> $type, $params { |
| 13 | + # Re-use same HOW. |
| 14 | + $num_parameterizations++; |
| 15 | + nqp::newtype($type.HOW, 'Uninstantiable'); |
| 16 | + }); |
| 17 | + $type |
| 18 | + } |
| 19 | + |
| 20 | + method parameterize($coercion_types, $to, $from) { |
| 21 | + nqp::parameterizetype($coercion_types, [$to, $from]); |
| 22 | + } |
| 23 | + |
| 24 | + sub check_instantiated($coercion_type) { |
| 25 | + nqp::die('Cannot perform this operation on an uninstantiated coercion type') |
| 26 | + if nqp::isnull(nqp::typeparameterized($coercion_type)); |
| 27 | + } |
| 28 | + |
| 29 | + method to_type($coercion_type) { |
| 30 | + check_instantiated($coercion_type); |
| 31 | + nqp::typeparameterat($coercion_type, 0) |
| 32 | + } |
| 33 | + |
| 34 | + method from_type($coercion_type) { |
| 35 | + check_instantiated($coercion_type); |
| 36 | + # Could be nqp::typeparameterat($coercion_type, 1), but want to test other op. |
| 37 | + nqp::atpos(nqp::typeparameters($coercion_type), 1) |
| 38 | + } |
| 39 | +} |
| 40 | + |
| 41 | +my $coercion_types := SimpleCoerceHOW.new_type(); |
| 42 | +ok(1, 'Can create a parameterized type'); |
| 43 | + |
| 44 | +my $failed := 0; |
| 45 | +try { |
| 46 | + nqp::setparameterizer($coercion_types, -> $type, $params { }); |
| 47 | + CATCH { $failed := 1; } |
| 48 | +} |
| 49 | +ok($failed, 'Cannot set up parametricity twice'); |
| 50 | + |
| 51 | +class A { } |
| 52 | +class B { } |
| 53 | +class C { } |
| 54 | + |
| 55 | +ok($num_parameterizations == 0, 'Sanity: did not yet run parameterization closure'); |
| 56 | +my $ct1 := $coercion_types.HOW.parameterize($coercion_types, A, B); |
| 57 | +ok($num_parameterizations == 1, 'Produced one parameterization'); |
| 58 | + |
| 59 | +ok(nqp::eqaddr($ct1.HOW, $coercion_types.HOW), 'TestCoerceHOW is shared'); |
| 60 | +ok(!nqp::eqaddr($ct1.WHAT, $coercion_types.WHAT), '.WHAT is not shared'); |
| 61 | + |
| 62 | +ok(nqp::eqaddr(nqp::typeparameterized($ct1), $coercion_types), 'Can get back to parametric type'); |
| 63 | + |
| 64 | +ok(nqp::eqaddr($ct1.HOW.to_type($ct1), A), 'Can get type parameter (1)'); |
| 65 | +ok(nqp::eqaddr($ct1.HOW.from_type($ct1), B), 'Can get type parameter (2)'); |
| 66 | + |
| 67 | +$failed := 0; |
| 68 | +try { |
| 69 | + $coercion_types.HOW.to_type($coercion_types); |
| 70 | + CATCH { $failed := 1 } |
| 71 | +} |
| 72 | +ok($failed, 'Cannot get type parameters on the unparameterized coercion type'); |
0 commit comments