I wrote an extension to implement fractions in I7. It’s targeted to 6M62.

I’m having some trouble making use of the `cast`

parameter, which I think means the same as `compatible-with`

in v10.1 (as listed in the definition for Neptune). From experimentation, it seems that for two types K and L, the inclusion of a line like:

```
cast: L_TY
```

in the definition of K_TY lets the compiler know that 1) that it is OK within I7 code to supply an L to a phrase expecting a K, and 2) it should expect to be supplied an I6 routine `L_TY_to_K_TY`

to be applied in order to convert a value from an L to a K when doing so.

I put together a fraction type, and it works, but converting to numbers or real numbers requires use of phrases to decide. I would like to be able to set up casting so that the average user can ignore the extra complexity of having to convert to other number types. I tried to define:

```
FRACTION_TY:
apply-macro:#BASE-KIND
singular:fraction
plural:fractions
...
instance-of:WORD_VALUE_TY
instance-of:SAYABLE_VALUE_TY
...
cast:NUMBER_TY
cast:REAL_NUMBER_TY
...
```

and use the following test rule:

```
When play begins (this is the test number casting rule):
if 4 is less than 6.0, say "4 < 6.0[line break]";
if 4.0 is less than 6, say "4.0 < 6[line break]";
if 5 over 2 is less than 2, say "5/2 < 2[line break]";
if 5 over 2 is greater than 2, say "5/2 > 2[line break]";
if 3 is less than 5 over 2, say "3 < 5/2[line break]";
if 3 is greater than 5 over 2, say "3 > 5/2[line break]".
```

Compilation works but the resulting I6 doesn’t make use of the provided casting routines:

```
[ R_845 ;
if (debug_rules) DB_Rule(R_845, 845);
! [2: if 4 is less than 6.0]
if (((REAL_NUMBER_TY_Compare(NUMBER_TY_to_REAL_NUMBER_TY(4), 1086324736) < 0)))
{! [3: say ~4 < 6.0[line break]~]
say__p=1;! [4: ~4 < 6.0~]
ParaContent(); print "4 < 6.0";! [5: line break]
ParaContent(); new_line; .L_Say1; .L_SayX1;}
! [6: if 4.0 is less than 6]
if (((REAL_NUMBER_TY_Compare(1082130432, NUMBER_TY_to_REAL_NUMBER_TY(6)) < 0)))
{! [7: say ~4.0 < 6[line break]~]
say__p=1;! [8: ~4.0 < 6~]
ParaContent(); print "4.0 < 6";! [9: line break]
ParaContent(); new_line; .L_Say2; .L_SayX2;}
! [10: if 5 over 2 is less than 2]
if (((FRACTION_TY_Compare((SimplifiedFraction(5, 2)), 2) < 0)))
{! [11: say ~5/2 < 2[line break]~]
say__p=1;! [12: ~5/2 < 2~]
ParaContent(); print "5/2 < 2";! [13: line break]
ParaContent(); new_line; .L_Say3; .L_SayX3;}
! [14: if 5 over 2 is greater than 2]
if (((FRACTION_TY_Compare((SimplifiedFraction(5, 2)), 2) > 0)))
{! [15: say ~5/2 > 2[line break]~]
say__p=1;! [16: ~5/2 > 2~]
ParaContent(); print "5/2 > 2";! [17: line break]
ParaContent(); new_line; .L_Say4; .L_SayX4;}
! [18: if 3 is less than 5 over 2]
if (((3 < (SimplifiedFraction(5, 2)))))
{! [19: say ~3 < 5/2[line break]~]
say__p=1;! [20: ~3 < 5/2~]
ParaContent(); print "3 < 5/2";! [21: line break]
ParaContent(); new_line; .L_Say5; .L_SayX5;}
! [22: if 3 is greater than 5 over 2]
if (((3 > (SimplifiedFraction(5, 2)))))
{! [23: say ~3 > 5/2[line break]~]
say__p=1;! [24: ~3 > 5/2~]
ParaContent(); print "3 > 5/2";! [25: line break]
ParaContent(); new_line; .L_Say6; .L_SayX6;}
rfalse;
];
```

Note that `SimplifiedFraction()`

is the I6 translation for the `N over D`

phrase at the I7 level, which is:

```
To decide which fraction is (X - number) over (Y - number):
(- (SimplifiedFraction({X}, {Y})) -).
```

I6 generation of the above is identical if I insert the casting parameter:

```
cast: FRACTION_TY
```

into the definitions for numbers and real numbers.

I’m noting that the `test number casting rule`

’s individual comparisons are being handled slightly differently by the compiler in that, for the lines involving fractions, the ones starting with a fraction make use of `FRACTION_TY_Compare()`

while the ones starting with numbers are just plain I6 comparison operators. This is different from the first two comparisons in the rule, which both correctly make use of `REAL_NUMBER_TY_Compare()`

and `NUMBER_TY_to_REAL_NUMBER_TY()`

regardless of which type comes first.

In the test scenario there is another rule:

```
When play begins (this is the test real number casting rule):
if 22 over 3 is less than 7.1, say "22/3 < 7.1[line break]";
if 22 over 3 is greater than 7.1, say "22/3 > 7.1[line break]";
if 7.1 is less than 22 over 3, say "7.1 < 22/3[line break]";
if 7.1 is greater than 22 over 3, say "7.1 > 22/3[line break]".
```

which translates into I6 (again, the same no matter whether it `REAL_NUMBER_TY`

or `FRACTION_TY`

that gets the casting parameter) as:

```
[ R_846 ;
! [2: if 22 over 3 is less than 7.1]
if (((REAL_NUMBER_TY_Compare(NUMBER_TY_to_REAL_NUMBER_TY((SimplifiedFraction(22, 3))), 1088631603) < 0)))
{! [3: say ~22/3 < 7.1[line break]~]
say__p=1;! [4: ~22/3 < 7.1~]
ParaContent(); print "22/3 < 7.1";! [5: line break]
ParaContent(); new_line; .L_Say7; .L_SayX7;}
! [6: if 22 over 3 is greater than 7.1]
if (((REAL_NUMBER_TY_Compare(NUMBER_TY_to_REAL_NUMBER_TY((SimplifiedFraction(22, 3))), 1088631603) > 0)))
{! [7: say ~22/3 > 7.1[line break]~]
say__p=1;! [8: ~22/3 > 7.1~]
ParaContent(); print "22/3 > 7.1";! [9: line break]
ParaContent(); new_line; .L_Say8; .L_SayX8;}
! [10: if 7.1 is less than 22 over 3]
if (((REAL_NUMBER_TY_Compare(1088631603, NUMBER_TY_to_REAL_NUMBER_TY((SimplifiedFraction(22, 3)))) < 0)))
{! [11: say ~7.1 < 22/3[line break]~]
say__p=1;! [12: ~7.1 < 22/3~]
ParaContent(); print "7.1 < 22/3";! [13: line break]
ParaContent(); new_line; .L_Say9; .L_SayX9;}
! [14: if 7.1 is greater than 22 over 3]
if (((REAL_NUMBER_TY_Compare(1088631603, NUMBER_TY_to_REAL_NUMBER_TY((SimplifiedFraction(22, 3)))) > 0)))
{! [15: say ~7.1 > 22/3[line break]~]
say__p=1;! [16: ~7.1 > 22/3~]
ParaContent(); print "7.1 > 22/3";! [17: line break]
ParaContent(); new_line; .L_Say10; .L_SayX10;}
rfalse;
];
```

and in this case the compiler seems to have decided to apply `NUMBER_TY_to_REAL_NUMBER()`

to a fraction type where I would expect it to have chosen `FRACTION_TY_to_REAL_NUMBER_TY()`

.

Am I doing something wrong, or is there some special compiler-level magic going on here involving the comparison relations (e.g. `numerically-greater-than-relation`

mentioned in the Standard Rules) that can’t be modified?