/oleg

Primary LanguageStandard ML

This directory contains the current samizdat version of OLEG, specifically

  src            the source code (still needs SML/NJ 0.93)
  bin            linux binaries compiled from the above
  examples       some demo scripts
  papers         related old drafts of papers now changed beyond recognition
                   (and generally for the better)
  emacs-hack.el  not so much an oleg mode; more a nightmare of comint and
                   font-lock


Things you might like to know


(1)  EMACS GADGETS

     Try adjusting the code in emacs-hack.el to point to your oleg binary,
     then run it when you start emacs (e.g. by pasting it into .emacs).
     Now, when you've just loaded an oleg script, do M-x run-lego and it'll
     start an oleg process for you. Moreover, the tab key in the script
     buffer will send a line to the oleg process. More moreover, most things
     will get coloured in properly.
  
     It's not even Proof Lance Corporal, but it's better than a poke in the
     eye.

     By the way, if things start going really slowly, try watching in black
     and white...


(2)  LIBRARY

     Er. Sorry about that. I can't quite remember how, but I seem to have
     broken the module system at some point---it's incompatible in some way
     with the labelling mechanism or something.

     Anyhow, the library as was isn't so useful for oleg development. On
     the other hand, you'll notice that each of the example files has the
     same prelude. More or less. I guess it could be an include file.


(3)  EXAMPLES

     BasicProg.l  demonstrates the basics of the exciting new programming
                    tactics
     TypeCheck.l  is the implementation of the typechecker from VfL version I
                    (the early funny one---see PAPERS)
     TYPES03.l    is the demo script used at TYPES 2003, in which we have
                    the joy of gcd
     Exception.l  is the code and correctness proof for my variation on the
                    theme of Hutton and Wright's compiler-with-exceptions;
                    as advertized in their paper
     Unify.l      if the code and correctness proof for first order unification
                    by structural recursion (see PAPERS)


(4)  PAPERS

     old-elim.ps  is the original no-you-can't-fit-all-that-in-19-pages
                    version of EwaM, which attempts to be forthcoming about
                    no confusion and no cycle proofs, and has some moderately
                    provocative ideas about what the gadgets might be good
                    for; most of which got censored, in favour of doing one
                    job well...
     view-I.ps    is the earlier funnier (and shorter) version of VfL; whilst
                    anonymous referees provoked significant improvements
                    and much useful work on elaboration, I do feel that the
                    official version has lost (a) the emphasis on interactive
                    programming (like we do it in oleg) and (b) the feeling
                    of how much fun it is to work this way, rather than how
                    hard you have to work to make a machine believe in it...
     unify.ps     is actually quite close to the real thing, and
     proof.ps     is the correctness proof which nobody read, but is actually
                    quite cool; the Unify.l file follows this pretty closely


(5)  EQUALITY

     The Elim, KJunify and Program X tactics all use John Major equality,
     but Qrepl (and its monster-in-the-basement chum Wave) still use
     Martin-Lof equality. Also, some of the gadget-makers expect to find
     M-L eq. So we need both. Sometimes we need to convert between the two.
     Not so hard.


(6)  GADGETS

     The brackets (!...!) enclose tags---the codes oleg tactics use to refer
     to constructions they exploit. The Generate tactic attempts to find a
     provider for the construction with a given tag. The Label tactic
     maps a tag to a given construction.

     Gadget generation is no longer automatically triggered when you
     declare an inductive datatype. Trigger it yourself, thus

       Inductive [Nat : Type] Constructors
         [zero : Nat]
         [suc  : {n:Nat}Nat];
       Generate (!Nat cases!);    (* the case analysis principle *)
       Generate (!Nat eduardo!);  (* the recursion principle *)

     Note that generating `eduardo' relies on finding

       Inductive [Unit  : Type] Constructors [void : Unit];
       Label (!unit!) Unit;
       Label (!unit void!) void;

     to provide the trivial memo structure.

     The gadgets which prove no confusion still generate the M-L equality
     version. Ugh! I never got around to automating the much simpler JM
     construction, although you can find the template in the example
     files. Here it is again

       [Absurd = {T:Type}T];

       Goal {x,y:Nat}Type;
       Program NatNoConfStmt x y;        (* compute matrix of statements *)
         Program Elim (!Nat cases!) x;
           Program Elim (!Nat cases!) y;
             Program Refine {Phi:Type}Phi->Phi;
             Program Refine Absurd;
           Program Elim (!Nat cases!) y;
             Program Refine Absurd;
             Program Names y x;
               Program Refine {Phi:Type}((x == y)->Phi)->Phi;
       Program Save;
        
       Goal {x,y:Nat}{q:x == y}{tg:Target q}NatNoConfStmt x y;
       Program NatNoConf x y q tg;       (* justify the injective diagonal *)
         Program Elim (!JM elim!) q;
           Program Elim (!Nat cases!) x;
             Program Refine [Phi:Type][phi:Phi]phi;
             Program Refine [Phi:Type][phi:(n == n)->Phi]phi (JMr n);
       Program Save;  
     
       Label (!Nat noConf!) NatNoConf;   (* tell KJunify *)

     Er, also, the effect of

       Label (!nat zero!) zero;
       Label (!nat suc!) suc;

     is to allow (!3!) to abbreviate suc (suc (suc zero)) and so on. Sadly
     only on the input side.


(7)  ELIMINATION

       Elim rule target ... target;

     eliminates with the given rule, after unifying the provided targets
     with the expressions marked as {tg:Target exp} in the rule's type;
     if the rule is not marked up in that way, Elim kind of guesses what
     to do with the targets you provide (in such a way that regular _elim
     rules are properly handled). Subgoal simplification by unification is
     automatic.


(8)  UNIFICATION

       KJunify;

     should actually be called JMunify

     relies on you providing (!Blah noConf!) for each family Blah you need
     to work with; see above recipe


(7)  NAMING HYPOTHESES

       Names x1 x2 x3 ...;

     (re)names the hyps in the goal without intros-ing them; long overdue


(8)  ABSTRACTION

       Abst x exp;

     abstracts every occurrence of exp from the goal as a new hyp called x;
     can cope with exp living under a prefix of hyps---x goes as far left as
     possible

       AbstEq x q exp;

     similar, but also keeps {q:x == exp} as a hyp; wot a larf!

     Examples can be found in Exception.l and Unify.l


(9)  REWRITING

       Wave > lawsProof;
       Wave < lawsProof;

     Wave is a multiple rewriting tactic. lawsProof is a term of type

       ({x:X}... (Eq l[x...] r[x...])) # ... # ({x:X}... (Eq l[x...] r[x...]))

     ie a tuple of universally quantified equations. Wave tries to
     rewrite like billyo, following these laws, in the direction you
     indicate. It's stupid, unsubtle (and potentially unsafe if you
     choose dangerous laws). But it doesn't lie to the typechecker.
     More safety is achievable via the gasoline-controlled version

       Wave n > lawsProof;
       Wave n < lawsProof;

     which limits the number of iterations allowed.

     Favourite applications include

       Wave > (plusAbsorbsZero,plusAssociative);

     Note the use of M-L Eq rather than JM ==. Also, Wave is not smart
     enough to rewrite under hypotheses.

     Examples in Unify.l


(10) PROGRAMMING

     Thrilling new programming tools!

     If your goal is

       ?0 : {x1:S1}...{xn:Sn}T

     and you say

       Program f x1 ... xn;

     you turn your goal into a programming problem! The new Program Blah
     tactics help you solve it! Read on...


(11) PROGRAMMING INFORMATION

     After the execution of each Program Blah tactic, you get not only the
     proof state, but the program state comprising

       (*) the type signatures of the programs currently under development
       (*) their code so far
       (*) information local to the bit of code you're supposed to write next

     All of this information is actually represented in the proof state,
     which comprises goals of form

       (*) {...}T_myFun p1 ... pn
             the unsolved programming problems
       (*) <myFun:{...}T>(myFun == [...]vomit[T_myFun goals])
             the ghastly proof term, so far
       (*) {...}U_myFun p1 ... pn
             one for each lhs, solved or not

     The program signatures are computed from the <myFun> goals; the
     program code is computed by running the ghastly term so far for each
     lhs given by the U_myFun goals.

     By the way, T_myFun is just a frozen function which computes the
     return type of your program. call_myFun and ret_myFun map between
     the two in the obvious (but frozen way). U_myFun is just a frozen
     function which computes a trivial Prop. Don't worry, they'll thaw
     out later.

       Program; (* with no args, note *)

     attempts to generate and print the program state, if you've
     lost it for some reason, eg hand-cranking a bit of the construction.


(12) PROGRAMMING TACTICS

       Program Elim rule target;

     splits a programming problem by rule on target;
     ie does elimination on the given target with the given rule to both the
     T_ goal and the U_ goal

       Program Refine blah;

     fills in blah as the right-hand side of the current goal;
     ie solves the relevant T_ goal (having first tried to extract recursive
     calls from T_ hypotheses); warning---sometimes the latter mechanism
     commits to a T_ hyp too early, leaving unsolvable equations as subgoals
     (hence the hand-cranking in gcd in TYPES03.l)

       Program Names x1 ... xn;

     renames pattern variables (often needed in induction-then-cases progs);
     warning---sometimes muddles the goals up, leaving no programming problem
     topmost, but nothing that Next can't cure.

       Program Abst myFriend arg ... arg;

     generates a programming problem for a helper function taking the given
     args, which are usually existing pattern vars or some (var as exp),
     where exp is an intermediate value you'd like abstracted, and var is
     what it gets called; by a miracle of modern technology, the helper
     function can still remember how to do recursive calls to the master
     function.


(13) KEEPING A PROGRAM

       Program Save;

     should be called when you've filled in all the bits of program and
     killed off any proof obligations apart from the <myFun> and U_ goals.
     It unfreezes what it needs to solve these goals, then after QED, it
     saves the big nasty term as the defined value of the function, freezes
     it, and gives it (iota) reduction rules instead. Freeze/Unfreeze toggles
     whether it's iota/delta reduction for that symbol.


(14) MYSTERIOUS Forget/KillRef PROBLEM

     I've got some sort of bureaucratic cockup in the lego-state/proof-state/
     twilight-zone, which means that retrograde steps sometimes throw away
     too much (e.g. KillRef discarding the reduction rules you just saved,
     or some such). I recommend ripping it all up and starting again.
     Computers are fast. OK, it's still a pain. Undo in proof state is still
     ok. Phew.


(15) SUPPORT

     Choke. Cough. Splutter.


(16) HAVE FUN

     No really, this is possible.