(* demonstration file for RTT typechecker *)
(* Jan 16:
It is now feasible to actually execute this file, if
rtt.sml has been compiled. The programs Test and Test2
now display the term entered and wait for the user to enter
input before displaying the type results.
There are some new Test2 examples. I'm interested in the testing of
complex propositions with the ostensibly complete checker -- examples
from readers are very welcome!
*)
(* Jan 15:
the Test and Test2 checkers have been updated.
Test now includes a label on the type it reports (called
"unconditional type"); Test2 now includes what should be a complete
type-checker for RTT -- it reports the unconditional type (output
of the original algorithm) plus the new "conditional type" which
requires the stated conditions for correctness.
Outputs in this file have NOT been updated to reflect this,
so it is worth running the commands again (especially the Test2
examples).
*)
(* due to version changes, reported outputs may differ
from what the latest version gives you. *)
(* Some example propositional functions to type are taken from the
unpublished paper of Kamareddine, Nederpelt, and Laan, and in some
of the comments I refer to the numbered examples or parts of examples
in the paper from which the pfs are taken. It is not necessary
to have their paper to understand what I am doing. It is a good idea
to read my draft paper's discussion of syntax and variable binding
conventions. *)
(* the syntax *)
(*
differs from only in that it can contain
propositional variables. Eventually, there will be a requirement
that 's contain at least one free variable (xi) as well as no
propositional variables
(* propositional variable *)
(* propositional variables were introduced because of the demands
of proof checking *)
p1, p2, p3...
(* variable *)
` x1, x2, x3...
(* individual constant *)
a1, a2, a3...
(* binary propositional connective *)
-- any nonempty string of lower case letters
(* relation symbol *)
any nonempty string of upper case letters followed by a numeral
--R2 is a relation symbol of arity 2.
(* quantifier *)
any string of upper case letters (including the empty string)
(* atomic terms *)
either `` or
(* general terms *)
= `` or or where is a
as below in which no propositional variable can appear,
and in which it will eventually be required that there
be a free variable (this requirement is not now implemented,
and probably will be implemented as something the user can
turn on and off; the effect will be to eliminate proposition
types as constituents of pf types, while still allowing
proposition types as types of propositions themselves)
(* propositions *)
= propositional variable -- example: p1
(,...,) The number of arguments
must agree with the arity of the relation symbol
elementary sentence example:
R3(a3,x1,a2)
~ negation example: ~p5
()
binary propositional connective example: (p1 v p2)
There is no order of operations
-- parentheses are mandatory
[``] The proposition must
contain a free occurrence of the variable.
quantified proposition example:
[x1]R2(x3,x1)
``(,...,)
``!(,...,)
propositional variable application examples:
x1(a1,x2,x1(x2)), x1!(a1,x2,x1(x2))
The exclamation point indicates that the
order of the pf represented by the variable
is exactly one higher than the maximum of the
orders of the arguments; it does not indicate
(as it would for Russell and Whitehead) that
the type of the pf represented by the variable
is actually predicative, but it will be predicative
if its argument types are predicative.
*)
(* Test takes a proposition or pf as argument and reports typing of
variables in the proposition at the three stages of the algorithm,
then reports the final type of the proposition or pf.
?!? signals ill-typedness.
Orders are supplied only where they are nontrivial (where the order
is the smallest permitted by the types of its constituents, it is not
given). |xi| is the unknown order of the polymorphic type of the
variable xi.
Test2 is as Test, but further reports (in the case of a proposition in
which all pf arguments are typable by this algorithm, but which this
algorithm cannot type), additional conditions (if there are any) under
which the proposition or pf could be typed. This report is currently
(and perhaps inevitably) quite long. The report is now shorter (usually)
as of second revision Jan 11, and also Test2 will sometimes report
some information about typable terms as well.
The function Typecheck will just return the type of a pf (taking its
string representation as an argument).
*)
(* examples *)
Typecheck "p1";
(* > val it = "()" : string *)
Typecheck "x1!(a1)";
(* > val it = "((0))" : string *)
(* in the next example, the order of the type of x1
is indeterminate (anything higher than 1 is possible) *)
Typecheck "x1(a1)";
(* > val it = "((0)^max(|x1|,1))" : string *)
(* examples from the paper *)
(* the stages of variable typing reported by Test2 are
basic list: types derived from syntax of the term.
unification list: additional type judgements derived by unification.
It's useful to be aware that a failure of unification is usually
signalled by the assignment of the nonsense type ?!? to the variable
x0 in the unification list.
final type list: judgments obtained by the rewriting of the unified
type list using each of the assignments in the list.
See the paper for more discussion.
*)
(* pfs from example 21 *)
Test2 "R1(x1)";
(*
basic list:
x1: 0
unification list:
x1: 0
final type list:
x1: 0
(0)
*)
(* this is also the term typed in example 32 *)
Test2 "x3(R1(x1),S1(a1))";
(*
basic list:
x1: 0
x3: ((0),())^max(|x3|,2)
x3: [x3]
unification list:
x1: 0
x3: ((0),())^max(|x3|,2)
x3: [x3]
final type list:
x1: 0
x3: ((0),())^max(|x3|,2)
(((0),())^max(|x3|,2))
*)
(* it seems more appropriate to use the
"predicative" version, and I'll do this in subsequent
examples from the paper *)
Test2 "x3!(R1(x1),S1(a1))";
(*
basic list:
x1: 0
x3: ((0),())
x3: [x3]
unification list:
x1: 0
x3: ((0),())
x3: [x3]
final type list:
x1: 0
x3: ((0),())
(((0),()))
*)
Test2 "(x1!(a1) v x2!())";
(*
basic list:
x1: (0)
x1: [x1]
x2: ()
x2: [x2]
unification list:
x1: (0)
x1: [x1]
x2: ()
x2: [x2]
final type list:
x1: (0)
x2: ()
((0),())
*)
Test2 "x3!(x2!(R1(x1)))";
(*
basic list:
x1: 0
x2: ((0))
x3: ((((0))))
x3: [x3]
unification list:
x1: 0
x2: ((0))
x3: ((((0))))
x3: [x3]
final type list:
x1: 0
x2: ((0))
x3: ((((0))))
(((((0)))))
*)
Test2 "[x1]R1(x1)";
(*
basic list:
x1: 0
unification list:
x1: 0
final type list:
x1: 0
()^1
*)
(* example 24 *)
(* I type the following term in the form with unbounded order first --
notice that while the type of x3 does not appear as a polymorphic type
[x3] (we know quite a lot about this type) its order |x3| is unknown
and appears as a variable, though we do know that it is greater than
or equal to 2 and greater than or equal to the polymorphic order
|x2|+1. *)
Test2 "x3(S1(x1),x2,a2)";
(*
basic list:
x1: 0
x2: [x2]
x3: ((0),[x2],0)^max(|x2|+1,|x3|,2)
x3: [x3]
unification list:
x1: 0
x2: [x2]
x3: ((0),[x2],0)^max(|x2|+1,|x3|,2)
x3: [x3]
final type list:
x1: 0
x2: [x2]
x3: ((0),[x2],0)^max(|x2|+1,|x3|,2)
([x2],((0),[x2],0)^max(|x2|+1,|x3|,2))
*)
(* Here's the same term with the exclamation point to control
the order. Notice that the type is polymorphic -- the type of the
variable x2 is left free. *)
Test2 "x3!(S1(x1),x2,a2)";
(*
basic list:
x1: 0
x2: [x2]
x3: ((0),[x2],0)
x3: [x3]
unification list:
x1: 0
x2: [x2]
x3: ((0),[x2],0)
x3: [x3]
final type list:
x1: 0
x2: [x2]
x3: ((0),[x2],0)
([x2],((0),[x2],0))
*)
(* the following calculation shows the polymorphic order of the
type shown above -- it is nontrivial but it is not displayed because
it is the smallest possible order determined by the structure of the
type *)
showorder(typeorder(Newtypecheck (parse "x3!(S1(x1),x2,a2)")));
(* > val it = "max(|x2|+2,3)" : string *)
Test2 "x2!(x1,R1(x1))";
(*
basic list:
x1: [x1]
x1: 0
x2: ([x1],(0))
x2: [x2]
unification list:
x1: [x1]
x1: 0
x2: ([x1],(0))
x2: [x2]
final type list:
x1: 0
x2: (0,(0))
(0,(0,(0)))
*)
(* example 49 *)
Test2 "S2(a1,a2)";
(*
basic list:
unification list:
final type list:
()
*)
Test2 "(R1(a1) v S1(a1))";
(*
basic list:
unification list:
final type list:
()
*)
Test2 "(R1(x1) v S1(x1))";
(*
basic list:
x1: 0
unification list:
x1: 0
final type list:
x1: 0
(0)
*)
Test2 "(R1(x1) v S1(x2))";
(*
basic list:
x1: 0
x2: 0
unification list:
x1: 0
x2: 0
final type list:
x1: 0
x2: 0
(0,0)
*)
(* the term finally typed in part 3 types polymorphically here *)
Test2 "x1!(x2,x2)";
(*
basic list:
x1: [x1]
x1: ([x2],[x2])
x2: [x2]
unification list:
x1: [x1]
x1: ([x2],[x2])
x2: [x2]
final type list:
x1: ([x2],[x2])
x2: [x2]
(([x2],[x2]),[x2])
*)
(* this term from the derivation of type 3 types as you typed it *)
Test2 "x3!(R1(x1),R1(x2))";
(*
basic list:
x1: 0
x2: 0
x3: ((0),(0))
x3: [x3]
unification list:
x1: 0
x2: 0
x3: ((0),(0))
x3: [x3]
final type list:
x1: 0
x2: 0
x3: ((0),(0))
(((0),(0)))
*)
(* given extra information, the term will type as you wanted it to: *)
(* the additional disjunct fixes the type of x2 *)
Test2 "(x1!(x2,x2) v x2!(a1))";
(*
basic list:
x1: [x1]
x1: ([x2],[x2])
x2: [x2]
x2: (0)
unification list:
x1: [x1]
x1: ([x2],[x2])
x2: [x2]
x2: (0)
final type list:
x1: ((0),(0))
x2: (0)
(((0),(0)),(0))
*)
(* example 4 types polymorphically *)
Test2 "x3!(x1,x2)";
(*
basic list:
x1: [x1]
x2: [x2]
x3: [x3]
x3: ([x1],[x2])
unification list:
x1: [x1]
x2: [x2]
x3: [x3]
x3: ([x1],[x2])
final type list:
x1: [x1]
x2: [x2]
x3: ([x1],[x2])
([x1],[x2],([x1],[x2]))
*)
(* and with extra info will type as you wanted it to *)
(* the disjuncts supply the extra information that x1 and x2
have type 0 *)
Test2 "(x3!(x1,x2) v (R1(x1) v R1(x2)))";
(*
basic list:
x1: 0
x1: [x1]
x2: 0
x2: [x2]
x3: [x3]
x3: ([x1],[x2])
unification list:
x1: 0
x1: [x1]
x2: 0
x2: [x2]
x3: [x3]
x3: ([x1],[x2])
final type list:
x1: 0
x2: 0
x3: (0,0)
(0,0,(0,0))
*)
(* in example 5, the type of x1 is deducible from the syntax,
but not the type of x2 *)
Test2 "(R1(x1) v ~x3!(x1,x2))";
(*
basic list:
x1: [x1]
x1: 0
x2: [x2]
x3: [x3]
x3: ([x1],[x2])
unification list:
x1: [x1]
x1: 0
x2: [x2]
x3: [x3]
x3: ([x1],[x2])
final type list:
x1: 0
x2: [x2]
x3: (0,[x2])
(0,[x2],(0,[x2]))
*)
(* an extra disjunct recovers the specific type you wanted *)
Test2 "((R1(x1) v ~x3!(x1,x2)) v S1(x2)";
(*
basic list:
x1: 0
x1: [x1]
x2: [x2]
x2: 0
x3: [x3]
x3: ([x1],[x2])
unification list:
x1: 0
x1: [x1]
x2: [x2]
x2: 0
x3: [x3]
x3: ([x1],[x2])
final type list:
x1: 0
x2: 0
x3: (0,0)
(0,0,(0,0))
*)
Test2 "(R1(x1) v ~T3(x1,x1,x2))";
(*
basic list:
x1: 0
x2: 0
unification list:
x1: 0
x2: 0
final type list:
x1: 0
x2: 0
(0,0)
*)
(* example 50 *)
Test2 "(x3!(a1) v S1(a1))";
(*
basic list:
x3: [x3]
x3: (0)
unification list:
x3: [x3]
x3: (0)
final type list:
x3: (0)
((0))
*)
Test2 "x3!(R1(a1),S1(a1))";
(*
basic list:
x3: [x3]
x3: ((),())
unification list:
x3: [x3]
x3: ((),())
final type list:
x3: ((),())
(((),()))
*)
Test2 "[x3](x3!() v ~x3!())";
(*
basic list:
x3: ()
x3: [x3]
unification list:
x3: ()
x3: [x3]
final type list:
x3: ()
()^1
*)
(* example 58 *)
(* Notice that the general type covers both cases in your example *)
(* subsequently I reconstruct both special cases you give by
supplying extra information in the term. *)
Test2 "x3!(x1)";
(*
basic list:
x1: [x1]
x3: [x3]
x3: ([x1])
unification list:
x1: [x1]
x3: [x3]
x3: ([x1])
final type list:
x1: [x1]
x3: ([x1])
([x1],([x1]))
*)
Test2 "(x3!(x1)vR1(x1))";
(*
basic list:
x1: 0
x1: [x1]
x3: [x3]
x3: ([x1])
unification list:
x1: 0
x1: [x1]
x3: [x3]
x3: ([x1])
final type list:
x1: 0
x3: (0)
(0,(0))
*)
Test2 "(x3!(x1)v x1!())";
(*
basic list:
x1: ()
x1: [x1]
x3: ([x1])
x3: [x3]
unification list:
x1: ()
x1: [x1]
x3: ([x1])
x3: [x3]
final type list:
x1: ()
x3: (())
((),(()))
*)
(* selected examples from comments in the source file *)
(* this one requires the algorithm to "think" a bit! *)
Test2 "((x5!(x6,x6)v x5!(x2,x3))v(x1!(x2)v x1!(x3)))";
(* the variables with negative indices are generated internally
as a device to support matching of orders of pf arguments,
which happens in the rewriting stage rather than the structural
unification stage *)
(*
basic list:
x1: [x1]
x1: ([x2])
x1: ([x3])
x2: [x2]
x3: [x3]
x5: ([x6],[x6])
x5: [x5]
x5: ([x2],[x3])
x6: [x6]
unification list:
x~4: [x~3]
x~4: ([x6],[x6])
x~4: ([x2],[x3])
x~3: ([x2],[x3])
x~3: [x~4]
x~3: ([x6],[x6])
x~2: ([x2])
x~2: [x~1]
x~2: ([x3])
x~1: ([x3])
x~1: ([x2])
x~1: [x~2]
x1: ([x3])
x1: ([x2])
x1: [x1]
x2: [x3]
x2: [x6]
x2: [x2]
x3: [x2]
x3: [x6]
x3: [x3]
x5: ([x6],[x6])
x5: [x5]
x5: ([x2],[x3])
x6: [x6]
x6: [x3]
x6: [x2]
final type list:
x~4: ([x6],[x6])
x~3: ([x6],[x6])
x~2: ([x6])
x~1: ([x6])
x1: ([x6])
x2: [x6]
x3: [x6]
x5: ([x6],[x6])
x6: [x6]
(([x6]),[x6],[x6],([x6],[x6]),[x6])
*)
Test2 "~x1(x1)";
(*circularity of types is detected at the third stage*)
(*
basic list:
x1: [x1]
x1: ([x1])
unification list:
x1: [x1]
x1: ([x1])
final type list:
x1: ?!?
?!?
*)
Test2 "x1!(x1!(x2))";
(*
basic list:
x1: ((([x2]),[x2]))
x1: [x1]
x1: ([x2])
x2: [x2]
unification list:
x~2: [x~1]
x~2: ((([x2]),[x2]))
x~2: ([x2])
x~1: ([x2])
x~1: [x~2]
x~1: ((([x2]),[x2]))
x1: ((([x2]),[x2]))
x1: ([x2])
x1: [x1]
x2: (([x2]),[x2])
x2: [x2]
final type list:
x~2: ?!?
x~1: ?!?
x1: ?!?
x2: ?!?
?!?
*)
(* with renaming of bound variables, this is the same as
the previous pf, and types correctly *)
Test2 "x1!(x2!(x3))";
(*
basic list:
x1: ((([x3]),[x3]))
x1: [x1]
x2: ([x3])
x3: [x3]
unification list:
x1: ((([x3]),[x3]))
x1: [x1]
x2: ([x3])
x3: [x3]
final type list:
x1: ((([x3]),[x3]))
x2: ([x3])
x3: [x3]
(((([x3]),[x3])))
*)
(* this does not type *)
Test2 "x1(x1(x2))";
(*
basic list:
x1: [x1]
x1: ((([x2])^max(|x1|,|x2|+1,1),[x2]))
unification list:
x1: [x1]
x1: ((([x2])^max(|x1|,|x2|+1,1),[x2]))
final type list:
x1: ?!?
?!?
*)
(* but this, with the same meaning, does type: *)
Test2 "x1(x3(x4))";
(*
basic list:y
x1: [x1]
x1: ((([x4])^max(|x3|,|x4|+1,1),[x4]))^max(|x1|,|x3|+2,|x4|+3,3)
unification list:
x1: [x1]
x1: ((([x4])^max(|x3|,|x4|+1,1),[x4]))^max(|x1|,|x3|+2,|x4|+3,3)
final type list:
x1: ((([x4])^max(|x3|,|x4|+1,1),[x4]))^max(|x1|,|x3|+2,|x4|+3,3)
(((([x4])^max(|x3|,|x4|+1,1),[x4]))^max(|x1|,|x3|+2,|x4|+3,3))
*)
Test2 "x1!(x2!(x1))";
(*
basic list:
x1: [x1]
x1: (([x1],([x1])))
unification list:
x1: [x1]
x1: (([x1],([x1])))
final type list:
x1: ?!?
?!?
*)
(* but with renaming of variables in the pf argument: *)
Test2 "x1!(x4!(x3))";
(*
basic list:
x1: (([x3],([x3])))
x1: [x1]
x3: [x3]
x4: ([x3])
unification list:
x1: (([x3],([x3])))
x1: [x1]
x3: [x3]
x4: ([x3])
final type list:
x1: (([x3],([x3])))
x3: [x3]
x4: ([x3])
((([x3],([x3]))))
*)
Test2 "x5(((x2!(x4)v x3!(x4))v[x1](x1(x2) v x1(x3))))";
(*
basic list:
x1: (([x4]))^max(|x1|,|x4|+2,2)
x2: ([x4])
x3: ([x4])
x4: [x4]
x5: ((([x4]),([x4]),[x4])^max(|x1|+1,|x4|+3,3))^max(|x1|+2,|x4|+4,|x5|,4)
x5: [x5]
unification list:
x1: (([x4]))^max(|x1|,|x4|+2,2)
x2: ([x4])
x3: ([x4])
x4: [x4]
x5: ((([x4]),([x4]),[x4])^max(|x1|+1,|x4|+3,3))^max(|x1|+2,|x4|+4,|x5|,4)
x5: [x5]
final type list:
x1: (([x4]))^max(|x1|,|x4|+2,2)
x2: ([x4])
x3: ([x4])
x4: [x4]
x5: ((([x4]),([x4]),[x4])^max(|x1|+1,|x4|+3,3))^max(|x1|+2,|x4|+4,|x5|,4)
*)
(* Here is a type failure caused by order alone: this would
check in STT *)
Test2 "(x1!(x2,x2)v x1!(R1(a1),[x4]R1(x4)))";
(*
basic list:
x1: [x1]
x1: ((),()^1)
x1: ([x2],[x2])
x2: [x2]
x4: 0
unification list:
x~4: [x~3]
x~4: ()
x~4: ()^1
x~3: ()^1
x~3: ()
x~3: [x~4]
x~2: ((),()^1)
x~2: ([x2],[x2])
x~2: [x~1]
x~1: ([x2],[x2])
x~1: ((),()^1)
x~1: [x~2]
x1: ((),()^1)
x1: ([x2],[x2])
x1: [x1]
x2: ()^1
x2: [x2]
x2: ()
x4: 0
final type list:
x~4: ()^1
x~4: ()
x~3: ()^1
x~3: ()
x~2: (()^1,()^1)
x~2: ((),()^1)
x~1: ((),()^1)
x~1: (()^1,()^1)
x1: ((),()^1)
x1: (()^1,()^1)
x2: ()
x2: ()^1
x4: 0
?!?
*)
(* The same term with the STT checker "Test2" *)
Test2 "(x1(x2,x2)v x1(R1(a1),[x4]R1(x4)))";
(*
basic list:
x1: ((),())
x1: ([x2],[x2])
x1: [x1]
x2: [x2]
unification list:
x1: [x1]
x1: ([x2],[x2])
x1: ((),())
x2: [x2]
x2: ()
final type list:
x1: ((),())
x2: ()
(((),()),())
*)
(* Here's an example of the use of Test2. *)
(* Test2 reports that this term cannot be typed by our algorithm, but
goes on to report (I hope!) addtional conditions under which the term
could be assigned a type. I'm not entirely confident about
correctness (there could be bugs). I have trouble seeing how a useful
type notation could be developed for the completely general case --
for practical work the more limited algorithm is probably sufficient.
*)
(* It would be worthwhile to check the conditions by hand -- they
are now much shorter than the original output of the Jan 10 version! *)
(* with the final Jan. 11 revision there is a single apparently
correct condition for typability generated *)
Test2 "(x1(x2,x2) v x1([x3]x3(x4),[x5][x7]x7(x5,x6)))";
(*
basic list:
x1: ((),())
x1: ([x2],[x2])
x1: [x1]
x2: [x2]
unification list:
x1: [x1]
x1: ([x2],[x2])
x1: ((),())
x2: [x2]
x2: ()
final type list:
x1: ((),())
x2: ()
(((),()),())
> val it = () : unit
- Test2 "(x1(x2,x2) v x1([x3]x3(x4),[x5][x7]x7(x5,x6)))";
basic list:
x1: [x1]
x1: (([x4])^max(|x3|+1,|x4|+2,2),([x6])^max(|x5|+2,|x6|+2,|x7|+1,2))^max(|x1|,|x3|+2,|x4|+3,|x5|+3,|x6|+3,|x7|+2,3)
x1: ([x2],[x2])^max(|x1|,|x2|+1,1)
x2: [x2]
x3: ([x4])^max(|x3|,|x4|+1,1)
x4: [x4]
x5: [x5]
x6: [x6]
x7: ([x5],[x6])^max(|x5|+1,|x6|+1,|x7|,1)
unification list:
x~2: [x~1]
x~2: ([x6])^max(|x5|+2,|x6|+2,|x7|+1,2)
x~2: ([x4])^max(|x3|+1,|x4|+2,2)
x~1: ([x4])^max(|x3|+1,|x4|+2,2)
x~1: [x~2]
x~1: ([x6])^max(|x5|+2,|x6|+2,|x7|+1,2)
x1: (([x4])^max(|x3|+1,|x4|+2,2),([x6])^max(|x5|+2,|x6|+2,|x7|+1,2))^max(|x1|,|x3|+2,|x4|+3,|x5|+3,|x6|+3,|x7|+2,3)
x1: ([x2],[x2])^max(|x1|,|x2|+1,1)
x1: [x1]
x2: ([x4])^max(|x3|+1,|x4|+2,2)
x2: ([x6])^max(|x5|+2,|x6|+2,|x7|+1,2)
x2: [x2]
x3: ([x4])^max(|x3|,|x4|+1,1)
x4: [x4]
x4: [x6]
x5: [x5]
x6: [x4]
x6: [x6]
x7: ([x5],[x6])^max(|x5|+1,|x6|+1,|x7|,1)
final type list:
x~2: ([x6])^max(|x3|+1,|x6|+2,2)
x~2: ([x6])^max(|x5|+2,|x6|+2,|x7|+1,2)
x~1: ([x6])^max(|x5|+2,|x6|+2,|x7|+1,2)
x~1: ([x6])^max(|x3|+1,|x6|+2,2)
x1: (([x6])^max(|x3|+1,|x6|+2,2),([x6])^max(|x5|+2,|x6|+2,|x7|+1,2))^max(|x1|,|x3|+2,|x5|+3,|x6|+3,|x7|+2,3)
x1: (([x6])^max(|x3|+1,|x6|+2,2),([x6])^max(|x3|+1,|x6|+2,2))^max(|x1|,|x3|+2,|x5|+3,|x6|+3,|x7|+2,3)
x2: ([x6])^max(|x3|+1,|x6|+2,2)
x2: ([x6])^max(|x5|+2,|x6|+2,|x7|+1,2)
x3: ([x6])^max(|x3|,|x6|+1,1)
x4: [x6]
x5: [x5]
x6: [x6]
x7: ([x5],[x6])^max(|x5|+1,|x6|+1,|x7|,1)
?!?
|x3| <= |x7| and
|x5|+1 <= |x7| and
|x6|+1 <= |x7| and
|x7|+2 <= |x1| and
|x7| <= |x3|
*)
(* this was a Test2 case that broke some of my early algorithms *)
Test2 "(x1(x3,x5) v (x3(x4) v (x5(x6) v x1(x2,x2)))";
(*
basic list:
x1: [x1]
x1: ([x2],[x2])^max(|x1|,|x2|+1,1)
x1: ([x3],[x5])^max(|x1|,|x3|+1,|x5|+1,1)
x2: [x2]
x3: ([x4])^max(|x3|,|x4|+1,1)
x3: [x3]
x4: [x4]
x5: [x5]
x5: ([x6])^max(|x5|,|x6|+1,1)
x6: [x6]
unification list:
x1: [x1]
x1: ([x2],[x2])^max(|x1|,|x2|+1,1)
x1: ([x3],[x5])^max(|x1|,|x3|+1,|x5|+1,1)
x2: ([x4])^max(|x3|,|x4|+1,1)
x2: ([x6])^max(|x5|,|x6|+1,1)
x2: [x3]
x2: [x2]
x2: [x5]
x3: ([x4])^max(|x3|,|x4|+1,1)
x3: [x3]
x3: ([x6])^max(|x5|,|x6|+1,1)
x3: [x5]
x3: [x2]
x4: [x4]
x4: [x6]
x5: [x2]
x5: ([x6])^max(|x5|,|x6|+1,1)
x5: [x5]
x5: ([x4])^max(|x3|,|x4|+1,1)
x5: [x3]
x6: [x6]
x6: [x4]
final type list:
x1: (([x6])^max(|x5|,|x6|+1,1),([x6])^max(|x5|,|x6|+1,1))^max(|x1|,|x5|+1,|x6|+2,2)
x2: ([x6])^max(|x5|,|x6|+1,1)
x3: ([x6])^max(|x5|,|x6|+1,1)
x4: [x6]
x5: ([x6])^max(|x5|,|x6|+1,1)
x6: [x6]
((([x6])^max(|x5|,|x6|+1,1),([x6])^max(|x5|,|x6|+1,1))^max(|x1|,|x5|+1,|x6|+2,2),([x6])^max(|x5|,|x6|+1,1),([x6])^max(|x5|,|x6|+1,1),[x6],([x6])^max(|x5|,|x6|+1,1),[x6])
*)
(* another example with Test2 -- it is quite clear that the
conditions described for typability are the correct ones *)
Test2 "(x1!(x2,x2)v x1!([x3][x5]x3!(x5,x8),[x6][x9]x6!(x4,x9)))";
(*
basic list:
x1: [x1]
x1: (([x8])^max(|x5|+2,|x8|+2,2),([x4])^max(|x4|+2,|x9|+2,2))
x1: ([x2],[x2])
x2: [x2]
x3: ([x5],[x8])
x4: [x4]
x5: [x5]
x6: ([x4],[x9])
x8: [x8]
x9: [x9]
unification list:
x~4: [x~3]
x~4: ([x4])^max(|x4|+2,|x9|+2,2)
x~4: ([x8])^max(|x5|+2,|x8|+2,2)
x~3: ([x8])^max(|x5|+2,|x8|+2,2)
x~3: [x~4]
x~3: ([x4])^max(|x4|+2,|x9|+2,2)
x~2: (([x8])^max(|x5|+2,|x8|+2,2),([x4])^max(|x4|+2,|x9|+2,2))
x~2: ([x2],[x2])
x~2: [x~1]
x~1: ([x2],[x2])
x~1: (([x8])^max(|x5|+2,|x8|+2,2),([x4])^max(|x4|+2,|x9|+2,2))
x~1: [x~2]
x1: (([x8])^max(|x5|+2,|x8|+2,2),([x4])^max(|x4|+2,|x9|+2,2))
x1: ([x2],[x2])
x1: [x1]
x2: ([x4])^max(|x4|+2,|x9|+2,2)
x2: [x2]
x2: ([x8])^max(|x5|+2,|x8|+2,2)
x3: ([x5],[x8])
x4: [x4]
x4: [x8]
x5: [x5]
x6: ([x4],[x9])
x8: [x4]
x8: [x8]
x9: [x9]
final type list:
x~4: ([x8])^max(|x5|+2,|x8|+2,2)
x~4: ([x8])^max(|x8|+2,|x9|+2,2)
x~3: ([x8])^max(|x8|+2,|x9|+2,2)
x~3: ([x8])^max(|x5|+2,|x8|+2,2)
x~2: (([x8])^max(|x8|+2,|x9|+2,2),([x8])^max(|x8|+2,|x9|+2,2))
x~2: (([x8])^max(|x5|+2,|x8|+2,2),([x8])^max(|x8|+2,|x9|+2,2))
x~1: (([x8])^max(|x5|+2,|x8|+2,2),([x8])^max(|x8|+2,|x9|+2,2))
x~1: (([x8])^max(|x8|+2,|x9|+2,2),([x8])^max(|x8|+2,|x9|+2,2))
x1: (([x8])^max(|x5|+2,|x8|+2,2),([x8])^max(|x8|+2,|x9|+2,2))
x1: (([x8])^max(|x8|+2,|x9|+2,2),([x8])^max(|x8|+2,|x9|+2,2))
x2: ([x8])^max(|x5|+2,|x8|+2,2)
x2: ([x8])^max(|x8|+2,|x9|+2,2)
x3: ([x5],[x8])
x4: [x8]
x5: [x5]
x6: ([x8],[x9])
x8: [x8]
x9: [x9]
?!?
|x5| <= |x9| and
|x8| <= |x9| and
|x9| <= |x5|
OR
|x5| <= |x8| and
|x9| <= |x8|
*)
(* the file needs some nontrivial examples for Test2 -- RTT terms with
interesting type conditions *)
Test2 "(x1([x4][x2][x3]x4(x2,x3)) and x1([x6][x8][x7]x6(x7,x8)))";
(*
[some output omitted]
final type list:
x~2: ()^max(|x2|+2,|x3|+2,|x4|+1,2)
x~2: ()^max(|x6|+1,|x7|+2,|x8|+2,2)
x~1: ()^max(|x2|+2,|x3|+2,|x4|+1,2)
x~1: ()^max(|x6|+1,|x7|+2,|x8|+2,2)
x1: (()^max(|x2|+2,|x3|+2,|x4|+1,2))^max(|x1|,|x2|+3,|x3|+3,|x4|+2,|x6|+2,|x7|+3,|x8|+3,3)
x1: (()^max(|x6|+1,|x7|+2,|x8|+2,2))^max(|x1|,|x2|+3,|x3|+3,|x4|+2,|x6|+2,|x7|+3,|x8|+3,3)
x2: [x2]
x3: [x3]
x4: ([x2],[x3])^max(|x2|+1,|x3|+1,|x4|,1)
x6: ([x7],[x8])^max(|x6|,|x7|+1,|x8|+1,1)
x7: [x7]
x8: [x8]
unconditional type:
?!?
conditional type:
((()^max(|x2|+2,|x3|+2,|x4|+1,2))^max(|x1|,|x2|+3,|x3|+3,|x4|+2,|x6|+2,|x7|+3,|x8|+3,3))
WITH
|x2|+1 <= |x6| and
|x3|+1 <= |x6| and
|x4| <= |x6| and
|x6|+2 <= |x1| and
|x6| <= |x4| and
|x7|+1 <= |x6| and
|x8|+1 <= |x6|
*)
Test2 "(x1!([x2][x3](x2(x4) v x3(x4))) v x1!([x5][x7]x5(x4,x7)))";
(*
[some output omitted]
unconditional type:
?!?
conditional type:
((([x4])^max(|x4|+2,|x5|+1,|x7|+2,2)))
WITH
|x2| <= |x5| and
|x3| <= |x5| and
|x4|+1 <= |x3| and
|x5| <= |x2| and
|x7|+1 <= |x5|
OR
|x2| <= |x5| and
|x3| <= |x5| and
|x4|+1 <= |x2| and
|x5| <= |x3| and
|x7|+1 <= |x5|
*)
(* the interesting feature of this next example is that you
can see the complete checker determining that the order of the type of the
"free floating" variable x7 must be exactly 2 *)
Test2 "(x6([x5](x5!(R1(x1)) implies x5!(x2))) and x6!((x2(a1) and [x7]x7())))";
(*
[some output omitted]
final type list:
x~6: ((0))^max(|x7|+1,2)
x~6: ((0))^3
x~5: ((0))^3
x~5: ((0))^max(|x7|+1,2)
x~4: (0)
x~3: ((0))
x~2: ((0))
x1: 0
x2: (0)
x5: ((0))
x6: (((0))^3)^max(|x6|,|x7|+2,4)
x6: (((0))^max(|x7|+1,2))^max(|x6|,|x7|+2,4)
x7: ()^max(|x7|,0)
unconditional type:
?!?
conditional type:
((((0))^3)^max(|x6|,|x7|+2,4))
WITH
|x7| >= 2 and
|x7| <= 2 and
|x7|+2 <= |x6|
*)
Test2 "(x6!([x2](R1(x1) or (x2!(x1) or [Ex3](x3!(x2) or [Ex4](x4!(x3) or [Ex5]x5!(x4)))))) and x6!([x8][x9][x10](x10!(x8,x9,x1) or x8(a1))))";
(*
conditional type:
(((0)^5))
WITH
|x8| >= 3 and
|x8| <= 3 and
|x9| <= |x8|
OR
|x9| >= 3 and
|x8| <= |x9| and
|x9| <= 3 and
|x9| <= |x8|+2
*)
`