A Logiweb base page

Klaus Grue

GRD-2006-06-06.UTC:07:18:19.012409

Contents

1 Introduction 7 1.1 The attributes of a Logiweb page . . . . . . . . . . . . . . . . . . 7 1.2 Base pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2 Elementary definitions 8

2.1 Proclamations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.1.1 Loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.1.2 Revelations . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.3 Logiweb symbols . . . . . . . . . . . . . . . . . . . . . . . 10 2.1.4 Preconceived opinions . . . . . . . . . . . . . . . . . . . . 10 2.1.5 Bootstrapping and proclamation constructs . . . . . . . . 11 2.1.6 Self-proclamation . . . . . . . . . . . . . . . . . . . . . . . 11

2.2 Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.2.1 Aspects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.2.2 The pyk aspect . . . . . . . . . . . . . . . . . . . . . . . . 12 2.2.3 The tex aspect . . . . . . . . . . . . . . . . . . . . . . . . 12

2.3 Associativity and priority . . . . . . . . . . . . . . . . . . . . . . 13 2.3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.3.2 Open and closed constructs . . . . . . . . . . . . . . . . . 13 2.3.3 Priority interference . . . . . . . . . . . . . . . . . . . . . 14 2.3.4 Openness coherence . . . . . . . . . . . . . . . . . . . . . 14 2.3.5 Priority tables . . . . . . . . . . . . . . . . . . . . . . . . 14 2.3.6 The page symbol . . . . . . . . . . . . . . . . . . . . . . . 15 2.3.7 The priority aspect . . . . . . . . . . . . . . . . . . . . . . 15 2.3.8 Flush left environment . . . . . . . . . . . . . . . . . . . . 16 2.3.9 The priority table . . . . . . . . . . . . . . . . . . . . . . 16 2.3.10 Priority table constructors . . . . . . . . . . . . . . . . . . 16 2.3.11 Tex aspects . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.4 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.4.2 Construction of strings . . . . . . . . . . . . . . . . . . . . 18 2.4.3 Pyk strings . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.4.4 Rendering of strings . . . . . . . . . . . . . . . . . . . . . 19 2.4.5 Rendering of special characters . . . . . . . . . . . . . . . 19 2.4.6 Talking about strings . . . . . . . . . . . . . . . . . . . . 20 2.4.7 Breaking strings . . . . . . . . . . . . . . . . . . . . . . . 20 2.4.8 Formulas in text . . . . . . . . . . . . . . . . . . . . . . . 21 2.4.9 Juxtaposition . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.4.10 Purism versus pragmatism . . . . . . . . . . . . . . . . . . 22

3 The Engine 22

3.1 Elementary concepts . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.1.1 Fundamental, computable constructs . . . . . . . . . . . . 23 3.1.2 Reduction system . . . . . . . . . . . . . . . . . . . . . . . 24 3.1.3 Root equivalence . . . . . . . . . . . . . . . . . . . . . . . 24 3.1.4 Mathematical equality . . . . . . . . . . . . . . . . . . . . 25

3.2 Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3.2.1 The value aspect . . . . . . . . . . . . . . . . . . . . . . . 25 3.2.2 Parentheses . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.2.3 Bottom . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3.3 Peano trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.3.1 Raw pairs . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.3.2 Peano trees . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.3.3 Canonical and liberal representations . . . . . . . . . . . . 27 3.3.4 Eager pairs . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3.4 Cardinals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 3.4.1 Untagged cardinals . . . . . . . . . . . . . . . . . . . . . . 29 3.4.2 Operations on untagged cardinals . . . . . . . . . . . . . . 29 3.4.3 Retracts and representations . . . . . . . . . . . . . . . . 30 3.4.4 The untagged cardinals from zero to nine . . . . . . . . . 30 3.4.5 Tagged cardinals . . . . . . . . . . . . . . . . . . . . . . . 30 3.4.6 Operations on tagged cardinals . . . . . . . . . . . . . . . 30 3.4.7 The tagged cardinals from one to nine . . . . . . . . . . . 31

3.5 Tagged trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.5.1 Tagged pairs . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.5.2 Cardinal trees . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.5.3 Tagged maps . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.5.4 The retract for tagged trees . . . . . . . . . . . . . . . . . 32 3.5.5 Predicates on tagged trees . . . . . . . . . . . . . . . . . . 32 3.5.6 Operations on tagged trees . . . . . . . . . . . . . . . . . 32 3.5.7 Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.5.8 Semitagged maps . . . . . . . . . . . . . . . . . . . . . . . 33

3.6 Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.6.1 On-stage and off-stage semantics . . . . . . . . . . . . . . 34 3.6.2 Optimized bottom . . . . . . . . . . . . . . . . . . . . . . 35 3.6.3 Strictness . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.6.4 Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.6.5 User defined strict operations . . . . . . . . . . . . . . . . 36 3.6.6 Fitness analysis . . . . . . . . . . . . . . . . . . . . . . . . 36 3.6.7 Strict variables . . . . . . . . . . . . . . . . . . . . . . . . 37 3.6.8 Fitness of conjunction . . . . . . . . . . . . . . . . . . . . 37 3.6.9 Logical connectives . . . . . . . . . . . . . . . . . . . . . . 38 3.6.10 Auxiliary operations . . . . . . . . . . . . . . . . . . . . . 38 3.6.11 Equality . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

3.7 Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.7.1 Addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.7.2 Comparison . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.7.3 Subtraction . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.7.4 Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.7.5 Bit access . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

3.8 Quoting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.8.1 Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.8.2 Gödel trees . . . . . . . . . . . . . . . . . . . . . . . . . . 41

4 The macro expansion facility 42

4.1 Logiweb identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . 43 4.1.1 Representation scheme . . . . . . . . . . . . . . . . . . . . 43 4.1.2 Representation of ASCII strings . . . . . . . . . . . . . . 44 4.1.3 Constructors for binary numbers . . . . . . . . . . . . . . 44 4.1.4 Representation of Logiweb identifiers . . . . . . . . . . . . 44

4.2 Associative structures . . . . . . . . . . . . . . . . . . . . . . . . 45 4.2.1 Associations trees . . . . . . . . . . . . . . . . . . . . . . 45 4.2.2 Finite functions . . . . . . . . . . . . . . . . . . . . . . . . 45 4.2.3 Addresses . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 4.2.4 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 4.2.5 Array access . . . . . . . . . . . . . . . . . . . . . . . . . 46 4.2.6 Racks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 4.2.7 Multidimensional arrays . . . . . . . . . . . . . . . . . . . 47 4.2.8 Array assignment . . . . . . . . . . . . . . . . . . . . . . . 47 4.2.9 Multidimensional assignment . . . . . . . . . . . . . . . . 48 4.2.10 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4.2.11 Stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

4.3 Static semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 4.3.1 The structure of Logiweb pages . . . . . . . . . . . . . . . 49 4.3.2 Transitive bibliographies . . . . . . . . . . . . . . . . . . . 50 4.3.3 Loading, referencing, and verbatim copying . . . . . . . . 50 4.3.4 The cache of a page . . . . . . . . . . . . . . . . . . . . . 50 4.3.5 The value of the page construct . . . . . . . . . . . . . . . 51 4.3.6 The rack of a page . . . . . . . . . . . . . . . . . . . . . . 51 4.3.7 The codex of a page . . . . . . . . . . . . . . . . . . . . . 53 4.3.8 Aspects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.3.9 Domestic and foreign definitions . . . . . . . . . . . . . . 54 4.3.10 A codex accessor . . . . . . . . . . . . . . . . . . . . . . . 55 4.3.11 Value proclamations . . . . . . . . . . . . . . . . . . . . . 55 4.3.12 Codification of revelations . . . . . . . . . . . . . . . . . . 56 4.3.13 Message proclamations . . . . . . . . . . . . . . . . . . . . 56 4.3.14 Definition proclamation . . . . . . . . . . . . . . . . . . . 57 4.3.15 Priority proclamations . . . . . . . . . . . . . . . . . . . . 57 4.3.16 The code of a page . . . . . . . . . . . . . . . . . . . . . . 57

4.4 Macro expansion . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.4.1 A self interpreter . . . . . . . . . . . . . . . . . . . . . . . 58 4.4.2 A macro expander . . . . . . . . . . . . . . . . . . . . . . 59 4.4.3 The initial macro state . . . . . . . . . . . . . . . . . . . . 60 4.4.4 Pruning . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 4.4.5 Potentially inherited page aspects . . . . . . . . . . . . . 61 4.4.6 Installing the macro expander . . . . . . . . . . . . . . . . 61 4.4.7 Iterated macro expansion . . . . . . . . . . . . . . . . . . 62

4.5 Macro definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 4.5.1 Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 4.5.2 Self references . . . . . . . . . . . . . . . . . . . . . . . . . 63 4.5.3 Avoid macro expansion and harvesting of strings . . . . . 63 4.5.4 Macro definitions . . . . . . . . . . . . . . . . . . . . . . . 63 4.5.5 Parentheses . . . . . . . . . . . . . . . . . . . . . . . . . . 65

4.6 Tagged lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.6.1 Local abbreviations . . . . . . . . . . . . . . . . . . . . . 65 4.6.2 Other kinds of definitions . . . . . . . . . . . . . . . . . . 65 4.6.3 Tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 4.6.4 Typography of the expansion . . . . . . . . . . . . . . . . 67

4.7 Programming aids . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4.7.1 Newlines in definitions . . . . . . . . . . . . . . . . . . . . 67 4.7.2 The visibility operator . . . . . . . . . . . . . . . . . . . . 68 4.7.3 Self-evaluation . . . . . . . . . . . . . . . . . . . . . . . . 68 4.7.4 Open if . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 4.7.5 The “let” construct . . . . . . . . . . . . . . . . . . . . . 69 4.7.6 Macro defined connectives . . . . . . . . . . . . . . . . . . 69 4.7.7 Display construct . . . . . . . . . . . . . . . . . . . . . . . 69 4.7.8 Introduction of new constructs . . . . . . . . . . . . . . . 70 4.7.9 Further intro constructs . . . . . . . . . . . . . . . . . . . 70

5 Claims 72 5.1 The claim aspect . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 5.2 Conjunction of claims . . . . . . . . . . . . . . . . . . . . . . . . 73 5.3 The checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 5.4 Installing the checker . . . . . . . . . . . . . . . . . . . . . . . . . 74 5.5 Test for truth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 5.6 Test for falsehood . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 5.7 Raw test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 5.8 Spy construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 6 Logiweb sequent calculus 75

6.1 Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 6.1.1 Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 6.1.2 The statement aspect . . . . . . . . . . . . . . . . . . . . 77 6.1.3 Axioms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 6.1.4 Axiom schemes . . . . . . . . . . . . . . . . . . . . . . . . 78 6.1.5 Inference rules . . . . . . . . . . . . . . . . . . . . . . . . 78 6.1.6 Contradictions . . . . . . . . . . . . . . . . . . . . . . . . 78 6.1.7 Theories . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 6.1.8 Conjectures, lemmas, and antilemmas . . . . . . . . . . . 79 6.1.9 Statement constructors . . . . . . . . . . . . . . . . . . . 79 6.1.10 Self-evaluation . . . . . . . . . . . . . . . . . . . . . . . . 80

6.2 Metavariables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.2.1 Definition of metavariables . . . . . . . . . . . . . . . . . 81 6.2.2 Recognition of metavariables . . . . . . . . . . . . . . . . 81 6.2.3 Closedness . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.2.4 The “free in” predicate . . . . . . . . . . . . . . . . . . . 82 6.2.5 The “free for” predicate . . . . . . . . . . . . . . . . . . . 82 6.2.6 Metavariable substitution . . . . . . . . . . . . . . . . . . 82

6.3 Sequent calculus . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 6.3.1 Term sets . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 6.3.2 Sequents . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 6.3.3 Sequent equality . . . . . . . . . . . . . . . . . . . . . . . 84 6.3.4 Sequent operations . . . . . . . . . . . . . . . . . . . . . . 84 6.3.5 Proof initiation . . . . . . . . . . . . . . . . . . . . . . . . 85 6.3.6 Inference introduction . . . . . . . . . . . . . . . . . . . . 85 6.3.7 Endorsement and quantifier introduction . . . . . . . . . 86 6.3.8 Inference and endorsement elimination . . . . . . . . . . . 86 6.3.9 Quantifier elimination . . . . . . . . . . . . . . . . . . . . 86 6.3.10 Verification . . . . . . . . . . . . . . . . . . . . . . . . . . 86 6.3.11 Currying . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 6.3.12 Referencing and dereferencing . . . . . . . . . . . . . . . . 87 6.3.13 The cut operation . . . . . . . . . . . . . . . . . . . . . . 87 6.3.14 Rule lemmas . . . . . . . . . . . . . . . . . . . . . . . . . 88

6.4 Implementation of the twelve sequent operations . . . . . . . . . 88 6.4.1 Evaluation of the init operation . . . . . . . . . . . . . . . 89 6.4.2 Evaluation of the modus operation . . . . . . . . . . . . . 89 6.4.3 Evaluation of the verify operation . . . . . . . . . . . . . 89 6.4.4 Evaluation of the decurrying operation . . . . . . . . . . . 89 6.4.5 Evaluation of the currying operation . . . . . . . . . . . . 89 6.4.6 Evaluation of the dereferencing operation . . . . . . . . . 89 6.4.7 Evaluation of quantifier elimination . . . . . . . . . . . . 90 6.4.8 Evaluation of inference introduction . . . . . . . . . . . . 90 6.4.9 Evaluation of endorsement introduction . . . . . . . . . . 90 6.4.10 Evaluation of the referencing operation . . . . . . . . . . 90 6.4.11 Evaluation of quantifier introduction . . . . . . . . . . . . 91

6.4.12 Evaluation of the cut operation . . . . . . . . . . . . . . . 91 6.5 The proof evaluator . . . . . . . . . . . . . . . . . . . . . . . . . 91

6.5.1 Coloring . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 6.5.2 Error message generation . . . . . . . . . . . . . . . . . . 92 6.5.3 Error recognition . . . . . . . . . . . . . . . . . . . . . . . 92 6.5.4 Sequent evaluation . . . . . . . . . . . . . . . . . . . . . . 93 6.5.5 Lemma verification . . . . . . . . . . . . . . . . . . . . . . 93

6.6 The verifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 6.6.1 Conjunction membership . . . . . . . . . . . . . . . . . . 94 6.6.2 The proof aspect . . . . . . . . . . . . . . . . . . . . . . . 95 6.6.3 Verifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 6.6.4 The rule lemma tactic . . . . . . . . . . . . . . . . . . . . 99 6.6.5 Stating rules . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.6.6 Stating theories . . . . . . . . . . . . . . . . . . . . . . . . 100 6.6.7 Rule collection . . . . . . . . . . . . . . . . . . . . . . . . 101 6.6.8 Example lemmas . . . . . . . . . . . . . . . . . . . . . . . 102

6.7 Unification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 6.7.1 Parameter terms . . . . . . . . . . . . . . . . . . . . . . . 102 6.7.2 Substitutions . . . . . . . . . . . . . . . . . . . . . . . . . 102 6.7.3 Occurrence . . . . . . . . . . . . . . . . . . . . . . . . . . 103 6.7.4 Unifications . . . . . . . . . . . . . . . . . . . . . . . . . . 103 6.7.5 Unification algorithm . . . . . . . . . . . . . . . . . . . . 103

6.8 Proof generation . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 6.8.1 Proof tactics . . . . . . . . . . . . . . . . . . . . . . . . . 104 6.8.2 Medium level proofs . . . . . . . . . . . . . . . . . . . . . 105 6.8.3 The “tactic” aspect . . . . . . . . . . . . . . . . . . . . . 106 6.8.4 The proof expander . . . . . . . . . . . . . . . . . . . . . 106 6.8.5 The initial proof state . . . . . . . . . . . . . . . . . . . . 106 6.8.6 The conclusion tactic . . . . . . . . . . . . . . . . . . . . 107 6.8.7 Proof constructors . . . . . . . . . . . . . . . . . . . . . . 108

A TEX definitions 108

A.1 The TEX language . . . . . . . . . . . . . . . . . . . . . . . . . . 108 A.1.1 Use of newline characters . . . . . . . . . . . . . . . . . . 109 A.1.2 Interpretation of the tex aspect . . . . . . . . . . . . . . . 110 A.1.3 The tex name aspect . . . . . . . . . . . . . . . . . . . . . 110 A.1.4 Uses of the tex name aspect . . . . . . . . . . . . . . . . . 111 A.1.5 Brackets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 A.1.6 The tex aspect of definitions . . . . . . . . . . . . . . . . 112

A.2 TEX definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 A.3 Further TEX definitions . . . . . . . . . . . . . . . . . . . . . . . 141 A.4 Line numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 A.5 Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

A.5.1 Tex aspects of characters . . . . . . . . . . . . . . . . . . 158 A.5.2 Tex name aspects of characters . . . . . . . . . . . . . . . 161 B Pyk definitions 162

B.1 The pyk language . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 B.2 Uses of pyk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 B.3 Autogeneration of pyk definitions . . . . . . . . . . . . . . . . . . 164 B.4 Autogenerated pyk definitions . . . . . . . . . . . . . . . . . . . . 164

C Test 182

D Priority table 189

E Index 191

1 Introduction

This is a Logiweb base page^{1}. The Logiweb system [6] is able to bootstrap using a page like the present one. Logiweb itself is a system for machine verification and distribution of formal mathematics.

The base page contains quite a number of elementary definitions:

• On top of the Logiweb computing engine, the base page defines elementary operations on lists and cardinals (where cardinal means natural number).

• On top of the operations on lists and cardinals, the base page defines a macro expansion facility and a number of useful macros.

• On top of the operations on lists and cardinals, the base page defines a proof checker and a number of useful mathematical theories.

• Finally, the base page defines how to render the syntactic constructs defined on the page in the pyk and TEX languages.

1.1 The attributes of a Logiweb page

In general, a page has several attributes:

The reference of a page is a cardinal that identifies the page. The reference of a page is world-wide unique. The Logiweb system includes Logiweb servers that can translate Logiweb references to Uniform Resource Locators (URLs) so that, having the reference of a page, one can locate the page without knowing which physical mirrors hold a copy of the page.

The vector of a page is the sequence of bytes that encode the page when it is stored on disk or transmitted over a network. All attributes of a page, including the reference, can be computed from the vector.

1For the convenience of the reader, things that enter the index are in italics

The bibliography of a page is a list of references to Logiweb pages. Entry number zero of the bibliography (i.e. the first element of the list of references) is the reference of the page itself. Appart from this self-reference, Logiweb pages and bibliographic references form a directed, acyclic graph.

The dictionary of a page is a list of all concepts defined on the page.

The body of a page comprises all the text and definitions of the page. When a user wants to read a Logiweb page, the system renders the body of the page using the TEX system and shows that to the user. What you read right now is such a rendering.

The expansion of a page is the macro expanded version of the body. Proof checking is done after macro expansion.

The codex of a page is an associative structure for fast lookup of all definitions made on a page.

The cache of a page is an associative structure for fast lookup of any attribute of any referenced page.

The diagnose (if any) of a page indicates what is wrong with the page (if anything).

1.2 Base pages

A Logiweb base page is a page whose Logiweb bibliography references no other pages.

As mentioned, Logiweb bibliographies form directed, acyclic graphs, so if one follows bibliographic references one can be sure to end up in a base page eventually.

What you read right now is the body of a base page. The body does not include the Logiweb bibliography, so you cannot verify that the present page is a base page by reading the present text. The bibliography at the end of the present body is an ordinary BibTEX bibliography which is unrelated to the Logiweb bibliography.

To see the Logiweb bibliography of a page, you must view the page in a Logiweb browser and open the bibliography. If the page is generated from a pyk source, you may also see the Logiweb bibliography in that source.

2 Elementary definitions

2.1 Proclamations

2.1.1 Loading

When Logiweb reads a Logiweb page in order to “understand” it, we shall say that Logiweb loads the page. Logiweb loads a page as follows:

Resolving Given the reference of the page, Logiweb uses the mesh of Logiweb servers to resolve the reference, i.e. to locate a mirror that holds a copy of the page. That mirror typically is the server of the author of the page, but important pages may exist many places.

Retrieving Once the reference is resolved into a Uniform Resource Locator (URL), Logiweb retrieves the vector of the page, i.e. the sequence of bytes that encode the page when it is stored on disk or transmitted over a network.

Unpacking Once the vector is retrieved, Logiweb unpacks it into a bibliography, a dictionary, and a body. During this process, Logiweb recursively loads all pages referenced in the bibliography of the page.

Codifying Once the bibliography, dictionary, and body are available, Logiweb codifies the body. Logiweb does so by reading the body over and over again (c.f. Section 4.4.7). During these iterations, Logiweb is supposed to obtain a deeper and deeper “understanding” of the page. The iterations end when the understanding reaches a fixed point. This is similar to TEX that has to read a TEX source over and over again to get the references right. The outcome of the codification is a codex and an expansion. The expansion is a macro expanded version of the body. The codex is an associative structure for fast lookup of all definitions made on a page.

Verifying Once the page is codified, Logiweb verifies the page. Verification involves execution of the claim of the page as described later. The claim of a page typically runs a proof verifyer on all proofs on the page and typically also does several other chores to ensure that the formal mathematics presented on the page is correct.

Once a page is loaded, Logiweb can render it using TEX to produce a human readable version of it.

As a more exotic facility, Logiweb can also render a page in pyk to produce a pyk source file from which the page can be recompiled. This corresponds to “view source” when viewing html-pages but is more complex since Logiweb uses a compact, binary format from which the source has to be reverse engineered.

Finally, Logiweb is supposed to be able to execute the page, but that is not implemented at the time of writing. The execution facility will be a general programming facility including general I/O facilities. Logiweb itself is ultimately intended to be implemented using this facility. At the time of writing, Logiweb is implemented in Lisp.

2.1.2 Revelations

Logiweb has three kinds of revelation constructs that connect syntactic constructs with semantic concepts. The three kinds of revelations are called proclamations, definititions, and introductions.

Logiweb has a small number of predefined concepts; a proclamation connects a syntactic construct with one of these predefined concepts. Definitions and introductions allow to connect syntactic constructs with user defined concepts.

On the present page, proclamations are made using the proclamation construct [x ▷◁ y]^{2}. As we shall see in Section 2.1.6, [x ▷◁ y] proclaims [x] to denote the concept identified by [y].

2.1.3 Logiweb symbols

Every Logiweb construct is identified by a reference and an identifier, both of which are cardinals (i.e. natural numbers). The reference of a construct equals the reference of the page that introduces the construct. The identifier identifies the operation among all operations introduced by that page.

The reference of the [x ▷◁ y] construct equals the reference of the present page (which is a big number) and the identifier equals one. As we shall see, it is important to Logiweb that the identifier equals one.

We shall refer to a pair consisting of the reference and identifier of a Logiweb construct as a Logiweb symbol. Logiweb symbols resemble Common Lisp symbols [11] which is the same as Lisp atoms in the original sense of the word [9].

There is a one-to-one correpondence between Logiweb symbols and Logiweb constructs. But the concepts are not identical; Logiweb constructs are things one may encounter on Logiweb pages, Logiweb symbols are pairs of integers that represent the constructs.

2.1.4 Preconceived opinions

To begin with, and with two exceptions, Logiweb does not assign any particular meaning to any particular construct. The general rule that Logiweb has no preconceived opinion about the meaning of constructs makes Logiweb flexible and ensures the notational freedom of each, individual author. The exceptions allow Logiweb to bootstrap.

The two exceptions relate to page constructs and proclamation constructs. A page construct is a Logiweb construct whose identifier equals zero. There

is a one-to-one correspondence between Logiweb pages and Logiweb page constructs: Given the reference of a page, one just adds a zero to get its page construct, and given a page construct one just removes the zero to get the reference of the page.

Page constructs are used whenever there is a need to reference a page in a context that requires a symbol. As an example, Logiweb allows to assign names (i.e. pyk names) to symbols. Logiweb does not allow to assign names to pages. But every page has a page symbol, and the name of the page symbol effectively becomes the name of the page.

2For the convenience of the reader, mathematics is enclosed in brackets to distinguish it clearly from other text. Such use of brackets is a stylistic choice which is independent of Logiweb.

Page constructs are unrelated to the bootstrapping of Logiweb. Rather, bootstrapping depends on proclamation constructs.

2.1.5 Bootstrapping and proclamation constructs

As mentioned in Section 2.1.1, Logiweb codifies a page by reading its body over and over again. At each reading, Logiweb “understands” the page in the light of what Logiweb already knows. This knowledge includes anything Logiweb managed to extract from pages referenced in the bibliography and anything Logiweb managed to extract from the present page at the previous reading.

In one situation, Logiweb has no prior knowledge when reading a page. That happens when Logiweb reads a base page first time (recall that a base page is a Logiweb page that references no other pages).

To get started, Logiweb has the preconceived opinion that, on first reading of a base page, the symbol whose identifier equals one is a proclamation symbol.

The proclamation construct in turn has the preconceived opinion that Logiweb constructs with identifiers from [97] to [122] denote the small letters from a to z and that certain sequences of such letters denote particular concepts. How the constructs with identifiers from [97] to [122] are used to form strings is treated in Section 2.4.

2.1.6 Self-proclamation

The first task of the proclamation symbol is to secure itself. Logiweb only has the preconceived opinion that the symbol whose identifier equals one is a proclamation symbol on first reading of a base page. On the second reading, Logiweb has no such preconceived opinion. For that reason, we make the following proclamation:

[[x ▷◁ y] ▷◁ “proclaim”]

The proclaimation construct happens to have the preconceived opinion that the string “proclaim” denotes the proclamation concept. Hence, during first reading of the present base page, Logiweb sees that [x ▷◁ y] is proclaimed to denote proclamation and, hence, [x ▷◁ y] denotes proclaimation during second reading of the base page. During second reading, [x ▷◁ y] is again proclaimed to denote proclamation and, hence, [x ▷◁ y] denotes proclaimation during third reading and so on.

Readers with plenty of spare time may find fun in constructing a base page for which the constructs whose identifiers equal two and three end up being proclamation constructs whereas the construct whose identifier equals one ends up not being a proclamation construct.

2.2 Definitions

2.2.1 Aspects

As mentioned in Section 2.1.2, Logiweb has three kinds of revelations: proclamations, definititions, and introductions. We now proclaim [y →^{x} z] as a construct for definitions:

[[y →^{x} z] ▷◁ “define”]

The construct [y →^{x} z] states that the [x] aspect of [y] equals [z].

A mathematical definition like [r(x, y) ≐ \sqrt{x^{2} + y^{2}}] corresponds to a Logiweb definition in which the value aspect of [r(x, y)] is defined to be [\sqrt{x^{2} + y^{2}}]. In general, ordinary, mathematical definitions correspond to Logiweb value definitions. Logiweb, however, allows the user to define a variety aspects of each construct.

2.2.2 The pyk aspect

A particular important aspect is the pyk aspect. We use [pyk] to denote the pyk aspect:

[pyk ▷◁ “pyk”]

The pyk aspect of a construct indicates how to render the construct in the pyk language. That rendering allows to read a Logiweb page using an ordinary text editor. See Appendix B for pyk definitions of each and every construct introduced on the present Logiweb page.

One may also use the pyk language for editing Logiweb pages. To construct a Logiweb page, one may prepare a pyk source file using a text editor and run the pyk file through the pyk compiler. At the time of writing, the pyk compiler is the only available tool for producing Logiweb pages. Logiweb, however, is not tied to the pyk compiler and other tools for producing Logiweb pages may emerge.

2.2.3 The tex aspect

The tex aspect is another important aspect. The tex aspect of a construct indicates how to render the construct in the TEX language. We use [tex] to denote the tex aspect:

[tex ▷◁ “tex”]

Tex definitions for the present page are collected in Appendix A. In that Appendix, one may find a definition like

[x →^{tex} x]

which defines how to render that particular variable. For more information, see Appendix A.

Note that the tex aspect of x is defined both above and in Appendix A. Logiweb just uses the definition that is leftmost after macro expansion. The pyk compiler is a little more touchy: it prints a warning if there are definitions that contradict one another. The pyk compiler accepts the two tex definitions of x without notice since all the definitions are identical after macro expansion.

2.3 Associativity and priority

2.3.1 Introduction

A “preassociative” construct is left associative in text that runs left to right, right associative in text that runs right to left, top associative in text that runs from top to bottom, counterclockwise associative in text written in left turning spirals, and so on. Text on Logiweb pages may run in any conceivable direction. Pyk source text runs from left to right.

The pyk compiler uses associativities when parsing pyk source text. As an example, if the construct “* plus *” is preassociative then “var x plus var y plus var z” is interpretted as “(var x plus var y) plus var z. Likewise, if “* pair *” is postassociative then “var x pair var y pair var z” means “var x pair (var y pair var z)”.

The pyk compiler also uses priorities. As an example, it “* plus *” has greater priority than “* pair *” then “var x plus var y pair var z” means “(var x plus var y) pair var z” and “var x pair var y plus var z” means “var x pair (var y plus var z)”.

If two constructs have equal priority, then they are forced to have the same associativity as well. As an example, if “* minus *” has the same priority as “* plus *” then “* minus *” automatically becomes preassociative. Hence, “var x plus var y minus var z” means “(var x plus var y) minus var z” and “var x minus var y plus var z” means “(var x minus var y) plus var z”.

2.3.2 Open and closed constructs

A construct is said to be “preopen” if it starts with an asterisk and to be “preclosed” otherwise. Likewise, a construct is “postopen” and “postclosed” if it does and doesn’t end with an asterisk, respectively.

A construct is said to be “open” if it is pre- and postopen and “closed” if it is pre- and postclosed. A construct is said to be “prefix” if it is preclosed and post open and “suffix” if it is preopen and post closed. Here are some examples:

parenthesis * end preclosed postclosed closed
* apply *  preopen postopen open
lambda * dot *  preclosed postopen prefix
factorial  preopen postclosed suffix

None of the four constructs above are declared on this page; they are just included for the example.

Associativity and priority is irrelevant for closed constructs.

Associativity does affect prefix and suffix constructs. As an example, if “* apply *”, “lambda * dot *” and “* factorial” have the same priority, then “lambda var x dot var y apply var z factorial” means “((lambda var x dot var y) apply var z) factorial” if the constructs are preassociative and “lambda var x dot (var y apply (var z factorial))” if they are postassociative.

2.3.3 Priority interference

Prefixness and suffixness occasionally interfere with priorities. As an example, suppose “* apply *” has greater priority than “lambda * dot *” and consider the following pyk source:

var x apply lambda var y dot var y apply var y

First step in disambiguating the text above is to put parentheses around the operator that has the lowest priority and to put parentheses around its parameters:

var x apply (lambda (var y) dot (var y apply var y))

This divides the problem into two smaller problems: disambiguating “var x apply ⋯” and disambiguating “var y apply var y” both of which are trivial:

((var x) apply (lambda (var y) dot ((var y) apply (var y))))

Hence, the principal operator of “var x apply lambda var y dot var y apply var y” is the leftmost “apply” which may be surprising since the lambda is the operator with the lowest priority.

2.3.4 Openness coherence

When defining the pyk and tex aspects of a construct it is important to let them have the same “openness”, i.e. to make them both open, both closed, both prefix, or both suffix. As an example, if one renders a pair as e.g. x : : y which is open then one should ensure that the pyk aspect is also open as in “* plus *”. If one renders the pair as e.g. (x, y) which is closed then one should ensure that the pyk aspect is closed as in “pair * comma * end pair”.

Failure to make openness coherent may seriously baffle the reader since it may make the pyk compiler and a human reader interpret terms differently.

Some constructs are non-trivial to classify. As an example, exponentiation x^{y} is best classified as a suffix construct because a + x^{y} could mean (a + x)^{y} or a + (x^{y}) whereas x^{y} + a can only mean (x^{y}) + a and, thus, x^{y} is ambiguous the way suffix constructs are. Hence, the pyk name of exponentiation should be something like “* power * end power”.

2.3.5 Priority tables

A Logiweb page may contain constructs from the page itself as well as constructs from all pages it references in its Logiweb bibliography.

The pyk compiler insists on knowing the associativity and priority af each non-closed construct that might possibly appear on a page. The pyk compiler is somewhat relaxed about whether or not priorities and associativities are specified for closed constructs because the associativities and priorities of such constructs have no effect.

To avoid double work, a Logiweb page should contain a priority table which the pyk compiler can import when the page is included in the Logiweb bibliography of another Logiweb page.

A page should contain one priority table, not one for each construct. Hence, the priority table is an aspect of the page rather than an aspect of each, individual construct. This is a problem because Logiweb allows to define aspects of constructs but does not allow to define aspects of pages. So what do we do?

2.3.6 The page symbol

As mentioned, every construct in Logiweb is identified by a reference [r] and an id [i], both of which are cardinals. The reference uniquely identifies the Logiweb page that introduces the construct and the id identifies the construct within the page. We shall refer to a construct with reference [r] and id [i] as the [i]’th construct of page [r].

The zero’th construct of a Logiweb page will be referred to as the “page construct” of the page. Aspects of the page construct should be thought of as aspects that concern the entire page.

As an example, consider the following pyk definition of the page construct of the present page:

[base →^{pyk} “base”]

Because of the definition above we shall say that the present page is named “base”.

To see that [base] is the page construct of the present page one has to open the present page in a Logiweb browser, find the id of the construct, and see that the id is zero. In the Logiweb crossbrowser, one may do that by opening the “dictionary” window. More advanced browsers would probably allow the user to click on [base] and view its properties somehow.

We do not define a tex aspect of the page construct, and for that reason the tex aspect defaults to \mathrm{base}. We do not define a tex name aspect either, and for that reason the tex name aspect defaults to be identical to the tex aspect.

The page construct is forced to have arity zero, i.e. it has no parameters.

2.3.7 The priority aspect

The priority table is defined as a “priority aspect” of the page construct. We introduce the priority aspect thus:

[prio ▷◁ “priority”]

[prio →^{tex} “

\mathrm{prio}”] 2.3.8 Flush left environment

The priority table is a long, heterogeneous formula which is difficult to linebreak. For that reason we shall typeset it ragged right or flush left. To do so, we introduce a [flush left [x]]construct which typesets its argument with a ragged right margin.

2.3.9 The priority table

For convenience, we introduce a variable named [∗] which we use in pyk, TEX, and priority definitions where parameter names are ignored.

The priority table itself is given in Appendix D. The number of constructs in it is colossal, but that is normal for large base pages since the table contains lots of trivia like characters and variable names.

2.3.10 Priority table constructors

The priority table in Appendix D is constructed from the following four constructs:

[Preassociative x; y →^{pyk} “preassociative " greater than "”]

[Postassociative x; y →^{pyk} “postassociative " greater than "”]

[[x], y →^{pyk} “priority " equal "”]

[priority x end →^{pyk} “priority " end priority”]

The pyk source of the table looks something like

math define priority of base as
preassociative
priority bracket var x end bracket equal
priority math var x end math equal
...
priority priority end priority
greater than preassociative
priority unicode start of text var x end unicode text equal
...
priority priority var x end priority end priority
greater than postassociative
priority var x , var y equal
priority var x [ var y ] var z end priority
greater than base end define end math

From the structure of the table, the pyk compiler can guess that “priority * equal *” denotes “equal priority” and that “priority * end priority” marks the end of a list of equal priorities.

The pyk compiler can also guess that “preassociative * greater than *” and “postassociative * greater than *” denote pre- and postassociativity but cannot guess which is which. For that reason, we have to reveal that to Logiweb explicitly using proclamations:

[Preassociative x; y ▷◁ “pre”]

[Postassociative x; y ▷◁ “post”]

2.3.11 Tex aspects

Tex aspects of priority table constructors read:

[Preassociative x; y →^{tex} “ \newline \mathbf {Preassociative} \newline #1. ; #2.”]

[Preassociative x; y →^{name} “ \mathbf{Preassociative}\, #1. ; #2.”]

[Postassociative x; y →^{tex} “ \newline\mathbf{Postassociative} \newline #1. ; #2.”]

[Postassociative x; y →^{name} “ \mathbf{Postassociative}\, #1. ; #2.”]

[[x], y →^{tex} “

[#1/tex name/tex. ] , \linebreak [0] #2.”]

[[x], y →^{name} “

[#1. ] , \linebreak [0] #2.”]

[priority x end →^{tex} “ [#1/tex name/tex. ]”]

[priority x end →^{name} “ \mathrm{priority} \, #1. \, \mathrm{end}”]

2.4 Strings

2.4.1 Introduction

The pyk language itself is a rather purist language that merely uses the small letters from a to z and space and newline characters for expressing Logiweb pages of arbitrary complexity. Capital letters and punktuation marks have been omitted to prepare the language for input via a microphone (it is easy, though, to adapt pyk to allow letters from other alphabets).

Furthermore, the rather purist Logiweb computing engine described elsewhere has sufficient power to render pages all the way from layout to pixels without resorting to external systems like TEX or BibTEX or whatever. Or, at least, programs like TEX may be translated to the Logiweb language, placed on a Logiweb page, and executed from there by the Logiweb engine.

During the early phases of the development of Logiweb, however, too much purism is unaffordable. TEX is a very mature system that cannot be replaced overnight. To allow Logiweb pages to include TEX source, the pyk language has support for strings.

The treatment of strings in the following should make sense in itself, but the motivation for going through the pain of introducing strings requires quite some overview of how all the parts of Logiweb play together.

2.4.2 Construction of strings

As mentioned earlier, every construct in Logiweb is identified by a reference [r] and an id [i], both of which are cardinals.

We shall say that a construct is “blind” if its id is between zero and nine, inclusive, or between 11 and 31, inclusive. We shall say that constructs whose ids equal 10 or are greater than 31 are non-blind.

When used in strings, non-blind constructs represents the character whose unicode equals the id of the construct. Blind constructs represent no characters.

As an example, The id’s of the pyk construct “unicode small a *”, “unicode small b *”, “unicode small c *”, and “unicode end of text” equal 97, 98, 99, and 3, respectively (to see that one needs access to the pyk source of the present page or needs to view the page in a Logiweb browser). The expression

unicode small a unicode small b unicode small c unicode end of text

is interpretted as

unicode small a ( unicode small b ( unicode small c ( unicode end of text ) ) )

When read from left to right, the id’s of the constructs are 97, 98, 99, and 3. Ignoring 3 which is blind, we are left with 97, 98, and 99 which are the unicodes for “a”, “b”, and “c”, respectively. For that reason,

unicode small a unicode small b unicode small c unicode end of text

represents the string “abc”.

2.4.3 Pyk strings

Continuing the previous example, the id of the pyk construct “unicode start of text * end unicode text” equals two. Whenever the pyk compiler sees a string like "abc" inside a mathematical expression, it translates it to

unicode start of text
  unicode small a
  unicode small b
  unicode small c
  unicode end of text
end unicode text

Ignoring blind constructs, the expression above represents the string “abc”. Logiweb itself assigns no particular semantics to constructs like “unicode

start of text * end unicode text” and “unicode end of text” whose ids equal two or three. But the pyk compiler consistently add constructs with these particular ids whenever it translates a string.

The representation of Logiweb pages is such that characters with codes below 128 take up one byte. A string like “abc” takes up five bytes because the start and end of text characters also take up one byte.

2.4.4 Rendering of strings

Rendering of “a”, “b”, and “c” is completely straighforward:

[ax →^{tex} “a#1.”]

[bx →^{tex} “b#1.”]

[cx →^{tex} “c#1.”]

Pyk and tex definitions for “a”, “b”, “c”, and many other non-blind characters are collected in the appendix.

The tex aspects of the start of text character clearly show that it is blind:

[“x” →^{tex} “#1.”]

However, when talking about the start of text character it is inconvenient if it is blind. Instead, we represent it by double quotes:

[“x” →^{name} “

\mbox{‘‘}#1. \mbox{’’}”]

We shall take the liberty to make the end of text character completely blind:

[→^{tex} “”]

As you can see (or, rather, cannot see), there are no glyphs in the left hand side of the definition above. That indicates that the left hand side comprises a unicode end of text. We shall define no other constructs that are completely blind, i.e. blind when talking about them. Lots of constructs are blind when using them, but the unicode end of text is the only one that is blind when talking about it. The unicode end of text should be used with caution is it may baffle the reader.

2.4.5 Rendering of special characters

The rendering of a backslash reads:

[\x →^{tex} “\#1.”]

[\x →^{name} “

\mbox{$\backslash$}#1.”]

The tex aspect of a backslash generates a backslash character in the input to TEX. In contrast, the tex name aspect generates a backslash in the output from TEX.

2.4.6 Talking about strings

The id of the pyk construct “text * end text” equals six so it is yet another blind construct. The construct is rendered thus:

[(x)^{t} →^{tex} “#1/tex name.”]

[(x)^{t} →^{name} “

(#1. )ˆ {\bf t}”]

The tex aspect of “text * end text” is invisible in itself but has the effect that all of its argument is rendered using the tex name aspect. As an example, the expression

text
  unicode start of text
    unicode backslash
    unicode small b
    unicode small f
    unicode end of text
  end unicode text
end text

generates a start double quote, a backslash, a “b”, an “f”, and an end double quote in the output from TEX. Without the “text * end text”, the expression generates \bf in the input to TEX which makes TEX change to bold face.

2.4.7 Breaking strings

The id of the pyk construct “text * plus *” equals seven and the construct is rendered thus:

[string(x) + y →^{tex} “ \mathrm{#1/tex name. }+\newline#2.”]

[string(x) + y →^{name} “ \mbox{string}(#1. )+#2.”]

A term like

text
  unicode start of text
    unicode small a
    unicode small b

    unicode end of text
  end unicode text
plus
  text
    unicode start of text
      unicode small c
      unicode end of text
    end unicode text
  end text

denotes the string “abc”. This is so because if one scans the text left to right (or scans the associated parse tree root to leaf, left to right) then one encounters the id’s 7, 2, 97, 98, 3, 6, 99, 3 in that order. Ignoring blind codes leaves one with the sequence 97, 98, 99 which represents “abc”.

The rendering of the string consists of “ab” on one line and “c” on the next. The “text * plus *” construct allows the author of a Logiweb page to split a long string over several lines.

The id of the “text * plus indent *” construct equals eight; the construct does the same as “text * plus *” but also indents the second line:

[string(x) ++ y →^{tex} “ \mathrm{#1/tex name. }\; {++}\newline{}\qquad#2.”]

[string(x) ++ y →^{name} “\mbox{string}(#1. )\mathrel{++}#2.”]

2.4.8 Formulas in text

The id of the pyk construct “" [ " ] "” equals five and the construct is rendered thus:

[x[y]z →^{tex} “#1.#2.#3.”]

[x[y]z →^{name} “#1.

{[}#2. {]}#3.”]

As an example of use, the pyk source

"abc"[ math var x end math ]"def"

is equivalent to

  unicode start of text
    unicode small a
    unicode small b
    unicode small c
    unicode end of text
  end unicode text
[
  math var x end math

]
  unicode start of text
    unicode small d
    unicode small e
    unicode small f
    unicode end of text
  end unicode text

The tex face of the expression above reads

abc$\mathsf{x}$def

which, when run through TEX, places the variable “x” in the middle of the string “abcdef”.

In general, the “" [ " ] "” construct allows to place mathematical formulas in text.

The space character between the left bracket and the “m” in “math” above is obligatory.

2.4.9 Juxtaposition

The id of the pyk construct “" , "” equals four and the construct is rendered thus:

[x , y →^{tex} “#1.#2.”]

[x , y →^{name} “#1.

\mathrel{\mathrm{, }}#2.”] For that reason one may write

var x, "\cdots", var y

to obtain [x ⋯ y].

2.4.10 Purism versus pragmatism

Purism is a good thing when defining, designing, implementing, debugging, testing, explaining, teaching, learning, understanding, and using a computational system, and one should only resort to pragmatism when neccessary. The pyk compiler is rather puristic, but resorts to pragmatism in the treatment of strings: Double quotes, brackets, and commas are treated specially and constructs whose id equal two, three, four, and five are used when translating those special characters.

3 The Engine

This section describes the Logiweb computing engine.

The Logiweb engine is the computing machinery that performs proof checking, macro expansion, and general evaluation in the Logiweb system.

At a later stage of the development of Logiweb, the engine is supposed to take over the layout and rendering of Logiweb pages. As mentioned previously, that task is currently done by TEX[7] and related programs.

The engine is just a computing engine; it has no facilities to communicate with the outside world. The Logiweb “machine” described elsewhere contains the Logiweb engine and also contains facilities for input/output.

Apart from introducing the engine, the present page also introduces a number of operations suited for manipulation of “tagged trees”. Tagged trees are to Logiweb what Lisp S-expressions are to Lisp[9].

3.1 Elementary concepts

3.1.1 Fundamental, computable constructs

The Logiweb engine has four fundamental, computable constructs: lambda abstraction [λx.y]^{3}, functional application [x ’ y], truth [T], and conditional [if(x, y, z)].

[λx.y] denotes lambda abstraction[2]. Lambda abstraction is a predefined concept of Logiweb in the sense that knowledge of lambda abstraction is hardwired into Logiweb. Logiweb does not connect lambda abstraction with any, particular syntax, so we must connect the syntactic construct [λx.y] with the concept of lamdba abstraction. We do so using a proclamation: [λx.y ▷◁ “lambda”].

The proclamation [λx.y ▷◁ “lambda”] makes [λx.y] denote lambda abstraction on the present Logiweb page and on all Logiweb pages that include the present page in their Logiweb bibliography. This does not exclude other constructs from denoting lambda abstraction as well. One may proclaim any number of binary constructs to denote lambda abstraction. Neither does this exclude the possibility of using the notation [λx.y] for other concepts than lambda abstraction on other Logiweb pages.

[x ’ y] denotes functional application. As an example, if [x] equals [λz.z + 3] then [x ’ 2] equals [2 + 3] which in turn equals [5]. We connect syntax and semantics of functional application thus: [x ’ y ▷◁ “apply”].

All computable functions can be expressed in pure lambda calculus, i.e. using only [λx.y] and [x ’ y]. Doing so is inconvenient, however. As an example, the range of any function of pure lambda calculus contains one or infinitely many values, and one often wants a computer program to have a finite range of possible responses. Just think of a computer program which is required to loop indefinitely or answer “yes” or “no” for arbitrary input, and which is required to answer “yes” in certain situations and “no” in certain, other, situations. Such a computer program cannot be implemented in pure lambda calculus since its range is finite and contains more than one possible response.

One symptom of the inconvenience of pure lambda calculus is the difficulty of constructing models for it. Another symptom is the inability so far to construct a foundation of mathematics upon pure lambda calculus.

3For the convenience of the reader, mathematics is enclosed in brackets to distinguish it clearly from other text. Such use of brackets is a stylistic choice which is independent of Logiweb.

If one adds two more constructs, truth [T] and conditional [if(x, y, z)], then the problems disappear: One may express functions like [λx.if(x, y, z)] whose range is finite, one may construct rather simple models[1], and one may extend the system into a foundation of mathematics by the drop of a quantifier[4].

[T ▷◁ “true”] denotes truth. The main property of [T] is that it differs from [λx.y] for all variables [x] and all terms [y] (of course, we make the convention that [λx.y] represents falsehood for all variables [x] and all terms [y]).

Since [T] is no function, it does not make sense to apply it to an argument. For completeness, however, we make the convention that [T] applied to anything equals [T] itself: [T ’ x = T].

[if(x, y, z) ▷◁ “if”] is a conditional which allows to test whether [x] equals [T] or is a function:

[ \begin{matrix}if(T, u, v) & = & u \\ if(λx.y, u, v) & = & v \end{matrix} ]

3.1.2 Reduction system

The Logiweb reduction system is thus:

(λx.y)^{I} ’ z  →^{+} ⟨y |x:= z⟩
T ’ z  →^{+} T
if(T, u, v)  →^{+} u
if(λx.y, u, v) →^{+} v

⟨y |x:= z⟩ denotes the result of replacing all free occurrences of the variable [x] in the term [y] by the term [z], possibly renaming bound variables as needed.

We shall say that a term [z] is on truth normal form if the term [z] is identical to [T].

We shall say that a term [z] is on function normal form if the term [z] has form [λx.y] where [x] is a variable and [y] is a term.

We shall say that a term is on root normal form if the term is on truth or function normal form.

When given a term, the Logiweb engine starts reducing the term using leftmost reduction. The Logiweb engine stops again if the term reaches root normal form.

3.1.3 Root equivalence

We shall say that a term is a true term if the engine can reduce it to truth normal form and that it is a function term if it can reduce it to function normal form. We shall say that a term is perpetual if the engine reduces it forever without reaching a root normal form.

We shall say that two terms are root equivalent if they are both true terms, both function terms, or both perpetual. Root equivalence is undecidable in general but is decidable on terms that have a root normal form.

3.1.4 Mathematical equality

The Logiweb computing engine does not support the parallel “or” operation [x ∥ y], but the operation is interesting for theoretical reasons. The parallel “or” operation has the following properties:

T ∥ y  = T
x ∥ T  = T
(λx.y)^{I} ∥ (λu.v)^{I} = λx.T

If the parallel “or” operation were added to the Logiweb computing engine, then the engine would be required to reduce both [x] and [y] in parallel whenever the engine had to reduce [x ∥ y]. If the engine managed to reduce [x] to [T] then it should stop reducing [y] and vice versa.

We shall refer to the Logiweb engine extended with parallel “or” as the parallel engine.

The notions of “root normal form” and “root equivalence” are defined for the parallel engine as they are for the Logiweb engine.

Two terms [x] and [y] are considered mathematically equal, written [x = y], if [z ’ x] is root equivalent to [z ’ y] for all terms [z] (where the term [z] is allowed to include parallel “or”). This defines equality of term [x] and [y] that may include parallel “or” and, in particular, defines equality of terms that do not include paralle “or”. Mathematical equality is undecidable in general.

At this point, parallel “or” has played its role and we shall not refer to it anymore. But we shall use mathematical equality to state things like [(λx.x)^{I}’y = y]. For an axiomatization of mathematical equality see [4].

3.2 Definitions

3.2.1 The value aspect

One may define many “aspects” of each construct. As an example, the “tex” aspect of a construct defines how the construct should be rendered using TEX. Likewise, the “pyk” aspect of a construct defines what the construct looks like in a pyk source file from which a Logiweb page may be compiled.

An ordinary mathematical definition of a construct corresponds to a definition of the value aspect of the construct in Logiweb. The value aspect is proclaimed thus: [val ▷◁ “value”].

As an example of a value definition, consider the following:

[f(x) →^{val} if(x, T, f(x ’ T))]

With the definition above we have [f(λx.λx.λx.T) = f(λx.λx.T) = f(λx.T) = f(T) = T] 3.2.2 Parentheses

It is best to macro define parentheses, i.e. to define them by defining the macro aspect of the parenthesis construct. To keep the present page simple and to the point, however, we shall not deal with macro definitions here. Instead, we value define parentheses:

[(x)^{I} →^{val} x]

3.2.3 Bottom

As mentioned, a term is perpetual if reduction of the term proceeds indefinitely without yielding a root normal form. As an example, [(λx.x ’ x)^{I} ’ (λx.x ’ x)^{I}] is a perpetual term. Some authors prefer to use a capital omega for that term.

There are different opinions on whether or not all perpetual terms are equal. Intuitionists will typically say that there are perpetual terms that are not provably equal. Other blends of mathematicians go further and claim there are perpetual terms that are provably different. With the definition of mathematical equality stated earlier, however, all perpetual terms are equal.

Having decided that all perputual terms are equal or, equivalently, that they all have the same value, it is reasonable to introduce a name for that unique value. We shall follow tradition and call that value bottom since it lurks at the bottom of kappa-Scott domains.

Furthermore, we shall follow tradition and use [⊥] to denote bottom. We do so by making the following definition:

[⊥ ⇒^{val} (λx.x ’ x)^{I} ’ (λx.x ’ x)^{I}]

The equal sign in the definition deviates slightly from the equal sign used previously. Formally, that has no effect on the definition. See Section 3.6 for further details.

With the definition above we have that [⊥] is perpetual, since evaluating it causes a computer to look indefinitely. For that reason, the value of [⊥] is bottom.

Mathematics is referentially transparent, meaning that any term silently denotes the value of the term. For that reason, [⊥] denotes bottom.

By abuse of the language, we shall say that an operator returns [⊥] when the operator does not return anything ever.

3.3 Peano trees

3.3.1 Raw pairs

Define

[y ˙. . z ⇒^{val} λx.if(x, y, z)]

[F ⇒^{val} T ˙. . T]

[x^{H} →^{val} x ’ T]

[x^{T} →^{val} x ’ F]

We shall use [T] and [F] to denote truth and falsehood, respectively.

Furthermore, we shall use [y ˙. . z] as the most fundamental (most raw) among several pair constructs. The components of a pair may be found using the head operation [x^{H}] and tail operation [x^{T}]:

[(y ˙. . z)^{I}^{H} = y]

[(y ˙. . z)^{I}^{T} = z]

In principle, we may use any definition for [y ˙. . z] as long as it is possible to compute [y] and [z] from [y ˙. . z]. The definition above differs from anything tenable in pure lambda calculus: The range of any function in pure lambda calculus has one or infinitely many elements whereas the range of [(y ˙. . z)^{I} ’ x] comprises [y], [z], and [⊥].

3.3.2 Peano trees

As is well known, Dedekind and Peano both managed to axiomatize the natural numbers. Dedekind was first, but Peano had best public relations, so we know the axioms as the Peano axioms today.

In short, the Peano axioms are axioms for the smallest set [N] which contains [0] and which contains the successor of [x] whenever it contains [x].

Now consider the smallest set [P] which contains [T] and which contains [x ˙. . y] whenever it contains [x] and [y]. We shall refer to the elements of [P] as Peano trees due to the similarity to the structure of natural numbers.

Peano trees are good substitutes for natural numbers in elementary recursion theory because it is much easier to work with “Gödel trees” than to work with “Gödel numbers”. Peano trees are early precursors of the maps used in Map Theory and Logiweb, and they constitute convenient stepping stones for building up more advanced data structures.

In early versions of Map Theory and Logiweb, Peano trees have been called “Binary trees”, “Finite trees”, and “Bintrees”, but those names are inconvenient because it is convenient to reserve “B” for “Boolean” and “F” for “False”. The “P” in “Peano tree” may be mistaken to denote “Pair”, but that is acceptable since Peano trees are little more than a bunch of pairs.

As far as possible, we shall represent data structures by Peano trees. As an example, we represented truth values by Peano trees in the previous section.

3.3.3 Canonical and liberal representations

In Logiweb (as in most computational systems) one has to distinguish between canonical and liberal representations. By a canonical representation we shall mean a representation scheme that assigns one and only one representation to each concept to be represented. By a liberal one we shall mean a representation scheme that assigns at least one.

For each set of concepts to be represented, we shall assign a canonical as well as a liberal representation. And we shall make sure the representations are compatible in the sense that the canonical representation of any concept is among the liberal representations of the concept.

We make the convention that [T] liberally represents truth and that any lambda abstraction liberally represents falsehood. This convention is compatible with the convention that [T] represents truth and [T ˙. . T] represents falsehood.

[T]^{4} of Map Theory and Logiweb corresponds to Nil in Lisp and Null in C. Hence, the convention to let [T] represent truth and anything else falsehood is opposite to the choice made in Lisp and C. But the choice is in line with Gödels choice to let 0 denote truth. Gödels choice to make the simplest possible data structure represent truth and everything else denote falsehood is a smart one; it has the consequence that when programming primitive recursive functions, one tends to treat the simple case first and the recursive case afterwards which enhances the readability of the code. Gödels 1931 paper [3] is the best example I have ever seen of “literate programming”, and the syntax of that particular paper has been a driving force in the development of Logiweb since 1984 where the first version of the “Pyk” compiler was implemented. The present implementation of Logiweb depends heavily on the existence of TEX and the World Wide Web.

3.3.4 Eager pairs

We now introduce an eager version of [x ˙. . y]. In many situations, the eager version is more efficient to compute than the lazy one.

Define

[x : y →^{val} if(x, y, y)]

[x \underline{˙. .} y →^{val} x : y : x ˙. . y]

The guard construct [x : y] equals [⊥] whenever [x] equals [⊥] and equals [y] otherwise. In Logiweb, one may use guards when one needs the value of one construct [y] but also wants to force another construct [x] to be computed.

The guard construct is used in the definition of the eager pair [x \underline{˙. .} y] above. Computation of [x \underline{˙. .} y] forces [x] and [y] to be computed. Whenever [x] and [y] differ from [⊥], the eager pair equals the raw pair.

We shall say that [x \underline{˙. .} y] is strict in [x] because [⊥ \underline{˙. .} y = ⊥] for all maps [y]. Similarly, we shall say that [x \underline{˙. .} y] is strict in [y] because [x \underline{˙. .} ⊥ = ⊥] for all

maps [x].

Furthermore, we shall say that [x \underline{˙. .} y] is “strict” (without mentioning a particular argument) because it is strict in all arguments.

4It is generally considered to be bad style to start a sentence with a formula. But, in my opinion, the reasons for deprecating such opening formulas disappear when formulas are consistently surrounded by brackets.

We shall say that [x ˙. . y] is lazy in [x] because it is not strict in [x] and lazy in [y] for similar reasons. We shall say that [x ˙. . y] is “lazy” (without mentioning a particular argument) because it is lazy in at least one argument.

3.4 Cardinals

3.4.1 Untagged cardinals

Cardinal numbers are the numbers “one”, “two”, “three”, and so on as opposed to the ordinal numbers “first”, “second”, “third”, and so on.

In set theory, the words “cardinal” and “ordinal” are used in a somewhat technical sense in which cardinals and ordinals may be infinite. We shall not use the words in that sense here.

In programming context, the word “cardinal” is sometimes simply used as a synonym for “natural number”. We shall use the word in that sense here.

We shall use [b_{0} \underline{˙. .} b_{1} \underline{˙. .} ⋯ \underline{˙. .} b_{n−1} \underline{˙. .} T] to represent

[∑_{i=0}^{n−1} 2^{i}if(b_{i}, 0, 1)]

As an example, [T \underline{˙. .} F \underline{˙. .} F \underline{˙. .} T] represents six. The rightmost [T] marks the end of the structure. The other elements, [T], [F], and [F], are the bits of [6 = 110_{2}], stated with the least significant bit first.

3.4.2 Operations on untagged cardinals

Define

[x \underline{+2∗} y →^{val} if(x, if(y, T, x \underline{˙. .} y), x \underline{˙. .} y)]

If [y] is an untagged cardinal, then [T \underline{+2∗} y] represents two times [y] and [F \underline{+2∗} y] represents one plus two times [y].

[x \underline{+2∗} y] is right associative so that e.g. [T \underline{+2∗} F \underline{+2∗} T] equals [T \underline{+2∗} (F \underline{+2∗} T)^{I}] which in turn equals two.

The set of untagged cardinals is the smallest set that contains [T] (which represents zero) and which contains [T \underline{+2∗} y] and [F \underline{+2∗} y] whenever it contains [y].

Now define

[x^{C} →^{val} if(x, T, x^{H}^{B} \underline{+2∗} x^{T}^{C})]

For all untagged cardinals [x] we have [x^{C} = x]. Furthermore we have [⊥^{C} = ⊥].

We shall say that [x] is a lifted, untagged cardinal if [x] is an untagged cardinal or equals [⊥]. [x^{C} = x] if and only if [x] is a lifted, untagged cardinal.

Moreover, [x^{C}] is a lifted, untagged cardinal for all maps [x]. Hence, [x^{C}] is a construct that leaves lifted, untagged cardinals alone and converts everything else to lifted, untagged cardinals.

From the remarks above it follows that [x^{C}] is idempotent in the sense that [x^{C}^{C} = x^{C}] for all maps [x].

We shall say that an operation is a normalization construct or retract for a set [S] if the operation is unary, strict, idempotent, and its range equals [S∪{⊥}]. Hence, [x^{C}] is a retract for untagged cardinals.

3.4.3 Retracts and representations

Given a map [x] one may use the liberal representation of Booleans to translate the map to a Boolean and then use the canonical representation to translate the Boolean back to a map. The operation thus defined is a retract of Booleans:

[x^{B} →^{val} if(x, T, F)]

In general, any pair consisting of a liberal and a canonical representation defines a retract.

3.4.4 The untagged cardinals from zero to nine

Define [\underline{0} →^{val} T], [\underline{1} →^{val} F \underline{+2∗} \underline{0}], [\underline{2} →^{val} T \underline{+2∗} \underline{1}], [\underline{3} →^{val} F \underline{+2∗} \underline{1}], [\underline{4} →^{val} T \underline{+2∗} \underline{2}], [\underline{5} →^{val} F \underline{+2∗} \underline{2}], [\underline{6} →^{val} T \underline{+2∗} \underline{3}], [\underline{7} →^{val} F \underline{+2∗} \underline{3}], [\underline{8} →^{val} T \underline{+2∗} \underline{4}], and [\underline{9} →^{val} F \underline{+2∗} \underline{4}].

3.4.5 Tagged cardinals

For all untagged cardinals [y] we shall refer to [T \underline{˙. .} y] as the corresponding tagged cardinal. [T] in [T \underline{˙. .} y] is a tag which, in a moment, allows to distringuish tagged cardinals from other data structures.

3.4.6 Operations on tagged cardinals

For all tagged cardinals [x],

[x^{U} →^{val} if(x^{H}, x^{T}, T)]

is the corresponding untagged cardinal. The untag operation maps data other than tagged cardinals to untagged zero or bottom.

Now define

[x +2∗ y ⇒^{val} T \underline{˙. .} x^{B} \underline{˙. .} y^{U}^{C}]

If [y] is a tagged cardinal, then [T +2∗ y] represents two times [y] and [F +2∗ y] represents one plus two times [y].

[0 ⇒^{val} T ˙. . T] is a tagged zero.

The set of tagged cardinals is the smallest set that contains [0] and which contains [T +2∗ y] and [F +2∗ y] whenever it contains [y].

3.4.7 The tagged cardinals from one to nine

Define [1 →^{val} F +2∗ 0], [2 →^{val} T +2∗ 1], [3 →^{val} F +2∗ 1], [4 →^{val} T +2∗ 2], [5 →^{val} F +2∗ 2], [6 →^{val} T +2∗ 3], [7 →^{val} F +2∗ 3], [8 →^{val} T +2∗ 4], and [9 →^{val} F +2∗ 4]

3.5 Tagged trees

3.5.1 Tagged pairs

For all [x] and [y], we shall refer to

[x \underline{: :} y →^{val} (\underline{0} \underline{˙. .} \underline{0} \underline{˙. .} T)^{I} \underline{˙. .} x \underline{˙. .} y]

as the tagged pair of [x] and [y]. In [(\underline{0} \underline{˙. .} \underline{0} \underline{˙. .} T)^{I} \underline{˙. .} x \underline{˙. .} y] we shall refer to [x] and [y] as the head and tail, respectively, of the tagged pair.

The set of tagged Peano trees is the smallest set which contains [T] and which contains [x \underline{: :} y] whenever [x] and [y] are tagged Peano trees.

3.5.2 Cardinal trees

The set of cardinal trees is the smallest set which contains [T] and all tagged cardinals and which contains [x \underline{: :} y] whenever [x] and [y] are cardinal trees.

Cardinal trees are even more suited to replace Gödel numbers than Peano trees are. For that reason, Logiweb represents terms by Cardinal trees. In Logiweb, terms are represented by Cardinal trees as follows:

Every operation in Logiweb is identified by a reference cardinal [r] and an id [i], which is also a cardinal. The reference cardinal uniquely identifies the home page of the operation, which is the page that introduces the operation. The id is a cardinal which identifies the operation among all operations introduced by that page.

In Logiweb, an operation with reference cardinal [r] and id [i] applied to arguments is represented by the cardinal tree

[((r \underline{˙. .} i \underline{˙. .} x)^{I} \underline{˙. .} y \underline{˙. .} ⋯ \underline{˙. .} z \underline{˙. .} T)^{I}]

where [y, …, z] are representations of the arguments and [x] is a structure which is ignored by Logiweb except when generating human readable error messages ([x] indicates the location the operation in the body before macro expansion so that a browser can locate and highlight it).

3.5.3 Tagged maps

We shall refer to

[M(x) →^{val} (\underline{0} \underline{˙. .} \underline{1} \underline{˙. .} T)^{I} ˙. . x]

as a tagged map where [\underline{0} \underline{˙. .} \underline{1} \underline{˙. .} T] is the tag and [x] is the map itself.

The set of tagged trees is the smallest set which contains [T] and all tagged cardinals, which contains [x \underline{: :} y] whenever [x] and [y] are tagged trees, and which contains [(\underline{0} \underline{˙. .} \underline{1} \underline{˙. .} T)^{I} ˙. . x] for all maps [x].

3.5.4 The retract for tagged trees

We define the retract for tagged trees thus:

[x^{M} ⇒^{val} if(x, T, if(x^{H}, T \underline{˙. .} x^{T}^{C}, if(x^{H}^{T}^{H}, x^{T}^{H}^{M} \underline{: :} x^{T}^{T}^{M}, M(x^{T}))))]

We define the constructor operation for tagged pairs such that it normalises its arguments and, hence, is guaranteed to return [⊥] or a tagged tree:

[x : : y ⇒^{val} x^{M} \underline{: :} y^{M}]

Operations that retract their arguments allow certain optimizations to occur behind the scene (c.f. Section 3.6).

3.5.5 Predicates on tagged trees

The following predicate tests for being data (as opposed to being a tagged map):

[x^{d} ⇒^{val} x^{M}^{H}^{T}^{H}^{B}]

The following predicate tests for being a cardinal:

[x^{c} ⇒^{val} if(x, F, x^{M}^{H}^{B})]

We shall say that [0] is singular among tagged cardinals, that [T] is singular among tagged peano trees, and that [M(T)] is singular among tagged maps. Non-singular entities are called regular. The following predicate tests for singularity:

[x^{s} ⇒^{val} x^{M}^{T}^{B}]

3.5.6 Operations on tagged trees

We define the head of a tagged cardinal [x] to be [T] if [x] is even and [F] otherwise. All operations on tagged trees are defined such that they retract their arguments before operating on them. The head operation is defined thus:

[x^{h} ⇒^{val} if(x^{d}, x^{M}^{T}^{H}, T)]

We define the tail of a tagged cardinal [x] to be [x] integer divided by two (i.e. divided by two and rounded to the nearest cardinal in the direction of minus infinity). The tail of a tagged pair is the second component of the pair. The tail of a tagged map or [T] equals [T]:

[x^{t} ⇒^{val} if(x^{d}, if(x^{c}, T \underline{˙. .} x^{M}^{T}^{T}, x^{M}^{T}^{T}), T)]

Accessors for the zeroth to ninth element of a list [x] read [x^{0} →^{val} x^{h}], [x^{1} →^{val} x^{t}^{0}], [x^{2} →^{val} x^{t}^{1}], [x^{3} →^{val} x^{t}^{2}], [x^{4} →^{val} x^{t}^{3}], [x^{5} →^{val} x^{t}^{4}], [x^{6} →^{val} x^{t}^{5}], [x^{7} →^{val} x^{t}^{6}], [x^{8} →^{val} x^{t}^{7}], and [x^{9} →^{val} x^{t}^{8}].

3.5.7 Selection

The following operation is a retracting if-then-else construct which plays an important role in connection with optimizations and fitness and strictness analysis that occur behind the scene:

[If(x, y, z) ⇒^{val} if(x^{M}, y^{M}, z^{M})]

We shall use selection

[x \{ \begin{matrix}y \\ z \end{matrix} ⇒^{val} If(x, y, z)]

as an alternative for [If(x, y, z)]. It would be very natural to macro define selection, but macro definitions depend on the Logiweb self-interpretter which in turn depends on the definitions presented on the present page. To keep the present page simple and to the point, we omit introducing the notion of macro definitions and, hence, avoid macro defining selection.

3.5.8 Semitagged maps

We introduce a semitagged representation of maps as follows:

1. The canonical representation of a map [m] is [M(m)].

2. Any tagged tree [x] liberally represents the map [If(x^{d}, x, x^{T})].

[U(x)] returns the map represented by the semitagged [x]. The untagger [U(x)] leaves tagged data untouched and untags tagged maps:

[Ũ(x) →^{val} if(x^{d}, x, x^{T})]

[U(x) →^{val} Ũ(x^{M})]

The construct [apply(f, x)] applies a tagged map [f] to a semitagged map [x] and returns the result as a tagged map. If [f] is tagged data then [apply(f, x)] equals [f]:

[apply(f, x) ⇒^{val} apply_{1}(f^{M}, x^{M})]
[apply_{1}(f, x) →^{val} f^{d} \{ \begin{matrix}If(x^{d}, f, f) \\ If(x^{d}, M(f^{T} ’ x), M(f^{T} ’ (x^{T})^{I})) \end{matrix} ]

A short version of [apply(f, x)] reads:

[f ‘ x →^{val} apply(f, x)]

We shall also introduce a tagged version of lambda abstraction. Logiweb, however, does not support value definitions of new binding constructs. This is convenient for designers of proof systems who can rely on lambda being the only binding construct in Logiweb.

In Logiweb it is the intension that new binding constructs should be macro defined so that binding constructs are expanded into lambdas before proof checking. At the present stage of the bootstrap of Logiweb, however, we do not yet have macro definitions.

For that reason we introduce a unary operator [Λx] and use [Λλx.y] to denote tagged lambda abstraction. At a later stage we introduce a construct that macro expands into [Λλx.y]. We define [Λx] thus:

[Λx ⇒^{val} M(λu.U(x ’ M(u)))]

[U^{M}(x)] is a version of [U(x)] which untags and then normalizes a semitagged map.

[U^{M}(x) ⇒^{val} U(x)^{M}]

3.6 Optimization

3.6.1 On-stage and off-stage semantics

The Logiweb computing engine maintains an on-stage semantics and off-stage semantics. The on-stage semantics concerns the input-output relation of operations. The off-stage semantics concerns the run time and memory usage of operations.

One needs to know the on-stage semantics to make correct programs and one needs to know the off-stage semantics to make efficient programs.

The on-stage semantics of operations must be the same on all implementations of Logiweb. The off-stage semantics may vary considerably. For that reason, it is only possible to say something definite about the on-stage semantics. The remarks on off-stage semantics below concern one, particular implementation of the Logiweb computing engine which we shall refer to as the first edition engine.

The on-stage semantics of [x^{h}] is that the Logiweb computing engine reduces [x^{h}] to [x^{M}^{T}^{H}] because of the definition [x^{h} ⇒^{val} x^{M}^{T}^{H}].

Logiweb has three kinds of revelation constructs that connect syntactic constructs with semantic concepts. The three kinds of revelations are called proclamations, definititions, and introductions. The revelation of [x^{h}] above is an introduction rather than a definition. One can see that by looking at the equal sign which deviates from a normal equal sign.

The first edition engine maintains a list of constructs that it can compute using hardcoded functions. Whenever the first edition engine sees an introduction, it runs through its list of known constructs to see, if it can recognize the construct being introduced. When doing so, the first edition engine is insensitive to names of bound variables, names of parameters, and names of auxiliary functions, but apart from that the engine merely recognises an introduction if its right hand side is identical to something the engine knows. If the first edition engine cannot recognize an introduction, it prints a warning and treats the introduction as if it were a definition.

The notion of introduction is proclaimed: [[y ⇒^{x} z] ▷◁ “introduce”].

On the first-edition engine, the off-stage semantics of [x^{h}] is that, behind the scenes, the engine converts the argument of [x^{h}] to an internal, efficient representation, then manipulates that internal representation, and then converts the internal representation back to maps.

The conversion back and forth takes time, but the manipulation of the internal representation is fast. When computing a single head operation, it does not pay off to round the internal representation. But when performing a long sequence of head and other, hardcoded operations, the engine merely has to convert back and forth once at the beginning and end of the computation.

3.6.2 Optimized bottom

The revelation [⊥ ⇒^{val} (λx.x ’ x)^{I} ’ (λx.x ’ x)^{I}] of bottom is an introduction

Bottom has the property that evaluation of it never returns a value. Genuine bottom [(λx.x’x)^{I}’(λx.x’x)^{I}] never returns a value because it makes the computer run forever.

As any other optimized construct, optimized bottom must have exactly the same behavior as genuine bottom and, hence, optimized bottom must avoid returning a value. When evaluated on the first edition engine, optimized bottom signals an irrecoverable error and, hence, satisfies the requirements.

Another valid implementation of optimized bottom would be to let it decrease the priority of the current operating system process so much that the process received no more cpu-time.

The Logiweb machine described later is multitasking, so the latter implementation of optimized bottom would be reasonable there.

Please never do “bessermachen” by introducing a construct that can test for optimized bottomness. That would ruin the applicative behaviour of the Logiweb reduction system. If a bottomness test seems desirable to have in some situation, consider using exceptions and exception handling instead; and don’t try to solve Turings halting problem.

3.6.3 Strictness

Define

[x ∧ y →^{val} x \{ \begin{matrix}If(y, T, F) \\ If(y, F, F) \end{matrix} ]

We shall say that [x ∧ y] is strict in its first argument because

[⊥ ∧ y = ⊥]

When an equation contains a free variable, it is understood that the equation holds for all values of the free variable. Hence, above, it is understood that the equation holds for all [y].

We shall say that [x ∧ y] is strict in its second argument because

[x ∧ ⊥ = ⊥]

We shall say that [x ∧ y] is strict because it is strict in all its arguments.

3.6.4 Types

We shall say that that the return value of [x ∧ y] is of type tagged tree because [(x ∧ y)^{I}^{M} = x ∧ y] We shall say that the first argument of [x ∧ y] is of type tagged tree because [x^{M} ∧ y = x ∧ y] Likewise, we shall say that the second argument of [x ∧ y] is of type tagged

tree because [x ∧ y^{M} = x ∧ y] Summing up, we shall say that [x ∧ y] is an operation over tagged trees

because its return value and all its arguments are of type tagged tree.

Being an operation over tagged trees does not exclude being an operation over other types as well.

3.6.5 User defined strict operations

We shall say that an operation is fit for optimization if the first edition engine can prove that the operation is a strict operation over tagged trees. The first edition engine translates operations that are fit for optimization in a particularly efficient way.

Users of the first edition engine need some understanding of fitness for optimization in order to make definitions that the first edition engine can compute efficiently.

We shall refer to [T], [0], [x^{M}], [x +2∗ y], [x : : y], [x^{h}], [x^{t}], [x^{s}], [x^{c}], and [If(x, y, z)] as the basic tagged tree operations.

The first edition engine knows that the basic tagged tree operations are operations over tagged trees and that all but [If(x, y, z)] are strict.

From this the first edition engine can deduce that all operations defined from these constructs are operations over tagged trees. This includes operations that are defined by recursion or mutual recursion. There is one pathological exception, though. A projection operation like [f(x, y) = x] may be defined using the functions above zero times but is not an operation over tagged trees.

3.6.6 Fitness analysis

Operations defined from the basic tagged tree operations need not be strict because [If(x, y, z)] is non-strict. But the first edition engine performs fitness analysis as follows:

The engine classifies all operations as “fit”, “unfit”, or “possibly fit” for optimization. As a fourth classification, the engine classifies [If(x, y, z)] as a “conditional”.

Among the four elementary, computable constructs, the engine classifies [T] as fit and [λx.y], [x ’ y], and [if(x, y, z)] as unfit.

Among the basic tagged tree operations the engine classifies [If(x, y, z)] as a conditional and the other ones as fit.

The engine classifies all other operations as possibly fit, except that it classifies projection operations as unfit. Then the engine reclassifies possibly fit operations as unfit according to certain rules described in the following. And when no further operations can be reclassified as unfit, all remaining possibly fit operations are reclassified as fit.

In other words, operations are considered fit unless they are provably unfit. This happens to be completely safe.

Possibly fit operations are reclassified as unfit according to two rules:

A possibly fit operation is reclassified as unfit if its definition contains an unfit operation.

A possibly fit operation if reclassified as unfit if some variable one the left hand side of the definition does not occur strict in the right hand side where “occurs strict” is defined in the next section.

3.6.7 Strict variables

Possibly fit operations are reclassified as unfit according to two rules. The first is rather simple:

A possibly fit operation is reclassified as unfit if its definition contains an unfit operation.

The other rule is more complex and makes reference to the notion of a strict variable. The notion of a strict variable is similar to the notion of a free variable. In fact, the strict variables of a term comprise a subset of the free variables of the term.

The notion of strict variables of a term [\underline{a}] is defined by structural induction in [\underline{a}] by the following three cases:

If the term [\underline{a}] is the variable [x], then the strict variables of [\underline{a}] comprises [x].

If the term [\underline{a}] is an operation applied to subtrees and the operation is not classified as conditional, then the free variables of [\underline{a}] comprises the strict variables of the subtrees.

If the term [\underline{a}] is a conditional operation applied to three subtrees like [If(x, y, z)], then the strict variables of [\underline{a}] comprises the strict variables of [x] plus all variables that occur strict in both [y] and [z].

As an example, [x] and [y] are the strict variables of [If(x, y, If(y, z, y))].

3.6.8 Fitness of conjunction

The first edition engine classifies

[x ∧ y →^{val} x \{ \begin{matrix}If(y, T, F) \\ If(y, F, F) \end{matrix} ]

as fit for optimization because conjunction is not the conditional construct and because the engine does not classify conjunction as unfit. The engine does not classify conjunction as unfit because the right hand side of the definition above contains no unfit operations and because both variables, [x] and [y], occur strict in the right hand side.

3.6.9 Logical connectives

Define

[¬x →^{val} If(x, F, T)]
[x ∨ y →^{val} x \{ \begin{matrix}If(y, T, T) \\ If(y, T, F) \end{matrix} ]

The operations above are fit for optimization.

Sometimes, when programming, it is useful to have lazy versions of the connectives that compute the first argument before they decide whether or not to compute the second, but we shall not need them here.

If such lazy connectives are needed, one should consider to macro define them rather than value defining them. If lazy connectives are value defined, they will be classified as unfit for optimization. On the contrary, if they are macro defined they will be macro expanded away before fitness analysis and, hence, they can be used for defining operations that are fit for optimization.

3.6.10 Auxiliary operations

Parentheses cannot occur in definitions that are fit for optimization since [(x)^{I}] does not normalize its argument.

Later, we macro define parentheses. Once parentheses are macro defined, they disappear from terms before fitness analysis. Hence, once parentheses are macro defined, they can be used in optimizable definitions. Until we macro define parentheses, we shall use a normalizing version of parentheses:

[(x)^{M} →^{val} x^{M}]

The following normalizing guard operation can be used in definitions for making the defined function strict:

[x!y ⇒^{val} If(x, y, y)]

3.6.11 Equality

Define [x ≈ y ⇒^{val} x^{d} \{ \begin{matrix}If(y^{d}, x ≈^{D} y, F) \\ If(y^{d}, F, T) \end{matrix} ]

[x ≈^{D} y →^{val} x^{c} \{ \begin{matrix}If(y^{c}, x ≈^{C} y, F) \\ If(y^{c}, F, x ≈^{P} y) \end{matrix} ]

[x ≈^{C} y →^{val} x^{s} \{ \begin{matrix}If(y^{s}, T, F) \\ If(y^{s}, F, x^{h} ≈^{B} y^{h} ∧ x^{t} ≈^{C} y^{t}) \end{matrix} ]

[x ≈^{B} y →^{val} x \{ \begin{matrix}If(y, T, F) \\ If(y, F, T) \end{matrix} ]

[x ≈^{P} y →^{val} x^{s} \{ \begin{matrix}If(y^{s}, T, F) \\ If(y^{s}, F, x^{h} ≈ y^{h} ∧ x^{t} ≈ y^{t}) \end{matrix} ]

[x ≈ y] is an example of an operation defined by mutual recursion which is fit for optimization.

3.7 Arithmetic

3.7.1 Addition Addition of cardinals is defined thus:

[x + y →^{val} If(x^{c} ∧ y^{c}, x +_{0} y, T)]

[x +_{0} y →^{val} x^{s} \{ \begin{matrix}y \\ y^{s} \{ \begin{matrix}x \\ x^{h} \{ \begin{matrix}y^{h} \{ \begin{matrix}T +2∗ x^{t} +_{0} y^{t} \\ F +2∗ x^{t} +_{0} y^{t} \end{matrix} \\ y^{h} \{ \begin{matrix}F +2∗ x^{t} +_{0} y^{t} \\ T +2∗ x^{t} +_{1} y^{t} \end{matrix} \end{matrix} \end{matrix} \end{matrix} ]

[x +_{1} y →^{val} x^{s} \{ \begin{matrix}y +_{0} 1 \\ y^{s} \{ \begin{matrix}x +_{0} 1 \\ x^{h} \{ \begin{matrix}y^{h} \{ \begin{matrix}F +2∗ x^{t} +_{0} y^{t} \\ T +2∗ x^{t} +_{1} y^{t} \end{matrix} \\ y^{h} \{ \begin{matrix}T +2∗ x^{t} +_{1} y^{t} \\ F +2∗ x^{t} +_{1} y^{t} \end{matrix} \end{matrix} \end{matrix} \end{matrix} ]

3.7.2 Comparison Comparison of cardinals is defined thus:

[x < y →^{val} If(x^{c} ∧ y^{c}, x <′ y, F)] [x <′ y →^{val} y^{s} \{ \begin{matrix}x!F \\ x^{s} \{ \begin{matrix}T \\ x^{h} \{ \begin{matrix}y^{h} \{ \begin{matrix}x^{t} <′ y^{t} \\ x^{t} ≤′ y^{t} \end{matrix} \\ y^{h} \{ \begin{matrix}x^{t} <′ y^{t} \\ x^{t} <′ y^{t} \end{matrix} \end{matrix} \end{matrix} \end{matrix} ]

[x ≤′ y →^{val} x^{s} \{ \begin{matrix}y!T \\ y^{s} \{ \begin{matrix}F \\ x^{h} \{ \begin{matrix}y^{h} \{ \begin{matrix}x^{t} ≤′ y^{t} \\ x^{t} ≤′ y^{t} \end{matrix} \\ y^{h} \{ \begin{matrix}x^{t} <′ y^{t} \\ x^{t} ≤′ y^{t} \end{matrix} \end{matrix} \end{matrix} \end{matrix} ]

3.7.3 Subtraction Subtraction of cardinals is defined below. Subtraction yields zero when a large number is subtracted from a small.

[x − y →^{val} If(x^{c} ∧ y^{c}, If(x < y, 0, x −_{0} y), T)]

[x −_{0} y →^{val} y^{s} \{ \begin{matrix}x \\ x^{h} \{ \begin{matrix}y^{h} \{ \begin{matrix}T +2∗ x^{t} −_{0} y^{t} \\ F +2∗ x^{t} −_{1} y^{t} \end{matrix} \\ y^{h} \{ \begin{matrix}F +2∗ x^{t} −_{0} y^{t} \\ T +2∗ x^{t} −_{0} y^{t} \end{matrix} \end{matrix} \end{matrix} ]

[x −_{1} y →^{val} y^{s} \{ \begin{matrix}x −_{0} 1 \\ x^{h} \{ \begin{matrix}y^{h} \{ \begin{matrix}F +2∗ x^{t} −_{1} y^{t} \\ T +2∗ x^{t} −_{1} y^{t} \end{matrix} \\ y^{h} \{ \begin{matrix}T +2∗ x^{t} −_{0} y^{t} \\ F +2∗ x^{t} −_{1} y^{t} \end{matrix} \end{matrix} \end{matrix} ]

3.7.4 Multiplication Multiplication of cardinals is defined thus:

[x · y →^{val} If(x^{c} ∧ y^{c}, x ·_{0} y, T)]

[x ·_{0} y →^{val} y^{s} \{ \begin{matrix}x!0 \\ y^{h} \{ \begin{matrix}T +2∗ x ·_{0} y^{t} \\ (T +2∗ x ·_{0} y^{t})^{M} +_{0} x \end{matrix} \end{matrix} ]

3.7.5 Bit access [bit(x, y)] is true if bit number [x] of the cardinal [y] is zero. The least significant bit is bit number zero.

[bit(x, y) →^{val} If(x^{c} ∧ y^{c}, bit_{1}(x, y), T)]

[bit_{1}(x, y) →^{val} If(x^{s}, y^{h}, bit(x − 1, y^{t}))]

3.8 Quoting

3.8.1 Terms

Terms have form [(r : : i : : d)^{I} : : a] where [r] and [i] are the reference and identifier, respectively, of the root symbol of the term and the argument list [a] is a list of terms. The debugging information [d] indicates the location of the root symbol on the page and allows a browser to highlight the root symbol even if the root symbol has been moved around by such processes as macro expansion.

Accessors for the reference, identifier, and debug information of a term [x] read [x^{r} →^{val} x^{h}^{h}], [x^{i} →^{val} x^{h}^{t}^{h}], and [x^{d} →^{val} x^{h}^{t}^{t}], respectively.

[x^{R} →^{val} x^{r} : : x^{i} : : T] returns the root of the term [x] without debugging information.

[x =^{r} y]is true if the roots of the terms [x] and [y] are equal except for debugging information:

[x =^{r} y →^{val} If(x^{r} ≈ y^{r}, x^{i} ≈ y^{i}, F)]

When testing two terms for identity, one should disregard debugging information. [x =^{t} y] tests two terms [x] and [y] for identity disregarding debugging information:

[x =^{t} y →^{val} If(x =^{r} y, x^{t} =^{t^{∗}} y^{t}, F)]

[x =^{t^{∗}} y] tests two lists [x] and [y] of terms for identity disregarding debugging information:

[x =^{t^{∗}} y →^{val} x^{a} \{ \begin{matrix}If(y^{a}, T, F) \\ If(y^{a}, F, If(x^{h} =^{t} y^{h}, x^{t} =^{t^{∗}} y^{t}, F)) \end{matrix} ]

3.8.2 Gödel trees

In addition to the fundamental, computable constructs [T], [λx.y], [f ’ x], and [if(x, y, z)] we introduce the quote construct [⌈\underline{a}⌉] for pragmatic reasons.

The quote construct is computable but does not add to the computational power of the Logiweb engine. If it were omitted from Logiweb, one could replace it with a macro defined construct.

The quote construct resembles “quote” in Lisp [9] and Gödel numbers as introduced in [3].

The reason for introducing quoting as a fundamental construct rather than macro defining it is that a macro defined quote would expand into rather large terms. In other words, quotes are introduced to enhance the efficiency of the macro facility. End users will probably prefer “backquote” like macros that are based on the quote construct rather than using quote raw.

The quote construct is proclaimed thus:

[⌈x⌉ ▷◁ “quote”]

For a term [\underline{a}], [⌈\underline{a}⌉] denotes the tagged tree that represents [\underline{a}]. As an example,

[⌈x ≈ y⌉]

is the tagged tree that represents the term [x ≈ y]. We have

[⌈x ≈ y⌉ = (r : : i : : d : : T)^{I} : : ⌈x⌉ : : ⌈y⌉ : : T]

except for debugging information present in each occurrence of [x] and [y].

The [r] and [i] above are the reference and identifier, respectively, of the [∗ ≈ ∗] symbol. The reference [r] is a large cardinal (around 200 bits long) which identifies the home page of the [∗ ≈ ∗] symbol, i.e. the page on which the [∗ ≈ ∗] symbol is introduced. The identifier [i] identifies the [∗ ≈ ∗] symbol among all symbols introduced on that page.

The [d] above is debugging information that indicates the location of the particular instance of the [∗ ≈ ∗] symbol. The value of [d] has form [p_{1} : : p_{2} : : ⋯: : p_{n} : : q : : T] which indicates that the particular instance of the [∗ ≈ ∗] symbol occurs as the p_{1}’s subtree of the p_{2}’s subtree of the p_{3}’s subtree etc. of page [q]. Since the particular instance of the [∗ ≈ ∗] symbol occurs on the present page we have that [q] equals the reference of the present page.

In general, [⌈\underline{a}⌉^{t}] is the list of subterms of the term [\underline{a}] and [⌈\underline{a}⌉^{h}] represents the identity and location of the root symbol of the term. As an example,

[⌈x ≈ y⌉^{r}]

and

[⌈x ≈ y⌉^{i}]

are the reference and identifier, respectively, of the equality construct. As another example, we have

[⌈base⌉^{i} = 0]

because the identifier of the page symbol [base] is zero.

4 The macro expansion facility

This section describes the macro expansion facility of Logiweb[6]. The macro facility allows expressions that are easy to read for humans to expand into more machine readable formats before computer consumption.

4.1 Logiweb identifiers

4.1.1 Representation scheme Occasionally, we shall represent strings of characters by cardinals. To translate a string

[c_{1}c_{2} ⋯ c_{m}] of characters to a cardinal, we proceed as follows. First, we mirror the string

to get:

[c_{m} ⋯ c_{2}c_{1}] Then we translate each character [c_{i}] into its Unicode representation [u_{i}],

yielding a list of cardinals:

[u_{m} ⋯ u_{2}u_{1}] Then we express each cardinal [u_{i}] as a sequence of digits

[d_{in_{i}} ⋯ d_{i1}d_{i0}] in radix [128] such that [0 ≤ d_{ij} < 128] and such that

u_{i} = [∑_{j=0}^{n_{i}} d_{ij}128^{j}]

In addition, we require [d_{in_{i}} ≠ 0] except when [u_{i} = 0] in which case we require [n_{i} = 1] instead.

Next, we add 128 do all digits except leading ones, i.e. we define

[d′_{ij} = \{ \begin{matrix}d_{ij} + 128 & if 0 ≤ j < n_{i} \\ d_{ij} & if j = n_{i} \end{matrix} ]

This gives rise to a sequence

[ d′_{mn_{m}} ⋯ d′_{m0}
⋯
d′_{2n_{2}} ⋯ d′_{20}
d′_{1n_{1}} ⋯ d′_{10} ]

of cardinals in the range from [0] to [255]. Renumbering the sequence above gives the sequence

[d′′_{p} ⋯ d′′_{1}d′′_{0}] which we then interpret as a sequence of digits in radix 256, so that we

represent the string

[c_{1}c_{2} ⋯ c_{m}] by the cardinal

c = [∑_{k=0}^{p} d′′_{k}256^{k}]

4.1.2 Representation of ASCII strings

Logiweb ASCII is a character encoding that is very close to the American Standard Code for Information Interchange (ASCII). The differences are:

In Logiweb ASCII, character codes in the ranges [0. .9] and [11. .31] as well as character code [127] are dead character codes in the sense that if they occur in input, they should be discarded before they make their way into strings.

In Logiweb ASCII, character code [10], nothing but character code [10], and always character code [10], represents the newline character.

Logiweb ASCII is similar to ASCII in that no characters have codes outside [0. .127].

Logiweb ASCII has two formatting character: newline (code [10]) and space (code [32]). All characters in the range [33. .126] are printable glyphs.

When running Logiweb under some host operating system, the convention that character [10] is the newline character may equate or differ from the convention of the host operating system. In the very few cases where strings are exchanged between Logiweb and surrounding systems, one should translate between the newline conventions of Logiweb and the surroundings during the exchange.

Translation from ASCII strings to cardinals and vice versa is particularly simple. To translate e.g. the string “abc”, do as follows. First, write the string backwards: “cba”. Then convert each character to an eight bit byte:

[0110 0011 0110 0010 0110 0001]

Finally, interpret the result as a binary number.

Needless to say (so we say it for safety’s sake), the above representation of ASCII strings by cardinals is quite memory efficient.

4.1.3 Constructors for binary numbers

To express binary numbers easily, we introduce the following three constructs:

[x0 →^{val} T +2∗ x]

[x1 →^{val} F +2∗ x]

[0b →^{val} 0]

4.1.4 Representation of Logiweb identifiers

We shall refer to a particular, short, finite list of strings as Logiweb indentifiers. The list of identifiers, and the semantics of each identifier, is at the heart of the Logiweb standard. At the time of writing I, the author of the present paper, control that list.

Each Logiweb indentifier has the property that it only includes Unicode characters from 97 to 122 (small letter a to small letter z). Now define

[identifier(x) →^{val} If(x^{t}, 0, identifier_{1}(x^{i}, identifier(x^{1})))]

[identifier_{1}(x, y) →^{val} If(x^{6}, y, x^{0} +2∗ x^{1} +2∗ x^{2} +2∗ x^{3} +2∗ x^{4} +2∗ x^{5} +2∗

F +2∗ T +2∗ y)]

We have that e.g. [identifier(⌈“code”⌉)] is the string [“code”] translated to the cardinal specified in Section 4.1.1:

[identifier(⌈“code”⌉) ≈ 0b1100101011001000110111101100011]^{·}

In general, [identifier(⌈\underline{a}⌉)] converts the string [\underline{a}] correctly under the following conditions:

• All non-blind characters of the string are between 64 and 126

• All blind characters of the string are between 0 and 9 or between 11 and 31.

• All characters are represented by unary operators except the end-of-text character, which must be nulary and blind.

4.2 Associative structures

4.2.1 Associations trees

We define the set of associations as the set of pairs [k : : v] where [k] is a cardinal and [v] is a tagged tree. For an association [k : : v] we shall refer to [k] and [v] as the key and value of the association, respectively.

We define the set of association trees as the smallest set which contains [T], which contains all associations, and which contains [a : : b] for all association trees [a] and [b]. Each association tree represents a finite set of associations.

If all keys of an association tree [a] are distinct, then [a] represents the function that maps [k] to [v] whenever [k : : v] belongs to [a] and maps [k] to [T] whenever [k] is a cardinal which does not occur as a key in [a].

In particular, the association tree [T] represents the function that maps all cardinals to [T].

4.2.2 Finite functions

We shall say that a function [f] is a finite function if it maps cardinals to tagged trees and, furthermore, maps at most finitely many cardinals to tagged trees different from [T].

One may represent finite functions by association trees.

4.2.3 Addresses

Each association in an association tree [a] can be accessed using a sequence of head and tail operations. As an example, if [a] is an association tree and [a^{h}^{t}^{h}^{h}] is an association, then the association can be addressed by a head-tail-head-head sequence.

We now represent “head” by binary zero and “tail” by binary one. As an example, if [a] is an association tree and [a^{h}^{t}^{h}^{h}] is an association then we say that the association occurs at address [0, 1, 0, 0].

4.2.4 Arrays

A cardinal [k] may be written on form

[∑_{n=0}^{∞} b_{n}2^{n}]

where [b_{0}, b_{1}, b_{2}, …] are bits (i.e. “binary terms”, i.e. zero or one). We shall refer to [b_{0}, b_{1}, b_{2}, …] as the little endian, infinite binary representation of [k].

We shall say that an association tree [a] is an array if it satisfies the following two conditions:

1. For every association [k : : v] in [a], the address of the association is a prefix of the little endian, infinite binary representation of [k].

2. No substructure of [a] has form [T : : p] or [p : : T] where [p] is an association.

The first condition makes it fast and easy to look up a key [k] in an array. The second condition together with the first ensures that each finite function is represented by exactly one array.

4.2.5 Array access

We shall say that a data structure is atomic if it is not a pair. [x^{a}] is true if [x] is atomic:

[x^{a} →^{val} ¬x^{d} ∨ x^{c} ∨ x^{s}]

[a[k]] looks up the value associated to the key [k] in the array [a]:

[a[k] →^{val} assoc_{1}(a, k, k)]

[assoc_{1}(a, d, i) →^{val} a^{a} \{ \begin{matrix}d!i!T \\ a^{h}^{c} \{ \begin{matrix}i ≈ a^{h} \{ \begin{matrix}d!a^{t} \\ d!T \end{matrix} \\ d^{h} \{ \begin{matrix}assoc_{1}(a^{h}, d^{t}, i) \\ assoc_{1}(a^{t}, d^{t}, i) \end{matrix} \end{matrix} \end{matrix} ]

The above representation of arrays allows array access and update to occur reasonably efficiently. If even greater efficiency is needed, one may implement arrays as hash tables behind the scenes. The first edition engine (the only Logiweb engine in existence at the time of writing) does not treat arrays specially behind the scenes. But arrays are still defined the way they are in order to allow improvements in the future.

As a matter of terminology, we shall refer to keys of arrays as incices. So an array maps indices to values.

4.2.6 Racks

Formally, we shall use “rack” as a synonym for “array”. Informally, we shall use “array” and “rack” for homogeneous and heterogeneous structures, respectively. So an array is an association list whose values are of homogeneous format and a rack is an association list with heterogeneous values.

As a matter of terminology, we shall refer to keys of racks as hooks. So a rack maps hooks to values.

4.2.7 Multidimensional arrays

We shall refer to arbitrary values as zero dimensional arrays and to arrays of [n]-dimensional arrays as [n + 1]-dimensional arrays. As an example, if [a] is a three-dimensional array and [u], [v], and [w] are cardinals, then

[a[u][v][w]]

is the value indexed by [u], [v], and [w].

4.2.8 Array assignment

[a[i→v]] equals the array [a] except that [a[i→v]] maps the index [i] to the value [v].

[a[i→v] →^{val} i^{c} \{ \begin{matrix}v \{ \begin{matrix}array-remove(i, a, 0) \\ array-put(i, v, a, 0) \end{matrix} \\ v!a \end{matrix} ]

[array-plus(x, y) →^{val} x^{a} \{ \begin{matrix}y^{a} \{ \begin{matrix}T \\ y^{h}^{c} \{ \begin{matrix}y \\ x : : y \end{matrix} \end{matrix} \\ y^{a} \{ \begin{matrix}x^{h}^{c} \{ \begin{matrix}x \\ x : : y \end{matrix} \\ x : : y \end{matrix} \end{matrix} ]

[array-remove(i, a, l) →^{val}

i!l!a^{a} \{ \begin{matrix}T \\ a^{h}^{c} \{ \begin{matrix}a^{h} ≈ i \{ \begin{matrix}T \\ a \end{matrix} \\ bit(l, i) \{ \begin{matrix}array-plus(array-remove(i, a^{h}, l + 1), a^{t}) \\ array-plus(a^{h}, array-remove(i, a^{t}, l + 1)) \end{matrix} \end{matrix} \end{matrix} ]

[array-put(i, v, a, l) →^{val}

l!a^{a} \{ \begin{matrix}i : : v \\ a^{h}^{c} \{ \begin{matrix}a^{h} ≈ i \{ \begin{matrix}i : : v \\ array-add(i, v, a^{h}, a^{t}, l) \end{matrix} \\ bit(l, i) \{ \begin{matrix}array-put(i, v, a^{h}, l + 1) : : a^{t} \\ a^{h} : : array-put(i, v, a^{t}, l + 1) \end{matrix} \end{matrix} \end{matrix} ]

[array-add(i, v, i′, v′, l) →^{val}

bit(l, i) \{ \begin{matrix}bit(l, i′) \{ \begin{matrix}array-add(i, v, i′, v′, l + 1) : : T \\ (i : : v)^{M} : : (i′ : : v′)^{M} \end{matrix} \\ bit(l, i′) \{ \begin{matrix}(i′ : : v′)^{M} : : (i : : v)^{M} \\ T : : array-add(i, v, i′, v′, l + 1) \end{matrix} \end{matrix} ]

4.2.9 Multidimensional assignment

[a[i⇒v]] equals the multidimensional array [a] except that [a[i⇒v]] maps the list [i] of indices to the value [v]. As an example, [T[1 : : 2 : : 3 : : T⇒4][1][2][3]] equals [4].

[a[i⇒v] →^{val} i^{a} \{ \begin{matrix}a!v \\ a[i^{h}→a[i^{h}][i^{t}⇒v]] \end{matrix} ]

4.2.10 Variables

The term [λx.x] contains the variable [x].

In Logiweb, any term may serve as a variable. Whether or not a given term is interpreted as a variable depends on context.

A lambda construct forces its first argument to be a variable. This forces the first occurrence of [x] in [λx.x] to be a variable.

The lambda does not force the second occurrence of [x] in [λx.x] to be a variable. But the second occurrence is a variable anyway because of another rule which says that any term whose root symbol has no value definition is a variable.

As a more bizarre example,

[λ2.2]

is a valid term. The lambda forces the first occurrence of [2] to be a variable. The second occurrence of [2] is no variable, however, since nothing forces the second [2] to be a variable and [2] has a value definition. Renaming of the bound variable [2] to [x] shows that [λ2.2] equals [λx.2]:

[λ2.2 = λx.2]

We now introduce the binary construct [x_{y}], but we assign no value to it. For that reason, any term with the [x_{y}] construct in the root will be a variable. As an example of use,

[λx_{1}.λx_{2}.x_{1} : : x_{2}]

equals

[λu.λv.u : : v]

To boost the number of available variables even further, we introduce a unary prime operator [x′]which allows to use [x′], [y′], [z′′′], and so on as variables.

Two variables are equal if they are identical terms (disregarding debugging information). For that reason, even if we defined [x+y] such that [2+2] equaled [4], [x_{2+2}] and [x_{4}] would still be distinct variables.

4.2.11 Stacks

We shall refer to dynamic environments as stacks. A stack is an association list from variables to values.

We cannot use [s[v]] to look up the variable [v] in the stack [s] because we should disregard debugging information present in [v]. For that reason, we use the following construct instead:

[lookup(v, s, d) →^{val} v!d!If(s, d, If(v =^{t} s^{h}^{h}, s^{h}^{t}, lookup(v, s^{t}, d)))]

[lookup(v, s, d)] looks up the variable [v] in the stack [s]. If the variable is not found, [lookup(v, s, d)] returns the default value [d] instead.

The [zip(p, a)] construct zips two lists into a list of pairs and is suited for forming stacks:

[zip(p, a) →^{val} a!If(p, T, (p^{h} : : a^{h})^{M} : : zip(p^{t}, a^{t}))]

4.3 Static semantics

4.3.1 The structure of Logiweb pages

As far as Logiweb is concerned, a Logiweb page consists of a bibliography, a dictionary, and a body. What you read right now is a rendering of the body of a Logiweb page.

The Logiweb bibliography of a page is a list of Logiweb references. The first reference (reference number zero) is the reference of the page itself, and the other references are references of other Logiweb pages.

The bibliography at the end of the present page is a BibTEX bibliography which is part of the body of the page. The BibTEX bibliography is completely unrelated to the Logiweb bibliography.

The Logiweb dictionary of a page is an array which maps identifiers to arities. If the dictionary of the page with reference [r] maps the cardinal [i] to [a] then, by definition, there exists a Logiweb symbol with reference [r] and identifier [i], and that symbol has arity [a].

The Logiweb body of a page is one, big term.

4.3.2 Transitive bibliographies

As mentioned, the first entry of the Logiweb bibliography of any page is the reference of the page itself. Apart from this, the bibliographic references of Logiweb form a non-cyclic graph.

Given a Logiweb page [p], we shall define the transitive bibliography of [p] as the set of references of all pages reachable following bibliographic links starting at [p]. The transitive bibliography of a page includes the reference of the page itself.

We define the transitive, irreflexive bibliography of a Logiweb page as the transitive bibliography with the reference of the page itself removed.

4.3.3 Loading, referencing, and verbatim copying

Logiweb is able to load Logiweb pages. Loading a Logiweb page involves a number of activities such as locating, retrieving, unpacking, and codifying the page. To display a page the system has to load and then render the page.

Loading a page is cascading in that loading a page requires loading of all pages in the transitive bibliography of the page.

A page cannot be loaded unless all pages in the transitive bibliography can be found. Hence, deleting a page from Logiweb is a serious thing since it ruins all pages that refer, directly or indirectly, to the deleted page. Fortunately, Logiweb allows duplication of pages so that a single Logiweb page may reside several places in the world. The author of a Logiweb page should secure a local copy of all pages in the transitive bibliography of the page unless the author trusts other people very much.

Referencing, indexing, and verbatim copying are core activities of Logiweb; if one does not allow referencing, indexing, and verbatim copying of a page, one should not submit it to Logiweb. In other words, the author of a page silently permits referencing, indexing, and verbatim copying by submitting it.

Authors may of course still claim copyright to a Logiweb page. That copyright may prevent other people from e.g. modifying the page, publishing the page outside Logiweb, or other activities other than the core activities of Logiweb.

4.3.4 The cache of a page

Loading a page results in the construction of a cache and a rack for the page. The cache and rack of a page represent the static semantics of the page.

The cache [c] of a page [p] is an array which maps the references in the transitive bibliography of [p] to the rack of the associated page. Hence, [c[r]] is the rack of the page referenced by [r]. In particular, the cache of a page contains the rack of the page itself.

The cache [c] of a page is an almost homogeneous array. The only exception is that [c[0]] equals the reference of the page. As a consequence, if [c] is the cache of a page then [c[c[0]]] is the rack of the page.

4.3.5 The value of the page construct

A page construct (the construct of a page whose id is zero) represents the page. As an example, the pyk and tex aspects of a page construct effectively become the name of the page expressed in pyk and TEX, respectively. The page construct is always nulary.

Evaluation of a page construct always yields the Logiweb cache of the associated page. In this way, the evaluator has a clean way to access its environment. Logiweb ignores value definitions of page constructs.

From the point of view of mathematical reasoning, page constructs are constants whose values happen to be the cache of their associated pages.

[base] is the page construct of the present page. Hence, the value of [base] is the cache of the present page.

According to Section 4.3.4, [base[0]] is the reference of the present page. If we take any construct introduced on the present page, say [7], then the reference of the root of that construct must equal [base[0]]:

[base[0] ≈ ⌈7⌉^{r}]^{·}

In section 4.5.2 we macro define [base] so that [base] macro expands to the page construct of the page on which the construct occurs. Hence, on the present page,

[base] expands to [base]. On other pages, [base] expands to the page construct of those other pages.

We could use [base] in place of [base] above. Logiweb does not care about the order of definitions, and it is completely valid to use macros before they are defined. But beware of circularities, they can lead to intractable errors.

4.3.6 The rack of a page

According to Section 4.3.4, [rack →^{val} base[base[0]]]is the rack of the present page.

The rack of a page maps various, predefined hooks to various values. The hooks of the rack are Logiweb identifiers (c.f. Section 4.1.4). At the time of writing, the rack [a] of a page has the following hooks:

• ["vector" →^{val} identifier(⌈“vector”⌉)]The vector of the page, i.e. the sequence of bytes that constitute the page when it is stored on disc or transmitted over a network. As an example, [rack["vector"]^{h}] is the first byte of the vector that represents the present page. That byte happens to be the major version number so, since the present page is encoded using Logiweb version [1] we have [rack["vector"]^{h} ≈ 1]^{·}.

• ["bibliography" →^{val} identifier(⌈“bibliography”⌉)]The bibliography of the page, i.e. a list of references where the first reference is the reference of the page itself and the other references are references of other pages. The present page is a base page in the sense that it references no other pages: [rack["bibliography"] ≈ ⌈7⌉^{r} : : T]^{·}.

• ["dictionary" →^{val} identifier(⌈“dictionary”⌉)]The dictionary of the page, i.e. an array that maps the identifiers of the symbols introduced on the page to their arities. As an example, the arity of [x : : y] is two:

[rack["dictionary"][⌈x : : y⌉^{i}] ≈ 2]^{·}

We say that a symbol exists if the dictionary of the page pointed out by the reference of the symbol maps the identifier of the symbol to a value different from [T].

• ["body" →^{val} identifier(⌈“body”⌉)]The body of the page, i.e. the term that one should typeset when viewing the page. On a base page, the root of the body necessarily comes from the page itself: [rack["body"]^{r} ≈ ⌈7⌉^{r}]^{·}.

• ["codex" →^{val} identifier(⌈“codex”⌉)]An array that contains all revelations (i.e. proclamations, definitons, and introductions) of the page as described in Section 4.3.7.

• ["expansion" →^{val} identifier(⌈“expansion”⌉)]The macro expanded version of the body of the page. The expanded version is always a syntactically valid term, i.e. a term in which all symbols exist and have correct arities as specified in the dictionaries. Logiweb ensures this syntactic validity in a roundabout way: The macro expansion facility is Turing complete and can produce any value as an output. Macro expansion may even loop indefinitely, in which case the author of the page should consider to correct the page before submitting it to Logiweb. If macro expansion does produce a value, then Logiweb checks the result for syntactical validity, and whenever it finds an invalid symbol or a symbol whose arity does not match the number of subtrees, Logiweb replaces the tree rooted at the invalid symbol with the page construct of the present page.

• ["code" →^{val} identifier(⌈“code”⌉)]An array that contains compiled versions of all value revelations of a page. With two exceptions, the compiled versions are tagged, curried functions: [U(rack["code"][⌈x : : y⌉^{i}] ‘ 2 ‘ 3) ≈ 2 : : 3]^{·}. The first exceptions is lambda abstraction which, rather arbitrarily, is represented by a zero: [rack["code"][⌈λx.y⌉^{i}] ≈ 0]^{·}. The other exception is quoting which is represented by a one: [rack["code"][⌈⌈x⌉⌉^{i}] ≈ 1]^{·}.

• ["cache" →^{val} identifier(⌈“cache”⌉)]An array which maps all references in the transitive, irreflexive bibliography of the page [p] to the caches of the associated pages. The present page is a base page in the sense that it references no other pages, so the cache that hangs on the cache hook is empty: [rack["cache"] ≈ T]^{·}. If the present page did reference a page with reference [r] then [rack["cache"][r]] would be the cache of page [r]. In that case, [base[r]] as well as [rack["cache"][r][r]] would be the rack of page [r]. In general, the racks and caches of referenced pages can be addressed several ways.

• ["diagnose" →^{val} identifier(⌈“diagnose”⌉)]If the value that hangs on the diagnose hook is [T] then the page is correct. Otherwise, the value is a term which, when typeset, is supposed to explain what is wrong with the page. In other words, the diagnose hook is where the checking machinery hangs its complaints. The diagnose is pruned to a term the same way as the expansion is. The diagnose is added after checking. During checking the value that hangs on the diagnose hook is always [T].

Constants (i.e. nulary constructs) like the ones above are computed lazily and the result is kept. For that reason, constants are computed at most once when a Logiweb page is loaded. Computation of e.g. [identifier(⌈“diagnose”⌉)] is not particularly time and memory efficient but that is irrelevant when using ["diagnose"] since it is only evaluated once.

4.3.7 The codex of a page

The codex [c] of a page is a four dimensional array that hangs on the ["codex"] hook of the rack of the page.

A page may contain revelations (i.e. proclamations, definitions, and introductions), and each revelation defines some aspect of some symbol.

If [r_{s}] and [i_{s}] are the reference and identifier, respectively, of a symbol and if [r_{a}] and [i_{a}] are the reference and identifier, respectively, of an aspect, then

[c[r_{s}][i_{s}][r_{a}][i_{a}]]

is the revelation (if any) of the given aspect of the given symbol.

If the revelation is a definition or introduction, the thing stored in the codex is the entire term that constitutes the revelation. In this case, the first argument of the definition is the aspect (with possible parameters), the second argument is the left hand side of the definition (with possible parameters), and the third argument is the right hand side. The root of the term is a symbol that is proclaimed to denote the “definition” or “introduction” concept.

If the revelation is a proclamation, the thing stored in the codex has form [0 : : i : : T : : T] where [i] where the cardinal [i] identifies the proclamation as explained in Section 4.3.12.

4.3.8 Aspects

An aspect may be predefined or user defined.

User defined aspects are introduced using a mechanism described later. The reference and identifier of a user defined aspect always identify an existing Logiweb symbol.

The reference of a predefined aspect equals zero and the identifier is a Logiweb identifier. At the time of writing, the following Logiweb identifiers denote predefined aspects:

• ["value" →^{val} identifier(⌈“value”⌉)]

• ["pyk" →^{val} identifier(⌈“pyk”⌉)]

• ["tex" →^{val} identifier(⌈“tex”⌉)]

• ["texname" →^{val} identifier(⌈“texname”⌉)]

• ["message" →^{val} identifier(⌈“message”⌉)]

• ["macro" →^{val} identifier(⌈“macro”⌉)]

• ["definition" →^{val} identifier(⌈“definition”⌉)]

• ["unpack" →^{val} identifier(⌈“unpack”⌉)]

• ["claim" →^{val} identifier(⌈“claim”⌉)]

• ["priority" →^{val} identifier(⌈“priority”⌉)]

As an example, if [c] is the codex of a page and if the page makes a value definition of a symbol with reference [r] and identifier [i] then

[c[r][i][0]["value"]]

will equal that definition.

4.3.9 Domestic and foreign definitions

If a page with reference [r] has cache [c] then e.g.

[c[r]["codex"][r_{s}][i_{s}][0]["value"]]

denotes the value aspect of the symbol with reference [r_{s}] and identifier [i_{s}] as defined on page [r].

We shall say that a definition is domestic if [r = r_{s}] and foreign otherwise. In other words, a definition is domestic if it occurs on the home page of the symbol being defined.

Logiweb ignores foreign value definitions but store them in the codex for the record. In general, Logiweb ignores foreign definitions of any predefined aspect.

One could decide that foreign definitions could shadow domestic ones in certain situations. Actually, shadowing of pyk, tex, and tex name aspects has been considered for Logiweb, but has been rejected to keep core Logiweb simple. Authors who define their own user aspects may decide if and how foreign definitions may shadow domestic ones for their aspects.

4.3.10 A codex accessor

[aspect(a, c)]looks up the the aspect [a] in the subcodex [c]. The subcodex is assumed to be the result of accessing a codex be the reference and identifier of a symbol. The subcodex is what is called a property list in Lisp [9, 11].

If [a] is a cardinal then it is interpreted as the Logiweb identifier of a predefined aspect. Otherwise, [a] is interpreted as a term whose root symbol denotes a user defined aspect.

[aspect(a, c) →^{val} a^{c} \{ \begin{matrix}c[0][a] \\ c[a^{r}][a^{i}] \end{matrix} ]

[aspect(a, t, c)]looks up the domestic definition of the root of the term [t] for the aspect [a] in the cache [c]. If [a] is a cardinal then it is interpreted as the Logiweb identifier of a predefined aspect. Otherwise, [a] is interpreted as a term whose root symbol denotes a user defined aspect.

[aspect(a, t, c) →^{val} aspect(a, c[t^{r}]["codex"][t^{r}][t^{i}])]

4.3.11 Value proclamations

Proclaiming a construct to denote “apply”, “lambda”, “true”, “if”, or “quote” affects the value aspect of the construct. For that reason we shall refer to proclamations with one of these strings in the right hand side as value proclamations.

The strings that make sense in the right hand side of proclamations form a subset of the strings that define Logiweb identifiers. The Logiweb identifiers associated to the five value proclamations are defined thus:

• ["lambda" →^{val} identifier(⌈“lambda”⌉)]

• ["apply" →^{val} identifier(⌈“apply”⌉)]

• ["true" →^{val} identifier(⌈“true”⌉)]

• ["if" →^{val} identifier(⌈“if”⌉)]

• ["quote" →^{val} identifier(⌈“quote”⌉)] 4.3.12 Codification of revelations

Logiweb codifies a definition like

[x^{H} →^{val} x ’ T]

simply by placing the entire definition in the codex:

[aspect("value", ⌈x^{H}⌉, base) =^{t} ⌈[x^{H} →^{val} x ’ T]⌉]^{·}

Having that definition, one can gain access not only to the right hand side of the definition, but also e.g. the parameter list of the left hand side. If one decides to have parameterized aspects, then one will also have access to the parameter list of the aspect in the codex.

Introductions are treated exactly the same way. An introduction like

[y ˙. . z ⇒^{val} λx.if(x, y, z)]

results in the following entry in the codex:

[aspect("value", ⌈y ˙. . z⌉, base) =^{t} ⌈[y ˙. . z ⇒^{val} λx.if(x, y, z)]⌉]^{·}

In contrast, a proclamation like

[λx.y ▷◁ “lambda”]

results in an entry like

[aspect("value", ⌈λx.y⌉, base) ≈ (0 : : "lambda" : : T)^{I} : : T]^{·}

In general, a proclamation results in an entry of form [(0 : : i : : T)^{I} : : T] where [i] is the Logiweb identifier that corresponds to the string in the right hand side of the proclamation.

4.3.13 Message proclamations

A construct denotes an aspect if the construct has a “message” aspect.

Proclaiming a construct to denote “pyk”, “tex”, “texname”, “value”, “message”, “macro”, “unpack”, “claim”, or “priority” affects the message aspect of the construct. For that reason we shall refer to proclamations with one of these strings in the right hand side as message proclamations.

The aspects mentioned above are said to be “predefined”. User defined aspects are treated later.

In addition to the predefined aspects mentioned above, Logiweb recognizes one more predefined aspect: the “definition” aspect, which is unproclaimable and which is treated in Section 4.3.14.

As an example of use,

[aspect("message", ⌈pyk⌉, base) ≈ (0 : : "pyk" : : T)^{I} : : T]^{·} 4.3.14 Definition proclamation

A construct denotes a revelation if the construct has a “definition” aspect.

Proclaiming a construct to denote “proclaim”, “define”, “introduce”, or “hide” affects the revelation aspect of the construct. For that reason we shall refer to proclamations with one of these strings in the right hand side as definition proclamations. The Logiweb identifiers associated to the definition proclamations are defined thus:

• ["proclaim" →^{val} identifier(⌈“proclaim”⌉)]

• ["define" →^{val} identifier(⌈“define”⌉)]

• ["introduce" →^{val} identifier(⌈“introduce”⌉)]

• ["hide" →^{val} identifier(⌈“hide”⌉)]

Constructs proclaimed to “hide” disable all proclamations in their subtrees to have effect as described in Section 4.5.3.

As an example of use of the definitions aspect we have

[aspect("definition", ⌈[x^{H} →^{val} x ’ T]⌉, base) ≈ (0 : : "define" : : T)^{I} : : T]^{·}

4.3.15 Priority proclamations

Proclaiming a construct to denote “pre” or “post” affects the priority aspect of the construct. For that reason we shall refer to proclamations with one of these strings in the right hand side as priority proclamations. The Logiweb identifiers associated to the priority proclamations are defined thus:

• ["pre" →^{val} identifier(⌈“pre”⌉)]

• ["post" →^{val} identifier(⌈“post”⌉)]

As an example,

[aspect("priority", ⌈ Preassociative x; y⌉, base) ≈ (0 : : "pre" : : T)^{I} : : T]^{·}

4.3.16 The code of a page

The code of a page is a one-dimensional array that hangs on the ["code"] hook of the rack of the page.

If [c] is the cache of a page and [r] belongs to the transitive bibliography of the page, then

[c[r]["code"][i]] is a tagged, Curried version of

[c[r]["codex"][r][i][0]["value"]]

As an example, if [r] and [i] are the reference and identifier, respectively, of the [x : : y] construct, then

[c[r]["code"][i] = M(λx.λy.x : : y)]

The first edition engine performs compilation backstage so that the code of a page contains a compiled versions of the value aspects of the codex.

If [r] and [i] are the reference and identifier, respectively, of a symbol that is proclaimed to denote lambda abstraction, then [c[r]["code"][i] = 0]. If [r] and [i] are the reference and identifier, respectively, of a symbol that is proclaimed to denote quoting, then [c[r]["code"][i] = 1].

4.4 Macro expansion

4.4.1 A self interpreter

Before we can define a macro expander we need a self interpreter. We define a self interpreter in the following.

The result of evaluating a term is a map, but the evaluator returns a semitagged map for efficiency reasons. To get the map itself one has to untag the return value.

The self interpreter [E(t, s, c)] evaluates the term [t] for the stack [s] and the cache [c] and returns the result as a semitagged map. [U(E(t, s, c))] is the map itself.

The self interpreter computes the reference [t^{r}] and identifier [t^{i}] of the root of the term and passes control to an auxiliary function:

[E(t, s, c) →^{val} E_{2}(t, t^{r}, t^{i}, s, c)]

[E_{2}(t, r, i, s, c)] evaluates the term [t] whose root symbol has reference [r] and identifier [i] for the stack [s] and the cache [c]. If the root symbol is a page symbol, it returns the associated cache. Otherwise, it looks up the code of the root symbol:

[E_{2}(t, r, i, s, c) →^{val} i^{s} \{ \begin{matrix}t!s!If(r ≈ c[0], c, c[c[0]]["cache"][r]) \\ E_{3}(t, c[r]["code"][i], s, c) \end{matrix} ]

[E_{3}(t, f, s, c)] evaluates the term [t] whose root symbol has code [f] for the stack [s] and the cache [c]. If the code equals [T] then the root symbol has no value definition and, hence, the term [t] is treated a variable. If the code equals zero then the root symbol denotes lambda abstraction and is treated accordingly. If the code equals one then the root symbol denotes the quote construct and is treated accordingly. Otherwise, the code is a tagged, Curried function to be applied to the argument list [t^{t}] of the term [t]:

[E_{3}(t, f, s, c) →^{val} f^{c} \{ \begin{matrix}f^{s} \{ \begin{matrix}abstract(t^{1}, t^{2}, s, c) \\ c!s!t^{1} \end{matrix} \\ f \{ \begin{matrix}c!lookup(t, s, T) \\ E_{4}(f, t^{t}, s, c) \end{matrix} \end{matrix} ]

[E_{4}(f, a, s, c)] applies the function [f] to the arguments [a] evaluated for the stack [s] and the cache [c]:

[E_{4}(f, a, s, c) →^{val} If(a, s!c!f, E_{4}(apply(f, E(a^{h}, s, c)), a^{t}, s, c))]

[abstract(v, t, s, c)] abstracts the variable [v] in the term [t] for the stack [s] and the cache [c]:

[abstract(v, t, s, c) →^{val} v!t!s!c!Λλx.E(t, (v : : x)^{M} : : s, c)]

4.4.2 A macro expander

Macro definitions are based on definitions of the macro aspect of symbols. Definitions of macro aspects will be referred to as macro definitions. Other kinds of definitions treated so far include value, pyk, TEX, and priority definitions. To make macro definitions we must proclaim [macro] to denote the macro aspect:

[macro ▷◁ “macro”]

The macro expander [M(t, s, c)] macro expands the term [t] for the macro state [s] and the cache [c] and returns the result as a semitagged map. The untagged version [U(M(t, s, c))] is the expansion itself.

As we shall see, macros typically use the macro state to define what should happen after one macro expansion. The initial macro state defined in Section 4.4.3 just specifies that the macro expander should be reinvoked which ensures that macro expansion proceeds until all macros are expanded. But macros may decide not to reinvoke the macro expander. Or they may decide to reinvoke it but with a modified macro state. Or they may decide to invoke an entirely different macro expander.

If the term to be expanded is a page construct, the macro expander returns the term unchanged (page constructs should not be macro expanded for reasons explained later). Otherwise, the macro expander looks up the macro definition of the root of the term and passes control to an auxiliary function:

[M(t, s, c) →^{val} s!c!If(t^{i}^{s}, t, M_{2}(t, aspect("macro", t, c), s, c))]

[M_{2}(t, d, s, c)] macro expands the term [t] whose root symbol has macro definition [d] for the macro state [s] and the cache [c]. If the macro definition equals [T] then the root symbol has no macro definition. In this case, the subterms of the term are macro expanded. Otherwise, [M_{2}(t, d, s, c)] evaluates the right hand side [d^{3}] of the definition (for completeness: [d^{0}] is a symbol that denotes the “definition” concept, [d^{1}] is a term that represents the macro aspect, [d^{2}] is the left hand side and [d^{3}] is the right hand side of the definition). Finally, the evaluated right hand side is applied to the term [t], the macro state [s], and the cache [c] so that the user defined macro [d] gets access to term, state, and cache (at expansion time, the cache will be the cache of the page on which the term being macro expanded resides).

[M_{2}(t, d, s, c) →^{val} d \{ \begin{matrix}t^{h} : : M^{∗}(t^{t}, s, c) \\ U^{M}(E(d^{3}, T, c) ‘ t ‘ s ‘ c) \end{matrix} ]

The [M^{∗}(a, s, c)] construct macro expands the elements of the list [a].

[M^{∗}(a, s, c) →^{val} s!c!If(a, T, M(a^{h}, s, c) : : M^{∗}(a^{t}, s, c))]

4.4.3 The initial macro state

The initial macro state [s_{0}] is useful for passing as the second parameter to [M(t, s, c)]. [s_{0}] is a pair whose head is the macro expander itself and whose tail is left blank. The definition of [s_{0}] reads:

[s_{0} →^{val} M(λt.λs.λc.M(t, s, c)) : : T]

In the definition of [s_{0}] note that the first M is a unary “map tag” operation that converts the lambda abstraction into a tagged map whereas the second M is the ternary macro expansion operation.

Advanced users may write macros that pass down a macro state different from [s_{0}]. Such users should pass down a macro state of form [m : : p] where [m] is a ternary macro expander and [p] is a parameter that can contain arbitrary data. The default macro expander [M(t, s, c)] makes no use of the parameter and for that reason the parameter is set to [T] in [s_{0}].

4.4.4 Pruning

In connection with macro expansion, Logiweb uses a hardwired retract on Gödel trees which we shall refer to as pruning.

Given the cache of a page and an arbitrary data structure, the pruning operation scans the data structure as if it were a Gödel tree. Whenever the pruning operation encounters a branch that cannot be a Gödel tree, it replaces the branch by the page construct of the given page.

The pruning operation first applies the retract for tagged trees to the given data structure. Then, for each branch of the Gödel tree, it checks that the reference and identifier are cardinals. Then it looks up the arity of the associated symbol in the proper dictionary inside the cache of the given page. If no arity is found, the symbol is invalid and the branch is pruned. Otherwise, the pruning operation checks that the number of subtrees agree with the arity and descend recursively into the subtrees.

If no arity is found for a given symbol it either means that the symbol does not exist on Logiweb or that it exists, but not on a page transitively referenced by the given page.

4.4.5 Potentially inherited page aspects

Macro expansion of a page is governed by the “potentially inherited macro aspect” of the page. The potentially inherited macro aspect is an example of a potentially inherited page aspect. Let us take “potentially inherited page aspect” one word at a time.

Aspects of the page construct of a page are “page aspects” for that page. An “inherited page aspect” of a page [p] is a page aspect of the page bed [b] of

page [p]. The bed [b] of a page [p] is the first page referenced in the bibliography of page [p]. If page [p] is a base page, i.e. if page [p] references no other pages, then the bed of page [p] is page [p] itself. The bed [b] of a page [p] is the page on which page [p] rests.

Note for programmers: The first entry of the bibliography of a page is the one that comes after the zeroth entry. The zeroth entry references the page itself. A bibliography is a list of references, and the head of the list is the zeroth entry.

But back to “potentially inherited page aspects”. A potentially inherited page aspect of a page [p] is taken from the page construct of [p] if that aspect is available, and is taken from the page construct of the bed of [p] otherwise. As an example, the potentially inherited macro aspect of page [p] is the macro aspect of the page construct of page [p] if such an aspect is defined, and else the macro aspect of the page construct of the bed of [p] if such an aspect is defined.

At the time of writing, Logiweb makes use of two potentially inherited page aspects: the macro aspect described in the following, and the claim aspect described in Section 5. At a later stage, Logiweb will also make use of a potentially inherited value aspect which defines things to be computed once and for all when pages are loaded and an unconditionally inherited unpack aspect which may decompress and/or decrypt Logiweb vectors when loaded.

4.4.6 Installing the macro expander

We shall refer to the Gödel tree that constitutes the macro expanded version of a page as the expansion of the page. We define the expander of a page to be the potentially inherited macro aspect of the page.

Logiweb expands a page by applying the expander to the body and cache of the page. If no expander is defined then Logiweb does no macro expansion and uses the body unchanged as expansion.

Now define

[base →^{macro} λt.λc.M(t, s_{0}, c)]

Because of the definition above, the expansion of the present page is the pruned version of [M(t, s_{0}, c)] where [t] and [c] are the body and cache, respectively, of the page.

Another page that uses the present page as bed and defines no expander of its own also has expansion [M(t, s_{0}, c)] but then [t] and [c] are the body and cache, respectively, of that other page.

Recall that the macro expander [M(t, s, c)] does not macro expand page constructs. One reason for that is that the macro aspect of the page construct defines an expander rather than a macro.

4.4.7 Iterated macro expansion

The description of macro expansion above is part of the story rather than the whole story.

As descripted in Section 2.1.1, Logiweb “loads” a page by “resolving” its reference into a Uniform Resource Locator, then “retrieves” the page as a vector of bytes, then “unpacks” the vector into bibliography, dictionary, and body, then “codifies” the page into codex and expansion, and finally “verifies” the page.

Codification comprises macro expansion and “harvesting”. Harvesting is done by scanning the expansion of a page for revelations, i.e. proclamations, definitions, and introductions. The process of harvesting converts the expansion, which is a Gödel tree, into a codex.

Codification proceeds thus: First, with the exception stated in Section 2.1.5, Logiweb sets the codex of the page to be empty. Then Logiweb macro expands the body of the page using the empty codex for the page in question plus all the codicies of referenced pages. Then Logiweb sets the codex of the page to the result of harvesting the expansion, and then Logiweb macro expands the body of the page once more. Logiweb proceeds this way until the codex does not change anymore (if ever). This is what was meant by “reading the page over and over again” in Section 2.1.1 and 2.1.5.

4.5 Macro definitions

4.5.1 Protection

[x] is a particularly important macro; it protects its argument against macro expansion. During macro expansion, the protection construct itself disappears. The definition of protection is not completely trivial:

[(x)^{p} →^{macro} λt.λs.λc.t^{1}]

Note that the definition has two occurrences of the protection construct: an outermost and an innermost.

At first reading of the page, no expander has been defined yet, the definition construct has not yet been proclaimed, and Logiweb has not yet understood what the protection construct is supposed to do.

After a couple of readings, Logiweb has still not understood what the protection construct is supposed to do, but has reached a level where it can understand that the formula above defines the macro aspect of the protection construct.

At the next reading of the page, the protection construct is operational, and for that reason, the outermost protection construct protects the innermost protection construct from macro expansion. Without the outermost protection construct, the innermost protection construct would disappear so that it was [x] that was macro defined to denote protection, which leads to disaster.

It should be noted that base pages as large as the present one are not particularly easy to write. There are many things that can go wrong in intractable ways. Authors who insist on writing their own base page are encouraged to build them up in small steps, starting with a base page as simple as possible.

4.5.2 Self references

We macro define [base] such that each instance of [base] expands to the page construct of the page on which the instance occurs.

[self →^{macro} λt.λs.λc.(c[0] : : 0 : : t^{d})^{I} : : T]

Alternatively, one could define [base] to expand into an invalid tree and let pruning insert a page construct. As an example, one could replace the entire right hand side above by [T]. But the definition above ensures that resulting page sysmbol enherits the debugging information present in the [base] construct.

4.5.3 Avoid macro expansion and harvesting of strings

Good Logiweb pages contain loads of text. Actually, the formal mathematics present on well written Logiweb pages only constitute a minor fraction of the page. Since macro expansion takes time, we arrange that strings are not macro expanded.

The pyk compiler puts a unicode start and end of text construct at the root and leaf of strings, respectively, with the individual characters of the string in between as a row of perls (or, rather, a column of perls; in the string itself, the characters are like a row of perls). We can protect strings against macro expansion by a proper definition of the macro aspect of the unicode start of text construct:

[“x” →^{macro} λt.λs.λc.t]

Once Logiweb has expanded the body of a page, it does harvesting of definitions: it scans the expansion and collects all definitions found. To avoid spending time on harvesting inside strings, we proclaim the unicode start of text construct to protect against harvesting:

[“x” ▷◁ “hide”]

4.5.4 Macro definitions

[x ¨= y] defines [x] as shorthand for [y]. Hence, [x ¨= y] makes ordinary macro definitions. The definition of [x ¨= y] is slightly involved since [x ¨= y] is defined such that it macro expands into a general macro definition.

[[x ¨= y] →^{macro} λt.λs.λc.M̃_{3}(t)]

[M̃(t, s, c)] macro expands the term [t] using the macro expander embedded in the macro state [s] using the cache [c].

[M̃(t, s, c) →^{val} U(s^{h} ‘ t ‘ s ‘ c)]

[M̃_{1}] is a template that defines what [x ¨= y] expands into:

[M̃_{1} →^{val} ⌈[x →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈d⌉)]⌉]

If [t] is a term of form [x ¨= y] then [M̃_{2}(t)] is a stack that maps the variable [x] to the left hand side of the macro definition and maps the variable [d] to the entire macro definition.

[M̃_{2}(t) →^{val} (⌈x⌉ : : t^{1})^{M} : : (⌈d⌉ : : t)^{M} : : T]

[M̃_{3}(t)] translates a term [t] of form [x ¨= y] into a general macro definition. This is done by replacing [x] and [d] in the template [M̃_{1}] by the left hand side of [t] and all of [t], respectively.

[M̃_{3}(t) →^{val} Q̃(t, M̃_{1}, M̃_{2}(t))]

[M̃_{4}(t, s, c, d)] performs the macro expansion defined by [x ¨= y]. The function above macro expands [x ¨= y]. The function below expands the macro defined by [x ¨= y].

[M̃_{4}(t, s, c, d) →^{val} M̃(Q̃(t, d^{2}, zip(d^{1}^{t}, t^{t})), s, c)]

[Q̃(r, t, s)] performs the substitutions defined by the stack [s] in the term [t]. Set the debugging information of all nodes taken from [t] to the debugging information of the root of the term [r].

[Q̃(r, t, s) →^{val} Q̃_{2}(r^{d}, t, s)]

[Q̃_{2}(r, t, s)] performs the substitutions defined by the stack [s] in the term [t]. Set the debugging information of all nodes taken from [t] to the debugging information [r].

[Q̃_{2}(r, t, s) →^{val} Q̃_{3}(r, t, s, lookup(t, s, T))]

[Q̃_{3}(r, t, s, v)] performs the substitutions defined by the stack [s] in the term [t]. Set the debugging information of all nodes taken from [t] to the debugging information [r]. If [v] differs from [T] then [t] is supposed to occur in [s] and [v] is supposed to be the associated value. Hence, if [v] differs from [T] then [v] is returned. Otherwise, the root of [t] is merged properly with the debugging information [r] and substitutions are performed in all subterms of [t].

[Q̃_{3}(r, t, s, v) →^{val} v \{ \begin{matrix}(t^{r} : : t^{i} : : r)^{M} : : Q̃^{∗}(r, t^{t}, s) \\ r!t!s!v \end{matrix} ]

[Q̃^{∗}(r, t, s)] performs the substitutions defined by the stack [s] in the list [t] of terms. Set the debugging information of all nodes taken from [t] to the debugging information [r].

[Q̃^{∗}(r, t, s) →^{val} t \{ \begin{matrix}r!t!s!T \\ Q̃_{2}(r, t^{h}, s) : : Q̃^{∗}(r, t^{t}, s) \end{matrix} ]

4.5.5 Parentheses

[x] is probably the most important among all macros, at least from the point of view of the working mathematician. Parentheses simply disappear when macro expanded:

[(x) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[(x) ¨= x]⌉)]

The following construct uses \left(...\right) to render parentheses. Beware that the construct disables line breaking.

[(x) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[(x) ¨= x]⌉)][(x) →^{tex} “
\left( #1.
\right) ”]

4.6 Tagged lambda

The following macro definition allows to state tagged lambdas in a readable way:

[Λx.y →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Λx.y ¨= Λλx.y]⌉)][Λx.y →^{tex} “
\Lambda #1.
. #2.”]

4.6.1 Local abbreviations

The following construct allows to override macros locally:

[let x ¨= y in z →^{macro} λt.λs.λc.
M̃(t^{3}, s, c[t^{1}^{r} : : "codex" : : t^{1}^{r} : : t^{1}^{i} : : 0 : : "macro" : : T⇒M̃_{3}(t)])]

As a somewhat constructed example of use,

[3 : : 3]

macro expands to

[3 : : 3]

4.6.2 Other kinds of definitions

The following constructs allow to define particular aspects of a left hand side to be the given right hand side.

The following construct is useful for value definitions.

[[x ˙= y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x ˙= y] ¨= [(x)^{p} →^{val} y]]⌉)]

Use of the construct above for value definitions on which the definition of the macro expander depends may lead to intractable errors. For that reason, the present page is organised such that the construct above is only used from Section 5 and on and such that the macro expander only depends on definitions stated before 5. Logiweb does not care about the order of definitions. The avoidance of vicious circles by dividing at the start of Section 5 is just for the sake of the author.

The following construct is suitable for value introductions, i.e. for value definitions of constructs for which the Logiweb system in use is expected to contain a hardcoded version. As with the value definition, it is not used before Section 5.

[[x ´= y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x ´= y] ¨= [(x)^{p} ⇒^{val} y]]⌉)]

The following constructs are convenient for defining [pyk], [tex], and [name] definitions. The constructs protect the left hand side against macro expansion and ensures that the right hand side is typeset as a string. The three constructs below are used uncritically on the present page since rendering is done after codification and, hence, cannot interfere with codification.

[[x =^{pyk} y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x =^{pyk} y] ¨= [(x)^{p} →^{pyk} y]]⌉)]
[[x =^{tex} y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x =^{tex} y] ¨= [(x)^{p} →^{tex} y]]⌉)]
[[x =^{name} y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x =^{name} y] ¨= [(x)^{p} →^{name} y]]⌉)]

Finally, the following construct is convenient for defining priority tables.

[Priority table[x] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Priority table[x] ¨= [self →^{prio}

(x)^{p}]]⌉)]

4.6.3 Tuples

We shall use [x : : T] and [x, y] to express tuples. [x : : T] will be macro defined such that e.g. [x : : y : : z : : T] macro expands into [x : : y : : z : : T].

[⟨x⟩ →^{macro} λt.λs.λc.M̃(tuple_{1}(t), s, c)]

[tuple_{1}(t)] expands the root of [x : : T]:

[tuple_{1}(t) →^{val} t^{1} =^{r} ⌈x, y⌉ \{ \begin{matrix}Q̃(t, ⌈x : : ⟨y⟩⌉, tuple_{2}(t^{1})) \\ Q̃(t, ⌈x : : T⌉, ⌈x⌉ : : t^{1} : : T) \end{matrix} ]

[tuple_{2}(t)] forms the stack used when expanding [x : : y : : T]:

[tuple_{2}(t) →^{val} ⌈x⌉ : : t^{1} : : ⌈y⌉ : : t^{2} : : T]

4.6.4 Typography of the expansion

The author of a Logiweb page should ensure that the tex aspect of the body looks good when typeset by TEX. Among other, the author should avoid overfull and underfull TEX boxes in the body.

When it comes to the expansion of the page, matters are a bit different. Firstly, the aesthetics of the expansion is less important since the expansion does not address the audience to the same degree as the body does. Secondly, precise control of the typography of the expansion is more intricate.

For these reasons it is convenient to typeset the expansion in a ragged right style. To do so we first introduce a contruct [ragged right]which produces a \raggedright command when typeset using its tex aspect.

Second, we introduce a construct which is invisible when typeset using its tex aspect but which macro expands into the construct above:

[ragged right expansion →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[ragged right expansion ¨= ragged right]⌉)]

Including the latter construct above near the start of a Logiweb page, the expansion of the page will be typeset ragged right without affecting the supposedly splendid typography the body.

4.7 Programming aids

4.7.1 Newlines in definitions

Traditional mathematical formulas typically fit on a single line. Formally, a computer program is nothing but a mathematical formula, but computer programs have a tendency to span more than one line. This is so even if one breaks up a computer program in individual definitions of computable functions and consider each definition at a time.

For the sake of readablity, it is often convenient to control where line breaks occur in definitions of computable functions. To allow such control we introduce a newline construct whose tex name aspect is “newline” but whose tex aspect simply forces the formula following it to begin on a new line.

The newline construct is prefix and should be put in front of the formula to begin a new line.

[newline x →^{val} x^{M}]

The newline construct is value defined such that it retracts which allows it to occur in functions that are fit for optimization.

The newline construct can be value or macro defined. Above, it has been value defined so that it also affects the typography of the expansion of the page. That is convenient for debugging. In formal reasoning about a computable function it is more convenient to have a newline construct that macro expands to nothingness:

[macro newline x →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[macro newline x ¨= x]⌉)]

4.7.2 The visibility operator

We now introduce a visibility operator [(x)^{v} →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[(x)^{v} ¨= x]⌉)]which forces its argument to be typeset using the tex name aspect and which macro expands to nothingness like parentheses do. The construct is useful in situations where e.g. the right hand side of a definition contains operators whose tex aspect make them invisible.

When typeset in the tex aspect, the visibility operator does not exhibit itself, it just affects how its argument is typeset. When typeset in the tex name aspect, the visibility operator reads [x].

The bracket [x] contains two visibility operators. The outermost operator makes the innermost visible.

The visibility operator [x] is almost identical to the text operator [x]. The difference is that the visibility operator macro expands into nothingness whereas the text operator is value defined such that it is self-evaluating.

The bracket [x] contains a visibility and a text operator. The visibility operator makes the text operator visible.

4.7.3 Self-evaluation

The juxtaposition operator [xy] has a tex name aspect that reads [xy] and a tex aspect that reads [xy]. The tex aspect of the juxtaposition operator allows to put two typographic entities back-to-back. In the following we silently use the [x] operator to make juxtaposition visible.

We make juxtaposition self-evaluating:

[x , y →^{val} ⌈∗∗⌉^{R} : : x : : y : : T]

The definition above has the effect that e.g. [⌈xy⌉] denotes the same term as [⌈x⌉⌈y⌉] except for debugging information present in the terms. The root of the latter is “clean” in the sense that its debugging information equals [T].

We also make the “text” construct self-evaluating:

[(x)^{t} →^{val} ⌈∗⌉^{R} : : x : : T]

4.7.4 Open if

The open if construct is defined thus:

[if x then y else z →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[if x then y else z ¨= If(x, y,

z)]⌉)]

The open if construct is useful when writing programs with long chains of ifconstructs.

4.7.5 The “let” construct

We define eager, retracting functional application [let_{1}(f, y)] and the let construct [let_{1}(λx.z, y)] as follows:

[let x = y in z →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[let x = y in z ¨= let_{1}(λx.z, y)]⌉)]

[let_{1}(f, y) ⇒^{val} let_{2}(f, y^{M})^{M}]
[let_{2}(f, y) →^{val} (y!f ’ y)^{I}]

The initial Logiweb engine translates all terms of form [let_{1}(λx.z, y)] to an efficient let-construct internally.

4.7.6 Macro defined connectives

The connectives [If(x, y, F)], [If(x, T, y)], and [If(x, y, T)] macro expand into constructs that only compute [y] when needed. Furthermore, the constructs return the value of [y] whenever [y] is computed.

Such a left-to-right computing behaviour can also be achieved using lazy constructs, but the macro defined connectives above have the benefit that, when used with caution, they can occur in definitions that are fit for optimization.

[x ¨∧ y →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[x ¨∧ y ¨= If(x, y, F)]⌉)]
[x ¨∨ y →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[x ¨∨ y ¨= If(x, T, y)]⌉)]
[x ¨⇒ y →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[x ¨⇒ y ¨= If(x, y, T)]⌉)]

4.7.7 Display construct

[display(x)][display(x) →^{tex} “

\addvspace{\abovedisplayskip}

\setlength{\leftskip}{\mathindent}\noindent #1. \everypar{\setlength{\parindent}{\docparindent}} \setlength{\parindent}{0mm}

\setlength{\leftskip}{0mm} \addvspace{\belowdisplayskip}

”][display(x) →^{name} “ display(#1. )”] typesets its argument as a paragraph whose left margin equals the indentation of a displayed equation. Space is added before and after the paragraph and the first paragraph after a display is unindented.

[statement(x)][statement(x) →^{tex} “

\addvspace{\abovedisplayskip}

\setlength{\leftskip}{0mm}\noindent #1. \everypar{\setlength{\parindent}{\docparindent}} \setlength{\parindent}{0mm}

\setlength{\leftskip}{0mm} \addvspace{\belowdisplayskip}

”][statement(x) →^{name} “ statement(#1. )”] does the same except that the left margin flushes the left margin of the document.

4.7.8 Introduction of new constructs

The following constructs allow to introduce a new construct (“introduce” in the normal sense of the word, not in the sense of a Logiweb revelation). The constructs allow to define the pyk aspect [p] and tex aspect [t] of a new construct [x] and also makes two entries in the index. The first of the constructs below adds the text [i] in front of one of the index entries.

[intro(x, i, p, t) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[intro(x, i, p, t) ¨= $[x =^{tex} t]$ ]⌉)]

[intro(x, p, t) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[intro(x, p, t) ¨= $[x =^{tex} t]$ ]⌉)]

4.7.9 Further intro constructs

The following four constructs all help introducing new constructs. Each of them expand into pyk and tex and, optionally, tex name definitions. But they also render the pyk definition as a footnote, defer the tex and tex name definitions to an appendix, and make two entries in the index. One of the entries has form “pyk: (pyk name) (tex rendering)”. The other entry has form “(index): (tex rendering) (pyk name)”. If no index is given, then the latter entry has form “(tex rendering) (pyk name)” and is placed in front of other entries in the index. The four constructs are defined thus:

[x/intro(y, p, t) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[x/intro(y, p, t) ¨= x $[y =^{tex} t]$ ]⌉)][x/intro(y, p, t) →^{tex} “#1.% \footnote{$[#2/tex name/tex. \stackrel {\mathrm {pyk}}{=} #3/tex name. ]$}\index{\alpha #3. @\back \makebox[20mm][l]{$[#2/tex name/tex.]$}#3.}% \index{pyk: #3. $[#2/tex name/tex.]$}% \tex{ $[#2/tex name/tex. \stackrel {\mathrm {tex}}{=} #4/tex name. ]$}”][x/intro(y, p, t) →^{name} “#1. /intro(#2. , #3. , #4. )”]

[x/indexintro(y, i, p, t) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[x/indexintro(y, i, p, t) ¨= x $[y =^{tex} t]$ ]⌉)][x/indexintro(y, i, p, t) →^{tex} “#1.% \footnote{$[#2/tex name/tex. \stackrel {\mathrm {pyk}}{=} #4/tex name. ]$}\index{#3.: #4. @#3.: $[#2/tex name/tex.]$ #4.}% \index{pyk: #4. $[#2/tex name/tex.]$}% \tex{ $[#2/tex name/tex. \stackrel {\mathrm {tex}}{=} #5/tex name. ]$}”][x/indexintro(y, i, p, t) →^{name} “#1. /indexintro(#2. , #3. , #4. , #5. )”]

[x/nameintro(y, p, t, n) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[x/nameintro(y, p, t, n) ¨= x $[y =^{tex} t]$ $[y =^{name} n]$ ]⌉)][x/nameintro(y, p, t, n) →^{tex} “#1.% \footnote{$[#2/tex name/tex. \stackrel {\mathrm {pyk}}{=} #3/tex name. ]$}\index{\alpha #3. @\back \makebox[20mm][l]{$[#2/tex name/tex.]$}#3.}% \index{pyk: #3. $[#2/tex name/tex.]$}% \tex{ $[#2/tex name/tex. \stackrel {\mathrm {tex}}{=} #4/tex name. ]$} \tex{ $[#2/tex name/tex. \stackrel {\mathrm {name}}{=} #5/tex name. ]$}”][x/nameintro(y, p, t, n) →^{name} “#1. /nameintro(#2. , #3. , #4. , #5. )”]

[x/bothintro(y, i, p, t, n) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[x/bothintro(y, i, p, t, n) ¨= x $[y =^{tex} t]$ $[y =^{name} n]$ ]⌉)][x/bothintro(y, i, p, t, n) →^{tex} “#1.% \footnote{$[#2/tex name/tex. \stackrel {\mathrm {pyk}}{=} #4/tex name. ]$}\index{#3.: #4. @#3.: $[#2/tex name/tex.]$ #4.}% \index{pyk: #4. $[#2/tex name/tex.]$}% \tex{ $[#2/tex name/tex. \stackrel {\mathrm {tex}}{=} #5/tex name. ]$} \tex{ $[#2/tex name/tex. \stackrel {\mathrm {name}}{=} #6/tex name. ]$}”][x/bothintro(y, i, p, t, n) →^{name} “#1. /bothintro(#2. , #3. , #4. , #5. , #6. )”]

5 Claims

5.1 The claim aspect

We define the claim of a page to be the potentially inherited claim aspect of the page (c.f. 4.4.5). Logiweb checks the correctness of a Logiweb page by applying the claim of the page to the expansion and cache of the page. If the result is [T] then the page is considered correct.

If the page has no potentially inherited claim aspect then the page is said to make no claim and is considered trivially correct.

We shall refer to the result of applying the claim of a page to the expansion and cache of the page as the correctness of the page. The correctness equals [T] for pages that are correct, including pages that are trivially correct.

Pages are in error if their correctness differs from [T]. In that case Logiweb prunes the correctness (c.f. Section 4.4.4) and hangs the result on the diagnose hook (c.f. Section 4.3.6) of the page.

The proclaimation of the “claim” aspect reads:

[claim ▷◁ “claim”]

For convenience, we define a construct for making claim definitions:

[[x =^{claim} y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x =^{claim} y] ¨= [x →^{claim} y]]⌉)]

5.2 Conjunction of claims

Logiweb merely allows a page to make one claim. But that claim can be arbitrarily complex. As we shall see, the claim of the present page is the conjuctions of a “checker” and a “verifier”.

The “checker” scans the expansion of the page for tests like [F +2∗ 3 ≈ 7]^{·} and checks the correctness of them all. In contrast, the “verifier” scans the codex for proofs and verifies all proofs found.

Claims may be combined into a conjunction using [x ∧_{c} y]:

[x ˜∧ y →^{val} if(x, y, x)]

[x ∧_{c} y →^{val} λt.λc.x ’ t ’ c ˜∧ y ’ t ’ c]

5.3 The checker

The checker checks the correctness of all test statements on a page:

[checker →^{val} λt.λc.check(t, c)]

The construct [check(t, c)] allows to check that all claims in the term [t] evaluate to [T].

If some claim is false then [check(t, c)] returns the value of the first false claim found. Such a non-nil value is a Logiweb diagnose. To be useful, a diagnose should be a Gödel tree that can be typeset and which gives a clue what went wrong.

[check(t, c)] skips all page constructs when checking [t].

[check(t, c) →^{val} If(t^{i}^{s}, c!T, check_{2}(t, c, aspect("claim", t, c)))]

The construct [check_{2}(t, c, d)] allows to check that all claims in [t] evaluate to [T] where [d] is the definition of the claim aspect of the root of [t].

[check_{2}(t, c, d) →^{val} d \{ \begin{matrix}check_{3}(t, c, aspect("definition", t, c)) \\ U^{M}(E(d^{3}, T, c) ‘ t ‘ c) \end{matrix} ]

The construct [check_{3}(t, c, d)] allows to check that all claims in [t] evaluate to [T]. [check_{3}(t, c, d)] does not descend into trees whose root has a definition aspect [d]. For that reason, checking does not occur inside definitions, introductions, proclamations, and trees with a “hide” construct in its root. In particular, no checking is done inside strings since strings have a “hide” construct in their root. This saves a lot of cpu-time. Furthermore, no checking is done inside definitions. This is convenient since otherwise one could not pyk, TEX, macro, and priority define test constructs (c.f. Section 5.5 ff) without getting spurious errors from the occurrences of the test constructs inside the definitions of the test constructs themselves.

[check_{3}(t, c, d) →^{val} If(d, check^{∗}(t^{t}, c), t!c!T)]

The construct [check^{∗}(t, c)] allows to check that all claims in the list [t] of terms evaluate to [T].

[check^{∗}(t, c) →^{val} If(t, c!T, check_{2}^{∗}(t^{t}, c, check(t^{h}, c)))]

The construct [check_{2}^{∗}(t, c, v)] also allows to check that all claims in the list [t] of terms evaluate to [T] except that it returns [v] if [v] is false.

[check_{2}^{∗}(t, c, v) →^{val} If(¬v, t!c!v, check^{∗}(t, c))]

5.4 Installing the checker

We now define

[base →^{claim} checker ∧_{c} verifier]

Because of the definition above, the present page claims that [check(t, c)] is true where [t] and [c] are the expansion and cache, respectively, of the present page (the claim above also invokes [verifier] which is defined later).

Another page that uses the present page as bed and makes no claim of its own also claims that [check(t, c)] is true but then [t] and [c] are the expansion and cache, respectively, of that other page.

5.5 Test for truth

The construct [t]^{·} allows to claim that a term [t] evaluates to [T].

[[t]^{·} →^{claim} λt.λc.if(U(E(t^{1}, T, c)), T, t)]

As an example, one may claim that [F +2∗ 3] equals seven:

[F +2∗ 3 ≈ 7]^{·}

[\underline{a}]^{·} returns the Gödel tree of [\underline{a}]^{·} as the diagnose if the claim fails. The overall claim defined in Section 5.4 returns the value of the first failing claim (if any). Hence, if [F +2∗ 3 ≈ 7]^{·} failed and was the first failing claim found, then the value of the claim of the page would be the Gödel tree of [F +2∗ 3 ≈ 7]^{·}. Reasonable Logiweb compilers typeset the diagnose so that the failing claim is easy to identify.

Note that macro expansion occurs before checking, so the Gödel tree of a failing claim is the macro expanded version of the claim. The macro expansion facility defined on the present page, however, carefully carries debugging information around when macro expanding, so the debugging information in the root of the expanded Gödel tree indicates the exact location of the failing claim in the unexpanded page.

Note that [t]^{·} does not fail; all unbound variables evaluate to [T].

5.6 Test for falsehood

The construct

[[x]^{−} →^{claim} λt.λc.if(U(E(t^{1}, T, c)), t, T)]

tests that its argument is false. As an example of use, one may claim that [2 ≈ 3] is false:

[2 ≈ 3]^{−}

5.7 Raw test

Like [t]^{·}, the construct [t]^{∘} allows to claim that a term [t] evaluates to [T]. Contrary to [x]^{·}, [x]^{∘} just returns the value of [x]. This is useful for constructs that generate their own error messages.

[[t]^{∘} →^{claim} λt.λc.U(E(t^{1}, T, c))]

5.8 Spy construct

[x spy y ⇒^{val} x!y][x spy y →^{tex} “#1. \mathrel{spy}#2.”] evaluates [x], discards the value, evaluates [y], and returns the value of [y]. However, behind the scene, [x spy y] also stores the value of [x] in the Lisp variable *spy*.

[[x]^{·} →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x]^{·} ¨= [⌈x⌉ spy x]^{·}]⌉)][[x]^{·} →^{tex} “ [#1. ]ˆ {\cdot}”] is exactly like an ordinary test except that it calls the spy function (the spying nature is emphasized by the fact that spying and non-spying tests are rendered identically:-). [[x]^{−} →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x]^{−} ¨= [⌈x⌉ spy

x]^{−}]⌉)][[x]^{−} →^{tex} “

[#1. ]ˆ -”] is a spying test for falsehood.

Spying tests are good for debugging when some test loops indefinitely. If a test case loops indefinitely, then *spy* will typically contain the last spying test that was executed before the infinite loop.

6 Logiweb sequent calculus

The Logiweb sequent calculus is the low level theory (or “metatheory”) that comes with Logiweb. Users may use Logiweb sequent calculus and its associated proof checker as they are or use them as a model for constructing their own proof checkers.

The Logiweb sequent calculus corresponds to the assembly language of computing machines. It is possible in principle to use it as it is, but it is much more efficient to use higher level theories built on top of the calculus. When building theories on top of the calculus, the calculus ensures correctness whereas the high level theories provide user friendliness. Programming bugs in the high level theories cannot compromise correctness since correctness is ensured by the low level sequent calculus. Only bugs in the implementation of the sequent calculus and in the levels below can compromise correctness.

In contrast, Map Theory described later is the high level theory that comes with Logiweb. Again, users may use Map Theory as it is or use it as a model for constructing their own theories. Map Theory is a high level theory implemented on top of the Logiweb sequent calculus.

Map Theory is a classical theory with power as classical ZFC set theory. Contrary to Set Theory, Map Theory builds on lambda calculus. More specificially, Map Theory is the result of adding quantifiers to the Logiweb computing engine. For that reason, Map Theory is suited both for classical mathematics and for reasoning about programs in general and programs for the Logiweb engine in particular.

Logiweb sequent calculus is intuitionistic and has much less power than Map Theory.

Now let [\underline{m}] be the intuitionistic conjunction of all axioms, axioms schemes, and inference rules of Map Theory and let [\underline{l}] be a lemma of Map Theory. In general, [\underline{l}] will not be intuitionistically valid and, hence, [\underline{l}] will not be a lemma of Logiweb sequent calculus. But the statement that [\underline{m}] infers [\underline{l}], written [\underline{m} ⊢ \underline{l}], will be intuitionistically valid, and that is the lemma to be proved from the point of view of the sequent calculus.

Hence, if the user proves a lemma [\underline{l}] in Map Theory, then the lemma will be translated into [\underline{m} ⊢ \underline{l}] and the proof will be translated into a proof of that statement in the sequent calculus.

Now let [\underline{z}] be the intuitionistic conjunction of all axioms, axiom schemes, and inference rules of classical ZFC set theory. At the time of writing, a rather large, formal proof of [\underline{m} ⊢ \underline{z}] exists, and that particular proof is going to be the main test case for checkout of the Logiweb system. The lemma [\underline{m} ⊢ \underline{z}] says that Map Theory can “simulate” ZFC set theory and that all developments possible in ZFC set theory are also possible in Map Theory.

6.1 Statements

6.1.1 Messages

Logiweb comes with a number of predefined aspects like [pyk], [tex], [val], and [macro]. Logiweb also has a facility for defining new aspects. New aspects are introduced using the message aspect. The message aspect is a predefined one and, hence, has to be proclaimed:

[msg ▷◁ “message”]

For convenience, we define a construct for making message definitions:

[[x =^{msg} y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x =^{msg} y] ¨= [(x)^{p} →^{msg} y]]⌉)]

Just like a construct may have e.g. a value aspect, a construct may have a message aspect. If a construct [\underline{a}] has a message aspect [\underline{b}], then [\underline{a}] denotes the aspect [\underline{b}]. Hence, [\underline{b}] becomes an aspect by occurring in the right hand side of a message definition.

If two constructs [\underline{a}_{1}] and [\underline{a}_{2}] both have message aspect [\underline{b}] then [\underline{a}_{1}] and [\underline{a}_{2}] denote the same aspect. The ability to have several constructs that denote the same aspect allows different users to use different notation for the same aspect. This is important because of the notational freedom of mathematics.

If a construct [\underline{a}] has a message aspect [\underline{b}] then both [\underline{a}] and [\underline{b}] may have parameters. Parameters of [\underline{a}] allow to define parameterised aspects. Parameters of [\underline{b}] have no effect since an aspect is identified by the reference and identifier of the root of [\underline{b}].

Aspects of Logiweb have a slight resemblance with messages in objectoriented programming, and for that reason, we use “aspect” and “message” as synonyms here. But why use “message” when “message” is just used as a synonym for “aspect”? The answer is that “message aspect” sounds better than “aspect aspect”.

6.1.2 The statement aspect

We shall refer to entities like axioms and inference rules as statements. To define such entities it is convenient to have a statement aspect. To introduce a statement aspect, we first introduce [<stmt>]to represent it.

[<stmt>] has a [pyk] definition so that it can be referred to in pyk source files and a [tex] definition so that it can be rendered in TEX output from Logiweb, and it evaluates to itself:

[<stmt> →^{val} ⌈<stmt>⌉]

Apart from that [<stmt>] is inert. Its purpose is to occur in the right hand side of a message definition where it identifies the statement aspect.

We shall use [stmt] to denote the statement aspect:

[stmt →^{msg} <stmt>]

For convenience, we define a construct for making statement definitions:

[[x =^{stmt} y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x =^{stmt} y] ¨= [(x)^{p} →^{stmt} y]]⌉)]

6.1.3 Axioms

An axiom is a statement that somebody accepts as true without proof. As an example, one could declare [T^{h} = T] as an axiom. The definition [HeadNil′ →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[HeadNil′ ¨= T^{h} = T]⌉)]allows to use [T^{h} = T] as shorthand for the given axiom.

6.1.4 Axiom schemes

An axiom scheme is a systematic collection of axioms. As an example, one could declare [∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a}] as an axiom scheme. The axiom scheme says that [\underline{a} : : \underline{b}^{h} = \underline{a}] for all terms [\underline{a}] and [\underline{b}]. The definition [HeadPair′ →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[HeadPair′ ¨= ∀A: ∀B: (A : : B)^{h} = A]⌉)]allows to use [∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a}] as shorthand for the given axiom scheme.

The variables [\underline{a}] and [\underline{b}] are metavariables. Metavariables range over terms as opposed to ordinary variables which range over values. For more on metavariables see Section 6.2.

6.1.5 Inference rules

An inference rule is a rule which states that a certain conclusion follows from one or more premisses. An inference rule states that the conclusion is provable if all the premisses are provable.

As an example, one could declare [∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c}] as an inference rule. The inference rule says that if [\underline{a}], [\underline{b}], and [\underline{c}] are arbitrary terms, and if [\underline{a} = \underline{b}] and [\underline{a} = \underline{c}] are provable, then [\underline{b} = \underline{c}] is provable.

The definition [Transitivity′ →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Transitivity′ ¨= ∀A: ∀B: ∀C: A = B ⊢ A = C ⊢ B = C]⌉)]allows to use [∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c}] as shorthand for the given inference rule.

6.1.6 Contradictions

We make the convention that [⊥ ⊥] represents absurdity.

A Logiweb contradiction is a statement that somebody accepts as false without proof. As an example, one could declare [T : : T = T] as a contradiction. The contradiction [T : : T = T] may be expressed as the statement [T : : T = T ⊢ ⊥ ⊥].

Contradictions were called “Logiweb contradictions” first time they were mentioned above. That was done to emphasize that the word “contradiction” is used here in a way that is not necessarily in line with the litterature.

As we shall see, contradictions have two uses. Firstly, they may be used to refute a conjecture by proving that the conjecture implies a contradiction. Secondly, they may be used to refute a theory as inconsistent by proving that a contradiction is provable within the theory.

The definition [Contra′ →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Contra′ ¨= T : : T = T ⊢ ⊥ ⊥]⌉)]allows to use [T : : T = T ⊢ ⊥ ⊥] as shorthand for the given contradiction.

6.1.7 Theories

We shall refer to axioms, axiom schemes, and inference rules as rules.

A Logiweb theory is a structure that encodes a finite set of rules and contradictions. As an example, one could declare the rules [T^{h} = T], [∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a}], and [∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c}] and the contradiction [T : : T = T ⊢ ⊥ ⊥] to form a theory.

The definition [T′_{E} →^{stmt} T^{h} = T ⊕ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕

T : : T = T ⊢ ⊥ ⊥]

allows to refer to the example theory as [T′_{E}] (“T” for “Theory”, “E” for “Example”, [T′_{E}] for “example theory”).

The notion of a “Logiweb theory” is close to the notion of an “axiotic theory” in the litterature. Some branches of the litterature use the word “theory” in a quite different sense, namely to denote the set of all statements provable from an axiomatic theory.

The notion of a “Logiweb theory” differs from the notion of an “axiomatic theory” in three ways:

Firstly, the notion of a “Logiweb theory” has a precise, technical meaning inside the Logiweb framework. The notion of an “axiomatic theory” is independent of any framework but is more vague.

Secondly, a Logiweb theory may include Logiweb contradictions. Axiomatic theories merely contain rules.

Finally, a Logiweb theory contains finitely many rules whereas an axiomatic theory may contain infinitely many. This is because Logiweb theories and axiomatic theories count rules differently.

Axiomatic theories count rules in a very peculiar way: (1) inference rules do not count. (2) axioms that are axioms of first order predicate calculus do not count. (3) axiom schemes count as infinitely many rules. A theory like ZFC set theory [10] has the property that it is “not finitely axiomatizable”. That result depends on the counting used in axiomatic theories. Using Logiweb counting, ZFC has finitely many rules. All axiomatic theories can be expressed as Logiweb theories using finitely many rules.

6.1.8 Conjectures, lemmas, and antilemmas

A Logiweb conjecture is a statement of form [\underline{t} ⊢ \underline{c}] where [\underline{t}] is a theory and [\underline{c}] is a statement that is expected to follow from the theory. As an example, one could declare [T′_{E} ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} = \underline{b} ⊢ \underline{b} = \underline{a}] as a conjecture.

The definition [L_{1} →^{stmt} T′_{E} ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} = \underline{b} ⊢ \underline{b} = \underline{a}] allows to refer to the given conjecture as [L_{1}].

Later, we introduce the “Logiweb proof checker” and the notion of a “Logiweb proof”. Once a proof of a conjecture is written, accepted by the proof checker, and published on Logiweb, one may refer to the conjecture as a Logiweb lemma.

Furthermore, if [\underline{t} ⊢ \underline{c} ⊢ ⊥ ⊥], i.e. [\underline{t} ⊢ \underline{c} ⊢ ⊥ ⊥] is a Logiweb lemma then one may refer to the conjecture [\underline{t} ⊢ \underline{c}] as a Logiweb antilemma.

6.1.9 Statement constructors

We shall refer to a term as a statement if we care about its mathematical truth. Hence, rules, contradictions, theories, conjectures, lemmas, and antilemmas are statements.

The constructors [x ⊢ y], [x ⊢⊢ y], [∀x: y], [⊥ ⊥], and [x ⊕ y]allow to form statements from arbitrary terms and statements:

• [\underline{a} ⊢ \underline{b}] reads [\underline{a}] infers [\underline{b}] and states that if [\underline{a}] is provable then [\underline{b}] is provable.

• [\underline{a} ⊢⊢ \underline{b}] reads [\underline{a}] endorses [\underline{b}] and states that if [\underline{a}] evaluates to [T] then [\underline{b}] is provable.

• [∀\underline{a}: \underline{b}] reads all [\underline{a}] indeed [\underline{b}] and states that [\underline{b}] is provable for all terms [\underline{a}].

• [⊥ ⊥] reads absurdity. One may claim that a term [\underline{a}] is disprovable by the statement [\underline{a} ⊢ ⊥ ⊥].

• [\underline{a} ⊕ \underline{b}] reads [\underline{a}] rule plus [\underline{b}] and states that [\underline{a}] and [\underline{b}] are provable.

All the constructors above except endorsement have been used in examples. According to the Unicode standard, [⊢⊢] reads “forses”, but we use [\underline{a} ⊢⊢ \underline{b}] for endorsement rather than enforcement.

[\underline{a} ⊢⊢ \underline{b}] states that the side condition [\underline{a}] endorses the conclusion [\underline{b}]. The construct can be used for statements like “[\underline{b}] is free for [\underline{x}] in [\underline{a}] endorses [λ\underline{x}.\underline{a} ’ \underline{b} = ⟨\underline{a} |\underline{x}:= \underline{b}⟩].

To give a meaningful example of the use of endorsement, however, one has to program some side condition like “is free for” first. Examples of use of endorsement will be given later.

6.1.10 Self-evaluation

We define the statement constructors such that they are “self-evaluating”. As an example, the definition of x ⊢ y is such that e.g. [⌈\underline{a}⌉ ⊢ ⌈\underline{b}⌉] and [⌈\underline{a} ⊢ \underline{b}⌉] are equal terms (equal except for debugging information present in the terms which indicates exactly where the terms occur on the Logiweb page). The following definitions make the constructors self-evaluating:

[x ⊢ y →^{val} ⌈x ⊢ y⌉^{R} : : x : : y : : T] [x ⊢⊢ y →^{val} ⌈x ⊢⊢ y⌉^{R} : : x : : y : : T] [∀x: y →^{val} ⌈∀x: y⌉^{R} : : x : : y : : T]

[⊥ ⊥ →^{val} ⌈⊥ ⊥⌉^{R} : : T]

[x ⊕ y →^{val} ⌈x ⊕ y⌉^{R} : : x : : y : : T] [x^{I} →^{val} ⌈x^{I}⌉^{R} : : x : : T] [x^{⊳} →^{val} ⌈x^{⊳} ⌉^{R} : : x : : T] [x^{V} →^{val} ⌈x^{V}⌉^{R} : : x : : T] [x^{+} →^{val} ⌈x^{+}⌉^{R} : : x : : T] [x^{−} →^{val} ⌈x^{−}⌉^{R} : : x : : T] [x^{∗} →^{val} ⌈x^{∗}⌉^{R} : : x : : T] [x @ y →^{val} ⌈x @ y⌉^{R} : : x : : y : : T] [x i.e. y →^{val} ⌈x i.e. y⌉^{R} : : x : : y : : T] [x; y →^{val} ⌈x; y⌉^{R} : : x : : y : : T]

6.2 Metavariables

6.2.1 Definition of metavariables

As mentioned in Section 6.1.4, metavariables range over terms as opposed to ordinary variables which range over values. In the sequent calculus presented in Section 6.3 we need to distinguish metavariables from other variables.

To do so, we simply introduce the unary operator [\underline{x}]and make the convention that a term is a metavariable iff it has the [\underline{∗}] construct in its root.

Having this convention in place, we introduce the metavariables [A →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[A ¨= \underline{a}]⌉)], [B →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[B ¨= \underline{b}]⌉)], [C →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[C ¨= \underline{c}]⌉)], [D →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[D ¨= \underline{d}]⌉)], [E →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[E ¨= \underline{e}]⌉)], [F →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[F ¨= \underline{f}]⌉)], [G →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[G ¨= \underline{g}]⌉)], [H →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[H ¨= \underline{h}]⌉)], [I →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[I ¨= \underline{i}]⌉)], [J →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[J ¨= \underline{j}]⌉)], [K →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[K ¨= \underline{k}]⌉)], [L →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[L ¨= \underline{l}]⌉)], [M →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[M ¨= \underline{m}]⌉)], [N →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[N ¨= \underline{n}]⌉)], [O →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[O ¨= \underline{o}]⌉)], [P →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[P ¨= \underline{p}]⌉)], [Q →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Q ¨= \underline{q}]⌉)], [R →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[R ¨= \underline{r}]⌉)], [S →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[S ¨= \underline{s}]⌉)], [T →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[T ¨= \underline{t}]⌉)], [U →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[U ¨= \underline{u}]⌉)], [V →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[V ¨= \underline{v}]⌉)], [W →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[W ¨= \underline{w}]⌉)], [X →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[X ¨= \underline{x}]⌉)], [Y →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Y ¨= \underline{y}]⌉)], and [Z →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Z ¨= \underline{z}]⌉)].

6.2.2 Recognition of metavariables

[t^{V}]is true if [t] is a metavariable:

[t^{V} →^{val} t =^{r} ⌈\underline{a}⌉]

6.2.3 Closedness

[t^{C}]is true if the term [t] contains no metavariables and [t^{C^{∗}}]is true if the list [t] of terms contains no metavariables:

[t^{C} →^{val} If(t^{V}, F, t^{t}^{C^{∗}})]
[t^{C^{∗}} →^{val} If(t, T, If(t^{h}^{C}, t^{t}^{C^{∗}}, F))]

6.2.4 The “free in” predicate

[v free in t]is true if the metavariable [v] is occurs free in the term [t]. Furthermore, [v free in^{∗} t]is true if the metavariable [v] is occurs free in the list [t] of terms.

[v free in t →^{val}

If(v =^{t} t, T,

If(¬t =^{r} ⌈∀∗: ∗⌉, v free in^{∗} t^{t}, If(v =^{t} t^{1}, F, v free in t^{2})))]

[v free in^{∗} t →^{val} If(t, v!F, If(v free in t^{h}, T, v free in^{∗} t^{t}))]

6.2.5 The “free for” predicate

[a free for x in b]is true if the term [a] is free for the metavariable [x] in the term [b]. Furthermore, [a free for^{∗} ∗ in b]is true if the term [a] is free for the metavariable [x] in the list [b] of terms.

[a free for x in b →^{val} a!x! If(b^{V}, T, If(¬b =^{r} ⌈∀∗: ∗⌉, a free for^{∗} x in b^{t},

If(x =^{t} b^{1}, T,

If(¬x free in b^{2}, T, If(b^{1} free in a, F, a free for x in b^{2})))))]

[a free for^{∗} x in b →^{val} If(b, a!x!T, If(a free for x in b^{h}, a free for^{∗} x in b^{t}, F))]

6.2.6 Metavariable substitution

[⟨a |x:= b⟩]replaces all free occurrences of the metavariable [x] by the term [b] in the term [a]. The operation does no renaming of bound variables, so variable clashes will occur if [b] is not free for [x] in [a]. Furthermore, [⟨^{∗}a |x:= b⟩]replaces all free occurrences of the metavariable [x] by the term [b] in the list [a] of terms.

[⟨a |x:= b⟩ →^{val} x!b! If(a^{V}, If(a =^{t} x, b, a), If(¬a =^{r} ⌈∀∗: ∗⌉, a^{h} : : ⟨^{∗}a^{t} |x:= b⟩,

If(a^{1} =^{t} x, a,

a^{0} : : a^{1} : : ⟨a^{2} |x:= b⟩ : : T)))]

[⟨^{∗}a |x:= b⟩ →^{val} x!b!If(a, T, ⟨a^{h} |x:= b⟩ : : ⟨^{∗}a^{t} |x:= b⟩)]

6.3 Sequent calculus

6.3.1 Term sets

We shall represent sets of terms as lists without repetitions. We require the lists to be without repetitions in the sense that a term [x] is not allowed to occur more than once and, furthermore, if two distinct terms [x] and [y] satisfy [x =^{t} y] then the lists are not allowed to contain them both.

The membership operation [x ∈_{t} y]is defined thus:

[x ∈_{t} y →^{val} If(y^{a}, x!F, If(x =^{t} y^{h}, T, x ∈_{t} y^{t}))]

The subset operation [x ⊆_{T} y]is defined thus:

[x ⊆_{T} y →^{val} If(x^{a}, y!T, If(x^{h} ∈_{t} y, x^{t} ⊆_{T} y, F))]

The set equality operation [x =^{T} y]is defined thus:

[x =^{T} y →^{val} If(x ⊆_{T} y, y ⊆_{T} x, F)]

The empty set [∅]is defined thus:

[∅ →^{val} T]

The operation [x ∪ {y}]adds the term [y] to the term set [x]:

[x ∪ {y} →^{val} If(y ∈_{t} x, x, y : : x)]

The operation [x\{y}]removes the term [y] from the term set [x]:

[x\{y} →^{val} If(x^{a}, y!∅, If(y =^{t} x^{h}, x^{t}, x^{h} : : x^{t}\{y}))]

The operation [x ∪ y]computes the union of the term sets [x] and [y]:

[x ∪ y →^{val} If(x^{a}, y, x^{t} ∪ y ∪ {x^{h}})]

6.3.2 Sequents

A Logiweb sequent is a triple [p : : s : : c : : T] where [p] and [s] are term sets and [c] is a term. In a sequent [p : : s : : c : : T] we shall refer to [p], [c], and [c] as premise, side condition, and conclusion, respectively, of the sequent.

A sequent [p : : s : : c : : T] represents the statement that if all members of [p] are provable and if all members of [s] evaluate to [T] then [c] is provable.

Sequents allow to express the same thing in many ways. As an example, the following five sequents all state that if [\underline{a}] and [\underline{b}] are provable then [\underline{a} ⊕ \underline{b}] is provable:

∅, ∅, \underline{a} ⊢ \underline{b} ⊢ \underline{a} ⊕ \underline{b} : : T
∅, ∅, \underline{b} ⊢ \underline{a} ⊢ \underline{a} ⊕ \underline{b} : : T
∅ ∪ \{\underline{a}\}, ∅, \underline{b} ⊢ \underline{a} ⊕ \underline{b} : : T
∅ ∪ \{\underline{b}\}, ∅, \underline{a} ⊢ \underline{a} ⊕ \underline{b} : : T
∅ ∪ \{\underline{a}\} ∪ \{\underline{b}\}, ∅, \underline{a} ⊕ \underline{b} : : T

The sequent [∅ ∪ \{\underline{b}\} ∪ \{\underline{a}\}, ∅, \underline{a} ⊕ \underline{b} : : T] is considered equal to the last of the sequents above since the order of elements in term sets is considered unimportant.

From an operational point of view one may think of a sequent [p : : s : : c : : T] as a tool makers workshop where [c] is the anvil where lemmas are forged. [p] may be seen as a storage room for premises, in which case part of the tool makers work is to bring premises back and forth between anvil and storage room. Alternatively, [p] may be seen as a backlog of proof obligations. [s] is like [p] except that it stores side conditions.

As we shall see, the storage room [p] will be used for several different things. As an example, when proving [\underline{a} = \underline{b} ⊢ \underline{b} = \underline{a}] in [T′_{E}], [p] will be used to contain the axiomatic theory [T′_{E}] itself, it will be used to contain the premise [\underline{a} = \underline{b}], and it will be used to contain conclusions of individual lines of the proof.

6.3.3 Sequent equality

The sequent equality operation [x =^{s} y]is defined thus:

[x =^{s} y →^{val} If(¬x^{2} =^{t} y^{2}, F, If(x^{0} =^{T} y^{0}, x^{1} =^{T} y^{1}, F))]

6.3.4 Sequent operations

Logiweb sequent calculus comprises twelve sequent operations. We shall refer to a term that is built up from these twelve operations as a sequent proof. We shall say that a term [c] is a sequent lemma if there exists a sequent proof which evaluates to [∅ : : ∅ : : c : : T]. In the tool makers analogy, the sequent [∅ : : ∅ : : c : : T] represents the situation where [c] has been forged and the backlogs of remaining work are empty.

We shall refer to a sequent operation as sequent-nulary, sequent-unary, or sequent-binary if it depends on zero, one, or two sequents, respectively. As an example, a binary operation that depends on one sequent and one non-sequent is sequent-unary. Logiweb sequent calculus comprises one sequent-nulary, ten sequent-unary, and one sequent-binary operation. The sole sequent-binary operation of Logiweb sequent calculus is the “cut” operation.

In the tool makers analogy, each sequent-unary operation corresponds to a work process such as moving a premise from anvil to storage room. The sequent-nulary operation is the starting point of any work process, and the sequent-binary operation allows to use the outcome of one work process as a tool in another process.

6.3.5 Proof initiation

The sequent-nulary operation [x^{I}]performs the following operation:

[a^{I}] evaluates to [∅, ∅, a ⊢ a : : T]

In section 6.5 we introduce a “proof evaluator” which, given a sequent proof, computes the value of the proof. It is the proof evaluator that is going to evaluate [a^{I}] as shown above.

As an example of use, [\underline{a} ⊕ \underline{b} ⊢ \underline{a} ⊕ \underline{b}] is a sequent lemma because [\underline{a} ⊕ \underline{b}^{I}] evaluates to [∅, ∅, \underline{a} ⊕ \underline{b} ⊢ \underline{a} ⊕ \underline{b} : : T]. In other words, [proof(⌈\underline{a} ⊕ \underline{b}^{I}⌉, ⌈\underline{a} ⊕ \underline{b} ⊢ \underline{a} ⊕ \underline{b}⌉, base)]^{∘}, where the “proves” predicate will be defined in Section 6.5.5.

The statement that

[\underline{a} ⊕ \underline{b}^{I}] proves [\underline{a} ⊕ \underline{b} ⊢ \underline{a} ⊕ \underline{b}]

is just an informal statement that the given sequent proof proves the given term. In contrast, the statement that

[proof(⌈\underline{a} ⊕ \underline{b}^{I}⌉, ⌈\underline{a} ⊕ \underline{b} ⊢ \underline{a} ⊕ \underline{b}⌉, base)]^{∘}

is a formal one that uses the formally defined [proof(⌈x⌉, ⌈y⌉, base)] relation defined in Section 6.5.5. The latter statement makes Logiweb verify the claim formally.

The statement that

[proof(⌈\underline{a} ⊕ \underline{b}^{I}⌉, ⌈\underline{a} ⊕ \underline{b} ⊢ \underline{a} ⊕ \underline{b}⌉, base)]^{·}

also forces Logiweb to verify the claim formally, but if the claim turned out to fail, the user would merely get the information that that particular claim failed. If [x] does not prove [y] then [proof(⌈x⌉, ⌈y⌉, base)] returns a term which, when typeset, explains why not. For that reason,

[proof(⌈\underline{a} ⊕ \underline{b}^{I}⌉, ⌈\underline{a} ⊕ \underline{b} ⊢ \underline{a} ⊕ \underline{b}⌉, base)]^{∘}

has the benefit that if the claim fails then the generated error message will be more precise.

6.3.6 Inference introduction

We overload [x ⊢ y] to denote both an operation on statements and a sequent operation. Ambiguity cannot occur since the proof evaluator will decide what [x ⊢ y] means on a case by case basis.

[a ⊢ q] is sequent-unary; it takes a premise [a] and a sequent [q] and moves the premise from storage room to anvil:

[a ⊢ p : : s : : c : : T] evaluates to [p\{a}, s, a ⊢ c : : T]

Note that a premise can be moved from storage room to anvil even if there the premise was not present in the storage room to begin with. A premise may be seen as work to be done, and moving a premise that did not exist before corresponds to creation of work to be done from nothing.

As an example of use, [proof(⌈\underline{a} ⊢ \underline{b}^{I}⌉, ⌈\underline{a} ⊢ \underline{b} ⊢ \underline{b}⌉, base)]^{∘}.

6.3.7 Endorsement and quantifier introduction

We also overload [x ⊢⊢ y] and [∀x: y]:

[a ⊢⊢ p : : s : : c : : T] evaluates to [p, s\{a}, a ⊢⊢ c : : T]

[∀x: p : : s : : c : : T] evaluates to [p : : s : : ∀x: c : : T] if [x] is a metavariable and is not free in [p] and [s]

As an example of use, [proof(⌈∀\underline{a}: ∀\underline{b}: \underline{a} ⊢ \underline{b}^{I}⌉, ⌈∀\underline{a}: ∀\underline{b}: \underline{a} ⊢ \underline{b} ⊢ \underline{b}⌉, base)]^{∘}.

6.3.8 Inference and endorsement elimination

The operation [x^{⊳} ]eliminates an inference or endorsement:

[p, s, a ⊢ c : : T^{⊳} ] evaluates to [p ∪ {a} : : s : : c : : T]

[p, s, a ⊢⊢ c : : T^{⊳} ] evaluates to [p : : s ∪ {a} : : c : : T]

As an example of use, [proof(⌈\underline{a} ⊢ \underline{b} ⊢ \underline{a}^{I}^{⊳} ⌉, ⌈\underline{a} ⊢ \underline{b} ⊢ \underline{a}⌉, base)]^{∘}.

We shall refer to [x^{⊳} ] as the modus operation. As we shall see, the inference rule of modus ponens will be implemented by the modus operation together with the cut operation described later: the modus operation is used for preparation whereas a cut is used for the actual execution.

Inferences can be eliminated by modus ponens whereas endorsements can be eliminated by either modus probans or verification. Modus ponens says that if [x ⊢ y] and if we can prove [x] then we positivily have [y]. Verification says that if [x ⊢⊢ y] and if [x] evaluates to [T] then [y] is verified. Modus probans says that if [x ⊢⊢ y] and if we happen to know or assume that [x] evaluates to [T] then this knowledge approves [y]. The modus operation implements half of modus ponens or modus probans. Verification is treated in Section 6.3.10.

6.3.9 Quantifier elimination

The operation [x @ y]eliminates a quantifer:

[p : : s : : ∀x: c : : T @ a] evaluates to [p : : s : : ⟨c |x:= a⟩ : : T] if [x] is a metavariable and [a] is free for [x] in [c]

As an example of use, [proof(⌈∀\underline{a}: \underline{a} = \underline{a} ⊢ ∀\underline{a}: \underline{a} = \underline{a}^{I}^{⊳} @ 0⌉, ⌈∀\underline{a}: \underline{a} = \underline{a} ⊢ 0 = 0⌉, base)]^{∘}.

6.3.10 Verification

The operation [x^{V}]eliminates a side condition by evaluating it and seeing that it is true:

[p, s, a ⊢⊢ b : : T^{V}] evaluates to [p : : s : : b : : T] if [U^{M}(E(a, T, c) ‘ c)] evaluates to [T] where [c] is the cache of the page on which the verification operation occurs As an example of use, [proof(⌈∀\underline{a}: λc.U^{M}(E(⌈\underline{a}⌉, T, c)) ⊢⊢ \underline{a} ⊢ ∀\underline{a}: λc.U^{M}(E(⌈\underline{a}⌉, T, c)) ⊢⊢ \underline{a}^{I}^{⊳} @ F +2∗ 2 ≈ 5^{V}⌉, ⌈∀\underline{a}: λc.U^{M}(E(⌈\underline{a}⌉, T, c)) ⊢⊢ \underline{a} ⊢ F +2∗ 2 ≈ 5⌉, base)]^{∘} where

[T (x) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[T (x) ¨= λc.U^{M}(E(⌈x⌉, T, c))]⌉)]

In the example above, [∀\underline{a}: λc.U^{M}(E(⌈\underline{a}⌉, T, c)) ⊢⊢ \underline{a}] is an axiom scheme that says that any term that evaluates to [T] is provable.

6.3.11 Currying

The operations [x^{+}]and [x^{−}]add and remove a [⊕], respectively:

[p, s, a ⊢ b ⊢ c : : T^{+}] evaluates to [p, s, a ⊕ b ⊢ c : : T]
[p, s, a ⊕ b ⊢ c : : T^{−}] evaluates to [p, s, a ⊢ b ⊢ c : : T]

[x^{−}] and [x^{+}] are known as currying and decurrying, respectively.

As an example of use, [proof(⌈\underline{a} ⊢ \underline{b}^{I}^{+}⌉, ⌈\underline{a} ⊕ \underline{b} ⊢ \underline{b}⌉, base)]^{∘}.

As another example, [proof(⌈\underline{a} ⊕ \underline{b}^{I}^{−}⌉, ⌈\underline{a} ⊢ \underline{b} ⊢ \underline{a} ⊕ \underline{b}⌉, base)]^{∘}.

6.3.12 Referencing and dereferencing

The operations [x i.e. y]and [x^{∗}]change from term to name and vice versa, respectively:

[p : : s : : c : : T i.e. n] evaluates to [p : : s : : n : : T] if [c] is the statement aspect of [n]

[p : : s : : n : : T^{∗}] evaluates to [p : : s : : c : : T] where [c] is the statement aspect of [n]

We shall refer to [x i.e. y] and [x^{∗}] as referencing and dereferencing, respectively. The asterisk in [x^{∗}] is inspired by the C programming language.

As an example of use, [proof(⌈T′_{E} ⊢ T′_{E}^{I}^{⊳} ^{∗}⌉, ⌈T′_{E} ⊢ T^{h} = T ⊕ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕ T : : T = T ⊢ ⊥ ⊥⌉, base)]^{∘}.

As another example, [proof(⌈T^{h} = T ⊕ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕ T : : T = T ⊢ ⊥ ⊥ ⊢ T^{h} = T ⊕ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕ T : : T = T ⊢ ⊥ ⊥^{I}^{⊳} i.e. T′_{E}⌉, ⌈T^{h} = T ⊕ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕ T : : T = T ⊢ ⊥ ⊥ ⊢ T′_{E}⌉, base)]^{∘}.

6.3.13 The cut operation

The sequent-binary operation [x; y]is the well-known cut operation. It satisfies:

[p_{1} : : s_{1} : : c_{1} : : T; p_{2} : : s_{2} : : c_{2} : : T] evaluates to [p_{1} ∪ p_{2}\{c_{1}} : : s_{1} ∪ s_{2} : :

c_{2} : : T]

As an example of use, let [∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕ T : : T = T ⊢ ⊥ ⊥]denote all of [T′_{E}] except [T^{h} = T]:

[Remainder →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Remainder ¨= HeadPair′ ⊕ Transitivity′ ⊕

Contra′]⌉)]

We have that

[T′_{E}^{I}^{⊳} ^{∗}]

evaluates to

[T′_{E}, ∅, T^{h} = T ⊕ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕

T : : T = T ⊢ ⊥ ⊥ : : T]

and that

[T^{h} = T ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕ T : :

T = T ⊢ ⊥ ⊥ ⊢ T^{h} = T^{I}^{+}^{⊳} ]

evaluates to

[T^{h} = T ⊕ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕ T : :
T = T ⊢ ⊥ ⊥, ∅, T^{h} = T : : T]

so

[proof(⌈T′_{E} ⊢ T′_{E}^{I}^{⊳} ^{∗}; T^{h} = T ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} =
\underline{c} ⊢ \underline{b} = \underline{c} ⊕ T : : T = T ⊢ ⊥ ⊥ ⊢ T^{h} = T^{I}^{⊳} ^{+}^{⊳} ⌉, ⌈T′_{E} ⊢ T^{h} = T⌉, base)]^{∘}.

The lemma says that [T^{h} = T] is provable in [T′_{E}]. In general, as one should expect, all rules of a theory are provable in the theory.

6.3.14 Rule lemmas

For a rule [\underline{r}] of a theory [\underline{t}] we shall refer to [\underline{t} ⊢ \underline{r}] as the rule lemma of [\underline{r}].

In proofs, one constantly needs rule lemmas. Hence, as soon as one has defined a theory it is convenient to prove the rule lemma of each rule. Once that is done one can forget about the rules and use the rule lemmas instead.

For that reason, one should not waste good names on rules; one should reserve good names for rule lemmas.

6.4 Implementation of the twelve sequent operations

Sequent evaluators for the twelve individual sequent operations of Logiweb sequent calculus are defined in the following sections. See Section 6.3 for explanations of what each operation does.

6.4.1 Evaluation of the init operation

[S^{I}(c, t) →^{val} c!∅ : : ∅ : : t-color(t^{1} ⊢ t^{1}) : : T]

6.4.2 Evaluation of the modus operation

[S^{⊳} (c, t) →^{val} S_{1}^{⊳} (c, t, S(c, t^{1}))]

[S_{1}^{⊳} (c, t, q) →^{val} c!t! If(q^{E}, q,

If(q^{2} =^{r} ⌈∗ ⊢ ∗⌉, q^{0} ∪ {q^{2}^{1}} : : q^{1} : : q^{2}^{2} : : T,

If(q^{2} =^{r} ⌈∗ ⊢⊢ ∗⌉, q^{0} : : q^{1} ∪ {q^{2}^{1}} : : q^{2}^{2} : : T,

error_{2}(⌈“The modus operation requires the conclusion of its argument to be an inference or an endorsement”⌉, t))))]

6.4.3 Evaluation of the verify operation

[S^{E}(c, t) →^{val} S_{1}^{E}(c, t, S(c, t^{1}))]

[S_{1}^{E}(c, t, q) →^{val} c!t! If(q^{E}, q, If(¬q^{2} =^{r} ⌈∗ ⊢⊢ ∗⌉, error_{2}(⌈“The verify operation requires the conclusion of its argument to be an endorsement:”⌉, t), If(U^{M}(E(q^{2}^{1}, T, c) ‘ c), q^{0} : : q^{1} : : q^{2}^{2} : : T, error_{2}(⌈“False side condition:”⌉, t))))]

6.4.4 Evaluation of the decurrying operation

[S^{+}(c, t) →^{val} S_{1}^{+}(c, t, S(c, t^{1}))]

[S_{1}^{+}(c, t, q) →^{val} c!t! If(q^{E}, q,

If(q^{2} =^{r} ⌈∗ ⊢ ∗⌉ ∧ q^{2}^{2} =^{r} ⌈∗ ⊢ ∗⌉,

q^{0} : : q^{1} : : t-color(q^{2}^{1} ⊕ q^{2}^{2}^{1} ⊢ q^{2}^{2}^{2}) : : T, error_{2}(⌈“Term; conclusion not fit for decurrying:”⌉, t; q^{2})))]

6.4.5 Evaluation of the currying operation

[S^{−}(c, t) →^{val} S_{1}^{−}(c, t, S(c, t^{1}))]

[S_{1}^{−}(c, t, q) →^{val} c!t! If(q^{E}, q,

If(q^{2} =^{r} ⌈∗ ⊢ ∗⌉ ∧ q^{2}^{1} =^{r} ⌈∗ ⊕ ∗⌉,

q^{0} : : q^{1} : : t-color(q^{2}^{1}^{1} ⊢ q^{2}^{1}^{2} ⊢ q^{2}^{2}) : : T, error_{2}(⌈“Term; conclusion not fit for decurrying:”⌉, t; q^{2})))]

6.4.6 Evaluation of the dereferencing operation

[S^{∗}(c, t) →^{val} S_{1}^{∗}(c, t, S(c, t^{1}))] [S_{1}^{∗}(c, t, q) →^{val} c!t! If(q^{E}, q, S_{2}^{∗}(c, t, q, aspect(<stmt>, q^{2}, c)))]

[S_{2}^{∗}(c, t, q, d) →^{val} c!t!q! If(d, error_{2}(⌈“Dereferencing construct that has no statement def:”⌉, t), q^{0} : : q^{1} : : d^{3} : : T)]

6.4.7 Evaluation of quantifier elimination

[S^{@}(c, t) →^{val} S_{1}^{@}(c, t, S(c, t^{1}))]

[S_{1}^{@}(c, t, q) →^{val} c!t! If(q^{E}, q, If(¬q^{2} =^{r} ⌈∀∗: ∗⌉, error_{2}(⌈“Quantifier elimination requires the conclusion of its argument to be a quantifier:”⌉, t), If(¬t^{2} free for q^{2}^{1} in q^{2}^{2}, error_{2}(⌈“Quantifier elimination leads to variable clash:”⌉, t), q^{0} : : q^{1} : : ⟨q^{2}^{2} |q^{2}^{1}:= t^{2}⟩ : : T)))]

6.4.8 Evaluation of inference introduction

[S^{⊢}(c, t) →^{val} S_{1}^{⊢}(c, t, t^{1}, S(c, t^{2}))]

[S_{1}^{⊢}(c, t, p, q) →^{val} c!t!p! If(q^{E}, q, q^{0}\{p} : : q^{1} : : t-color(p ⊢ q^{2}) : : T)]

6.4.9 Evaluation of endorsement introduction

[S⊢ ⊢(c, t) →^{val} S⊢ ⊢ ; 1(c, t, t^{1}, S(c, t^{2}))]

[S⊢ ⊢ ; 1(c, t, p, q) →^{val} c!t!p! If(q^{E}, q, q^{0} : : q^{1}\{p} : : t-color(p ⊢⊢ q^{2}) : : T)]

6.4.10 Evaluation of the referencing operation

[S^{i.e.}(c, t) →^{val} S_{1}^{i.e.}(c, t, t^{2}, S(c, t^{1}))]

[S_{1}^{i.e.}(c, t, a, q) →^{val} c!t!a! If(q^{E}, q, S_{2}^{i.e.}(c, t, a, q, aspect(<stmt>, a, c)))]

[S_{2}^{i.e.}(c, t, a, q, d) →^{val} c!t!a!q! If(d, error_{2}(⌈“Referencing construct that has no statement def:”⌉, t), If(¬d^{3} =^{t} q^{2}, error_{2}(⌈“Reference; conclusion do not match:”⌉, a; q^{2}), q^{0} : : q^{1} : : a : : T))] 6.4.11 Evaluation of quantifier introduction

[S^{∀}(c, t) →^{val} S_{1}^{∀}(c, t, t^{1}, S(c, t^{2}))]

[S_{1}^{∀}(c, t, v, q) →^{val} c!t!v!

If(q^{E}, q,

If(¬v^{V}, error_{2}(⌈“Metageneralization over non-metavariable:”⌉, t), If(v free in q^{0}, error_{2}(⌈“Metageneralization over metavariable that occurs free in some premise:”⌉, t), If(v free in q^{1}, error_{2}(⌈“Metageneralization over metavariable that occurs free in some side condition:”⌉, t), q^{0} : : q^{1} : : t-color(∀v: q^{2}) : : T))))]

6.4.12 Evaluation of the cut operation

[S^{;}(c, t) →^{val} S_{1}^{;}(c, t, S(c, t^{1}))]
[S_{1}^{;}(c, t, p) →^{val} c!t!
If(p^{E}, p, S_{2}^{;}(c, t, p, S(c, t^{2})))]
[S_{2}^{;}(c, t, p, q) →^{val} c!t!p!
If(q^{E}, q, p^{0} ∪ q^{0}\{p^{2}} : : p^{1} ∪ q^{1} : : q^{2} : : T)]

6.5 The proof evaluator

6.5.1 Coloring

[x ⊢ y] is self-evaluating. For that reason, [⌈x⌉ ⊢ ⌈y⌉] and [⌈x ⊢ y⌉] are equal terms except for debugging information.

The debugging information of the root of [⌈x⌉ ⊢ ⌈y⌉] equals [T] which represents no debugging information. For that reason we shall call the root uncolored.

Proper debugging information comprises a list of cardinals where the last cardinal in the list is the reference of the page on which the given node occurs. Hence, proper debugging information always differs from [T]. We shall refer to nodes whose debugging information differs from [T] as colored.

Whenever terms are generated using self-evaluating constructs, there will be uncolored nodes near the root of the generated term. The binary [a-color(t)] operation returns the term [t] but copies the debugging information from the root of [a] into uncolored nodes of [t]. We shall refer to this artistic touch as coloring.

The coloring operation merely descends into the tree until it meets nodes with proper debugging information, so the operation will miss uncolored nodes hidden deeply inside the tree.

The coloring operation is defined thus:

[a-color(t) →^{val} t^{d} \{ \begin{matrix}t^{r} : : t^{i} : : a^{d} : : a-color^{∗}(t^{t}) \\ a!t \end{matrix} ]

[a-color^{∗}(t) →^{val} t \{ \begin{matrix}a!T \\ a-color(t^{h}) : : a-color^{∗}(t^{t}) \end{matrix} ]

6.5.2 Error message generation

The following macro expands into a construct that returns an error message. The first argument is supposed to be a string and the value of the second is supposed to be a term.

When used, the construct generates an error message consisting of the string followed by a newline followed by the term, which is of course rather limited. Whenever it is convenient to include more than one term in a message we take the rather crude approach to combine the messages by the cut operation! The cut operation is self-evaluating and, when typeset, puts a semicolon between its arguments, which is close to tolerable.

The error generation macro simply quotes the string argument and leaves the actual generation of the error message to an auxiliary function:

[error(m, t) →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[error(m, t) ¨= error_{2}(⌈m⌉, t)]⌉)]

The following function generates an error message from a message [m] and a term [t].

[m] is supposed to be a unicode string with a unicode start of text in the root. That start of text character is removed by computing [m^{1}] to drop the “double quotes” from the string, but a [x] ensures that the unquoted string is still typeset as a string eventually.

The text is glued together with a string that merely contains a newline character and which is treated similarly. Furthermore, the text plus newline character are glued together with the term [t].

The text, newline character, and term are glued together with the [xy]. The [x] and [xy] are invisible when typeset using their tex aspects and, hence, do not exhibit themselves in the final error message. These two constructs are visible in the right hand side of the definition below and in several places above because they are made visible using [x].

A [t-color(x)] copies the debugging information in the root of [t] to nodes in the error message that are generated by [x] and [xy] and have no debugging information of their own. The definition reads:

[error_{2}(m, t) →^{val} t-color(m^{1}⌈“
”⌉^{1}t)]

6.5.3 Error recognition

The sequent evaluator returns a sequent or an error message. For obvious reasons, we shall need the ability to tell whether a return value is the one or the other.

Error messages are terms that can be typeset by the Logiweb system. When recognizing error messages, we assume that they are generated by the error message generator of the previous section or similar means that put a [xy] operator in the root of the message. That particular operator is harmless to have in the root of error messages because typesetting of [xy] results in [x] and [y] being typeset and then concatenated. Note that [xy] above reads [xy] in the source of the present page, otherwise the comma would have been invisible as in [xy].

The predicate below is true if the argument is an error message and false if the argument is a sequent. It is also false in many other cases as we shall benefit from later.

[x^{E} →^{val} x =^{r} ⌈xy⌉]

6.5.4 Sequent evaluation

The sequent evaluation function [S(c, t)] evaluates the sequent proof [t] in the context defined by the cache [c]. The result is a sequent or an error message. If it is a sequent, then the proof is valid and the sequent is the conclusion of the proof.

The sequent evaluation function recognises the twelve sequent operations of Logiweb sequent calculus and turns against any other operations in [t].

[S(c, t) →^{val} c!

If(t^{E}, t,

If(t =^{r} ⌈∗^{I}⌉, S^{I}(c, t),

If(t =^{r} ⌈∗^{⊳} ⌉, S^{⊳} (c, t),

If(t =^{r} ⌈∗^{V}⌉, S^{E}(c, t),

If(t =^{r} ⌈∗^{+}⌉, S^{+}(c, t),

If(t =^{r} ⌈∗^{−}⌉, S^{−}(c, t),

If(t =^{r} ⌈∗^{∗}⌉, S^{∗}(c, t),

If(t =^{r} ⌈∗ @ ∗⌉, S^{@}(c, t),

If(t =^{r} ⌈∗ ⊢ ∗⌉, S^{⊢}(c, t),

If(t =^{r} ⌈∗ ⊢⊢ ∗⌉, S⊢ ⊢(c, t),

If(t =^{r} ⌈∗ i.e. ∗⌉, S^{i.e.}(c, t),

If(t =^{r} ⌈∀∗: ∗⌉, S^{∀}(c, t),

If(t =^{r} ⌈∗; ∗⌉, S^{;}(c, t),

error_{2}(⌈“Unknown sequent operator:”⌉, t))))))))))))))]

6.5.5 Lemma verification

The macro [proof(⌈p⌉, ⌈t⌉, base)] claims that [p] proves [t]:

[p proves t →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[p proves t ¨= proof(⌈p⌉, ⌈t⌉, self)]⌉)]

As an example, the following verifies [2 ⊢ 2]:

[proof(⌈2^{I}⌉, ⌈2 ⊢ 2⌉, base)]^{∘}

Perturbing the conclusion to e.g. [2 ⊢ 3] provokes the diagnose aspect of the page symbol to be set to a term which, if typeset using the tex aspect, generates an appropriate error message.

[proof(p, t, c)] equals [T] if the proof [p] proves the sequent lemma [t] in the context defined by the cache [c]. Otherwise, [proof(p, t, c)] returns an error message:

[proof(p, t, c) →^{val} proof_{2}(S(c, p), t)]

[proof_{2}(q, t)] equals [T] if [q] is a sequent which proves the sequent lemma [t]. Otherwise, [proof_{2}(q, t)] returns an error message:

[proof_{2}(q, t) →^{val} t!

If(q^{E}, q,

If(¬q^{0}, error_{2}(⌈“Proof has at least one unresolved premise. Lemma; premise reads:”⌉, t; q^{0}^{h}), If(¬q^{1}, error_{2}(⌈“Proof has at least one unresolved side condition. Lemma; condition reads:”⌉, t; q^{1}^{h}),

If(q^{2} =^{t} t, T,

error_{2}(⌈“Lemma does not match conclusion. Lemma; conclusion reads:”⌉, t; q^{2})))))]

6.6 The verifier

6.6.1 Conjunction membership

The verifier allows proofs to refer to previously proved lemmas. Such previously proved lemmas may occur on the same page as the proof or in transitively referenced pages.

When a lemma on another page is referenced, the verifier needs to ensure that that other page has been properly checked. The verifier does so by looking up the diagnose aspect of the referenced page to see that the referenced page is correct. Furthermore, the verifier looks up the claim aspect of the referenced page to see that the claim is a conjunction that includes the verifier itself.

The above verification check for referenced pages is fast because the verifier itself is not invoked on the page. Rather, the verifier just ensures that the verifier was invoked successfully when the page was loaded.

Furthermore, the verification check is flexible in that the verifier only requires referenced pages to be checked by the verifier if those other pages actually contribute to proofs. This allows pages that contain proofs to reference pages that are unrelated to proofs such as pages that define computer programs, formatting constructs, fonts, or whatever.

The verifier is also flexible in that it allows referenced pages to be checked by any number of other checkers alongside the verifier itself. That allows the verifier to coexist with other proof checkers and all sorts of other checkers. As an example, one may decide to impose strong typing on a page using some type checker without affecting the ability to check proofs.

To implement the above verification check we need a relation [x ∈_{c} y] which is true iff the term [x] belongs to the conjunction [y]:

[x ∈_{c} y →^{val} y =^{r} ⌈x ∧_{c} y⌉ \{ \begin{matrix}If(x ∈_{c} y^{1}, T, x ∈_{c} y^{2}) \\ x =^{t} y \end{matrix} ]

Furthermore, we need a function [claims(t, c, r)] which is true if the term [t] belongs to the potentially inherited claim of page [r] according to the cache [c]:

[claims(t, c, r) →^{val}
If(claims_{2}(t, c, r), T, claims_{2}(t, c, c[r]["bibliography"]^{1}))]
[claims_{2}(t, c, r) →^{val} If(¬r^{c}, t!c!F, t ∈_{c} c[r]["codex"][r][0][0]["claim"]^{3})]

6.6.2 The proof aspect

The “proves” predicate in Section 6.5.5 is useful for testing the validity of a single, stand-alone proof which proves some lemma from scratch without reference to any auxilliary lemmas.

For more complex proofs, we introduce a proof aspect and make the convention that whenever a construct has a proof aspect, then the construct should also have a statement aspect and, furthermore, the proof aspect should be a proof of the statement aspect. We make the proof aspect self-evaluating and use [proof] to denote it:

[<proof> →^{val} ⌈<proof>⌉]
[proof →^{msg} <proof>]

From the point of view of Logiweb, lemmas and proofs are just definitions:

[[Lemma x: y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[Lemma x: y] ¨= [x →^{stmt} y]]⌉)]

[[Proof of x: y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[Proof of x: y] ¨= [x →^{proof} y]]⌉)]

The following construct provides a reader friendly way of stating that a statement [z] is provable in a theory [x] and giving the conjecture the name [y].

[[x lemma y: z] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x lemma y: z] ¨= [y =^{stmt} x ⊢

z]]⌉)]

As an example of use,

[HeadNil′′ →^{stmt} T′_{E} ⊢ T^{h} = T]

conjectures that [T^{h} = T] is provable in [T′_{E}].

The following construct provides a reader friendly way of stating that a statement [z] is disprovable in a theory [x] and giving the anticonjecture the name [y].

[[x antilemma y: z] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x antilemma y: z] ¨= [x lemma y: z ⊢

⊥ ⊥]]⌉)]

As an example of use,

[Contra′′ →^{stmt} T′_{E} ⊢ T : : T = T ⊢ ⊥ ⊥]

conjectures that [T : : T = T] is disprovable in [T′_{E}].

6.6.3 Verifier

The [verifier] checks the correctness of all proofs on a page. It is suited to appear in a conjunction that makes up the claim of a page. The verifier ignores the macro expanded tree [t] and merely uses the cache [c].

[verifier →^{val} λt.λc.V_{1}(c)]

[V_{1}(c)] extracts the reference [r] of the page to be checked from the cache [c] of the page. Then it extracts the subcodex [x] of all domestic definition of the page and uses [V_{2}(c, x)] to evaluate the array of proofs into an array [p] of sequents. Then it uses [V_{3}(c, r, p, d)] to verify the correctness of all proofs.

[V_{1}(c) →^{val}

let_{1}(λr. let_{1}(λx. let_{1}(λp. let_{1}(λd. If(¬d, d, let_{1}(λi. If(¬i^{c}, T, error_{2}(⌈“Circular proof. Circle includes:”⌉, p[i]^{0}^{h})), V_{5}(c, r, p, p))), V_{3}(c, r, p, T)), V_{2}(c, x)), c[r]["codex"][r]), c[0])]

[V_{2}(c, p)] evaluates all proofs in the subcodex [p] and returns the result as a onedimensional array of sequents (indexed by the identifier of each proof). [V_{2}(c, p)] is not particularly efficient since it continues to evaluate all proofs even if one of the proofs returns an error message.

For each symbol in the subcodex, [V_{2}(c, p)] extracts the proof definition [d] (i.e. the right hand side of the [<proof>] aspect) of the symbol. If the proof aspect exists (i.e. differs from [T]) then [V_{2}(c, p)] uses the evaluator [E(d, T, c)] to compute the value of [d], applies the result to the cache [c] in order to give access to the cache from proof tactics inside [d], and then uses the sequent evaluator [S(c, t)] to evaluate the proof into a sequent.

[V_{2}(c, p) →^{val} c!

If(p, T,

If(¬p^{h}^{c}, V_{2}(c, p^{h}) : : V_{2}(c, p^{t}), p^{h} : :

let_{1}(λd.

If(d, T, let_{1}(λr. If(r^{E}, error_{2}(⌈“Error in proof of”⌉, d^{2}⌈“ ”⌉^{1}r), r), S(c, U^{M}(E(d^{3}, T, c) ‘ c ‘ p)))), aspect(<proof>, p^{t}))))]

[V_{3}(c, r, p, d)] returns the diagnose [d] if [d] differs from [T]. Otherwise, it traverses the array [p] of sequents and checks each sequent [q] for correctness. During the check, [i] is bound to the identifier of the proof being checked and [d] is bound to the lemma being checked.

[V_{3}(c, r, p, d) →^{val} c!r!p! If(¬d, d, If(p, T, If(¬p^{h}^{c}, V_{3}(c, r, p^{t}, V_{3}(c, r, p^{h}, T)), let_{1}(λi. let_{1}(λq. If(q, T, If(q^{E}, q, If(¬q^{1}, error_{2}(⌈“Unchecked sidecondition:”⌉, q^{1}^{h}), let_{1}(λd. If(d, error_{2}(⌈“Proof of non-existent lemma:”⌉, q^{2}), If(¬q^{2} =^{t} d^{3}, error_{2}(⌈“Lemma/proof mismatch:”⌉, d^{2}; q^{2}), V_{4}(c, q^{0}))), aspect(<stmt>, c[r]["codex"][r][i]))))), p^{t}), p^{h}))))]

[V_{4}(c, p)] checks that the list [p] of premises consists of proved lemmas. That is done by verifying that each member of [p] has a proof and belongs to a correct page that lists the verifier among its claims. The page being verified is considered correct during the check since the diagnose aspect is not yet set while checking the page. The only thing [V_{4}(c, p)] does not check for is circular proofs (e.g. proofs that make use of the lemma they prove). Checking for circularity is done elsewhere.

[V_{4}(c, p) →^{val} c!

If(p, T, let_{1}(λd. If(¬d, d, let_{1}(λp. let_{1}(λr. let_{1}(λi. If(¬c[r]["diagnose"], error_{2}(⌈“Reference to erroneous page”⌉, p), If(¬claims(⌈verifier⌉, c, r), error_{2}(⌈“Reference to unchecked lemma”⌉, p), If(aspect(<proof>, p, c), error_{2}(⌈“Reference to unproved lemma”⌉, p), T))), p^{i}), p^{r}), p^{h})), V_{4}(c, p^{t})))] [V_{7}(c, r, i, q)] takes as input an array [q] that contains the conclusions of all proofs on the present page. These conclusions are all sequents and they are indexed by the identifiers of the symbols they belong to.

The sequents are allowed to have unresolved premises provided the premises are proved elsewhere. Furthermore, the directed graph with sequents as nodes and premises as edges is required to be non-cyclic. [V_{7}(c, r, i, q)] performs a search for cycles.

Logiweb pages and Logiweb bibliographic references form a non-cyclic graph, so whenever a premise refers to a lemma proved on another page, that premise cannot be part of a cycle. For that reason, [V_{7}(c, r, i, q)] ignores premises whose reference differs from the reference [r] of the page being checked.

[V_{7}(c, r, i, q)] checks all nodes and edges reachable from the node with identifier [i] for cycles. If a cycle is found, the identifier of one of the nodes in the cycle is returned. Hence, a return value which is a cardinal indicates that a cycle is found. Otherwise, [V_{7}(c, r, i, q)] replaces all reachable nodes in [q] by the cardinal [1] and returns the modified [q].

When [V_{7}(c, r, i, q)] reaches a node that is set to [1] then it assumes that that node has already been checked for cycles.

During the search for cycles, [V_{7}(c, r, i, q)] temporarily sets all nodes being considered to [0]. When [V_{7}(c, r, i, q)] reaches a node that is set to [0] it assumes that a cycle has been found and returns the identifier of the node.

[V_{7}(c, r, i, q) →^{val} c!r!
let_{1}(λv.
If(v, q,
If(v ≈ 0, i,
If(v ≈ 1, q,
let_{1}(λq.
If(q^{c}, q, q[i→1]), V_{6}(c, r, v^{0}, q[i→0]))))), q[i])]

[V_{6}(c, r, p, q)] checks all indices in the list [p] if premises for circularity in the array [q] of sequents.

[V_{6}(c, r, p, q) →^{val} c!r!p!
If(q^{c}, q,
If(p, q,
let_{1}(λq.
If(q^{c}, q,
If(¬r ≈ p^{h}^{r}, q,
V_{7}(c, r, p^{h}^{i}, q))), V_{6}(c, r, p^{t}, q))))]

[V_{5}(c, r, a, q)] checks all indices in the array [a] for circularity in the array [q] of sequents.

[V_{5}(c, r, a, q) →^{val} c!r!a!
If(q^{c}, q,

If(a, q,
If(¬a^{h}^{c}, V_{5}(c, r, a^{t}, V_{5}(c, r, a^{h}, q)),
V_{7}(c, r, a^{h}, q))))]

6.6.4 The rule lemma tactic

In Section 6.6.2 we stated two lemmas:

[HeadNil′′ →^{stmt} T′_{E} ⊢ T^{h} = T]

[Contra′′ →^{stmt} T′_{E} ⊢ T : : T = T ⊢ ⊥ ⊥]

Both lemmas are trivial; they are both instances of the general fact that all rules of a theory are provable in the theory. It is rather straightforward to prove both lemmas using suitable sequent operations but instead of writing a handmade proof for each lemma we shall write a proof tactic which, given a theory and a rule of the theory, generates a proof that the rule follows from the theory. We shall refer to the tactic as the [Rule tactic], and we shall arrange that the following become valid proofs of the above lemmas:

[HeadNil′′ →^{proof} Rule tactic]

[Contra′′ →^{proof} Rule tactic]

We define the rule tactic thus:

[Rule tactic →^{val} λc.λp.rule(c, p)]

When invoked from the verifier, the tactic is applied to the cache [c] of the current page and a pair [p] whose first component is the identifier of the lemma to be proved and whose second component is the subcodex containing all aspects of that lemma. The rule tactic passes control to the function below.

[rule(c, p) →^{val} c!

let_{1}(λs.

If(s, ⌈“Rule has no statement aspect”⌉,

If(¬s =^{r} ⌈x ⊢ y⌉, error_{2}(⌈“Rule has invalid statement aspect”⌉, s),

let_{1}(λt.

If(t, ⌈“Theory has no statement aspect”⌉,

let_{1}(λr.

If(r^{c}, error_{2}(⌈“The theory does not assert the given rule”⌉, s; t),

s^{1} ⊢ Cut(s^{1}^{I}^{⊳} ^{∗}, r)), rule_{1}(s^{2}, t))), aspect(<stmt>, s^{1}, c)^{3}))), aspect(<stmt>, p^{t})^{3})]

The function above finds out what the rule tactic is supposed to prove and then passes control to the function below for constructing the proofs.

[rule_{1}(s, t) →^{val}

If(s =^{t} t, T,

If(¬t =^{r} ⌈x ⊕ y⌉, 0,

let_{1}(λp.

If(¬p^{c}, Cut(Head_{⊕}(t), p),

let_{1}(λp.

If(¬p^{c}, Cut(Tail_{⊕}(t), p), 0), rule_{1}(s, t^{2}))), rule_{1}(s, t^{1}))))]

The function above searches for the given rule in the given theory. When found, it constructs a proof using the three proof constructors below.

[Cut(a, b) →^{val} If(b, a, a; b)]
[Head_{⊕}(s) →^{val} s^{1} ⊢ s^{2} ⊢ s^{1}^{I}^{⊳} ^{+}^{⊳} ]
[Tail_{⊕}(s) →^{val} s^{1} ⊢ s^{2}^{I}^{+}^{⊳} ]

6.6.5 Stating rules

The rule tactic of the previous section allows to prove that all rules of a theory are provable in the theory. The following macros allow to express lemma and proof in one go:

[[x rule y: z] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x rule y: z] ¨= [x lemma y: z][Proof of y: Rule tactic]]⌉)]

[[x antirule y: z] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x antirule y: z] ¨= [x rule y: z ⊢

⊥ ⊥]]⌉)]

Having these constructs it is easy to state that all four rules of [T′_{E}] are provable in [T′_{E}]:

[HeadNil′′ →^{stmt} T′_{E} ⊢ T^{h} = T][HeadNil′′ →^{proof} Rule tactic]

[HeadPair′′ →^{stmt} T′_{E} ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a}][HeadPair′′ →^{proof} Rule tactic]

[Transitivity′′ →^{stmt} T′_{E} ⊢ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c}][Transitivity′′ →^{proof} Rule tactic]

[Contra′′ →^{stmt} T′_{E} ⊢ T : : T = T ⊢ ⊥ ⊥][Contra′′ →^{proof} Rule tactic]

6.6.6 Stating theories

We have now defined the theory [T′_{E}] and stated the four rule lemmas there are for that theory, namely one for each rule of the theory. Once the rules are stated, the definition if [T′_{E}] is a bit redundant since the four rules contain all information about the theory.

We now define the theory and the four rule lemmas once more, but in a more elegant way:

[HeadNil →^{stmt} T_{E} ⊢ T^{h} = T][HeadNil →^{proof} Rule tactic]

[HeadPair →^{stmt} T_{E} ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a}][HeadPair →^{proof} Rule tactic]

[Transitivity →^{stmt} T_{E} ⊢ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c}][Transitivity →^{proof} Rule tactic]

[Contra →^{stmt} T_{E} ⊢ T : : T = T ⊢ ⊥ ⊥][Contra →^{proof} Rule tactic]

[T_{E} →^{stmt} ∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ T : : T = T ⊢ ⊥ ⊥ ⊕ T^{h} = T ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c}]

In the next section we define [Theory x] such that [Theory T_{E}] macro expands into a definition which defines the statement aspect of [T_{E}] to be a conjunction of [T^{h} = T], [∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a}], [∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c}], and [T : : T = T ⊢ ⊥ ⊥], in some, arbitrary order.

When [Theory x] is macro expanded, it scans the codex of the page it occurs on for rules that belong to the theory [x], then forms a conjunction of the rules found, and then constructs a suitable definition for [x].

6.6.7 Rule collection

Here is the macro for collecting all rules of a theory from the codex:

[[Theory n] →^{macro} λt.λs.λc.theory_{2}(t, c)]

[theory_{2}(t, c) →^{val}

let_{1}(λn. let_{1}(λs. Q̃(t, ⌈[n →^{stmt} x]⌉, s), ⌈n⌉ : : n : : ⌈x⌉ : : theory_{3}(c, n) : : T), t^{1})]

[theory_{3}(c, n) →^{val} n!

let_{1}(λr.

theory_{4}(c[r]["codex"][r], n, T), c[0])]

[theory_{4}(c, n, s) →^{val} n!

If(c, s,

If(¬c^{h}^{c}, theory_{4}(c^{t}, n, theory_{4}(c^{h}, n, s)),

If(¬aspect(<proof>, c^{t})^{3} =^{t} ⌈Rule tactic⌉, s,

let_{1}(λd.

If(¬d^{1} =^{t} n, s,

Plus(d^{2}, s)), aspect(<stmt>, c^{t})^{3}))))]

[Plus(a, b) →^{val} If(b, a, a ⊕ b)] 6.6.8 Example lemmas

One may think of the Logiweb sequent calculus as an assembly language for expressing proofs. Proofs directly expressed in the calculus are somewhat obscure to read and write, but before we solve that problem in Section 6.8, we state and prove two lemmas the hard way. The first lemma proves reflexivity in the [T_{E}] theory:

[Reflexivity →^{stmt} T_{E} ⊢ ∀\underline{a}: \underline{a} = \underline{a}]

[Reflexivity →^{proof} ⌈T_{E} ⊢ ∀\underline{a}: HeadPair^{I}^{⊳} ^{∗}^{⊳} @ \underline{a} @ \underline{a}; Transitivity^{I}^{⊳} ^{∗}^{⊳} @ \underline{a} : : \underline{a}^{h} @ \underline{a} @ \underline{a}^{⊳} ^{⊳} ⌉]

Now that we have reflexivity available, we may use it to prove commutativity in [T_{E}]:

[Commutativity →^{stmt} T_{E} ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} = \underline{b} ⊢ \underline{b} = \underline{a}]

[Commutativity →^{proof} ⌈T_{E} ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} = \underline{b} ⊢ Reflexivity^{I}^{⊳} ^{∗}^{⊳} @ \underline{a}; Transitivity^{I}^{⊳} ^{∗}^{⊳} @ \underline{a} @ \underline{b} @ \underline{a}^{⊳} ^{⊳} ⌉]

As can be seen on the diagnose hook of the present page, the proofs above are correct according the the machine check made by the verifier.

6.7 Unification

The facilities defined in Section 6.8 for expressing proofs in a human-tolerant style makes use of unification. Section 6.7 implements unification.

6.7.1 Parameter terms

We shall refer to terms in which bound metavariables are replaced by cardinals as parameter terms. The function [parm(t, s, n)] converts an ordinary term [t] into a parameter term in which numbers are constructed from [n] using [b +2∗ n] iteratively. When calling [parm(t, s, n)], [s] should be [T].

[parm(t, s, n) →^{val} n!
If(t =^{r} ⌈∀x: y⌉, ∀n: parm(t^{2}, t^{1} : : n : : s, T +2∗ n),
let_{1}(λm.
If(¬m, m, t^{R} : : parm^{∗}(t^{t}, s, n)), lookup(t, s, T)))]
[parm^{∗}(t, s, n) →^{val} s!n!If(t^{a}, T, parm(t^{h}, s, n) : : parm^{∗}(t^{t}, s, n))]

6.7.2 Substitutions

We shall refer to an array of parameter terms as a substitution. The following function instantiates a parameter term [t] using a substitution [s]:

[inst(t, s) →^{val} If(t^{c}, inst(s[t], s), t^{R} : : inst^{∗}(t^{t}, s))]

[inst^{∗}(t, s) →^{val} s!If(t^{a}, T, inst(t^{h}, s) : : inst^{∗}(t^{t}, s))]

Instantiation may loop indefinitely. As an example, a substitution which maps [\underline{a}] to [\underline{a} : : \underline{a}] will keep expanding [\underline{a}] forever. We shall say that a substitution [s] is circular if there exists a term [t] for which [inst(t, s)] loops indefinitely.

6.7.3 Occurrence

[occur(t, u, s)] is true if the parameter [t] occurs in [inst(u, s)]. [occur(t, u, s)] may loop indefinitely if the substitution [s] is circular.

[occur(t, u, s) →^{val} s!If(u^{c}, If(t ≈ u, T, occur(t, s[u], s)), occur^{∗}(t, u^{t}, s))]
[occur^{∗}(t, u, s) →^{val} t!s!If(u^{a}, F, If(occur(t, u^{h}, s), T, occur^{∗}(t, u^{t}, s)))]

6.7.4 Unifications

We shall refer to the result of applying a substitution to a parameter term as an instance of the term. We shall refer to a common instance of two parameter terms as a unification of the terms. As an example, [\underline{a} : : F] and [T : : \underline{b}] (where [\underline{a}] and [\underline{b}] denote numbers) have exactly one unification, namely [T : : F]. We shall say that two terms are compatible if they have at least one unification and incompatible otherwise.

A substitution which yields the same result when applied to two terms [u] and [v] is said to unify the terms. As an example, the substitution which maps [\underline{a}] to [T] and [\underline{b}] to [F] unifies [\underline{a} : : F] and [T : : \underline{b}].

The unification algorithm presented in the following takes two terms as input and returns a unifying substitution if the terms are compatible. As an example, when applied to [\underline{a} : : F] and [T : : \underline{b}], the unification algorithm returns the substitution which maps [\underline{a}] to [T] and [\underline{b}] to [F].

There is more than one substitution which unifies [\underline{a} : : F] and [T : : \underline{b}]. As an example the substitution that maps [\underline{a}] to [T], [\underline{b}] to [F], and [\underline{c}] to some term [x] also unifies [\underline{a} : : F] and [T : : \underline{b}].

6.7.5 Unification algorithm

The original unification algorithm by Robinson takes a set of equations (i.e. a set of pairs of parameter terms) as input and unifies all the pairs. In contrast, [unify(t = u, s)] defined below adds the result of unifying [t] and [u] to the substitution [s]. To unify a set of equations one should start with the empty substitution [T] and call [unify(t = u, s)] once for each equation.

[unify(t = u, s)] extends the substitution [s] to a substitution that unifies [t] with [u] if such a substitution exists and returns [0] otherwise. In particular, [unify(t = u, s)] returns zero if [s] equals zero since in that case there is no substitution to extend.

[unify(t = u, s)] calls to auxiliary functions, [unify_{2}(t = u, s)] and [unify^{∗}(t = u, s)]. [unify_{2}(t = u, s)] does the same as [unify(t = u, s)] but only covers the special case where [t] is a parameter. [unify^{∗}(t = u, s)] unifies two lists [t] and [u] of parameter terms.

[unify(t = u, s)] errors out if [s ≈ 0], calls [unify_{2}(∗ = ∗, ∗)] if [t] or [u] happens to be a parameter, and calls [unify^{∗}(∗ = ∗, ∗)] otherwise:

[unify(t = u, s) →^{val} t!u!
If(s^{c}, s,
If(t^{c}, unify_{2}(t = u, s),
If(u^{c}, unify_{2}(u = t, s),
If(t =^{r} u, unify^{∗}(t^{t} = u^{t}, s), 0))))]

[unify^{∗}(t = u, s)] iterates [unify(t = u, s)]; it depends on the fact that [unify(t = u, s)] equals zero if [s] equals zero so that failure to find a unification propagates.

[unify^{∗}(t = u, s) →^{val} u!If(t^{a}, s, unify^{∗}(t^{t} = u^{t}, unify(t^{h} = u^{h}, s)))]

[unify_{2}(t = u, s)] extends the substitution [s] with the result of unifying the parameter [t] with the parameter term [u]. [s] is assumed to be a genuine substituion (i.e. not zero). Furthermore, [s] is assumed to be non-circular.

[unify_{2}(t = u, s)] first tests [t] and [u] for equality. If they are equal, they are already unified and [s] is returned. Otherwise, if [s] already associates the parameter [t] with a term, then [unify_{2}(t = u, s)] unifies [u] with that term. Otherwise, [unify_{2}(t = u, s)] extends the substitution [s] with an association from [t] to [u]. If [occur(t, u, s)] is true, however, such an association would create a circular substitution. In that case no unification exists and [unify_{2}(t = u, s)] returns zero:

[unify_{2}(t = u, s) →^{val}

If(t ≈ u, s, let_{1}(λt′. If(¬t′, unify(t′ = u, s), If(occur(t, u, s), 0, s[t→u])), s[t]))]

6.8 Proof generation

6.8.1 Proof tactics

Counted in sequent operators, proofs typically comprise a small amount of original thought and a lot of trivial derivations. Frequently, trivial derivations can be generated by computer programs. Such programs are typically called tactics or proof tactics [8].

To support proof tactics, we introduce a tactic aspect for defining them and a proof expander for evaluating them. The proof evaluator evaluates proof tactics and generates sequent proofs, which the proof evaluator may then evaluate to sequents.

The proof expander is itself a tactic since it generates proofs. The proof expander is a value defined tactic like the rule lemma tactic defined previously. But the proof expander is a particularly general tactic which brings life to tactics that are defined using the “tactic aspect” which is introduced later.

6.8.2 Medium level proofs

The proof tactics and the proof expander defined later can translate medium level proofs like those below to Logiweb sequent calculus proofs like those in Section 6.6.8. Actually, the proofs below exactly translate to the proofs in Section 6.6.8. We start out proving reflexivity:

[Reflexivity_{1} →^{stmt} T_{E} ⊢ ∀\underline{a}: \underline{a} = \underline{a}]

[Reflexivity_{1} →^{proof} λc.λx.P(⌈T_{E} ⊢ ∀\underline{a}: HeadPair ≫ \underline{a} : : \underline{a}^{h} = \underline{a}; Transitivity ⊳ \underline{a} : : \underline{a}^{h} = \underline{a} ⊳ \underline{a} : : \underline{a}^{h} = \underline{a} ≫ \underline{a} = \underline{a}⌉, p_{0}, c)]

In the proof above, the first line declares that [\underline{a}] denotes an arbitrary term.

The second line uses [HeadPair] to prove [\underline{a} : : \underline{a}^{h} = \underline{a}]. In Section 6.6.8, that statement is proved by [HeadPair^{I}^{⊳} ^{∗}^{⊳} @ \underline{a} @ \underline{a}]. As we shall see, the tactic introduced in Section 6.8.6 adds the [∗^{I}^{⊳} ^{∗}^{⊳} ] formula for referencing lemmas. That tactic also adds the [⋯ @ \underline{a} @ \underline{a}] for instantiating the meta-quantifiers in [HeadPair]. The tactic uses unification and [⋯ ≫ \underline{a} : : \underline{a}^{h} = \underline{a}] to decide that both meta-quantifiers should be instantiated to an [\underline{a}].

The third line uses [Transitivity] and the meta-modus-ponens operator [∗⊳∗] to prove [\underline{a} = \underline{a}]. The tactic defined in Section 6.8.6 translates a meta-modus-ponens into a modus operation followed by a cut (c.f. the expanded proof in Section 6.6.8).

The tactic can expand modus ponens [∗ ⊳ ∗] and modus probans [∗ ⊳ ⊳ ∗]. Modus ponens says that if [\underline{a}] is proved and [\underline{a}] infers [\underline{b}] then we may conclude [\underline{b}]. Modus probans (“probans” for “approve”) says that if [\underline{a}] is known to evaluate to [T] and the side condition [\underline{a}] endorses [\underline{b}] then we may conclude [\underline{b}].

The tactic eliminates side conditions using modus probans when told to do so using [∗ ⊳ ⊳ ∗] and otherwise eliminates them using the [∗^{V}] sequent operation which actually evaluates the side condition. Modus probans is useful in situations where a lemma assumes some side condition to hold. Assumed sideconditions are introduced in proofs using a Side-condition operation which is similar to the Premise used in Line 3 of the proof of [Commutativity_{1}] stated in a moment.

Line 3 above contains two references to Line 2. Each reference expands into the conclusion of Line 2 at macro expansion time. Hence, Line 3 reads [Transitivity ⊳ \underline{a} : : \underline{a}^{h} = \underline{a} ⊳ \underline{a} : : \underline{a}^{h} = \underline{a} ≫ \underline{a} = \underline{a}] when the proof tactic is invoked.

Now let us turn to the proof of [Commutativity_{1}]:

[Commutativity_{1} →^{stmt} T_{E} ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} = \underline{b} ⊢ \underline{b} = \underline{a}]

[Commutativity_{1} →^{proof} λc.λx.P(⌈T_{E} ⊢ ∀\underline{a}: ∀\underline{b}: \underline{a} = \underline{b} ⊢ Reflexivity_{1} ≫ \underline{a} = \underline{a}; Transitivity ⊳ \underline{a} = \underline{b} ⊳ \underline{a} = \underline{a} ≫ \underline{b} = \underline{a}⌉, p_{0}, c)]

The proof above only contains one new thing: Line 3 assumes [\underline{a} = \underline{b}].

6.8.3 The “tactic” aspect

We now return to the actual implementation of proof tactics and the proof expander. We make the [<tactic>] aspect self-evaluating and use [tactic] to denote it:

[<tactic> →^{val} ⌈<tactic>⌉]
[tactic →^{msg} <tactic>]

For convenience, we define a construct for making tactic definitions:

[[x =^{tactic} y] →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[[x =^{tactic} y] ¨= [(x)^{p} →^{tactic} y]]⌉)]

6.8.4 The proof expander

The proof expander [P(t, s, c)] proof expands the term [t] for the proof state [s] and the cache [c] and returns the result as a semitagged map. The untagged version [U(P(t, s, c))] is the expansion itself.

The proof expander [P(t, s, c)] differs from the macro expander [M(t, s, c)] in that it has no special treatment for page symbols and in that it uses the [tactic] aspect instead of the [macro] aspect.

When proofs are expanded, they are first macro expanded and then proof expanded. Macro expansion is done iteratively until the codex reaches a fixed point whereas proof expansion is done only once. Furthermore, the result of macro expansion is kept in the codex whereas the result of proof expansion is discarded as soon as a proof is checked. Hence, proof expansion is a momentary burden to the computers memory whereas macro expansion is chronic.

The definition of [P(t, s, c)] is almost identical to that of [M(t, s, c)]. But it is easier to express since we can use macros like the ‘let’ macro when defining proof expansion. For obvious reasons, macros cannot be used when defining the notion of macro expansion. The definition of [P(t, s, c)] reads:

[P(t, s, c) →^{val} s!

let_{1}(λd.

If(d, t^{h} : : P^{∗}(t^{t}, s, c),

U^{M}(E(d^{3}, T, c) ‘ t ‘ s ‘ c)), aspect(<tactic>, t, c))]

[P^{∗}(t, s, c) →^{val} s!c!If(t, T, P(t^{h}, s, c) : : P^{∗}(t^{t}, s, c))]

6.8.5 The initial proof state

Proof states have exactly the same format as macro states.

The initial proof state [p_{0}] is useful for passing as the second parameter to [P(t, s, c)]. [p_{0}] is a pair whose head is the proof expander itself and whose tail is left blank. The definition of [p_{0}] reads:

[p_{0} →^{val} M(λt.λs.λc.P(t, s, c)) : : T]

The function [M̃(t, s, c)] defined previously macro expands the term [t] using the macro expander embedded in the macro state [s] using the cache [c]. Since proof states have exactly the same syntax and semantics as macro states, we shall take the liberty to use [M̃(t, s, c)] for proof states also.

6.8.6 The conclusion tactic

The conclusion tactic [x ≫ y] constructs a proof of [y] from the partial proof [x] as described in Section 6.8.2.

Among other, the tactic tactic expands modus ponens [x ⊳ y] and modus probans [x ⊳ ⊳ y] which we make self-evaluating:

[x ⊳ y →^{val} ⌈x ⊳ y⌉^{R} : : x : : y : : T]

[x ⊳ ⊳ y →^{val} ⌈x ⊳ ⊳ y⌉^{R} : : x : : y : : T]

The conclusion tactic is defined thus:

[x ≫ y →^{tactic} λt.λs.λc.conclude_{1}(t, c)]

[conclude_{1}(t, c) →^{val} let_{1}(λr. If(r^{c}, error_{2}(⌈“Unification failed”⌉, t), r), conclude_{2}(t^{1}, t^{2}, c))]

[conclude_{2}(a, t, c) →^{val} t! If(a =^{r} ⌈x ⊳ y⌉, conclude_{2}(a^{1}, a-color(t ⊳ a^{2}), c), If(a =^{r} ⌈x ⊳ ⊳ y⌉, conclude_{2}(a^{1}, a-color(t ⊳ ⊳ a^{2}), c), If(a =^{r} ⌈x @ y⌉, conclude_{2}(a^{1}, a-color(t @ a^{2}), c), If(aspect(<proof>, a, c), error_{2}(⌈“Lemma expected”⌉, a), let_{1}(λd. conclude_{3}(a-color(conclude_{4}(a^{I}^{⊳} ^{∗}^{⊳} , d^{3}^{2})), t, parm(d^{3}^{2}, T, 1), T), aspect(<stmt>, a, c))))))]

[conclude_{3}(a, t, l, s) →^{val} a!t!l!s!

If(l =^{r} ⌈x ⊢ y⌉,

t =^{r} ⌈x ⊳ y⌉ \{ \begin{matrix}conclude_{3}(a^{⊳} , t^{1}, l^{2}, unify(l^{1} = t^{2}, s)) \\ conclude_{3}(a^{⊳} , t, l^{2}, s) \end{matrix} ,

If(l =^{r} ⌈x ⊢⊢ y⌉,

t =^{r} ⌈x ⊳ ⊳ y⌉ \{ \begin{matrix}conclude_{3}(a^{⊳} , t^{1}, l^{2}, unify(l^{1} = t^{2}, s)) \\ conclude_{3}(a^{V}, t, l^{2}, s) \end{matrix} ,

If(l =^{r} ⌈∀x: y⌉,

t =^{r} ⌈x @ y⌉ \{ \begin{matrix}conclude_{3}(a @ t^{2}, t^{1}, l^{2}, unify(l^{1} = t^{2}, s)) \\ conclude_{3}(a @ l^{1}, t, l^{2}, s) \end{matrix} ,

let_{1}(λs. If(s^{c}, s, inst(a, s)), unify(l = t, s)))))] [conclude_{4}(a, l) →^{val} a!l!

If(¬l =^{r} ⌈∀x: y⌉, a,

let_{1}(λv.∀v: conclude_{4}(a @ v, l^{2}), ⌈\underline{∗}⌉^{R} : : l^{1} : : T))]

6.8.7 Proof constructors

The following macros make it easy to construct medium level proofs:

[t proof of s : p →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[t proof of s : p ¨= [Proof of s: λc.λx.P(⌈t ⊢ p⌉, p_{0}, c)]]⌉)]

[Line l : a ≫ i; p →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Line l : a ≫ i; p ¨= (a ≫ i; let l ¨= i in p)]⌉)]

[Last line a ≫ i □ →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Last line a ≫ i □ ¨= (a ≫ i)]⌉)]

[Line l : Premise ≫ i; p →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Line l : Premise ≫ i; p ¨= (i ⊢ let l ¨= i in p)]⌉)]

[Line l : Side-condition ≫ i; p →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Line l : Side-condition ≫ i; p ¨= (i ⊢⊢ let l ¨= i in p)]⌉)]

[Arbitrary ≫ i; p →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Arbitrary ≫ i; p ¨= (∀i: p)]⌉)]

[Local ≫ a = i; p →^{macro} λt.λs.λc.M̃_{4}(t, s, c, ⌈[Local ≫ a = i; p ¨= (let a ¨= i in p)]⌉)]

Some of the constructs look different when used in proofs. As an example, the “Arbitrary” construct above gets a line number when used in a proof (or, more precisely, when typeset using the tex aspect instead of the tex name aspect).

Line numbers in proofs are generated automatically. As an example, one may write

line ell a because tactic reflexivity indeed meta a math equal meta a end line ...

in a pyk source text to get a numbered proof line saying [Reflexivity_{1} ≫ \underline{a} = \underline{a}]. The line number is assigned automatically, and afterwards references to “ell a” will refer to that line number.

A TEX definitions

A.1 The TEX language

From the point of view of Logiweb, TEX is an output format intended for the creation of beautiful Logiweb pages—and especially for Logiweb pages that contain a lot of mathematics (c.f. the preface of the TEXbook [7]). The PDF version of the present page is produced by the TEX system (including L^{A}TEX) and a program named dvipdfm.

TEX is chosen for this purpose because of the high quality and great maturity of that system. Early version of Logiweb also used MathML, but support for that was removed for several reasons, one of which was a desire to reduce the number of output formats to exactly one.

One application of Logiweb could be straightforward translation of pyk to TEX. A major purpose of Logiweb, however, is to allow the Logiweb system to understand the mathematics present on Logiweb pages. In particular, Logiweb is able to check proofs and execute programs defined on Logiweb pages.

A.1.1 Use of newline characters

As we shall see later,

[x →^{tex} “

\mathsf{x}”]

macro expands into

[x →^{tex} “

\mathsf{x}”]

which in turn defines the tex aspect of [x] to be a string that starts with a newline character followed by \mathsf{x}.

Internally, Logiweb consistently uses Unicode 10 for the newline character. Whenever Logiweb runs on a host operating system that uses another character or character sequence between lines of text, newline characters have to be translated in the interface between Logiweb and the operating system.

The tex definition above states that whenever Logiweb renders an [x] using the TEX system, it dumps ↓\mathsf{x} to a file and runs it through TEX (where the down arrow represents the newline character).

As another example, the pairing construct [x : : y] introduced later has the following tex aspect:

[x : : y →^{tex} “#1.

\mathrel { : \, : }#2.”]

Arguments are represented by double quotes in pyk aspects. In tex aspects, arguments are represented by sequences of characters that start with a hash mark and end with a period. As an example, #117. denotes the 117’th argument of a construct. A hash mark immediately followed by a period as in “#.” denotes a hash mark.

When sending text through TEX one has to be careful about newline characters. Firstly, one should avoid making lines that are too long for TEX or the host operating system. Secondly, one should avoid producing two newline characters in sequence since TEX assigns a special meaning to repeated newline characters.

To fulfill both, the present page makes the following convention for tex aspects: A newline character is added in front of the string whenever the string starts with a character rather than an argument. Furthermore, a newline character is inserted whenever a character follows an argument. Newlines are omitted, however, if they disturb TEX in achieving the intended rendering.

A.1.2 Interpretation of the tex aspect

Looking at the pyk source of the present page reveals that the tex aspect of the entire page looks like this:

        File page.tex
        ...
        End of file
        File page.bib
        ...
        End of file
        latex page
        makeindex page
        bibtex page
        latex page
        makeindex page
        latex page
        dvipdfm page

The tex aspect above is not run directly through TEX. Rather, it instructs an interpreter to place certain text in certain files and then run latex, bibtex, makeindex, and dvipdfm in a certain pattern.

For security reasons, the interpreter of the present system only allows execution of commands named tex, latex, bibtex, makeindex, and dvipdfm. Furthermore, the interpreter only accepts file names made up from the characters a to z, A to Z, 0 to 9, and dots.

At present, security holes in tex, latex, bibtex, makeindex, and dvipdfm may compromise security. For this and other reasons, these programs will run in a chroot gail in some future release of Logiweb.

A.1.3 The tex name aspect

Some constructs look different when using them and when talking about them.

As an example, consider ordinary typewriter text. When using a newline character, the character itself is invisible but has the effect that text following it starts on a new line. When talking about a newline character, one may call it “the newline character”. This way, a newline character is invisible when using it and consists of 19 characters and two spaces when talking about it.

As another example, the TEX bold face command may be called \bf when talking about it and changes the text that follows it to bold face when using it.

To cope with this, we introduce a tex name or name aspect to supplement the tex aspect:

[name ▷◁ “texname”]

The tex name aspect should be such that it can be typeset in TEX math mode. The tex name aspect defaults to the tex aspect, so if the tex and tex name aspects of a construct are identical then one should only define the tex aspect. (The tex aspect in turn defaults to something that is constructed from the pyk aspect, and the pyk aspect in turn defaults to something semi-readable constructed from the reference and identifier of the construct).

A.1.4 Uses of the tex name aspect

As an example of a construct for which the tex and tex name aspects differ, consider the following:

[ $x$ →^{tex} “$#1.$”]

[ $x$ →^{name} “

\ \$#1.\$\linebreak[0]\ ”]

The “math * end math” construct allows to insert mathematics in TEX horizontal mode by changing to math mode temporarily. The tex name aspect allows to talk about the construct. The left hand sides of the three definitions above are typeset using the tex name aspect.

Elaborating the example from the previous section, the pyk source of a definition like

[[y →^{x} z] ▷◁ “define”]

could read something like

math proclaim define var x of var y as var z end define as ⋯ end proclaim end math

The “math * end math” construct is invisible in the definition above but certainly affects the typography; without it, TEX would produce ugly error messages rather than beautiful typography.

By the way: note that “math * end math” changes to \rm immediately after changing to math mode. That is because Logiweb formulas contain loads of text and because the typography of e.g. variables is under tight control of Logiweb, so the defaults of TEX math mode are not the right ones for Logiweb.

A.1.5 Brackets

For completeness,

[bracket x end bracket →^{tex} “$[#1.]$”]

and

[big bracket x end bracket →^{tex} “$\left[#1.\right]$”]

are versions of “math * end math” that add brackets around the formula.

The latter adds large brackets using the large bracket facility of TEX, which is useful occasionally but which mainly leads to undesirable results. The large brackets in [5] adjust their height independently of their depth and allow line breaking of their argument. The brackets of [5] are not used here, however, because they would have an inconveniently large tex aspect.

By the way, two major Logiweb pages have been developed before Logiweb itself was developed. The first is [5] which is a three volume textbook on mathematics for first year computer science students used at the department of computer science at the University of Compenhagen as a replacement for discrete mathematics. The second is citegrue02b which contains a consistency proof for ZFC set theory expressed in Map theory. At the time of writing, these two are not yet published on Logiweb, but they have been drivers of the design of Logiweb.

A.1.6 The tex aspect of definitions

As stated in Appendix A.2, the TEX definition of [y →^{x} z] reads:

[[y →^{x} z] →^{tex} “

[#2/tex name/tex. \stackrel{#1. }{\rightarrow}#3. ]”]

In the definition, “#1.” says “insert the first argument (the aspect) here”. Likewise, “#3.” says “insert the third argument (the right hand side) here”.

The second argument (the left hand side), is more complicated. A definition talks about the left hand side rather than just using it. For that reason, the left hand side should be rendered using the tex name aspect instead of the tex aspect. On the other hand, if the left hand side has parameters, then those parameters should be rendered normally, i.e. using the tex aspect.

“#2/tex name/tex.” says “insert the second argument (the left hand side) here using the tex name aspect for the left hand side, but revert to the tex aspect for the parameters of the left hand side.

A.2 TEX definitions

[tex →^{tex} “

\mathrm{tex}”]

[flush left [x] →^{tex} “ \begin {flushleft}#1. \end {flushleft}”]

[flush left [x] →^{name} “ \mathbf{flush\ left\ }[ #1. ]”]

[x^{0} →^{tex} “#1.

{}ˆ {0}”]

[x^{1} →^{tex} “#1.

{}ˆ {1}”]

[x^{2} →^{tex} “#1.

{}ˆ {2}”]

[x^{3} →^{tex} “#1.

{}ˆ {3}”]

[x^{4} →^{tex} “#1.

{}ˆ {4}”]

[x^{5} →^{tex} “#1.

{}ˆ {5}”]

[x^{6} →^{tex} “#1.

{}ˆ {6}”]

[x^{7} →^{tex} “#1.

{}ˆ {7}”]

[x^{8} →^{tex} “#1.

{}ˆ {8}”]

[x^{9} →^{tex} “#1.

{}ˆ {9}”]

[x + y →^{tex} “#1.

+ #2.”]

[x +_{0} y →^{tex} “#1.

\mathop{+ 0} #2.”]

[x +_{1} y →^{tex} “#1.

\mathop{+ 1} #2.”]

[x < y →^{tex} “#1.

< #2.”]

[x <′ y →^{tex} “#1.

<’ #2.”]

[x ≤′ y →^{tex} “#1.

\le’ #2.”]

[x − y →^{tex} “#1.

- #2.”]

[x −_{0} y →^{tex} “#1.

\mathop{- 0} #2.”]

[x −_{1} y →^{tex} “#1.

\mathop{- 1} #2.”]

[x · y →^{tex} “#1.

\cdot #2.”]

[x ·_{0} y →^{tex} “#1.

\cdot 0 #2.”]

[bit(x, y) →^{tex} “ bit( #1. , #2. )”]

[bit_{1}(x, y) →^{tex} “ bit 1( #1. , #2. )”]

[x^{r} →^{tex} “#1.

{}ˆ {r}”]

[x^{i} →^{tex} “#1.

{}ˆ {i}”]

[x^{d} →^{tex} “#1.

{}ˆ {d}”]

[x^{R} →^{tex} “#1.

{}ˆ {R}”]

[x =^{r} y →^{tex} “#1.

\stackrel{r}{=} #2.”]

[identifier(x) →^{tex} “ identifier( #1. )”]

[identifier_{1}(x, y) →^{tex} “ identifier {1}( #1. , #2. )”]

[a[i→v] →^{tex} “#1.

[ #2. {\rightarrow} #3. ]”]

[array-plus(x, y) →^{tex} “ array\mbox{-}\linebreak[0]plus( #1. , #2. )”]

[array-remove(i, a, l) →^{tex} “ array\mbox{-}\linebreak[0]remove( #1. , #2. , #3. )”]

[array-put(i, v, a, l) →^{tex} “ array\mbox{-}\linebreak[0]put( #1. , #2. , #3. , #4. )”]

[array-add(i, v, i′, v′, l) →^{tex} “ array\mbox{-}\linebreak[0]add( #1. , #2. , #3. , #4. , #5. )”]

[a[i⇒v] →^{tex} “#1.

[ #2. {\Rightarrow} #3. ]”]

[x′ →^{tex} “#1.’”]

[rack →^{tex} “

rack”]

["vector" →^{tex} “ \mbox {\tt \char34}\mathrm {vector}\mbox {\tt \char34}”]

["bibliography" →^{tex} “ \mbox {\tt \char34}\mathrm {bibliography}\mbox {\tt \char34}”]

["dictionary" →^{tex} “ \mbox {\tt \char34}\mathrm {dictionary}\mbox {\tt \char34}”]

["body" →^{tex} “

\mbox {\tt \char34}\mathrm {body}\mbox {\tt \char34}”]

["codex" →^{tex} “ \mbox {\tt \char34}\mathrm {codex}\mbox {\tt \char34}”]

["expansion" →^{tex} “ \mbox {\tt \char34}\mathrm {expansion}\mbox {\tt \char34}”]

["code" →^{tex} “

\mbox {\tt \char34}\mathrm {code}\mbox {\tt \char34}”]

["cache" →^{tex} “ \mbox {\tt \char34}\mathrm {cache}\mbox {\tt \char34}”]

["diagnose" →^{tex} “ \mbox {\tt \char34}\mathrm {diagnose}\mbox {\tt \char34}”]

["value" →^{tex} “ \mbox {\tt \char34}\mathrm {value}\mbox {\tt \char34}”]

["pyk" →^{tex} “

\mbox {\tt \char34}\mathrm {pyk}\mbox {\tt \char34}”]

["tex" →^{tex} “

\mbox {\tt \char34}\mathrm {tex}\mbox {\tt \char34}”]

["texname" →^{tex} “ \mbox {\tt \char34}\mathrm {texname}\mbox {\tt \char34}”]

["message" →^{tex} “ \mbox {\tt \char34}\mathrm {message}\mbox {\tt \char34}”] ["macro" →^{tex} “

\mbox {\tt \char34}\mathrm {macro}\mbox {\tt \char34}”]

["definition" →^{tex} “ \mbox {\tt \char34}\mathrm {definition}\mbox {\tt \char34}”]

["unpack" →^{tex} “ \mbox {\tt \char34}\mathrm {unpack}\mbox {\tt \char34}”]

["claim" →^{tex} “ \mbox {\tt \char34}\mathrm {claim}\mbox {\tt \char34}”]

["priority" →^{tex} “ \mbox {\tt \char34}\mathrm {priority}\mbox {\tt \char34}”]

[aspect(a, c) →^{tex} “ \mathbf{aspect}( #1. , #2. )”]

[aspect(∗, ∗, ∗) →^{tex} “ \mathbf{aspect}( #1. , #2. , #3. )”]

["lambda" →^{tex} “ \mbox {\tt \char34}\mathrm {lambda}\mbox {\tt \char34}”]

["apply" →^{tex} “ \mbox {\tt \char34}\mathrm {apply}\mbox {\tt \char34}”]

["true" →^{tex} “

\mbox {\tt \char34}\mathrm {true}\mbox {\tt \char34}”]

["if" →^{tex} “

\mbox {\tt \char34}\mathrm {if}\mbox {\tt \char34}”]

["quote" →^{tex} “ \mbox {\tt \char34}\mathrm {quote}\mbox {\tt \char34}”]

["proclaim" →^{tex} “ \mbox {\tt \char34}\mathrm {proclaim}\mbox {\tt \char34}”]

["define" →^{tex} “ \mbox {\tt \char34}\mathrm {define}\mbox {\tt \char34}”] ["introduce" →^{tex} “

\mbox {\tt \char34}\mathrm {introduce}\mbox {\tt \char34}”]

["hide" →^{tex} “

\mbox {\tt \char34}\mathrm {hide}\mbox {\tt \char34}”]

["pre" →^{tex} “

\mbox {\tt \char34}\mathrm {pre}\mbox {\tt \char34}”]

["post" →^{tex} “

\mbox {\tt \char34}\mathrm {post}\mbox {\tt \char34}”]

[let x ¨= y in z →^{tex} “ \mathbf{let\ } #1. \mathrel{\ddot{=}} #2. \mathrel{\ in\ } #3.”]

[Priority table[x] →^{tex} “ \mathbf{Priority\ table} #1. \mathbf{End\ table}”]

[Priority table[x] →^{name} “ \mathbf{Priority\ table} [ #1. ]”]

[⟨∗⟩ →^{tex} “

\langle #1. \rangle ”]

[x, y →^{tex} “#1.

, \linebreak [0] #2.”]

[tuple_{1}(∗) →^{tex} “ \mathbf {tuple} 1( #1. ) ”]

[tuple_{2}(∗) →^{tex} “ \mathbf {tuple} 2( #1. ) ”]

[ragged right →^{tex} “ \raggedright”]

[ragged right →^{name} “ ragged\ right”]

[ragged right expansion →^{tex} “”] [ragged right expansion →^{name} “

ragged\ right\ expansion\ ”]

[newline x →^{tex} “ \newline #1.”]

[newline x →^{name} “ newline\ #1.”]

[macro newline x →^{tex} “ \newline #1.”]

[macro newline x →^{name} “ macro\ newline\ #1.”]

[(x)^{v} →^{tex} “#1/tex name.”]

[(x)^{v} →^{name} “

( #1. )ˆ {\bf v}”]

[if x then y else z →^{tex} “ {\bf if} \ #1. \ {\bf then} \ #2. \ {\bf else} \ #3.”]

[let x = y in z →^{tex} “ \mathbf{let\ } #1. = #2. \mathbf{\ in\ } #3.”]

[let_{1}(f, y) →^{tex} “ let 1( #1. , #2. )”]

[let_{2}(f, y) →^{tex} “ let 2( #1. , #2. )”]

[x ¨∧ y →^{tex} “#1.

\mathrel{\ddot{\wedge}} #2.”]

[x ¨∨ y →^{tex} “#1.

\mathrel{\ddot{\vee}} #2.”]

[x ¨⇒ y →^{tex} “#1.

\mathrel{\ddot{\Rightarrow}} #2.”] [intro(x, i, p, t) →^{tex} “\index{#2.: #3. @#2.: $[#1/tex name/tex.]$ #3.}%

\index{pyk: #3. $[#1/tex name/tex.]$}% \tex{ $[#1/tex name/tex. \stackrel {\mathrm {tex}}{=} #4/tex name. ]$}$[ #1/tex name/tex.% ]$\footnote{$[#1/tex name/tex. \stackrel {\mathrm {pyk}}{=} #3/tex name. ]$}”]

[intro(x, i, p, t) →^{name} “ intro(#1. , #2. , #3. , #4. )”]

[intro(x, p, t) →^{tex} “\index{\alpha #2. @\back \makebox[20mm][l]{$[#1/tex name/tex.]$}#2.}% \index{pyk: #2. $[#1/tex name/tex.]$}% \tex{ $[#1/tex name/tex. \stackrel {\mathrm {tex}}{=} #3/tex name. ]$}$[ #1/tex name/tex.% ]$\footnote{$[#1/tex name/tex. \stackrel {\mathrm {pyk}}{=} #2/tex name. ]$}”]

[intro(x, p, t) →^{name} “ intro(#1. , #2. , #3. )”]

[[∗ =^{claim} ∗] →^{tex} “ [#1/tex name/tex. \stackrel {claim}{=}#2. ]”]

[x ˜∧ y →^{tex} “#1.

\mathrel{\tilde{\wedge}} #2.”]

[x ∧_{c} y →^{tex} “#1.

\wedge c #2.”]

[check(∗, ∗) →^{tex} “ \mathbf{check}( #1.

, #2. )”]

[check_{2}(∗, ∗, ∗) →^{tex} “ \mathbf{check} 2( #1. , #2. , #3. )”]

[check_{3}(∗, ∗, ∗) →^{tex} “ \mathbf{check} 3( #1. , #2. , #3. )”]

[check^{∗}(∗, ∗) →^{tex} “ \mathbf{check}ˆ ∗( #1. , #2. )”]

[check_{2}^{∗}(∗, ∗, ∗) →^{tex} “ \mathbf{check}ˆ ∗ 2( #1. , #2. , #3. )”]

[[∗]^{·} →^{tex} “

\relax [ #1. \relax ]ˆ {\cdot} ”]

[[x]^{−} →^{tex} “

\relax [ #1. \relax ]ˆ {-} ”]

[[∗]^{∘} →^{tex} “

\relax [ #1. \relax ]ˆ {\circ} ”]

[msg →^{tex} “

msg”]

[[x =^{msg} y] →^{tex} “ [#1/tex name/tex. \stackrel {msg}{=} #2. ]”]

[<stmt> →^{tex} “

{<}stmt{>}”]

[stmt →^{tex} “

stmt”]

[[x =^{stmt} y] →^{tex} “ [#1/tex name/tex. \stackrel {stmt}{=}#2. ]”]

[HeadNil′ →^{tex} “ HeadNil’”]

[HeadPair′ →^{tex} “ HeadPair’”]

[Transitivity′ →^{tex} “ Transitivity’”]

[Contra′ →^{tex} “ Contra’”]

[T′_{E} →^{tex} “

T’ {E}”]

[L_{1} →^{tex} “

L {1}”]

[x ⊢ y →^{tex} “#1.

\vdash #2.”]

[x ⊢⊢ y →^{tex} “#1.

\mathrel {\makebox [0mm][l]{$\vdash $}\, {\vdash }} #2.”]

[∀x: y →^{tex} “

\forall #1. \colon #2.”]

[⊥ ⊥ →^{tex} “

{\makebox [0mm][l]{$\bot $}\, {\bot }}”]

[x ⊕ y →^{tex} “#1.

\mathrel {\oplus} #2.”]

[\underline{x} →^{tex} “\underline\{#1.\}”]

[A →^{tex} “{\cal A}”]

[B →^{tex} “{\cal B}”]

[C →^{tex} “{\cal C}”]

[D →^{tex} “{\cal D}”]

[E →^{tex} “{\cal E}”]

[F →^{tex} “{\cal F}”]

[G →^{tex} “{\cal G}”]

[H →^{tex} “{\cal H}”]

[I →^{tex} “{\cal I}”]

[J →^{tex} “{\cal J}”]

[K →^{tex} “{\cal K}”]

[L →^{tex} “{\cal L}”]

[M →^{tex} “{\cal M}”]

[N →^{tex} “{\cal N}”]

[O →^{tex} “{\cal O}”]

[P →^{tex} “{\cal P}”]

[Q →^{tex} “{\cal Q}”]

[R →^{tex} “{\cal R}”]

[S →^{tex} “{\cal S}”]

[T →^{tex} “{\cal T}”]

[U →^{tex} “{\cal U}”]

[V →^{tex} “{\cal V}”]

[W →^{tex} “{\cal W}”]

[X →^{tex} “{\cal X}”]

[Y →^{tex} “{\cal Y}”]

[Z →^{tex} “{\cal Z}”]

[t^{V} →^{tex} “#1.

{} ˆ {\cal V}”]

[t^{C} →^{tex} “#1.

{} ˆ {\cal C}”]

[t^{C^{∗}} →^{tex} “#1.

{} ˆ {{\cal C} ˆ { \ast }}”]

[x free in y →^{tex} “#1.

\mathrel {free\ in} #2.”]

[x free in^{∗} y →^{tex} “#1.

\mathrel {free\ in}ˆ {\ast} #2.”]

[a free for x in b →^{tex} “#1. \mathrel {free\ for} #2. \mathrel {in} #3.”]

[a free for^{∗} x in b →^{tex} “#1. \mathrel {free\ for}ˆ {\ast} #2. \mathrel {in} #3.”]

[⟨a |x:= b⟩ →^{tex} “

\langle #1. \, {\protect\vert}#2. {:=}\, #3. \rangle ”]

[⟨^{∗}a |x:= b⟩ →^{tex} “

\langle ˆ { \ast } #1. \, {\protect\vert}#2. {:=}\, #3. \rangle ”]

[x ∈_{t} y →^{tex} “#1.

\in t #2.”]

[x ⊆_{T} y →^{tex} “#1.

\subseteq T #2.”]

[x =^{T} y →^{tex} “#1.

\stackrel{T}{=} #2.”]

[∅ →^{tex} “

\emptyset ”]

[x ∪ {y} →^{tex} “#1.

\cup \{ #2. \}”]

[x\{y} →^{tex} “#1.

\backslash \{ #2. \}”]

[x ∪ y →^{tex} “#1.

\cup #2.”]

[x =^{s} y →^{tex} “#1.

\stackrel{s}{=} #2.”]

[x^{I} →^{tex} “#1.

{} ˆ { I }”]

[x^{⊳} →^{tex} “#1.

{} ˆ { \rhd }”]

[x @ y →^{tex} “#1.

\mathop {\char64} #2.”]

[x^{V} →^{tex} “#1.

{} ˆ { V } ”]

[T (x) →^{tex} “

{\cal T}( #1. )”]

[x^{+} →^{tex} “#1.

{} ˆ { + } ”]

[x^{−} →^{tex} “#1.

{} ˆ { - } ”]

[x i.e. y →^{tex} “#1.

\mathrel {i.e.} #2.”]

[x^{∗} →^{tex} “#1.

{} ˆ { \ast } ”]

[x; y →^{tex} “#1.

; #2.”]

[Remainder →^{tex} “ Remainder”]

[S^{I}(x, y) →^{tex} “

{\cal S}ˆ {I}(#1. , #2. )”]

[S^{⊳} (x, y) →^{tex} “

{\cal S}ˆ {\rhd}(#1. , #2. )”]

[S_{1}^{⊳} (x, y, z) →^{tex} “

{\cal S} {1}ˆ {\rhd}(#1. , #2. , #3. )”]

[S^{E}(x, y) →^{tex} “

{\cal S}ˆ {E}(#1. , #2. )”]

[S_{1}^{E}(x, y, z) →^{tex} “

{\cal S} {1}ˆ {E}(#1. , #2. , #3. )”]

[S^{+}(x, y) →^{tex} “

{\cal S}ˆ {+}(#1. , #2. )”]

[S_{1}^{+}(x, y, z) →^{tex} “

{\cal S} {1}ˆ {+}(#1. , #2. , #3. )”]

[S^{−}(x, y) →^{tex} “

{\cal S}ˆ {-}(#1. , #2. )”]

[S_{1}^{−}(x, y, z) →^{tex} “

{\cal S} {1}ˆ {-}(#1. , #2. , #3. )”]

[S^{∗}(x, y) →^{tex} “

{\cal S}ˆ {\ast}(#1. , #2. )”]

[S_{1}^{∗}(x, y, z) →^{tex} “

{\cal S} {1}ˆ {\ast}(#1. , #2. , #3. )”]

[S_{2}^{∗}(c, t, q, d) →^{tex} “

{\cal S} {2}ˆ {\ast}(#1. , #2. , #3. , #4. )”]

[S^{@}(x, y) →^{tex} “

{\cal S}ˆ {\char64}(#1. , #2. )”]

[S_{1}^{@}(c, t, q) →^{tex} “

{\cal S} {1}ˆ {\char64}(#1. , #2. , #3. )”]

[S^{⊢}(x, y) →^{tex} “

{\cal S}ˆ {\vdash}(#1. , #2. )”]

[S_{1}^{⊢}(x, y, z, u) →^{tex} “

{\cal S} {1}ˆ {\vdash}(#1. , #2. , #3. , #4. )”]

[S⊢ ⊢(x, y) →^{tex} “

{\cal S}ˆ {\makebox [0mm][l]{\scriptsize $\vdash $}\, {\vdash }}(#1. , #2. )”]

[S⊢ ⊢ ; 1(x, y, z, u) →^{tex} “

{\cal S} {1}ˆ {\makebox [0mm][l]{\scriptsize $\vdash $}\, {\vdash }}(#1. , #2. , #3. , #4. )”]

[S^{i.e.}(x, y) →^{tex} “

{\cal S}ˆ {i.e.}(#1. , #2. )”]

[S_{1}^{i.e.}(x, y, z, u) →^{tex} “ {\cal S} {1}ˆ {i.e.}(#1. , #2. , #3. , #4. )”]

[S_{2}^{i.e.}(c, t, a, q, d) →^{tex} “ {\cal S} {2}ˆ {i.e.}(#1. , #2. , #3. , #4. , #5. )”]

[S^{∀}(x, y) →^{tex} “

{\cal S}ˆ {\forall}(#1. , #2. )”]

[S_{1}^{∀}(c, t, v, q) →^{tex} “

{\cal S} {1}ˆ {\forall}(#1. , #2. , #3. , #4. )”]

[S^{;}(x, y) →^{tex} “

{\cal S}ˆ {; }(#1. , #2. )”]

[S_{1}^{;}(x, y, z) →^{tex} “

{\cal S} {1}ˆ {; }(#1.

, #2. , #3. )”]

[S_{2}^{;}(c, t, p, q) →^{tex} “

{\cal S} {2}ˆ {; }(#1. , #2. , #3. , #4. )”]

[x-color(y) →^{tex} “#1. \mbox {-color}( #2. )”]

[x-color^{∗}(y) →^{tex} “#1. \mbox {-color}ˆ {\ast}( #2. )”]

[error(m, t) →^{tex} “ error(#1/tex name. , #2. )”]

[error_{2}(m, t) →^{tex} “ error {2}(#1/tex name. , #2. )”]

[x^{E} →^{tex} “#1.

{} ˆ { E }”]

[S(x, y) →^{tex} “

{\cal S}(#1. , #2. )”]

[p proves t →^{tex} “#1. \ proves\ #2.”]

[proof(p, t, c) →^{tex} “ proof( #1. , #2. , #3. )”] [proof_{2}(q, t) →^{tex} “

proof {2}( #1. , #2. )”]

[x ∈_{c} y →^{tex} “#1.

\in c #2.”]

[claims(t, c, r) →^{tex} “ claims( #1. , #2. , #3. )”]

[claims_{2}(t, c, r) →^{tex} “ claims 2( #1. , #2. , #3. )”]

[<proof> →^{tex} “ {<}proof{>}”]

[proof →^{tex} “ proof”]

[[Lemma x: y] →^{tex} “ [ \mathbf{Lemma\ } #1. \colon #2. ]”]

[[Proof of x: y] →^{tex} “ [ \mathbf{Proof\ of\ }#1/tex name/tex. \colon #2. ]”]

[[x lemma y: z] →^{tex} “ [ #1. \mathbf{\ lemma\ } #2. \colon #3. ]”]

[HeadNil′′ →^{tex} “ HeadNil’’”]

[[x antilemma y: z] →^{tex} “ [ #1.

\mathbf{\ antilemma\ } #2. \colon #3. ]”]

[Contra′′ →^{tex} “ Contra’’”]

[V_{1}(c) →^{tex} “

{\cal V} 1( #1. )”]

[V_{2}(c, p) →^{tex} “

{\cal V} 2( #1. , #2. )”]

[V_{3}(c, r, p, d) →^{tex} “

{\cal V} 3( #1. , #2. , #3. , #4. )”]

[V_{4}(c, p) →^{tex} “

{\cal V} 4( #1. , #2. )”]

[V_{7}(c, r, i, q) →^{tex} “

{\cal V} 7( #1. , #2. , #3. , #4. )”]

[V_{6}(c, r, p, q) →^{tex} “

{\cal V} 6( #1. , #2. , #3. , #4. )”]

[V_{5}(c, r, a, q) →^{tex} “

{\cal V} 5( #1. , #2. , #3. , #4. )”] [Rule tactic →^{tex} “

Rule\ tactic”]

[rule(c, p) →^{tex} “ rule( #1. , #2. )”]

[rule_{1}(s, t) →^{tex} “ rule 1( #1. , #2. )”]

[Cut(a, b) →^{tex} “ Cut( #1. , #2. )”]

[Head_{⊕}(s) →^{tex} “ Head {\oplus} ( #1. )”]

[Tail_{⊕}(s) →^{tex} “ Tail {\oplus} ( #1. )”]

[[x rule y: z] →^{tex} “ [ #1. \mathbf{\ rule\ } #2. \colon #3. ]”]

[[x antirule y: z] →^{tex} “ [ #1. \mathbf{\ antirule\ } #2. \colon #3. ]”]

[HeadPair′′ →^{tex} “ HeadPair’’”]

[Transitivity′′ →^{tex} “ Transitivity’’”]

[HeadNil →^{tex} “ HeadNil”] [HeadPair →^{tex} “

HeadPair”]

[Transitivity →^{tex} “ Transitivity”]

[Contra →^{tex} “ Contra”]

[T_{E} →^{tex} “

T E”]

[[Theory n] →^{tex} “ [ \mathbf{Theory\ } #1. ]”]

[theory_{2}(t, c) →^{tex} “ theory 2( #1. , #2. )”]

[theory_{3}(c, n) →^{tex} “ theory 3( #1. , #2. )”]

[theory_{4}(c, n, s) →^{tex} “ theory 4( #1. , #2. , #3. )”]

[Plus(a, b) →^{tex} “ Plus( #1. , #2. )”]

[Reflexivity →^{tex} “ Reflexivity”]

[Commutativity →^{tex} “ Commutativity”]

[parm(t, s, n) →^{tex} “ parm(#1. , #2. , #3. )”] [parm^{∗}(t, s, n) →^{tex} “

parmˆ ∗(#1. , #2. , #3. )”]

[inst(t, s) →^{tex} “ inst(#1. , #2. )”]

[inst^{∗}(t, s) →^{tex} “ instˆ ∗(#1. , #2. )”]

[occur(t, u, s) →^{tex} “ occur(#1. , #2. , #3. )”]

[occur^{∗}(t, u, s) →^{tex} “ occurˆ ∗(#1. , #2. , #3. )”]

[unify(t = u, s) →^{tex} “ unify(#1. =#2. , #3. )”]

[unify^{∗}(t = u, s) →^{tex} “ unifyˆ ∗(#1. =#2. , #3. )”]

[unify_{2}(t = u, s) →^{tex} “ unify 2(#1. =#2. , #3. )”] [Reflexivity_{1} →^{tex} “

Reflexivity 1”]

[Commutativity_{1} →^{tex} “ Commutativity 1”]

[<tactic> →^{tex} “ {<}tactic{>}”]

[tactic →^{tex} “ tactic”]

[[x =^{tactic} y] →^{tex} “ [#1/tex name/tex. \stackrel {tactic}{=}#2. ]”]

[P(t, s, c) →^{tex} “

{\cal P}( #1. , #2. , #3. )”]

[P^{∗}(t, s, c) →^{tex} “

{\cal P}ˆ ∗( #1. , #2. , #3. )”]

[p_{0} →^{tex} “

p 0”]

[x ⊳ y →^{tex} “#1.

\rhd #2.”]

[x ⊳ ⊳ y →^{tex} “#1.

\mathrel {\makebox [0mm][l]{$\rhd $}\, {\rhd }} #2.”]

[x ≫ y →^{tex} “#1.

\gg #2.”]

[conclude_{1}(t, c) →^{tex} “ conclude 1 ( #1. , #2. )”] [conclude_{2}(a, t, c) →^{tex} “

conclude 2 ( #1. , #2. , #3. )”]

[conclude_{3}(a, t, l, s) →^{tex} “ conclude 3 ( #1. , #2. , #3. , #4. )”]

[conclude_{4}(a, l) →^{tex} “ conclude 4 ( #1. , #2. )”]

[t proof of s : p →^{tex} “ \if\relax\csname lgwprooflinep\endcsname \def\lgwprooflinep{x} \newcount\lgwproofline \fi \begingroup \def\insideproof{x} \lgwproofline=0 #1. \mathbf {\ proof\ of\ } #2. \colon #3. \gdef\lgwella{\relax} \gdef\lgwellb{\relax} \gdef\lgwellc{\relax} \gdef\lgwelld{\relax} \gdef\lgwelle{\relax} \gdef\lgwellf{\relax} \gdef\lgwellg{\relax} \gdef\lgwellh{\relax} \gdef\lgwelli{\relax} \gdef\lgwellj{\relax} \gdef\lgwellk{\relax} \gdef\lgwelll{\relax} \gdef\lgwellm{\relax} \gdef\lgwelln{\relax} \gdef\lgwello{\relax} \gdef\lgwellp{\relax} \gdef\lgwellq{\relax} \gdef\lgwellr{\relax} \gdef\lgwells{\relax} \gdef\lgwellt{\relax} \gdef\lgwellu{\relax} \gdef\lgwellv{\relax} \gdef\lgwellw{\relax} \gdef\lgwellx{\relax} \gdef\lgwelly{\relax} \gdef\lgwellz{\relax} \gdef\lgwellbiga{\relax} \gdef\lgwellbigb{\relax} \gdef\lgwellbigc{\relax} \gdef\lgwellbigd{\relax} \gdef\lgwellbige{\relax} \gdef\lgwellbigf{\relax} \gdef\lgwellbigg{\relax} \gdef\lgwellbigh{\relax} \gdef\lgwellbigi{\relax} \gdef\lgwellbigj{\relax} \gdef\lgwellbigk{\relax} \gdef\lgwellbigl{\relax} \gdef\lgwellbigm{\relax} \gdef\lgwellbign{\relax} \gdef\lgwellbigo{\relax} \gdef\lgwellbigp{\relax} \gdef\lgwellbigq{\relax} \gdef\lgwellbigr{\relax} \gdef\lgwellbigs{\relax} \gdef\lgwellbigt{\relax} \gdef\lgwellbigu{\relax} \gdef\lgwellbigv{\relax} \gdef\lgwellbigw{\relax} \gdef\lgwellbigx{\relax} \gdef\lgwellbigy{\relax} \gdef\lgwellbigz{\relax} \endgroup ”]

[t proof of s : p →^{name} “#1. \mathbf{\ proof\ of\ } #2. : #3.”]

[Line l : a ≫ i; p →^{tex} “ \newline \makebox [0.1\textwidth]{}% \parbox [b]{0.4\textwidth }{\raggedright \setlength {\parindent }{-0.1\textwidth }% \makebox [0.1\textwidth ][l]{$#1. $:}$#2.

{}\gg {}$}\quad \parbox [t]{0.4\textwidth }{$#3. $\hfill \makebox [0mm][l]{\quad ; }}#4.”]

[Line l : a ≫ i; p →^{name} “ Line \, #1. : #2. \gg #3. ; #4.”]

[Last line a ≫ i □ →^{tex} “ \newline \makebox [0.1\textwidth]{}% \parbox [b]{0.4\textwidth }{\raggedright \setlength {\parindent }{-0.1\textwidth }% \makebox [0.1\textwidth ][l]{$ \if \relax \csname lgwprooflinep\endcsname L ? \else \global \advance \lgwproofline by 1 L\ifnum \lgwproofline <10 0\fi \number \lgwproofline \fi $:}$#1. {}\gg {}$}\quad \parbox [t]{0.4\textwidth }{$#2. $\hfill \makebox [0mm][l]{\quad \makebox[0mm]{$\Box$}}}”]

[Last line a ≫ i □ →^{name} “ Last\ line \, #1. \gg #2. \, \Box”]

[Line l : Premise ≫ i; p →^{tex} “ \newline \makebox [0.1\textwidth ][l]{$#1. $:}\makebox [0.4\textwidth ][l]{$Premise{}\gg{}$}\quad \parbox [t]{0.4\textwidth }{$#2. $\hfill \makebox [0mm][l]{\quad ; }}#3.”]

[Line l : Premise ≫ i; p →^{name} “ Line \, #1. : Premise \gg #2. ; #3.”]

[Line l : Side-condition ≫ i; p →^{tex} “ \newline \makebox [0.1\textwidth ][l]{$#1. $:}\makebox [0.4\textwidth ][l]{% $\mbox{Side-condition}{}\gg{}$}\quad \parbox [t]{0.4\textwidth }{$#2. $\hfill \makebox [0mm][l]{\quad ; }}#3.”] [Line l : Side-condition ≫ i; p →^{name} “

Line \, #1. : \mbox{Side-condition} \gg #2. ; #3.”]

[Arbitrary ≫ i; p →^{tex} “ \newline \makebox [0.1\textwidth ][l]{$ \if \relax \csname lgwprooflinep\endcsname L ? \else \global \advance \lgwproofline by 1 L\ifnum \lgwproofline <10 0\fi \number \lgwproofline \fi $:}\makebox [0.4\textwidth ][l]{$Arbitrary{}\gg{}$}\quad \parbox [t]{0.4\textwidth }{$#1. $\hfill \makebox [0mm][l]{\quad ; }}#2.”]

[Arbitrary ≫ i; p →^{name} “ Arbitrary \gg #1. ; #2.”]

[Local ≫ a = i; p →^{tex} “ \newline\makebox[0.1\textwidth][l]{$ \if \relax \csname lgwprooflinep\endcsname L ? \else \global \advance \lgwproofline by 1 L\ifnum \lgwproofline <10 0\fi \number \lgwproofline \fi $:}% \makebox[0.4\textwidth][l]{$Local{}\gg{}$}% \quad% \parbox[t]{0.4\textwidth}{$#1. = #2. $\hfill\makebox[0mm][l]{\quad ; }}#3.”]

[Local ≫ a = i; p →^{name} “ Local \gg #1. = #2. ; #3.”]

[name →^{tex} “

\mathrm{name}”]

[ $x$ →^{tex} “$#1.$”]

[ $x$ →^{name} “

\ \$#1.\$\linebreak[0]\ ”]

[bracket x end bracket →^{tex} “$[#1.]$”] [bracket x end bracket →^{name} “

\mbox{bracket $#1.$ end bracket}”]

[big bracket x end bracket →^{tex} “$\left[#1.\right]$”]

[big bracket x end bracket →^{name} “ \mbox{big bracket $#1.$ end bracket}”]

[[x ▷◁ y] →^{tex} “

[#1/tex name/tex. \bowtie#2. ]”]

[[y →^{x} z] →^{tex} “

[#2/tex name/tex. \stackrel{#1. }{\rightarrow}#3. ]”]

[pyk →^{tex} “

\mathrm{pyk}”]

[x →^{tex} “

\mathsf{x}”]

[y →^{tex} “

\mathsf{y}”]

[z →^{tex} “

\mathsf{z}”]

[tex →^{tex} “

\mathrm{tex}”]

[name →^{tex} “

\mathrm{name}”]

[ $x$ →^{tex} “$#1.$”]

[ $x$ →^{name} “

\ \$#1.\$\linebreak[0]\ ”]

[bracket x end bracket →^{tex} “$[#1.]$”]

[bracket x end bracket →^{name} “ \mbox{bracket $#1.$ end bracket}”]

[big bracket x end bracket →^{tex} “$\left[#1.\right]$”] [big bracket x end bracket →^{name} “

\mbox{big bracket $#1.$ end bracket}”]

A.3 Further TEX definitions

This section contains tex definitions in an old style which the author has not yet turned into the style used in Appendix A.2

[∗ →^{tex} “

\ast ”]

[∗ ’ ∗ →^{tex} “#1.

\mathbin {\mbox {’}}#2.”]

[∗ ‘ ∗ →^{tex} “#1.

\mathbin {\mbox {‘}}#2.”]

[λ ∗ .∗ →^{tex} “

\lambda #1. .#2.”]

[Λ∗ →^{tex} “

\Lambda #1.”]

[T →^{tex} “

\mathsf {T}”]

[if(∗, ∗, ∗) →^{tex} “

\mathrm {if}(#1. , \linebreak [0]#2. , \linebreak [0]#3. )”]

[val →^{tex} “

\mathrm {val}”]

[claim →^{tex} “ \mathrm {claim}”]

[[∗ ⇒^{∗} ∗] →^{tex} “

[#2/tex name/tex. \stackrel {#1. }{\Rightarrow }#3. ]”]

[⊥ →^{tex} “

\bot ”]

[f(∗) →^{tex} “

f(#1. )”]

[(∗)^{I} →^{tex} “

(#1. ){}ˆ {I} ”]

[F →^{tex} “

\mathsf {F}”]

[\underline{0} →^{tex} “

\underline {0}”]

[\underline{1} →^{tex} “

\underline {1}”]

[\underline{2} →^{tex} “

\underline {2}”]

[\underline{3} →^{tex} “

\underline {3}”]

[\underline{4} →^{tex} “

\underline {4}”]

[\underline{5} →^{tex} “

\underline {5}”]

[\underline{6} →^{tex} “

\underline {6}”]

[\underline{7} →^{tex} “

\underline {7}”]

[\underline{8} →^{tex} “

\underline {8}”]

[\underline{9} →^{tex} “

\underline {9}”]

[0 →^{tex} “

0”]

[1 →^{tex} “

1”]

[2 →^{tex} “

2”]

[3 →^{tex} “

3”]

[4 →^{tex} “

4”]

[5 →^{tex} “

5”]

[6 →^{tex} “

6”]

[7 →^{tex} “

7”]

[8 →^{tex} “

8”]

[9 →^{tex} “

9”]

[a →^{tex} “

\mathsf {a}”]

[b →^{tex} “

\mathsf {b}”]

[c →^{tex} “

\mathsf {c}”]

[d →^{tex} “

\mathsf {d}”]

[e →^{tex} “

\mathsf {e}”]

[f →^{tex} “

\mathsf {f}”]

[g →^{tex} “

\mathsf {g}”]

[h →^{tex} “

\mathsf {h}”]

[i →^{tex} “

\mathsf {i}”]

[j →^{tex} “

\mathsf {j}”]

[k →^{tex} “

\mathsf {k}”]

[l →^{tex} “

\mathsf {l}”]

[m →^{tex} “

\mathsf {m}”]

[n →^{tex} “

\mathsf {n}”]

[o →^{tex} “

\mathsf {o}”]

[p →^{tex} “

\mathsf {p}”]

[q →^{tex} “

\mathsf {q}”]

[r →^{tex} “

\mathsf {r}”]

[s →^{tex} “

\mathsf {s}”]

[t →^{tex} “

\mathsf {t}”]

[u →^{tex} “

\mathsf {u}”]

[v →^{tex} “

\mathsf {v}”]

[w →^{tex} “

\mathsf {w}”]

[(∗)^{M} →^{tex} “

(#1. )ˆ M”]

[If(∗, ∗, ∗) →^{tex} “

\mathrm {If}(#1. , \linebreak [0]#2. , \linebreak [0]#3. )”]

[array{∗} ∗ end array →^{tex} “ \begin {array}{#1. }#2. \end {array}”]

[array{∗} ∗ end array →^{name} “\mathrm {array}\{#1. \}#2. \mathrm {end\ array}”]

[l →^{tex} “

l”]

[c →^{tex} “

c”]

[r →^{tex} “

r”]

[empty →^{tex} “ ”]

[empty →^{name} “ \mathrm {empty}”]

[⟨∗ | ∗:= ∗⟩ →^{tex} “

\langle #1. \, {|}#2. {:=}\, #3. \rangle ”]

[M(∗) →^{tex} “

{\cal M}(#1. )”]

[apply(∗, ∗) →^{tex} “ \mathbf {apply}(#1.

, #2. )”]

[apply_{1}(∗, ∗) →^{tex} “ \mathbf {apply} 1(#1. , #2. )”]

[∗^{H} →^{tex} “#1.

{}ˆ H”]

[∗^{T} →^{tex} “#1.

{}ˆ T”]

[∗^{c} →^{tex} “#1.

{}ˆ c”]

[∗^{d} →^{tex} “#1.

{}ˆ d”]

[∗^{U} →^{tex} “#1.

{}ˆ U”]

[∗^{h} →^{tex} “#1.

{}ˆ h”]

[∗^{t} →^{tex} “#1.

{}ˆ t”]

[∗^{s} →^{tex} “#1.

{}ˆ s”]

[∗^{B} →^{tex} “#1.

{}ˆ B”]

[∗^{C} →^{tex} “#1.

{}ˆ C”]

[∗^{M} →^{tex} “#1.

{}ˆ M”]

[Ũ(∗) →^{tex} “

\tilde {{\cal U}}(#1. )”]

[U(∗) →^{tex} “

{\cal U}(#1. )”]

[U^{M}(∗) →^{tex} “

{\cal U}ˆ M(#1. )”]

[∗ ˙. . ∗ →^{tex} “#1.

\mathrel { \dot { . \, . } }#2.”]

[∗ \underline{˙. .} ∗ →^{tex} “#1.

\mathrel { \underline { \dot { . \, . } } }#2.”]

[∗ \underline{: :} ∗ →^{tex} “#1.

\mathrel { \underline { : \, : } }#2.”]

[∗ \underline{+2∗} ∗ →^{tex} “#1.

\mathrel { \underline { {+} 2 \ast } }#2.”]

[x : : y →^{tex} “#1.

\mathrel { : \, : }#2.”]

[∗ +2∗ ∗ →^{tex} “#1.

\mathrel { {+} 2 \ast }#2.”]

[∗ ≈^{B} ∗ →^{tex} “#1.

\stackrel {B}{\approx }#2.”]

[∗ ≈^{D} ∗ →^{tex} “#1.

\stackrel {D}{\approx }#2.”]

[∗ ≈^{C} ∗ →^{tex} “#1.

\stackrel {C}{\approx }#2.”]

[∗ ≈^{P} ∗ →^{tex} “#1.

\stackrel {P}{\approx }#2.”]

[∗ ≈ ∗ →^{tex} “#1.

\approx #2.”]

[∗ = ∗ →^{tex} “#1.

=#2.”]

[∗ →^{+} ∗ →^{tex} “#1.

\stackrel {+}{\rightarrow }#2.”]

[¬∗ →^{tex} “

{\neg }#1.”]

[∗ ∧ ∗ →^{tex} “#1.

\wedge #2.”]

[∗ ∨ ∗ →^{tex} “#1.

\vee #2.”]

[∗ ∥ ∗ →^{tex} “#1.

\parallel #2.”]

[∗ : ∗ →^{tex} “#1.

:#2.”]

[∗!∗ →^{tex} “#1.

!#2.”]

[∗ \{ \begin{matrix}∗ \\ ∗ \end{matrix} →^{tex} “#1.

\left\{\protect \begin {array}{l}#2. \\#3. \protect \end {array}\right.”]

[∗&∗ →^{tex} “#1.

&#2.”]

[∗&∗ →^{name} “#1.

\& #2.”]

[∗\\∗ →^{tex} “#1.

\\ #2.”]

[∗\\∗ →^{name} “#1.

\backslash \backslash #2.”]

[macro →^{tex} “ \mathrm {macro}”]

["value" →^{tex} “ \mbox {\tt \char34}\mathrm {value}\mbox {\tt \char34}”]

["macro" →^{tex} “ \mbox {\tt \char34}\mathrm {macro}\mbox {\tt \char34}”]

[E(∗, ∗, ∗) →^{tex} “

{\cal E}(#1. , #2. , #3. )”]

[E_{2}(∗, ∗, ∗, ∗, ∗) →^{tex} “

{\cal E} 2(#1. , #2. , #3. , #4. , #5. )”]

[E_{3}(∗, ∗, ∗, ∗) →^{tex} “

{\cal E} 3(#1. , #2. , #3. , #4. )”]

[E_{4}(∗, ∗, ∗, ∗) →^{tex} “

{\cal E} 4(#1. , #2. , #3. , #4. )”]

[lookup(∗, ∗, ∗) →^{tex} “ \mathbf {lookup}(#1. , #2. , #3. )”]

[abstract(∗, ∗, ∗, ∗) →^{tex} “ \mathbf {abstract}(#1.

, #2. , #3. , #4. )”]

[∗^{a} →^{tex} “#1.

{}ˆ a”]

[⌈∗⌉ →^{tex} “

\lceil #1. \rceil ”]

[∗0 →^{tex} “#1.

0”]

[∗1 →^{tex} “#1.

1”]

[0b →^{tex} “

0 \mathrm {b}”]

[∗ =^{t} ∗ →^{tex} “#1.

\stackrel {t}{=}#2.”]

[∗ =^{t^{∗}} ∗ →^{tex} “#1.

\stackrel {tˆ ∗}{=}#2.”]

[∗[ ∗] →^{tex} “#1.

{[}#2. {]}”]

[M(∗, ∗, ∗) →^{tex} “

{\cal M}(#1. , #2. , #3. )”]

[M_{2}(∗, ∗, ∗, ∗) →^{tex} “

{\cal M} 2(#1. , #2. , #3. , #4. )”]

[s_{0} →^{tex} “

s 0”]

[M^{∗}(∗, ∗, ∗) →^{tex} “

{\cal M}ˆ ∗(#1. , #2. , #3. )”]

[zip(∗, ∗) →^{tex} “

\mathbf {zip}(#1.

, #2. )”]

[assoc_{1}(∗, ∗, ∗) →^{tex} “ \mathbf {assoc} 1(#1. , #2. , #3. )”]

[∗ {∗} →^{tex} “#1.

{#2. }”]

[∗ {∗} →^{name} “#1.

\ \{#2. \}”]

[(∗)^{p} →^{tex} “(#1.

)ˆ {\mathbf {p}}”]

[[∗ ¨= ∗] →^{tex} “

[#1/tex name/tex. \mathrel {\ddot {=}}#2. ]”]

[[∗ ˙= ∗] →^{tex} “

[#1/tex name/tex. \mathrel {\dot {=}}#2. ]”]

[[∗ ´= ∗] →^{tex} “

[#1/tex name/tex. \mathrel {\acute {=}}#2. ]”]

[[∗ =^{pyk} ∗] →^{tex} “

[#1/tex name/tex. \stackrel {\mathrm {pyk}}{=} #2/tex name. ]”]

[[∗ =^{tex} ∗] →^{tex} “

[#1/tex name/tex. \stackrel {\mathrm {tex}}{=} #2/tex name. ]”]

[[∗ =^{name} ∗] →^{tex} “

[#1/tex name/tex. \stackrel {\mathrm {name}}{=} #2/tex name. ]”]

[M̃_{1} →^{tex} “

\tilde {{\cal M}} 1”]

[M̃_{2}(∗) →^{tex} “

\tilde {{\cal M}} 2(#1.

)”]

[M̃_{3}(∗) →^{tex} “

\tilde {{\cal M}} 3(#1. )”]

[M̃_{4}(∗, ∗, ∗, ∗) →^{tex} “

\tilde {{\cal M}} 4(#1. , #2. , #3. , #4. )”]

[M̃(∗, ∗, ∗) →^{tex} “

\tilde {{\cal M}}(#1. , #2. , #3. )”]

[Q̃(∗, ∗, ∗) →^{tex} “

\tilde {{\cal Q}}(#1. , #2. , #3. )”]

[Q̃_{2}(∗, ∗, ∗) →^{tex} “

\tilde {{\cal Q}} 2(#1. , #2. , #3. )”]

[Q̃_{3}(∗, ∗, ∗, ∗) →^{tex} “

\tilde {{\cal Q}} 3(#1. , #2. , #3. , #4. )”]

[Q̃^{∗}(∗, ∗, ∗) →^{tex} “

\tilde {{\cal Q}}ˆ ∗(#1. , #2. , #3. )”]

[(∗) →^{tex} “

(#1. )”]

A.4 Line numbers

The following definitions are experimental definitions of line numbers named “ell a”, “ell b”, etc. which expand into [L_{01}], [L_{02}], etc. in such a way that proof lines are numbered in succession. The “ell dummy” operator expands into different line numbers each time it is used and can be used for lines that are never referenced.

[L_{a} →^{name} “L a”] [L_{b} →^{name} “L b”] [L_{c} →^{name} “L c”] [L_{d} →^{name} “L d”] [L_{e} →^{name} “L e”] [L_{f} →^{name} “L f”] [L_{g} →^{name} “L g”] [L_{h} →^{name} “L h”] [L_{i} →^{name} “L i”] [L_{j} →^{name} “L j”] [L_{k} →^{name} “L k”] [L_{l} →^{name} “L l”] [L_{m} →^{name} “L m”] [L_{n} →^{name} “L n”] [L_{o} →^{name} “L o”] [L_{p} →^{name} “L p”] [L_{q} →^{name} “L q”] [L_{r} →^{name} “L r”] [L_{s} →^{name} “L s”] [L_{t} →^{name} “L t”] [L_{u} →^{name} “L u”] [L_{v} →^{name} “L v”] [L_{w} →^{name} “L w”] [L_{x} →^{name} “L x”] [L_{y} →^{name} “L y”] [L_{z} →^{name} “L z”] [L_{A} →^{name} “L A”] [L_{B} →^{name} “L B”] [L_{C} →^{name} “L C”] [L_{D} →^{name} “L D”] [L_{E} →^{name} “L E”] [L_{F} →^{name} “L F”] [L_{G} →^{name} “L G”] [L_{H} →^{name} “L H”] [L_{I} →^{name} “L I”] [L_{J} →^{name} “L J”] [L_{K} →^{name} “L K”] [L_{L} →^{name} “L L”] [L_{M} →^{name} “L M”] [L_{N} →^{name} “L N”] [L_{O} →^{name} “L O”] [L_{P} →^{name} “L P”] [L_{Q} →^{name} “L Q”] [L_{R} →^{name} “L R”] [L_{S} →^{name} “L S”] [L_{T} →^{name} “L T”] [L_{U} →^{name} “L U”] [L_{V} →^{name} “L V”] [L_{W} →^{name} “L W”] [L_{X} →^{name} “L X”] [L_{Y} →^{name} “L Y”] [L_{Z} →^{name} “L Z”]

[L_{?} →^{name} “L ?”]

[L_{a} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L a \else \if \relax \csname lgwella\endcsname \global \advance \lgwproofline by 1 \xdef \lgwella {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwella \fi ”]

[L_{b} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L b \else \if \relax \csname lgwellb\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellb {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellb \fi ”]

[L_{c} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L c \else \if \relax \csname lgwellc\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellc {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellc \fi ”]

[L_{d} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L d \else \if \relax \csname lgwelld\endcsname \global \advance \lgwproofline by 1 \xdef \lgwelld {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwelld \fi ”]

[L_{e} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L e \else \if \relax \csname lgwelle\endcsname \global \advance \lgwproofline by 1 \xdef \lgwelle {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwelle \fi ”]

[L_{f} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L f \else \if \relax \csname lgwellf\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellf {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellf \fi ”]

[L_{g} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L g \else \if \relax \csname lgwellg\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellg {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellg \fi ”]

[L_{h} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L h \else \if \relax \csname lgwellh\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellh {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellh \fi ”]

[L_{i} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L i \else \if \relax \csname lgwelli\endcsname \global \advance \lgwproofline by 1 \xdef \lgwelli {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwelli \fi ”]

[L_{j} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L j \else \if \relax \csname lgwellj\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellj {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellj \fi ”]

[L_{k} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L k \else \if \relax \csname lgwellk\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellk {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellk \fi ”]

[L_{l} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L l \else \if \relax \csname lgwelll\endcsname \global \advance \lgwproofline by 1 \xdef \lgwelll {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwelll \fi ”]

[L_{m} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L m \else \if \relax \csname lgwellm\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellm {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellm \fi ”]

[L_{n} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L n \else \if \relax \csname lgwelln\endcsname \global \advance \lgwproofline by 1 \xdef \lgwelln {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwelln \fi ”]

[L_{o} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L o \else \if \relax \csname lgwello\endcsname \global \advance \lgwproofline by 1 \xdef \lgwello {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwello \fi ”]

[L_{p} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L p \else \if \relax \csname lgwellp\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellp {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellp \fi ”]

[L_{q} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L q \else \if \relax \csname lgwellq\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellq {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellq \fi ”]

[L_{r} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L r \else \if \relax \csname lgwellr\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellr {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellr \fi ”]

[L_{s} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L s \else \if \relax \csname lgwells\endcsname \global \advance \lgwproofline by 1 \xdef \lgwells {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwells \fi ”]

[L_{t} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L t \else \if \relax \csname lgwellt\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellt {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellt \fi ”]

[L_{u} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L u \else \if \relax \csname lgwellu\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellu {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellu \fi ”]

[L_{v} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L v \else \if \relax \csname lgwellv\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellv {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellv \fi ”]

[L_{w} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L w \else \if \relax \csname lgwellw\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellw {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellw \fi ”]

[L_{x} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L x \else \if \relax \csname lgwellx\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellx {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellx \fi ”]

[L_{y} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L y \else \if \relax \csname lgwelly\endcsname \global \advance \lgwproofline by 1 \xdef \lgwelly {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwelly \fi ”]

[L_{z} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L z \else \if \relax \csname lgwellz\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellz {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellz \fi ”]

[L_{A} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L A \else \if \relax \csname lgwellbiga\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbiga {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbiga \fi ”]

[L_{B} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L B \else \if \relax \csname lgwellbigb\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigb {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigb \fi ”]

[L_{C} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L C \else \if \relax \csname lgwellbigc\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigc {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigc \fi ”]

[L_{D} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L D \else \if \relax \csname lgwellbigd\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigd {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigd \fi ”]

[L_{E} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L E \else \if \relax \csname lgwellbige\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbige {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbige \fi ”]

[L_{F} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L F \else \if \relax \csname lgwellbigf\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigf {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigf \fi ”]

[L_{G} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L G \else \if \relax \csname lgwellbigg\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigg {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigg \fi ”]

[L_{H} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L H \else \if \relax \csname lgwellbigh\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigh {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigh \fi ”]

[L_{I} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L I \else \if \relax \csname lgwellbigi\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigi {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigi \fi ”]

[L_{J} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L J \else \if \relax \csname lgwellbigj\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigj {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigj \fi ”]

[L_{K} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L K \else \if \relax \csname lgwellbigk\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigk {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigk \fi ”]

[L_{L} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L L \else \if \relax \csname lgwellbigl\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigl {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigl \fi ”]

[L_{M} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L M \else \if \relax \csname lgwellbigm\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigm {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigm \fi ”]

[L_{N} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L N \else \if \relax \csname lgwellbign\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbign {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbign \fi ”]

[L_{O} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L O \else \if \relax \csname lgwellbigo\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigo {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigo \fi ”]

[L_{P} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L P \else \if \relax \csname lgwellbigp\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigp {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigp \fi ”]

[L_{Q} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L Q \else \if \relax \csname lgwellbigq\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigq {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigq \fi ”]

[L_{R} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L R \else \if \relax \csname lgwellbigr\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigr {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigr \fi ”]

[L_{S} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L S \else \if \relax \csname lgwellbigs\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigs {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigs \fi ”]

[L_{T} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L T \else \if \relax \csname lgwellbigt\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigt {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigt \fi ”]

[L_{U} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L U \else \if \relax \csname lgwellbigu\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigu {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigu \fi ”]

[L_{V} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L V \else \if \relax \csname lgwellbigv\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigv {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigv \fi ”]

[L_{W} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L W \else \if \relax \csname lgwellbigw\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigw {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigw \fi ”]

[L_{X} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L X \else \if \relax \csname lgwellbigx\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigx {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigx \fi ”]

[L_{Y} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L Y \else \if \relax \csname lgwellbigy\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigy {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigy \fi ”]

[L_{Z} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L Z \else \if \relax \csname lgwellbigz\endcsname \global \advance \lgwproofline by 1 \xdef \lgwellbigz {L\ifnum \lgwproofline <10 0\fi \number \lgwproofline } \fi \lgwellbigz \fi ”]

[L_{?} →^{tex} “

\if \relax \csname lgwprooflinep\endcsname L ? \else \global \advance \lgwproofline by 1 L\ifnum \lgwproofline <10 0\fi \number \lgwproofline \fi ”]

A.5 Characters

A.5.1 Tex aspects of characters

[

x →^{tex} “

#1.”]

[ x →^{tex} “ #1.”]

[!x →^{tex} “!#1.”]

["x →^{tex} “"#1.”]

[#x →^{tex} “#.#1.”]

[$x →^{tex} “$#1.”]

[%x →^{tex} “%#1.”]

[&x →^{tex} “&#1.”]

[’x →^{tex} “’#1.”]

[(x →^{tex} “(#1.”]

[)x →^{tex} “)#1.”]

[∗x →^{tex} “∗#1.”]

[+x →^{tex} “+#1.”]

[, x →^{tex} “, #1.”]

[-x →^{tex} “-#1.”]

[.x →^{tex} “.#1.”]

[/x →^{tex} “/#1.”]

[0x →^{tex} “0#1.”]

[1x →^{tex} “1#1.”]

[2x →^{tex} “2#1.”]

[3x →^{tex} “3#1.”]

[4x →^{tex} “4#1.”]

[5x →^{tex} “5#1.”]

[6x →^{tex} “6#1.”]

[7x →^{tex} “7#1.”]

[8x →^{tex} “8#1.”]

[9x →^{tex} “9#1.”]

[:x →^{tex} “:#1.”]

[; x →^{tex} “; #1.”]

[<x →^{tex} “<#1.”]

[=x →^{tex} “=#1.”]

[>x →^{tex} “>#1.”]

[?x →^{tex} “?#1.”]

[@x →^{tex} “@#1.”]

[Ax →^{tex} “A#1.”]

[Bx →^{tex} “B#1.”]

[Cx →^{tex} “C#1.”]

[Dx →^{tex} “D#1.”]

[Ex →^{tex} “E#1.”]

[Fx →^{tex} “F#1.”]

[Gx →^{tex} “G#1.”]

[Hx →^{tex} “H#1.”]

[Ix →^{tex} “I#1.”]

[Jx →^{tex} “J#1.”]

[Kx →^{tex} “K#1.”]

[Lx →^{tex} “L#1.”]

[Mx →^{tex} “M#1.”]

[Nx →^{tex} “N#1.”]

[Ox →^{tex} “O#1.”]

[Px →^{tex} “P#1.”]

[Qx →^{tex} “Q#1.”]

[Rx →^{tex} “R#1.”]

[Sx →^{tex} “S#1.”]

[Tx →^{tex} “T#1.”]

[Ux →^{tex} “U#1.”]

[Vx →^{tex} “V#1.”]

[Wx →^{tex} “W#1.”]

[Xx →^{tex} “X#1.”]

[Yx →^{tex} “Y#1.”]

[Zx →^{tex} “Z#1.”]

[[x →^{tex} “[#1.”]

[\x →^{tex} “\#1.”]

[]x →^{tex} “]#1.”]

[ˆ x →^{tex} “ˆ #1.”]

[ x →^{tex} “ #1.”]

[ax →^{tex} “a#1.”]

[bx →^{tex} “b#1.”]

[cx →^{tex} “c#1.”]

[dx →^{tex} “d#1.”]

[ex →^{tex} “e#1.”]

[fx →^{tex} “f#1.”]

[gx →^{tex} “g#1.”]

[hx →^{tex} “h#1.”]

[ix →^{tex} “i#1.”]

[jx →^{tex} “j#1.”]

[kx →^{tex} “k#1.”]

[lx →^{tex} “l#1.”]

[mx →^{tex} “m#1.”]

[nx →^{tex} “n#1.”]

[ox →^{tex} “o#1.”]

[px →^{tex} “p#1.”]

[qx →^{tex} “q#1.”]

[rx →^{tex} “r#1.”]

[sx →^{tex} “s#1.”]

[tx →^{tex} “t#1.”]

[ux →^{tex} “u#1.”]

[vx →^{tex} “v#1.”]

[wx →^{tex} “w#1.”]

[xx →^{tex} “x#1.”]

[yx →^{tex} “y#1.”]

[zx →^{tex} “z#1.”]

[‘x →^{tex} “‘#1.”]

[{x →^{tex} “{#1.”]

[|x →^{tex} “|#1.”]

[}x →^{tex} “}#1.”]

[˜ x →^{tex} “˜ #1.”]

A.5.2 Tex name aspects of characters

[

x →^{name} “

\newline #1.”]

[ x →^{name} “

\linebreak [0]\ \hskip0em plus2.0em{}#1.”]

["x →^{name} “

\mbox {\tt \char34}#1.”]

[#x →^{name} “

\#.#1.”]

[$x →^{name} “

\$#1.”]

[%x →^{name} “

\%#1.”]

[&x →^{name} “

\&#1.”]

[’x →^{name} “

\mbox {’}#1.”]

[∗x →^{name} “

{∗}#1.”]

[+x →^{name} “

{+}#1.”]

[-x →^{name} “

\mbox{-}#1.”]

[:x →^{name} “

{:}#1.”]

[<x →^{name} “

{<}#1.”]

[=x →^{name} “

{=}#1.”]

[>x →^{name} “

{>}#1.”]

[\x →^{name} “

\mbox {$\backslash $}#1.”]

[ˆ x →^{name} “

{\char94}#1.”]

[ x →^{name} “

\ #1.”]

[‘x →^{name} “

\mbox {‘}#1.”]

[{x →^{name} “

\{#1.”]

[}x →^{name} “

\}#1.”]

[˜ x →^{name} “

\char126 #1.”]

B Pyk definitions

B.1 The pyk language

From the point of view of Logiweb, the pyk language is a source language. A user may express a Logiweb page in pyk and then run the pyk source through the pyk compiler to obtain a Logiweb page.

A good way to learn the pyk language is to locate the pyk source of the present page and study it. The pyk source is likely to be in a file named “base.pyk”. Plentiful comments in the pyk source explain what is going on.

The name “pyk” is constructed from the name “Volapyk” in the same way that Rene Thom construct the word “versal” from “universal”: “pyk” is constructed by removing “Vola” from “Volapyk”.

Volapyk was an artificial language constructed from several other languages by simplifying their words and their grammar. As an example, the name of the language itself is constructed from “Vola” which is a simplification of “World” and “pyk” which is a simplification of “speak”.

The pyk language may be used for “spoken mathematics” and may, among other, be entered through a microphone when editing mathematical text. The language is partly called “pyk” because of this speach aspect, partly because it looks like Volapyk in the other sense of that word. As an example, in a proper setup, the pyk phrase

parenthesis var x plus var y end parenthesis square equals var x square plus two times var x times var y plus var y square may correspond to the formula

(x + y)^{2} = x^{2} + 2xy + y^{2}

Originally, the pyk language was restricted to use the letters from a to z plus spaces in order to ensure than anything could be entered through a microphone. Upon request, however, support for other characters has been added so that one may instead setup pyk such that the pyk phrase

( x + y ) ^2 = x ^2 + 2 x y + y ^2

generates the formula above or such that the pyk phrase

All A: All B: A => B => A

generates the formula

ΠA : ΠB : A ⇒ B ⇒ A

B.2 Uses of pyk

In principle, the pyk language is not part of Logiweb. The Logiweb standard merely defines how to interpret Logiweb vectors, i.e. Logiweb pages on binary format. The only formal link between Logiweb and pyk is the fact that Logiweb has a predefined concept that is proclaimable under the name of “pyk”. The pyk language and compiler are just means for producing Logiweb pages. One could imagine other means for producing Logiweb pages that were completely independent of pyk.

Nevertheless, authors who publish on Logiweb are encouraged to give a pyk definition of each and every construct that is introduced on the page. In the future, the pyk definitions may be used for entering mathematics through a microphone or for reading mathematics e.g. for blind people.

At the time of writing, pyk definitions have a much more immediate use as explained in the following.

At the time of writing, the pyk compiler is the only realistic means for producing Logiweb pages. The pyk compiler takes a pyk source text as input and produces a Logiweb page as output. The pyk compiler also has facilities for rendering pages, for making various soundness checks, and for printing warnings and error messages.

A pyk source consists of a preamble and a body. The preamble defines the bibliography and dictionary of the page. The bibliography is a list of referenced pages and the dictionary is the list of all constructs introduced on the page. The preamble also defines other things like the priority and associativity of constructs and preliminary pyk definitions for all constructs.

When the pyk compiler reads the preamble, it loads all pages referenced in the bibliography. Then it extracts all pyk definitions from all referenced pages, merge them with the preliminary pyk definitions of the preamble, and use the resulting grammar for parsing the body of the page.

The pyk compiler does not care whether or not the resulting grammar is ambiguous as long as the body of the page has one and only one possible interpretation.

When the pyk compiler generates the Logiweb page, all the preliminary pyk definitions from the preamble are lost. Only pyk definitions explicitly included in the body by the author make their way to the resulting Logiweb page.

Hence, if you publish a Logiweb page and want to make the life easy for people who want to build on your work, you’d better include pyk definitions of each and every construct on your page. Do not omit constructs you think are unimportant or “internal to the page” in an information hiding sense. In the context of proof checking there is no such thing as an unimportant construct or an “internal construct” that one should not look at.

B.3 Autogeneration of pyk definitions

The preamble of a pyk source text lists the pyk definitions of all constructs introduced on the page defined by the source text. When the pyk compiler sees the keyword ’Pyk’ (or whatever the keyword has been changed to by the -keyword option of the compiler) then it generates a list of pyk definitions, one for each construct.

The pyk compiler separates pyk definitions with construct 17 of the bed page. Construct 17 of the present page reads x y.

B.4 Autogenerated pyk definitions

[bracket ∗ end bracket →^{pyk} “bracket " end bracket”] [big bracket ∗ end bracket →^{pyk} “big bracket " end bracket”] [ $ ∗ $ →^{pyk} “math " end math”] [flush left [∗] →^{pyk} “flush left " end left”] [x →^{pyk} “var x”] [y →^{pyk} “var y”] [z →^{pyk} “var z”] [[∗ ▷◁ ∗] →^{pyk} “proclaim " as " end proclaim”] [[∗ →^{∗} ∗] →^{pyk} “define " of " as " end define”] [pyk →^{pyk} “pyk”] [tex →^{pyk} “tex”] [name →^{pyk} “tex name”] [prio →^{pyk} “priority”]

[∗ →^{pyk} “x”]

[T →^{pyk} “true”] [if(∗, ∗, ∗) →^{pyk} “if " then " else " end if”] [[∗ ⇒^{∗} ∗] →^{pyk} “introduce " of " as " end introduce”] [val →^{pyk} “value”] [claim →^{pyk} “claim”] [⊥ →^{pyk} “bottom”] [f(∗) →^{pyk} “function f of " end function”] [(∗)^{I} →^{pyk} “identity " end identity”] [F →^{pyk} “false”] [\underline{0} →^{pyk} “untagged zero”] [\underline{1} →^{pyk} “untagged one”] [\underline{2} →^{pyk} “untagged two”] [\underline{3} →^{pyk} “untagged three”] [\underline{4} →^{pyk} “untagged four”] [\underline{5} →^{pyk} “untagged five”] [\underline{6} →^{pyk} “untagged six”] [\underline{7} →^{pyk} “untagged seven”] [\underline{8} →^{pyk} “untagged eight”] [\underline{9} →^{pyk} “untagged nine”]

[0 →^{pyk} “zero”]

[1 →^{pyk} “one”]

[2 →^{pyk} “two”]

[3 →^{pyk} “three”]

[4 →^{pyk} “four”]

[5 →^{pyk} “five”]

[6 →^{pyk} “six”]

[7 →^{pyk} “seven”] [8 →^{pyk} “eight”]

[9 →^{pyk} “nine”]

[a →^{pyk} “var a”] [b →^{pyk} “var b”] [c →^{pyk} “var c”] [d →^{pyk} “var d”] [e →^{pyk} “var e”] [f →^{pyk} “var f”] [g →^{pyk} “var g”] [h →^{pyk} “var h”] [i →^{pyk} “var i”] [j →^{pyk} “var j”] [k →^{pyk} “var k”] [l →^{pyk} “var l”] [m →^{pyk} “var m”] [n →^{pyk} “var n”] [o →^{pyk} “var o”] [p →^{pyk} “var p”] [q →^{pyk} “var q”] [r →^{pyk} “var r”] [s →^{pyk} “var s”] [t →^{pyk} “var t”] [u →^{pyk} “var u”] [v →^{pyk} “var v”] [w →^{pyk} “var w”] [(∗)^{M} →^{pyk} “tagged parenthesis " end tagged”] [If(∗, ∗, ∗) →^{pyk} “tagged if " then " else " end if”] [array{∗} ∗ end array →^{pyk} “array " is " end array”] [l →^{pyk} “left”] [c →^{pyk} “center”] [r →^{pyk} “right”] [empty →^{pyk} “empty”] [⟨∗ | ∗:= ∗⟩ →^{pyk} “substitute " set " to " end substitute”] [M(∗) →^{pyk} “map tag " end tag”] [Ũ(∗) →^{pyk} “raw map untag " end untag”] [U(∗) →^{pyk} “map untag " end untag”] [U^{M}(∗) →^{pyk} “normalizing untag " end untag”] [apply(∗, ∗) →^{pyk} “apply " to " end apply”] [apply_{1}(∗, ∗) →^{pyk} “apply one " to " end apply”] [identifier(∗) →^{pyk} “identifier " end identifier”] [identifier_{1}(∗, ∗) →^{pyk} “identifier one " plus id " end identifier”] [array-plus(∗, ∗) →^{pyk} “array plus " and " end plus”] [array-remove(∗, ∗, ∗) →^{pyk} “array remove " array " level " end remove”] [array-put(∗, ∗, ∗, ∗) →^{pyk} “array put " value " array " level " end put”] [array-add(∗, ∗, ∗, ∗, ∗) →^{pyk} “array add " value " index " value " level " end add”] [bit(∗, ∗) →^{pyk} “bit " of " end bit”] [bit_{1}(∗, ∗) →^{pyk} “bit one " of " end bit”] [rack →^{pyk} “example rack”] ["vector" →^{pyk} “vector hook”] ["bibliography" →^{pyk} “bibliography hook”] ["dictionary" →^{pyk} “dictionary hook”] ["body" →^{pyk} “body hook”] ["codex" →^{pyk} “codex hook”] ["expansion" →^{pyk} “expansion hook”] ["code" →^{pyk} “code hook”] ["cache" →^{pyk} “cache hook”] ["diagnose" →^{pyk} “diagnose hook”] ["pyk" →^{pyk} “pyk aspect”] ["tex" →^{pyk} “tex aspect”] ["texname" →^{pyk} “texname aspect”] ["value" →^{pyk} “value aspect”] ["message" →^{pyk} “message aspect”] ["macro" →^{pyk} “macro aspect”] ["definition" →^{pyk} “definition aspect”] ["unpack" →^{pyk} “unpack aspect”] ["claim" →^{pyk} “claim aspect”] ["priority" →^{pyk} “priority aspect”] ["lambda" →^{pyk} “lambda identifier”] ["apply" →^{pyk} “apply identifier”] ["true" →^{pyk} “true identifier”] ["if" →^{pyk} “if identifier”] ["quote" →^{pyk} “quote identifier”] ["proclaim" →^{pyk} “proclaim identifier”] ["define" →^{pyk} “define identifier”] ["introduce" →^{pyk} “introduce identifier”] ["hide" →^{pyk} “hide identifier”] ["pre" →^{pyk} “pre identifier”] ["post" →^{pyk} “post identifier”] [E(∗, ∗, ∗) →^{pyk} “eval " stack " cache " end eval”] [E_{2}(∗, ∗, ∗, ∗, ∗) →^{pyk} “eval two " ref " id " stack " cache " end eval”] [E_{3}(∗, ∗, ∗, ∗) →^{pyk} “eval three " function " stack " cache " end eval”] [E_{4}(∗, ∗, ∗, ∗) →^{pyk} “eval four " arguments " stack " cache " end eval”] [lookup(∗, ∗, ∗) →^{pyk} “lookup " stack " default " end lookup”] [abstract(∗, ∗, ∗, ∗) →^{pyk} “abstract " term " stack " cache " end abstract”] [⌈∗⌉ →^{pyk} “quote " end quote”] [M(∗, ∗, ∗) →^{pyk} “expand " state " cache " end expand”] [M_{2}(∗, ∗, ∗, ∗) →^{pyk} “expand two " definition " state " cache " end expand”] [M^{∗}(∗, ∗, ∗) →^{pyk} “expand list " state " cache " end expand”] [macro →^{pyk} “macro”] [s_{0} →^{pyk} “macro state”] [zip(∗, ∗) →^{pyk} “zip " with " end zip”] [assoc_{1}(∗, ∗, ∗) →^{pyk} “assoc one " address " index " end assoc”] [(∗)^{p} →^{pyk} “protect " end protect”] [self →^{pyk} “self”] [[∗ ¨= ∗] →^{pyk} “macro define " as " end define”] [[∗ ˙= ∗] →^{pyk} “value define " as " end define”] [[∗ ´= ∗] →^{pyk} “intro define " as " end define”] [[∗ =^{pyk} ∗] →^{pyk} “pyk define " as " end define”] [[∗ =^{tex} ∗] →^{pyk} “tex define " as " end define”] [[∗ =^{name} ∗] →^{pyk} “tex name define " as " end define”] [Priority table[∗] →^{pyk} “priority table " end table”] [M̃_{1} →^{pyk} “macro define one”] [M̃_{2}(∗) →^{pyk} “macro define two " end define”] [M̃_{3}(∗) →^{pyk} “macro define three " end define”] [M̃_{4}(∗, ∗, ∗, ∗) →^{pyk} “macro define four " state " cache " definition " end define”] [M̃(∗, ∗, ∗) →^{pyk} “state expand " state " cache " end expand”] [Q̃(∗, ∗, ∗) →^{pyk} “quote expand " term " stack " end expand”] [Q̃_{2}(∗, ∗, ∗) →^{pyk} “quote expand two " term " stack " end expand”] [Q̃_{3}(∗, ∗, ∗, ∗) →^{pyk} “quote expand three " term " stack " value " end expand”] [Q̃^{∗}(∗, ∗, ∗) →^{pyk} “quote expand star " term " stack " end expand”] [(∗) →^{pyk} “parenthesis " end parenthesis”] [(∗) →^{pyk} “big parenthesis " end parenthesis”] [display(∗) →^{pyk} “display " end display”] [statement(∗) →^{pyk} “statement " end statement”] [[∗]^{·} →^{pyk} “spying test " end test”] [[∗]^{−} →^{pyk} “false spying test " end test”] [aspect(∗, ∗) →^{pyk} “aspect " subcodex " end aspect”] [aspect(∗, ∗, ∗) →^{pyk} “aspect " term " cache " end aspect”] [⟨∗⟩ →^{pyk} “tuple " end tuple”] [tuple_{1}(∗) →^{pyk} “tuple one " end tuple”] [tuple_{2}(∗) →^{pyk} “tuple two " end tuple”] [let_{2}(∗, ∗) →^{pyk} “let two " apply " end let”] [let_{1}(∗, ∗) →^{pyk} “let one " apply " end let”] [[∗ =^{claim} ∗] →^{pyk} “claim define " as " end define”] [checker →^{pyk} “checker”] [check(∗, ∗) →^{pyk} “check " cache " end check”] [check_{2}(∗, ∗, ∗) →^{pyk} “check two " cache " def " end check”] [check_{3}(∗, ∗, ∗) →^{pyk} “check three " cache " def " end check”] [check^{∗}(∗, ∗) →^{pyk} “check list " cache " end check”] [check_{2}^{∗}(∗, ∗, ∗) →^{pyk} “check list two " cache " value " end check”] [[∗]^{·} →^{pyk} “test " end test”] [[∗]^{−} →^{pyk} “false test " end test”] [[∗]^{∘} →^{pyk} “raw test " end test”] [msg →^{pyk} “message”] [[∗ =^{msg} ∗] →^{pyk} “message define " as " end define”] [<stmt> →^{pyk} “the statement aspect”] [stmt →^{pyk} “statement”] [[∗ =^{stmt} ∗] →^{pyk} “statement define " as " end define”] [HeadNil′ →^{pyk} “example axiom”] [HeadPair′ →^{pyk} “example scheme”] [Transitivity′ →^{pyk} “example rule”] [⊥ ⊥ →^{pyk} “absurdity”] [Contra′ →^{pyk} “contraexample”] [T′_{E} →^{pyk} “example theory primed”] [L_{1} →^{pyk} “example lemma”] [\underline{∗} →^{pyk} “metavar " end metavar”] [A →^{pyk} “meta a”] [B →^{pyk} “meta b”] [C →^{pyk} “meta c”] [D →^{pyk} “meta d”] [E →^{pyk} “meta e”] [F →^{pyk} “meta f”] [G →^{pyk} “meta g”] [H →^{pyk} “meta h”] [I →^{pyk} “meta i”] [J →^{pyk} “meta j”] [K →^{pyk} “meta k”] [L →^{pyk} “meta l”] [M →^{pyk} “meta m”] [N →^{pyk} “meta n”] [O →^{pyk} “meta o”] [P →^{pyk} “meta p”] [Q →^{pyk} “meta q”] [R →^{pyk} “meta r”] [S →^{pyk} “meta s”] [T →^{pyk} “meta t”] [U →^{pyk} “meta u”] [V →^{pyk} “meta v”] [W →^{pyk} “meta w”] [X →^{pyk} “meta x”] [Y →^{pyk} “meta y”] [Z →^{pyk} “meta z”] [⟨∗ | ∗:= ∗⟩ →^{pyk} “sub " set " to " end sub”] [⟨^{∗}∗ | ∗:= ∗⟩ →^{pyk} “sub star " set " to " end sub”] [∅ →^{pyk} “the empty set”] [Remainder →^{pyk} “example remainder”] [(∗)^{v} →^{pyk} “make visible " end visible”] [intro(∗, ∗, ∗, ∗) →^{pyk} “intro " index " pyk " tex " end intro”] [intro(∗, ∗, ∗) →^{pyk} “intro " pyk " tex " end intro”] [error(∗, ∗) →^{pyk} “error " term " end error”] [error_{2}(∗, ∗) →^{pyk} “error two " term " end error”] [proof(∗, ∗, ∗) →^{pyk} “proof " term " cache " end proof”] [proof_{2}(∗, ∗) →^{pyk} “proof two " term " end proof”] [S(∗, ∗) →^{pyk} “sequent eval " term " end eval”] [S^{I}(∗, ∗) →^{pyk} “seqeval init " term " end eval”] [S^{⊳} (∗, ∗) →^{pyk} “seqeval modus " term " end eval”] [S_{1}^{⊳} (∗, ∗, ∗) →^{pyk} “seqeval modus one " term " sequent " end eval”] [S^{E}(∗, ∗) →^{pyk} “seqeval verify " term " end eval”] [S_{1}^{E}(∗, ∗, ∗) →^{pyk} “seqeval verify one " term " sequent " end eval”] [S^{+}(∗, ∗) →^{pyk} “sequent eval plus " term " end eval”] [S_{1}^{+}(∗, ∗, ∗) →^{pyk} “seqeval plus one " term " sequent " end eval”] [S^{−}(∗, ∗) →^{pyk} “seqeval minus " term " end eval”] [S_{1}^{−}(∗, ∗, ∗) →^{pyk} “seqeval minus one " term " sequent " end eval”] [S^{∗}(∗, ∗) →^{pyk} “seqeval deref " term " end eval”] [S_{1}^{∗}(∗, ∗, ∗) →^{pyk} “seqeval deref one " term " sequent " end eval”] [S_{2}^{∗}(∗, ∗, ∗, ∗) →^{pyk} “seqeval deref two " term " sequent " def " end eval”] [S^{@}(∗, ∗) →^{pyk} “seqeval at " term " end eval”] [S_{1}^{@}(∗, ∗, ∗) →^{pyk} “seqeval at one " term " sequent " end eval”] [S^{⊢}(∗, ∗) →^{pyk} “seqeval infer " term " end eval”] [S_{1}^{⊢}(∗, ∗, ∗, ∗) →^{pyk} “seqeval infer one " term " premise " sequent " end eval”] [S⊢ ⊢(∗, ∗) →^{pyk} “seqeval endorse " term " end eval”] [S⊢ ⊢ ; 1(∗, ∗, ∗, ∗) →^{pyk} “seqeval endorse one " term " side " sequent " end eval”] [S^{i.e.}(∗, ∗) →^{pyk} “seqeval est " term " end eval”] [S_{1}^{i.e.}(∗, ∗, ∗, ∗) →^{pyk} “seqeval est one " term " name " sequent " end eval”] [S_{2}^{i.e.}(∗, ∗, ∗, ∗, ∗) →^{pyk} “seqeval est two " term " name " sequent " def " end eval”] [S^{∀}(∗, ∗) →^{pyk} “seqeval all " term " end eval”] [S_{1}^{∀}(∗, ∗, ∗, ∗) →^{pyk} “seqeval all one " term " variable " sequent " end eval”] [S^{;}(∗, ∗) →^{pyk} “seqeval cut " term " end eval”] [S_{1}^{;}(∗, ∗, ∗) →^{pyk} “seqeval cut one " term " forerunner " end eval”] [S_{2}^{;}(∗, ∗, ∗, ∗) →^{pyk} “seqeval cut two " term " forerunner " sequent " end eval”] [T (∗) →^{pyk} “computably true " end true”] [claims(∗, ∗, ∗) →^{pyk} “claims " cache " ref " end claims”] [claims_{2}(∗, ∗, ∗) →^{pyk} “claims two " cache " ref " end claims”] [<proof> →^{pyk} “the proof aspect”] [proof →^{pyk} “proof”] [[Lemma ∗: ∗] →^{pyk} “lemma " says " end lemma”] [[Proof of ∗: ∗] →^{pyk} “proof of " reads " end proof”] [[∗ lemma ∗: ∗] →^{pyk} “in theory " lemma " says " end lemma”] [[∗ antilemma ∗: ∗] →^{pyk} “in theory " antilemma " says " end antilemma”] [[∗ rule ∗: ∗] →^{pyk} “in theory " rule " says " end rule”] [[∗ antirule ∗: ∗] →^{pyk} “in theory " antirule " says " end antirule”] [verifier →^{pyk} “verifier”] [V_{1}(∗) →^{pyk} “verify one " end verify”] [V_{2}(∗, ∗) →^{pyk} “verify two " proofs " end verify”] [V_{3}(∗, ∗, ∗, ∗) →^{pyk} “verify three " ref " sequents " diagnose " end verify”] [V_{4}(∗, ∗) →^{pyk} “verify four " premises " end verify”] [V_{5}(∗, ∗, ∗, ∗) →^{pyk} “verify five " ref " array " sequents " end verify”] [V_{6}(∗, ∗, ∗, ∗) →^{pyk} “verify six " ref " list " sequents " end verify”] [V_{7}(∗, ∗, ∗, ∗) →^{pyk} “verify seven " ref " id " sequents " end verify”] [Cut(∗, ∗) →^{pyk} “cut " and " end cut”] [Head_{⊕}(∗) →^{pyk} “head " end head”] [Tail_{⊕}(∗) →^{pyk} “tail " end tail”] [rule_{1}(∗, ∗) →^{pyk} “rule one " theory " end rule”] [rule(∗, ∗) →^{pyk} “rule " subcodex " end rule”] [Rule tactic →^{pyk} “rule tactic”] [Plus(∗, ∗) →^{pyk} “plus " and " end plus”] [[Theory ∗] →^{pyk} “theory " end theory”] [theory_{2}(∗, ∗) →^{pyk} “theory two " cache " end theory”] [theory_{3}(∗, ∗) →^{pyk} “theory three " name " end theory”] [theory_{4}(∗, ∗, ∗) →^{pyk} “theory four " name " sum " end theory”] [HeadNil′′ →^{pyk} “example axiom lemma primed”] [HeadPair′′ →^{pyk} “example scheme lemma primed”] [Transitivity′′ →^{pyk} “example rule lemma primed”] [Contra′′ →^{pyk} “contraexample lemma primed”] [HeadNil →^{pyk} “example axiom lemma”] [HeadPair →^{pyk} “example scheme lemma”] [Transitivity →^{pyk} “example rule lemma”] [Contra →^{pyk} “contraexample lemma”] [T_{E} →^{pyk} “example theory”] [ragged right →^{pyk} “ragged right”] [ragged right expansion →^{pyk} “ragged right expansion”] [parm(∗, ∗, ∗) →^{pyk} “parameter term " stack " seed " end parameter”] [parm^{∗}(∗, ∗, ∗) →^{pyk} “parameter term star " stack " seed " end parameter”] [inst(∗, ∗) →^{pyk} “instantiate " with " end instantiate”] [inst^{∗}(∗, ∗) →^{pyk} “instantiate star " with " end instantiate”] [occur(∗, ∗, ∗) →^{pyk} “occur " in " substitution " end occur”] [occur^{∗}(∗, ∗, ∗) →^{pyk} “occur star " in " substitution " end occur”] [unify(∗ = ∗, ∗) →^{pyk} “unify " with " substitution " end unify”] [unify^{∗}(∗ = ∗, ∗) →^{pyk} “unify star " with " substitution " end unify”] [unify_{2}(∗ = ∗, ∗) →^{pyk} “unify two " with " substitution " end unify”] [L_{a} →^{pyk} “ell a”] [L_{b} →^{pyk} “ell b”] [L_{c} →^{pyk} “ell c”] [L_{d} →^{pyk} “ell d”] [L_{e} →^{pyk} “ell e”] [L_{f} →^{pyk} “ell f”] [L_{g} →^{pyk} “ell g”] [L_{h} →^{pyk} “ell h”] [L_{i} →^{pyk} “ell i”] [L_{j} →^{pyk} “ell j”] [L_{k} →^{pyk} “ell k”] [L_{l} →^{pyk} “ell l”] [L_{m} →^{pyk} “ell m”] [L_{n} →^{pyk} “ell n”] [L_{o} →^{pyk} “ell o”] [L_{p} →^{pyk} “ell p”] [L_{q} →^{pyk} “ell q”] [L_{r} →^{pyk} “ell r”] [L_{s} →^{pyk} “ell s”] [L_{t} →^{pyk} “ell t”] [L_{u} →^{pyk} “ell u”] [L_{v} →^{pyk} “ell v”] [L_{w} →^{pyk} “ell w”] [L_{x} →^{pyk} “ell x”] [L_{y} →^{pyk} “ell y”] [L_{z} →^{pyk} “ell z”] [L_{A} →^{pyk} “ell big a”] [L_{B} →^{pyk} “ell big b”] [L_{C} →^{pyk} “ell big c”] [L_{D} →^{pyk} “ell big d”] [L_{E} →^{pyk} “ell big e”] [L_{F} →^{pyk} “ell big f”] [L_{G} →^{pyk} “ell big g”] [L_{H} →^{pyk} “ell big h”] [L_{I} →^{pyk} “ell big i”] [L_{J} →^{pyk} “ell big j”] [L_{K} →^{pyk} “ell big k”] [L_{L} →^{pyk} “ell big l”] [L_{M} →^{pyk} “ell big m”] [L_{N} →^{pyk} “ell big n”] [L_{O} →^{pyk} “ell big o”] [L_{P} →^{pyk} “ell big p”] [L_{Q} →^{pyk} “ell big q”] [L_{R} →^{pyk} “ell big r”] [L_{S} →^{pyk} “ell big s”] [L_{T} →^{pyk} “ell big t”] [L_{U} →^{pyk} “ell big u”] [L_{V} →^{pyk} “ell big v”] [L_{W} →^{pyk} “ell big w”] [L_{X} →^{pyk} “ell big x”] [L_{Y} →^{pyk} “ell big y”] [L_{Z} →^{pyk} “ell big z”] [L_{?} →^{pyk} “ell dummy”] [Reflexivity →^{pyk} “sequent reflexivity”] [Reflexivity_{1} →^{pyk} “tactic reflexivity”] [Commutativity →^{pyk} “sequent commutativity”] [Commutativity_{1} →^{pyk} “tactic commutativity”] [<tactic> →^{pyk} “the tactic aspect”] [tactic →^{pyk} “tactic”] [[∗ =^{tactic} ∗] →^{pyk} “tactic define " as " end define”] [P(∗, ∗, ∗) →^{pyk} “proof expand " state " cache " end expand”] [P^{∗}(∗, ∗, ∗) →^{pyk} “proof expand list " state " cache " end expand”] [p_{0} →^{pyk} “proof state”] [conclude_{1}(∗, ∗) →^{pyk} “conclude one " cache " end conclude”] [conclude_{2}(∗, ∗, ∗) →^{pyk} “conclude two " proves " cache " end conclude”] [conclude_{3}(∗, ∗, ∗, ∗) →^{pyk} “conclude three " proves " lemma " substitution " end conclude”] [conclude_{4}(∗, ∗) →^{pyk} “conclude four " lemma " end conclude”] [∗ {∗} →^{pyk} “" sub " end sub”] [∗/indexintro(∗, ∗, ∗, ∗) →^{pyk} “" intro " index " pyk " tex " end intro”] [∗/intro(∗, ∗, ∗) →^{pyk} “" intro " pyk " tex " end intro”] [∗/bothintro(∗, ∗, ∗, ∗, ∗) →^{pyk} “" intro " index " pyk " tex " name " end intro”] [∗/nameintro(∗, ∗, ∗, ∗) →^{pyk} “" intro " pyk " tex " name " end intro”] [∗′ →^{pyk} “" prime”] [∗[ ∗] →^{pyk} “" assoc " end assoc”] [∗[∗→∗] →^{pyk} “" set " to " end set”] [∗[∗⇒∗] →^{pyk} “" set multi " to " end set”] [∗0 →^{pyk} “" bit nil”] [∗1 →^{pyk} “" bit one”] [0b →^{pyk} “binary”] [∗-color(∗) →^{pyk} “" color " end color”] [∗-color^{∗}(∗) →^{pyk} “" color star " end color”] [∗^{H} →^{pyk} “" raw head”] [∗^{T} →^{pyk} “" raw tail”] [∗^{U} →^{pyk} “" cardinal untag”] [∗^{h} →^{pyk} “" head”] [∗^{t} →^{pyk} “" tail”] [∗^{s} →^{pyk} “" is singular”] [∗^{c} →^{pyk} “" is cardinal”] [∗^{d} →^{pyk} “" is data”] [∗^{a} →^{pyk} “" is atomic”] [∗^{C} →^{pyk} “" cardinal retract”] [∗^{M} →^{pyk} “" tagged retract”] [∗^{B} →^{pyk} “" boolean retract”]

[∗^{r} →^{pyk} “" ref”]

[∗^{i} →^{pyk} “" id”]

[∗^{d} →^{pyk} “" debug”] [∗^{R} →^{pyk} “" root”] [∗^{0} →^{pyk} “" zeroth”] [∗^{1} →^{pyk} “" first”] [∗^{2} →^{pyk} “" second”] [∗^{3} →^{pyk} “" third”] [∗^{4} →^{pyk} “" fourth”] [∗^{5} →^{pyk} “" fifth”] [∗^{6} →^{pyk} “" sixth”] [∗^{7} →^{pyk} “" seventh”] [∗^{8} →^{pyk} “" eighth”] [∗^{9} →^{pyk} “" ninth”] [∗^{E} →^{pyk} “" is error”] [∗^{V} →^{pyk} “" is metavar”] [∗^{C} →^{pyk} “" is metaclosed”] [∗^{C^{∗}} →^{pyk} “" is metaclosed star”] [“ ∗ ” →^{pyk} “unicode start of text " end unicode text”] [ →^{pyk} “unicode end of text”] [(∗)^{t} →^{pyk} “text " end text”] [string(∗) + ∗ →^{pyk} “text " plus "”] [string(∗) ++ ∗ →^{pyk} “text " plus indent "”] [

∗ →^{pyk} “unicode newline "”] [ ∗ →^{pyk} “unicode space "”] [!∗ →^{pyk} “unicode exclamation mark "”] ["∗ →^{pyk} “unicode quotation mark "”] [#∗ →^{pyk} “unicode number sign "”] [$∗ →^{pyk} “unicode dollar sign "”] [%∗ →^{pyk} “unicode percent "”] [&∗ →^{pyk} “unicode ampersand "”] [’∗ →^{pyk} “unicode apostrophe "”] [(∗ →^{pyk} “unicode left parenthesis "”] [)∗ →^{pyk} “unicode right parenthesis "”] [∗∗ →^{pyk} “unicode asterisk "”] [+∗ →^{pyk} “unicode plus sign "”] [, ∗ →^{pyk} “unicode comma "”] [-∗ →^{pyk} “unicode hyphen "”] [.∗ →^{pyk} “unicode period "”] [/∗ →^{pyk} “unicode slash "”] [0∗ →^{pyk} “unicode zero "”] [1∗ →^{pyk} “unicode one "”] [2∗ →^{pyk} “unicode two "”] [3∗ →^{pyk} “unicode three "”] [4∗ →^{pyk} “unicode four "”] [5∗ →^{pyk} “unicode five "”] [6∗ →^{pyk} “unicode six "”] [7∗ →^{pyk} “unicode seven "”] [8∗ →^{pyk} “unicode eight "”] [9∗ →^{pyk} “unicode nine "”] [:∗ →^{pyk} “unicode colon "”] [; ∗ →^{pyk} “unicode semicolon "”] [<∗ →^{pyk} “unicode less than "”] [=∗ →^{pyk} “unicode equal sign "”] [>∗ →^{pyk} “unicode greater than "”] [?∗ →^{pyk} “unicode question mark "”] [@∗ →^{pyk} “unicode commercial at "”] [A∗ →^{pyk} “unicode capital a "”] [B∗ →^{pyk} “unicode capital b "”] [C∗ →^{pyk} “unicode capital c "”] [D∗ →^{pyk} “unicode capital d "”] [E∗ →^{pyk} “unicode capital e "”] [F∗ →^{pyk} “unicode capital f "”] [G∗ →^{pyk} “unicode capital g "”] [H∗ →^{pyk} “unicode capital h "”] [I∗ →^{pyk} “unicode capital i "”] [J∗ →^{pyk} “unicode capital j "”] [K∗ →^{pyk} “unicode capital k "”] [L∗ →^{pyk} “unicode capital l "”] [M∗ →^{pyk} “unicode capital m "”] [N∗ →^{pyk} “unicode capital n "”] [O∗ →^{pyk} “unicode capital o "”] [P∗ →^{pyk} “unicode capital p "”] [Q∗ →^{pyk} “unicode capital q "”] [R∗ →^{pyk} “unicode capital r "”] [S∗ →^{pyk} “unicode capital s "”] [T∗ →^{pyk} “unicode capital t "”] [U∗ →^{pyk} “unicode capital u "”] [V∗ →^{pyk} “unicode capital v "”] [W∗ →^{pyk} “unicode capital w "”] [X∗ →^{pyk} “unicode capital x "”] [Y∗ →^{pyk} “unicode capital y "”] [Z∗ →^{pyk} “unicode capital z "”] [[∗ →^{pyk} “unicode left bracket "”] [\∗ →^{pyk} “unicode backslash "”] []∗ →^{pyk} “unicode right bracket "”] [ˆ ∗ →^{pyk} “unicode circumflex "”] [ ∗ →^{pyk} “unicode underscore "”] [‘∗ →^{pyk} “unicode grave accent "”] [a∗ →^{pyk} “unicode small a "”] [b∗ →^{pyk} “unicode small b "”] [c∗ →^{pyk} “unicode small c "”] [d∗ →^{pyk} “unicode small d "”] [e∗ →^{pyk} “unicode small e "”] [f∗ →^{pyk} “unicode small f "”] [g∗ →^{pyk} “unicode small g "”] [h∗ →^{pyk} “unicode small h "”] [i∗ →^{pyk} “unicode small i "”] [j∗ →^{pyk} “unicode small j "”] [k∗ →^{pyk} “unicode small k "”] [l∗ →^{pyk} “unicode small l "”] [m∗ →^{pyk} “unicode small m "”] [n∗ →^{pyk} “unicode small n "”] [o∗ →^{pyk} “unicode small o "”] [p∗ →^{pyk} “unicode small p "”] [q∗ →^{pyk} “unicode small q "”] [r∗ →^{pyk} “unicode small r "”] [s∗ →^{pyk} “unicode small s "”] [t∗ →^{pyk} “unicode small t "”] [u∗ →^{pyk} “unicode small u "”] [v∗ →^{pyk} “unicode small v "”] [w∗ →^{pyk} “unicode small w "”] [x∗ →^{pyk} “unicode small x "”] [y∗ →^{pyk} “unicode small y "”] [z∗ →^{pyk} “unicode small z "”] [{∗ →^{pyk} “unicode left brace "”] [|∗ →^{pyk} “unicode vertical line "”] [}∗ →^{pyk} “unicode right brace "”] [˜ ∗ →^{pyk} “unicode tilde "”] [Preassociative ∗; ∗ →^{pyk} “preassociative " greater than "”] [Postassociative ∗; ∗ →^{pyk} “postassociative " greater than "”] [[∗], ∗ →^{pyk} “priority " equal "”] [priority ∗ end →^{pyk} “priority " end priority”] [newline ∗ →^{pyk} “newline "”] [macro newline ∗ →^{pyk} “macro newline "”] [∗ ’ ∗ →^{pyk} “" apply "”] [∗ ‘ ∗ →^{pyk} “" tagged apply "”] [∗ · ∗ →^{pyk} “" times "”] [∗ ·_{0} ∗ →^{pyk} “" times zero "”]

[∗ + ∗ →^{pyk} “" plus "”]

[∗ +_{0} ∗ →^{pyk} “" plus zero "”] [∗ +_{1} ∗ →^{pyk} “" plus one "”] [∗ − ∗ →^{pyk} “" minus "”] [∗ −_{0} ∗ →^{pyk} “" minus zero "”] [∗ −_{1} ∗ →^{pyk} “" minus one "”] [∗ ∪ {∗} →^{pyk} “" term plus " end plus”] [∗ ∪ ∗ →^{pyk} “" term union "”] [∗\{∗} →^{pyk} “" term minus " end minus”] [∗ ˙. . ∗ →^{pyk} “" raw pair "”] [∗ \underline{˙. .} ∗ →^{pyk} “" eager pair "”] [∗ \underline{: :} ∗ →^{pyk} “" tagged pair "”] [∗ \underline{+2∗} ∗ →^{pyk} “" untagged double "”]

[∗ : : ∗ →^{pyk} “" pair "”]

[∗ +2∗ ∗ →^{pyk} “" double "”] [∗, ∗ →^{pyk} “" comma "”] [∗ ≈^{B} ∗ →^{pyk} “" boolean equal "”] [∗ ≈^{D} ∗ →^{pyk} “" data equal "”] [∗ ≈^{C} ∗ →^{pyk} “" cardinal equal "”] [∗ ≈^{P} ∗ →^{pyk} “" peano equal "”] [∗ ≈ ∗ →^{pyk} “" tagged equal "”] [∗ = ∗ →^{pyk} “" math equal "”] [∗ →^{+} ∗ →^{pyk} “" reduce to "”] [∗ =^{t} ∗ →^{pyk} “" term equal "”] [∗ =^{t^{∗}} ∗ →^{pyk} “" term list equal "”] [∗ =^{r} ∗ →^{pyk} “" term root equal "”] [∗ ∈_{t} ∗ →^{pyk} “" term in "”] [∗ ⊆_{T} ∗ →^{pyk} “" term subset "”] [∗ =^{T} ∗ →^{pyk} “" term set equal "”] [∗ =^{s} ∗ →^{pyk} “" sequent equal "”] [∗ free in ∗ →^{pyk} “" free in "”] [∗ free in^{∗} ∗ →^{pyk} “" free in star "”] [∗ free for ∗ in ∗ →^{pyk} “" free for " in "”] [∗ free for^{∗} ∗ in ∗ →^{pyk} “" free for star " in "”] [∗ ∈_{c} ∗ →^{pyk} “" claim in "”]

[∗ < ∗ →^{pyk} “" less "”]

[∗ <′ ∗ →^{pyk} “" less zero "”] [∗ ≤′ ∗ →^{pyk} “" less one "”]

[¬∗ →^{pyk} “not "”]

[∗ ∧ ∗ →^{pyk} “" and "”]

[∗ ¨∧ ∗ →^{pyk} “" macro and "”] [∗ ˜∧ ∗ →^{pyk} “" simple and "”] [∗ ∧_{c} ∗ →^{pyk} “" claim and "”]

[∗ ∨ ∗ →^{pyk} “" or "”]

[∗ ∥ ∗ →^{pyk} “" parallel "”] [∗ ¨∨ ∗ →^{pyk} “" macro or "”] [∗ ¨⇒ ∗ →^{pyk} “" macro imply "”] [∗ : ∗ →^{pyk} “" guard "”] [∗ spy ∗ →^{pyk} “" spy "”] [∗!∗ →^{pyk} “" tagged guard "”] [∗ \{ \begin{matrix}∗ \\ ∗ \end{matrix} →^{pyk} “" select " else " end select”]

[λ ∗ .∗ →^{pyk} “lambda " dot "”] [Λ ∗ .∗ →^{pyk} “tagged lambda " dot "”] [Λ∗ →^{pyk} “tagging "”] [if ∗ then ∗ else ∗ →^{pyk} “open if " then " else "”] [let ∗ = ∗ in ∗ →^{pyk} “let " be " in "”] [let ∗ ¨= ∗ in ∗ →^{pyk} “let " abbreviate " in "”] [∗^{I} →^{pyk} “" init”] [∗^{⊳} →^{pyk} “" modus”] [∗^{V} →^{pyk} “" verify”] [∗^{+} →^{pyk} “" curry plus”] [∗^{−} →^{pyk} “" curry minus”] [∗^{∗} →^{pyk} “" dereference”]

[∗ @ ∗ →^{pyk} “" at "”]

[∗ ⊳ ∗ →^{pyk} “" modus ponens "”] [∗ ⊳ ⊳ ∗ →^{pyk} “" modus probans "”] [∗ ≫ ∗ →^{pyk} “" conclude "”] [∗ ⊢ ∗ →^{pyk} “" infer "”] [∗ ⊢⊢ ∗ →^{pyk} “" endorse "”] [∗ i.e. ∗ →^{pyk} “" id est "”] [∀∗: ∗ →^{pyk} “all " indeed "”] [∗ ⊕ ∗ →^{pyk} “" rule plus "”]

[∗; ∗ →^{pyk} “" cut "”]

[∗ proves ∗ →^{pyk} “" proves "”] [∗ proof of ∗ : ∗ →^{pyk} “" proof of " reads "”] [Line ∗ : ∗ ≫ ∗; ∗ →^{pyk} “line " because " indeed " end line "”] [Last line ∗ ≫ ∗ □ →^{pyk} “because " indeed " qed”] [Line ∗ : Premise ≫ ∗; ∗ →^{pyk} “line " premise " end line "”] [Line ∗ : Side-condition ≫ ∗; ∗ →^{pyk} “line " side condition " end line "”] [Arbitrary ≫ ∗; ∗ →^{pyk} “arbitrary " end line "”] [Local ≫ ∗ = ∗; ∗ →^{pyk} “locally define " as " end line "”]

[∗ , ∗ →^{pyk} “" , "”]

[∗[ ∗]∗ →^{pyk} “" [ " ] "”]

[∗&∗ →^{pyk} “" tab "”]

[∗\\∗ →^{pyk} “" row "”]

[∗ linebreak[4] ∗ →^{pyk} “" linebreak "”] [base →^{pyk} “base”]

C Test

[T + 0 ≈ T]^{·} [0 + T ≈ T]^{·} [T + T ≈ T]^{·} [0 + 0 ≈ 0]^{·} [0 + 1 ≈ 1]^{·} [0 + 2 ≈ 2]^{·} [0 + 3 ≈ 3]^{·} [1 + 0 ≈ 1]^{·} [1 + 1 ≈ 2]^{·} [1 + 2 ≈ 3]^{·} [1 + 3 ≈ 4]^{·} [2 + 0 ≈ 2]^{·} [2 + 1 ≈ 3]^{·} [2 + 2 ≈ 4]^{·} [2 + 3 ≈ 5]^{·} [3 + 0 ≈ 3]^{·} [3 + 1 ≈ 4]^{·} [3 + 2 ≈ 5]^{·} [3 + 3 ≈ 6]^{·} [T < 0 ≈ F]^{·} [0 < T ≈ F]^{·} [T < T ≈ F]^{·} [0 < 0 ≈ F]^{·}

[0 < 1 ≈ T]^{·}

[0 < 2 ≈ T]^{·}

[0 < 3 ≈ T]^{·}

[1 < 0 ≈ F]^{·}

[1 < 1 ≈ F]^{·}

[1 < 2 ≈ T]^{·}

[1 < 3 ≈ T]^{·}

[2 < 0 ≈ F]^{·}

[2 < 1 ≈ F]^{·}

[2 < 2 ≈ F]^{·}

[2 < 3 ≈ T]^{·}

[3 < 0 ≈ F]^{·}

[3 < 1 ≈ F]^{·}

[3 < 2 ≈ F]^{·}

[3 < 3 ≈ F]^{·}

[T − 0 ≈ T]^{·}

[0 − T ≈ T]^{·}

[T − T ≈ T]^{·}

[0 − 0 ≈ 0]^{·}

[0 − 1 ≈ 0]^{·}

[0 − 2 ≈ 0]^{·}

[0 − 3 ≈ 0]^{·}

[1 − 0 ≈ 1]^{·}

[1 − 1 ≈ 0]^{·}

[1 − 2 ≈ 0]^{·}

[1 − 3 ≈ 0]^{·}

[2 − 0 ≈ 2]^{·} [2 − 1 ≈ 1]^{·}

[2 − 2 ≈ 0]^{·}

[2 − 3 ≈ 0]^{·}

[3 − 0 ≈ 3]^{·}

[3 − 1 ≈ 2]^{·}

[3 − 2 ≈ 1]^{·}

[3 − 3 ≈ 0]^{·}

[T · 0 ≈ T]^{·}

[0 · T ≈ T]^{·}

[T · T ≈ T]^{·}

[0 · 0 ≈ 0]^{·}

[0 · 1 ≈ 0]^{·}

[0 · 2 ≈ 0]^{·}

[0 · 3 ≈ 0]^{·}

[1 · 0 ≈ 0]^{·}

[1 · 1 ≈ 1]^{·}

[1 · 2 ≈ 2]^{·}

[1 · 3 ≈ 3]^{·}

[2 · 0 ≈ 0]^{·}

[2 · 1 ≈ 2]^{·}

[2 · 2 ≈ 4]^{·}

[2 · 3 ≈ 6]^{·}

[3 · 0 ≈ 0]^{·}

[3 · 1 ≈ 3]^{·}

[3 · 2 ≈ 6]^{·}

[3 · 3 ≈ 9]^{·}

[bit(T, 0) ≈ T]^{·}

[bit(0, T) ≈ T]^{·} [bit(T, T) ≈ T]^{·} [bit(0, 0) ≈ T]^{·} [bit(0, 1) ≈ F]^{·} [bit(0, 2) ≈ T]^{·} [bit(0, 3) ≈ F]^{·} [bit(1, 0) ≈ T]^{·} [bit(1, 1) ≈ T]^{·} [bit(1, 2) ≈ F]^{·} [bit(1, 3) ≈ F]^{·} [bit(2, 0) ≈ T]^{·} [bit(2, 1) ≈ T]^{·} [bit(2, 2) ≈ T]^{·} [bit(2, 3) ≈ T]^{·} [bit(3, 0) ≈ T]^{·} [bit(3, 1) ≈ T]^{·} [bit(3, 2) ≈ T]^{·} [bit(3, 3) ≈ T]^{·} [identifier(⌈“code”⌉) ≈ 0b1100101011001000110111101100011]^{·} [T[0→1] ≈ 0 : : 1]^{·} [T[0→1][1→2] ≈ 0 : : 1 : : 1 : : 2]^{·} [T[0→1][2→4] ≈ 0 : : 1 : : 2 : : 4 : : T]^{·} [T[1→2][3→6] ≈ T : : 1 : : 2 : : 3 : : 6]^{·} [T[0→1][2→4][0→T] ≈ T[2→4]]^{·} [T[0→1][2→4][2→T] ≈ T[0→1]]^{·} [T[1→2][3→6][1→T] ≈ T[3→6]]^{·} [T[1→2][3→6][3→T] ≈ T[1→2]]^{·} [T[1→7][2→8][4→9][1] ≈ 7]^{·} [T[1→7][2→8][4→9][2] ≈ 8]^{·} [T[1→7][2→8][4→9][4] ≈ 9]^{·}

[T[1 : : 2 : : 3 : : T⇒1][2 : : T⇒2][1 : : 1 : : T⇒3][1 : : 2 : : 4 : : T⇒4][1][2][3] ≈ 1]^{·}

[2 : : 3 : : 2 : : T ≈ let_{1}(λx.x : : 3 : : x : : T, 2)]^{·}

[0 ≈ let_{1}(λx.T ˙. . F, F)]^{·}

[0 ≈ let_{1}(λx.T ˙. . x, F)]^{·}

[T : : 0 ≈ \underline{0} ˙. . \underline{0} ˙. . T ˙. . λy.y]^{·}

[T : : T ≈ let_{1}(λx.\underline{0} ˙. . \underline{0} ˙. . T ˙. . x, λy.y)]^{·}

[⌈2⌉ ⊢ ⌈3⌉ =^{t} ⌈2 ⊢ 3⌉]^{·}

[⌈2⌉ ⊢⊢ ⌈3⌉ =^{t} ⌈2 ⊢⊢ 3⌉]^{·}

[∀⌈2⌉: ⌈3⌉ =^{t} ⌈∀2: 3⌉]^{·}

[⊥ ⊥ =^{t} ⌈⊥ ⊥⌉]^{·}

[⌈2⌉ ⊕ ⌈3⌉ =^{t} ⌈2 ⊕ 3⌉]^{·}

[⌈2⌉^{I} =^{t} ⌈2^{I}⌉]^{·}

[⌈2⌉^{⊳} =^{t} ⌈2^{⊳} ⌉]^{·}

[⌈2⌉^{V} =^{t} ⌈2^{V}⌉]^{·}

[⌈2⌉^{+} =^{t} ⌈2^{+}⌉]^{·}

[⌈2⌉^{−} =^{t} ⌈2^{−}⌉]^{·}

[⌈2⌉^{∗} =^{t} ⌈2^{∗}⌉]^{·}

[⌈2⌉ @⌈3⌉ =^{t} ⌈2 @ 3⌉]^{·}

[⌈2⌉ i.e. ⌈3⌉ =^{t} ⌈2 i.e. 3⌉]^{·}

[⌈2⌉; ⌈3⌉ =^{t} ⌈2; 3⌉]^{·}

[⌈\underline{p}⌉^{V}]^{·}

[⌈p⌉^{V}]^{−}

[⌈x : : y : : z⌉^{C}]^{·}

[⌈x : : \underline{y} : : z⌉^{C}]^{−}

[⌈\underline{y}⌉ free in ⌈\underline{x} : : \underline{y} : : \underline{z}⌉]^{·} [⌈\underline{y}⌉ free in ⌈\underline{x} : : y : : \underline{z}⌉]^{−}

[⌈x : : \underline{y} : : z⌉ free for ⌈\underline{x}⌉ in ⌈∀\underline{x}: b : : \underline{x} : : c⌉]^{·}

[⌈x : : \underline{y} : : z⌉ free for ⌈\underline{x}⌉ in ⌈∀\underline{y}: b : : \underline{x} : : c⌉]^{−}

[⌈x : : \underline{y} : : z⌉ free for ⌈\underline{y}⌉ in ⌈∀\underline{x}: b : : \underline{x} : : c⌉]^{·}

[⌈x : : \underline{y} : : z⌉ free for ⌈\underline{y}⌉ in ⌈∀\underline{y}: b : : \underline{x} : : c⌉]^{·}

[⟨⌈\underline{a} : : ∀\underline{a}: \underline{a} : : \underline{b} : : \underline{a}⌉ |⌈\underline{a}⌉:= ⌈2⌉⟩ =^{t} ⌈2 : : ∀\underline{a}: \underline{a} : : \underline{b} : : 2⌉]^{·}

[⌈y⌉ ∈_{t} ⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T]^{·}

[⌈u⌉ ∈_{t} ⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T]^{−}

[⌈z⌉ : : ⌈x⌉ : : T ⊆_{T} ⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T]^{·}

[⌈z⌉ : : ⌈u⌉ : : T ⊆_{T} ⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T]^{−}

[⌈z⌉ : : ⌈y⌉ : : ⌈x⌉ : : T =^{T} ⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T]^{·}

[⌈z⌉ : : ⌈x⌉ : : T =^{T} ⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T]^{−}

[⌈z⌉ : : ⌈y⌉ : : ⌈x⌉ : : T =^{T} ⌈x⌉ : : ⌈z⌉ : : T]^{−}

[∅ ∪ {⌈x⌉} ∪ {⌈y⌉} ∪ {⌈z⌉} ∪ {⌈y⌉} =^{t^{∗}} ⌈z⌉ : : ⌈y⌉ : : ⌈x⌉ : : T]^{·}

[⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T\{⌈y⌉} =^{t^{∗}} ⌈x⌉ : : ⌈z⌉ : : T]^{·}

[⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T\{⌈u⌉} =^{t^{∗}} ⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T]^{·}

[⌈a⌉ : : ⌈y⌉ : : ⌈b⌉ : : T ∪ ⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T =^{t^{∗}} ⌈a⌉ : : ⌈b⌉ : : ⌈x⌉ : : ⌈y⌉ : : ⌈z⌉ : : T]^{·}

[⌈1⌉ : : ⌈2⌉ : : T : : ⌈3⌉ : : ⌈4⌉ : : T : : ⌈5⌉ : : T =^{s} ⌈2⌉ : : ⌈1⌉ : : T : : ⌈4⌉ : : ⌈3⌉ : : T : :

⌈5⌉ : : T]^{·}

[⌈6⌉ : : ⌈2⌉ : : T : : ⌈3⌉ : : ⌈4⌉ : : T : : ⌈5⌉ : : T =^{s} ⌈2⌉ : : ⌈1⌉ : : T : : ⌈4⌉ : : ⌈3⌉ : : T : :

⌈5⌉ : : T]^{−}

[⌈1⌉ : : ⌈6⌉ : : T : : ⌈3⌉ : : ⌈4⌉ : : T : : ⌈5⌉ : : T =^{s} ⌈2⌉ : : ⌈1⌉ : : T : : ⌈4⌉ : : ⌈3⌉ : : T : :

⌈5⌉ : : T]^{−}

[⌈1⌉ : : ⌈2⌉ : : T : : ⌈6⌉ : : ⌈4⌉ : : T : : ⌈5⌉ : : T =^{s} ⌈2⌉ : : ⌈1⌉ : : T : : ⌈4⌉ : : ⌈3⌉ : : T : :

⌈5⌉ : : T]^{−}

[⌈1⌉ : : ⌈2⌉ : : T : : ⌈3⌉ : : ⌈6⌉ : : T : : ⌈5⌉ : : T =^{s} ⌈2⌉ : : ⌈1⌉ : : T : : ⌈4⌉ : : ⌈3⌉ : : T : :

⌈5⌉ : : T]^{−}

[⌈1⌉ : : ⌈2⌉ : : T : : ⌈3⌉ : : ⌈4⌉ : : T : : ⌈6⌉ : : T =^{s} ⌈2⌉ : : ⌈1⌉ : : T : : ⌈4⌉ : : ⌈3⌉ : : T : :

⌈5⌉ : : T]^{−} [U(E(⌈F +2∗ 2 ≈ 5⌉, T, base))]^{·} [U^{M}(E(⌈F +2∗ 2 ≈ 5⌉, T, base))]^{·} [U^{M}(E(⌈λc.U^{M}(E(⌈F +2∗ 2 ≈ 5⌉, T, c))⌉, T, base) ‘ base)]^{·} [S(base, ⌈\underline{a}^{I}^{⊳} ⌉) =^{s} ⌈\underline{a}⌉ : : T : : ∅ : : ⌈\underline{a}⌉ : : T]^{·}

[⌈2⌉-color(⌈3⌉ ⊢ ⌈4⌉) =^{t} ⌈3 ⊢ 4⌉]^{·}

[S(base, ⌈\underline{a} ⊕ \underline{b}^{I}⌉) =^{s} ∅ : : ∅ : : ⌈\underline{a} ⊕ \underline{b} ⊢ \underline{a} ⊕ \underline{b}⌉ : : T]^{·} [S(base, ⌈\underline{a} ⊢ \underline{b}^{I}⌉) =^{s} ∅ : : ∅ : : ⌈\underline{a} ⊢ \underline{b} ⊢ \underline{b}⌉ : : T]^{·} [⌈checker⌉ ∈_{c} ⌈checker ∧_{c} verifier⌉]^{·} [⌈verifier⌉ ∈_{c} ⌈checker ∧_{c} verifier⌉]^{·} [⌈7⌉ ∈_{c} ⌈checker ∧_{c} verifier⌉]^{−} [claims(⌈verifier⌉, base, base[0])]^{·} [claims(⌈7⌉, base, base[0])]^{−} [inst(parm(⌈∀x: ∀y: x + y⌉, T, 4), T[4→⌈u⌉][8→⌈v⌉]) =^{t} ⌈∀u: ∀v: u + v⌉]^{·} math test occur eight in parameter term quote not all var x indeed var x end

quote substitution true end occur end test end math

math false test occur nine in parameter term quote not all var x indeed var x

end quote substitution true end occur end test end math

[unify(⌈2⌉ = ⌈2⌉, T)]^{·} [unify(⌈2⌉ = ⌈3⌉, T) ≈ 0]^{·} [unify(⌈2 + 3⌉ = ⌈2 + 3⌉, T)]^{·} [unify(⌈2 + 3⌉ = ⌈2 + 4⌉, T) ≈ 0]^{·}

[unify(⌈2⌉ = 3, T)[3] =^{t} ⌈2⌉]^{·}

[unify(3 = ⌈2⌉, T)[3] =^{t} ⌈2⌉]^{·}

[unify(⌈x + y⌉^{R} : : 1 : : ⌈3⌉ : : T = ⌈2 + 3⌉, T)[1] =^{t} ⌈2⌉]^{·} [unify(⌈x + y⌉^{R} : : 1 : : ⌈3⌉ : : T = ⌈x + y⌉^{R} : : ⌈2⌉ : : 2 : : T, T)[1] =^{t} ⌈2⌉]^{·} [unify(parm(⌈\underline{a} + 3⌉, ⌈\underline{a}⌉ : : 1 : : T, 1) = parm(⌈2 + \underline{b}⌉, ⌈\underline{b}⌉ : : 2 : : T, 1), T)[1] =^{t}

⌈2⌉]^{·}

[unify(parm(⌈\underline{a} + 3⌉, ⌈\underline{a}⌉ : : 1 : : T, 1) = parm(⌈2 + \underline{b}⌉, ⌈\underline{b}⌉ : : 2 : : T, 1), T)[2] =^{t}

⌈3⌉]^{·}

[inst(parm(⌈\underline{a} + \underline{b}⌉, ⌈\underline{a}⌉ : : 1 : : ⌈\underline{b}⌉ : : 2 : : T, 1), unify(parm(⌈\underline{a} + 3⌉, ⌈\underline{a}⌉ : : 1 : : T, 1) = parm(⌈2 + \underline{b}⌉, ⌈\underline{b}⌉ : : 2 : : T, 1), T)) =^{t} ⌈2 + 3⌉]^{·}

D Priority table

[base →^{prio} Preassociative [base], [bracket ∗ end bracket], [big bracket ∗ end bracket], [ $ ∗ $ ], [flush left [∗]], [x], [y], [z], [[∗ ▷◁ ∗]], [[∗ →^{∗} ∗]], [pyk], [tex], [name], [prio], [∗], [T], [if(∗, ∗, ∗)], [[∗ ⇒^{∗} ∗]], [val], [claim], [⊥], [f(∗)], [(∗)^{I}], [F], [\underline{0}], [\underline{1}], [\underline{2}], [\underline{3}], [\underline{4}], [\underline{5}], [\underline{6}], [\underline{7}], [\underline{8}], [\underline{9}], [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [a], [b], [c], [d], [e], [f], [g], [h], [i], [j], [k], [l], [m], [n], [o], [p], [q], [r], [s], [t], [u], [v], [w], [(∗)^{M}], [If(∗, ∗, ∗)], [array{∗} ∗ end array], [l], [c], [r], [empty], [⟨∗ | ∗:= ∗⟩], [M(∗)], [Ũ(∗)], [U(∗)], [U^{M}(∗)], [apply(∗, ∗)], [apply_{1}(∗, ∗)], [identifier(∗)], [identifier_{1}(∗, ∗)], [arrayplus(∗, ∗)], [array-remove(∗, ∗, ∗)], [array-put(∗, ∗, ∗, ∗)], [array-add(∗, ∗, ∗, ∗, ∗)], [bit(∗, ∗)], [bit_{1}(∗, ∗)], [rack], ["vector"], ["bibliography"], ["dictionary"], ["body"], ["codex"], ["expansion"], ["code"], ["cache"], ["diagnose"], ["pyk"], ["tex"], ["texname"], ["value"], ["message"], ["macro"], ["definition"], ["unpack"], ["claim"], ["priority"], ["lambda"], ["apply"], ["true"], ["if"], ["quote"], ["proclaim"], ["define"], ["introduce"], ["hide"], ["pre"], ["post"], [E(∗, ∗, ∗)], [E_{2}(∗, ∗, ∗, ∗, ∗)], [E_{3}(∗, ∗, ∗, ∗)], [E_{4}(∗, ∗, ∗, ∗)], [lookup(∗, ∗, ∗)], [abstract(∗, ∗, ∗, ∗)], [⌈∗⌉], [M(∗, ∗, ∗)], [M_{2}(∗, ∗, ∗, ∗)], [M^{∗}(∗, ∗, ∗)], [macro], [s_{0}], [zip(∗, ∗)], [assoc_{1}(∗, ∗, ∗)], [(∗)^{p}], [self], [[∗ ¨= ∗]], [[∗ ˙= ∗]], [[∗ ´= ∗]], [[∗ =^{pyk} ∗]], [[∗ =^{tex} ∗]], [[∗ =^{name} ∗]], [Priority table[∗]], [M̃_{1}], [M̃_{2}(∗)], [M̃_{3}(∗)], [M̃_{4}(∗, ∗, ∗, ∗)], [M̃(∗, ∗, ∗)], [Q̃(∗, ∗, ∗)], [Q̃_{2}(∗, ∗, ∗)], [Q̃_{3}(∗, ∗, ∗, ∗)], [Q̃^{∗}(∗, ∗, ∗)], [(∗)], [(∗)], [display(∗)], [statement(∗)], [[∗]^{·}], [[∗]^{−}], [aspect(∗, ∗)], [aspect(∗, ∗, ∗)], [⟨∗⟩], [tuple_{1}(∗)], [tuple_{2}(∗)], [let_{2}(∗, ∗)], [let_{1}(∗, ∗)], [[∗ =^{claim} ∗]], [checker], [check(∗, ∗)], [check_{2}(∗, ∗, ∗)], [check_{3}(∗, ∗, ∗)], [check^{∗}(∗, ∗)], [check_{2}^{∗}(∗, ∗, ∗)], [[∗]^{·}], [[∗]^{−}], [[∗]^{∘}], [msg], [[∗ =^{msg} ∗]], [<stmt>], [stmt], [[∗ =^{stmt} ∗]], [HeadNil′], [HeadPair′], [Transitivity′], [⊥ ⊥], [Contra′], [T′_{E}], [L_{1}], [\underline{∗}], [A], [B], [C], [D], [E], [F], [G], [H], [I], [J], [K], [L], [M], [N], [O], [P], [Q], [R], [S], [T ], [U], [V], [W], [X], [Y], [Z], [⟨∗ | ∗:= ∗⟩], [⟨^{∗}∗ | ∗:= ∗⟩], [∅], [Remainder], [(∗)^{v}], [intro(∗, ∗, ∗, ∗)], [intro(∗, ∗, ∗)], [error(∗, ∗)], [error_{2}(∗, ∗)], [proof(∗, ∗, ∗)], [proof_{2}(∗, ∗)], [S(∗, ∗)], [S^{I}(∗, ∗)], [S^{⊳} (∗, ∗)], [S_{1}^{⊳} (∗, ∗, ∗)], [S^{E}(∗, ∗)], [S_{1}^{E}(∗, ∗, ∗)], [S^{+}(∗, ∗)], [S_{1}^{+}(∗, ∗, ∗)], [S^{−}(∗, ∗)], [S_{1}^{−}(∗, ∗, ∗)], [S^{∗}(∗, ∗)], [S_{1}^{∗}(∗, ∗, ∗)], [S_{2}^{∗}(∗, ∗, ∗, ∗)], [S^{@}(∗, ∗)], [S_{1}^{@}(∗, ∗, ∗)], [S^{⊢}(∗, ∗)], [S_{1}^{⊢}(∗, ∗, ∗, ∗)], [S⊢ ⊢(∗, ∗)],

[S⊢ ⊢ ; 1(∗, ∗, ∗, ∗)], [S^{i.e.}(∗, ∗)], [S_{1}^{i.e.}(∗, ∗, ∗, ∗)], [S_{2}^{i.e.}(∗, ∗, ∗, ∗, ∗)], [S^{∀}(∗, ∗)],

[S_{1}^{∀}(∗, ∗, ∗, ∗)], [S^{;}(∗, ∗)], [S_{1}^{;}(∗, ∗, ∗)], [S_{2}^{;}(∗, ∗, ∗, ∗)], [T (∗)], [claims(∗, ∗, ∗)], [claims_{2}(∗, ∗, ∗)], [<proof>], [proof], [[Lemma ∗: ∗]], [[Proof of ∗: ∗]], [[∗ lemma ∗: ∗]], [[∗ antilemma ∗: ∗]], [[∗ rule ∗: ∗]], [[∗ antirule ∗: ∗]], [verifier], [V_{1}(∗)], [V_{2}(∗, ∗)], [V_{3}(∗, ∗, ∗, ∗)], [V_{4}(∗, ∗)], [V_{5}(∗, ∗, ∗, ∗)], [V_{6}(∗, ∗, ∗, ∗)], [V_{7}(∗, ∗, ∗, ∗)], [Cut(∗, ∗)], [Head_{⊕}(∗)], [Tail_{⊕}(∗)], [rule_{1}(∗, ∗)], [rule(∗, ∗)], [Rule tactic], [Plus(∗, ∗)], [[Theory ∗]], [theory_{2}(∗, ∗)], [theory_{3}(∗, ∗)], [theory_{4}(∗, ∗, ∗)], [HeadNil′′], [HeadPair′′], [Transitivity′′], [Contra′′], [HeadNil], [HeadPair], [Transitivity], [Contra], [T_{E}], [ragged right], [ragged right expansion ], [parm(∗, ∗, ∗)], [parm^{∗}(∗, ∗, ∗)], [inst(∗, ∗)], [inst^{∗}(∗, ∗)], [occur(∗, ∗, ∗)], [occur^{∗}(∗, ∗, ∗)], [unify(∗ = ∗, ∗)], [unify^{∗}(∗ = ∗, ∗)], [unify_{2}(∗ = ∗, ∗)], [L_{a}], [L_{b}], [L_{c}], [L_{d}], [L_{e}], [L_{f}], [L_{g}], [L_{h}], [L_{i}], [L_{j}], [L_{k}], [L_{l}], [L_{m}], [L_{n}], [L_{o}], [L_{p}], [L_{q}], [L_{r}], [L_{s}], [L_{t}], [L_{u}], [L_{v}], [L_{w}], [L_{x}], [L_{y}], [L_{z}], [L_{A}], [L_{B}], [L_{C}], [L_{D}], [L_{E}], [L_{F}], [L_{G}], [L_{H}], [L_{I}], [L_{J}], [L_{K}], [L_{L}], [L_{M}], [L_{N}], [L_{O}], [L_{P}], [L_{Q}], [L_{R}], [L_{S}], [L_{T}], [L_{U}], [L_{V}], [L_{W}], [L_{X}], [L_{Y}], [L_{Z}], [L_{?}], [Reflexivity], [Reflexivity_{1}], [Commutativity], [Commutativity_{1}], [<tactic>], [tactic], [[∗ =^{tactic} ∗]], [P(∗, ∗, ∗)], [P^{∗}(∗, ∗, ∗)], [p_{0}], [conclude_{1}(∗, ∗)], [conclude_{2}(∗, ∗, ∗)], [conclude_{3}(∗, ∗, ∗, ∗)], [conclude_{4}(∗, ∗)]; Preassociative [∗ {∗}], [∗/indexintro(∗, ∗, ∗, ∗)], [∗/intro(∗, ∗, ∗)], [∗/bothintro(∗, ∗, ∗, ∗, ∗)], [∗/nameintro(∗, ∗, ∗, ∗)], [∗′], [∗[ ∗]], [∗[∗→∗]], [∗[∗⇒∗]], [∗0], [∗1], [0b], [∗-color(∗)], [∗-color^{∗}(∗)], [∗^{H}], [∗^{T}], [∗^{U}], [∗^{h}], [∗^{t}], [∗^{s}], [∗^{c}], [∗^{d}], [∗^{a}], [∗^{C}], [∗^{M}], [∗^{B}], [∗^{r}], [∗^{i}], [∗^{d}], [∗^{R}], [∗^{0}], [∗^{1}], [∗^{2}], [∗^{3}], [∗^{4}], [∗^{5}], [∗^{6}], [∗^{7}], [∗^{8}], [∗^{9}], [∗^{E}], [∗^{V}], [∗^{C}], [∗^{C^{∗}}]; Preassociative [“ ∗ ”], [], [(∗)^{t}], [string(∗) + ∗], [string(∗) ++ ∗], [ ∗], [ ∗], [!∗], ["∗], [#∗], [$∗], [%∗], [&∗], [’∗], [(∗], [)∗], [∗∗], [+∗], [, ∗], [-∗], [.∗], [/∗], [0∗], [1∗], [2∗], [3∗], [4∗], [5∗], [6∗], [7∗], [8∗], [9∗], [:∗], [; ∗], [<∗], [=∗], [>∗], [?∗], [@∗], [A∗], [B∗], [C∗], [D∗], [E∗], [F∗], [G∗], [H∗], [I∗], [J∗], [K∗], [L∗], [M∗], [N∗], [O∗], [P∗], [Q∗], [R∗], [S∗], [T∗], [U∗], [V∗], [W∗], [X∗], [Y∗], [Z∗], [[∗], [\∗], []∗], [ˆ ∗], [ ∗], [‘∗], [a∗], [b∗], [c∗], [d∗], [e∗], [f∗], [g∗], [h∗], [i∗], [j∗], [k∗], [l∗], [m∗], [n∗], [o∗], [p∗], [q∗], [r∗], [s∗], [t∗], [u∗], [v∗], [w∗], [x∗], [y∗], [z∗], [{∗], [|∗], [}∗], [˜ ∗], [Preassociative ∗; ∗], [Postassociative ∗; ∗], [[∗], ∗], [priority ∗ end], [newline ∗], [macro newline ∗]; Preassociative [∗ ’ ∗], [∗ ‘ ∗]; Preassociative [∗ · ∗], [∗ ·_{0} ∗]; Preassociative [∗ + ∗], [∗ +_{0} ∗], [∗ +_{1} ∗], [∗ − ∗], [∗ −_{0} ∗], [∗ −_{1} ∗]; Preassociative [∗ ∪ {∗}], [∗ ∪ ∗], [∗\{∗}]; Postassociative [∗ ˙. . ∗], [∗ \underline{˙. .} ∗], [∗ \underline{: :} ∗], [∗ \underline{+2∗} ∗], [∗ : : ∗], [∗ +2∗ ∗]; Postassociative [∗, ∗]; Preassociative

[∗ ≈^{B} ∗], [∗ ≈^{D} ∗], [∗ ≈^{C} ∗], [∗ ≈^{P} ∗], [∗ ≈ ∗], [∗ = ∗], [∗ →^{+} ∗], [∗ =^{t} ∗], [∗ =^{t^{∗}} ∗], [∗ =^{r} ∗],

[∗ ∈_{t} ∗], [∗ ⊆_{T} ∗], [∗ =^{T} ∗], [∗ =^{s} ∗], [∗ free in ∗], [∗ free in^{∗} ∗], [∗ free for ∗ in ∗], [∗ free for^{∗} ∗ in ∗], [∗ ∈_{c} ∗], [∗ < ∗], [∗ <′ ∗], [∗ ≤′ ∗]; Preassociative [¬∗]; Preassociative [∗ ∧ ∗], [∗ ¨∧ ∗], [∗ ˜∧ ∗], [∗ ∧_{c} ∗]; Preassociative [∗ ∨ ∗], [∗ ∥ ∗], [∗ ¨∨ ∗]; Postassociative [∗ ¨⇒ ∗]; Postassociative [∗ : ∗], [∗ spy ∗], [∗!∗]; Preassociative

[∗ \{ \begin{matrix}∗ \\ ∗ \end{matrix} ];

Preassociative [λ ∗ .∗], [Λ ∗ .∗], [Λ∗], [if ∗ then ∗ else ∗], [let ∗ = ∗ in ∗], [let ∗ ¨= ∗ in ∗]; Preassociative [∗^{I}], [∗^{⊳} ], [∗^{V}], [∗^{+}], [∗^{−}], [∗^{∗}]; Preassociative [∗ @ ∗], [∗ ⊳ ∗], [∗ ⊳ ⊳ ∗], [∗ ≫ ∗]; Postassociative [∗ ⊢ ∗], [∗ ⊢⊢ ∗], [∗ i.e. ∗]; Preassociative [∀∗: ∗]; Postassociative [∗ ⊕ ∗]; Postassociative [∗; ∗]; Preassociative [∗ proves ∗]; Preassociative [∗ proof of ∗ : ∗], [Line ∗ : ∗ ≫ ∗; ∗], [Last line ∗ ≫ ∗ □], [Line ∗ : Premise ≫ ∗; ∗], [Line ∗ : Side-condition ≫ ∗; ∗], [Arbitrary ≫ ∗; ∗], [Local ≫ ∗ = ∗; ∗]; Postassociative [∗ , ∗], [∗[ ∗]∗]; Preassociative [∗&∗]; Preassociative [∗\\∗], [∗ linebreak[4] ∗]; ]

E Index

[⊥ ⊥] absurdity, 80 [∀x: y] all x indeed y, 80 [[x]^{−}] false test t end test, 75 [\underline{x}] metavar x end metavar, 81 [[t]^{∘}] raw test t end test, 75 [⟨^{∗}x |y:= z⟩] sub star x set y to z end sub , 82 [⟨x |y:= z⟩] sub x set y to z end sub , 82 [[t]^{·}] test t end test, 74 [∅] the empty set, 83 [x : : T] tuple x end tuple, 66 [x @ y] x at y, 86 [x ∧_{c} y] x claim and y, 73 [x ∈_{c} y] x claim in y, 94 [x, y] x comma y, 66 [x ≫ y] x conclude y, 107 [x^{−}] x curry minus, 87 [x^{+}] x curry plus, 87 [x; y] x cut y, 87 [x^{∗}] x dereference, 87 [x ⊢⊢ y] x endorse y, 80 [x^{1}] x first, 32 [x ⊢ y] x infer y, 80 [x ≤′ y] x less one y, 40 [x < y] x less y, 39 [x <′ y] x less zero y, 40 [If(x, y, F)] x macro and y, 69 [If(x, y, T)] x macro imply y, 69 [If(x, T, y)] x macro or y, 69 [x −_{1} y] x minus one y, 40 [x − y] x minus y, 40 [x −_{0} y] x minus zero y, 40 [x^{⊳} ] x modus, 86 [x ⊳ y] x modus ponens y, 107 [x ⊳ ⊳ y] x modus probans y, 107 [x +_{1} y] x plus one y, 39 [x + y] x plus y, 39 [x +_{0} y] x plus zero y, 39 [x′] x prime, 49 [x ⊕ y] x rule plus y, 80 [x =^{s} y] x sequent equal y, 84 [x[y⇒z]] x set multi y to z end set, 48 [x[y→z]] x set y to z end set, 47 [x ˜∧ y] x simple and y, 73 [x ∈_{t} y] x term in y, 83 [x\{y}] x term minus y end minus, 83 [x ∪ {y}] x term plus y end plus, 83 [x =^{r} y] x term root equal y, 41 [x =^{T} y] x term set equal y, 83 [x ⊆_{T} y] x term subset y, 83 [x ∪ y] x term union y, 83 [x · y] x times y, 40 [x ·_{0} y] x times zero y, 40

absurdity, 80 absurdity [⊥ ⊥], 80 algorithm, unification, 103 all x indeed y [∀x: y], 80 antilemma, 79 antilemma: [x antilemma y: z] in theory x antilemma y says z end antilemma, 95 antirule: [x antirule y: z] in theory x antirule y says z end antirule, 100 apply identifier ["apply"], 55 [∀y: z] arbitrary x end line y, 108 arbitrary x end line y [∀x: y], 108 array, 46 [array-add(x, y, z, a, b)] array add x value y index z value a level b end add, 48 array index, 47 [array-plus(x, y)] array plus x and y end plus, 47 [array-put(x, y, z, a)] array put x value y array z level a end put, 48 [array-remove(x, y, z)] array remove x array y level z end remove, 48 aspect, 12 [aspect(a, t, c)], 55 [aspect(x, y)] aspect x subcodex y end aspect, 55 aspect, potentially inherited page, 61 aspect, pyk, 12 aspect, statement, 77 aspect, tex, 12 association, 45 association tree, 45 atomic, 46 axiom, 77 axiom scheme, 78

base page, 7, 8 basic tagged tree operations, 36 because x indeed y qed [x ≫ y], 108 bed, page, 61 bibliography, 8, 49 bibliography hook ["bibliography"], 52 big bracket * end bracket, 112 [bit(x, y)] bit x of y end bit, 40 [bit_{1}(x, y)] bit one x of y end bit, 41 body, 8, 49 body hook ["body"], 52 bottom, 26 bracket * end bracket, 112

C*: [x^{C^{∗}}] x is metaclosed star, 81 C: [x^{C}] x is metaclosed, 81 c: [x ∈_{c} y] x claim in y, 94 c: [x ∧_{c} y] x claim and y, 73 cache, 8, 50 cache hook ["cache"], 52 calculus, sequent, 75 canonical, 27 cardinal, 7 cardinal number, 29 cardinal tree, 31 [check(t, c)], 73 [check_{2}(t, c, d)], 73 [check_{3}(t, c, d)], 73 [check^{∗}(t, c)], 74 [check_{2}^{∗}(t, c, v)], 74 checker, 73

[checker] checker, 73 circular, 103 claim, 9, 72 ["claim"] claim aspect, 54 claim define x as y end define [[x =^{claim} y]], 72 claim: [[x =^{claim} y]] claim define x as y end define, 72 [claims(t, c, r)] claims t cache c ref r end claims, 95 [claims_{2}(t, c, r)] claims two t cache c ref r end claims, 95 code hook ["code"], 52 codex, 8, 9 codex hook ["codex"], 52 codify, 9, 56 color*: [x-color^{∗}(y)] x color star y end color, 92 color: [x-color(y)] x color y end color, 91 colored, 91 coloring, 91 [Commutativity] sequent commutativity, 102 [Commutativity_{1}] tactic commutativity, 105 compatible, 28, 103 computably true x end true [λc.U^{M}(E(⌈x⌉, T, c))], 87 [conclude_{1}(x, y)] conclude one x cache y end conclude, 107 [conclude_{2}(x, y, z)] conclude two x proves y cache z end conclude, 107 [conclude_{3}(x, y, z, a)] conclude three x proves y lemma z substitution a end conclude, 107 [conclude_{4}(x, y)] conclude four x lemma y end conclude, 108 conclusion, 78, 83 conclusion tactic, 107 conjecture, 79 construct, page, 51

[Contra] contraexample lemma, 101 [T : : T = T ⊢ ⊥ ⊥] contraexample, 78 [Contra′′] contraexample lemma primed, 96 contradiction, 78 correctness, 72 currying, 87 cut, 87 [Cut(x, y)] cut x and y end cut, 100

d: [x^{d}] x debug, 41 dead character code, 44 decurrying, 87 define identifier ["define"], 57 definition aspect ["definition"], 54 definition proclamation, 57 definitition, 9 dereferencing, 87 diagnose, 8, 72, 73 diagnose hook ["diagnose"], 53 dictionary, 8, 49 dictionary hook ["dictionary"], 52 domestic definition, 54

E: [x^{E}] x is error, 93 eager, 28 endorse, 80 engine, parallel, 25 [error_{2}(⌈m⌉, t)] error x term y end error, 92 [error_{2}(m, t)] error two x term y end error, 92 example axiom [T^{h} = T], 77 example axiom lemma [HeadNil], 100 example axiom lemma primed [HeadNil′′], 95 example lemma [L_{1}], 79 example rack [rack], 51 example rule [∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c}], 78 example rule lemma [Transitivity], 101 example rule lemma primed [Transitivity′′], 100 example scheme [∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a}], 78 example scheme lemma [HeadPair], 101 example scheme lemma primed [HeadPair′′], 100 example theory [T_{E}], 101 example theory primed [T′_{E}], 78 execute, 9 exists, symbol, 52 expander, 61 expansion, 8, 9, 61 expansion hook ["expansion"], 52

false test x end test [[x]^{−}], 75 finite function, 45 first edition engine, 34 fit for optimization, 36 flush left, 16 [flush left [x]] flush left x end left, 16 foreign definition, 54 free for*: [x free for^{∗} y in z] x free for star y in z , 82 free for: [x free for y in z] x free for y in z , 82 free in*: [x free in^{∗} y] x free in star y , 82 free in: [x free in y] x free in y , 82 function normal form, 24 function term, 24

guard, 28

harvesting, 63 [Head_{⊕}(x)] head x end head, 100 [HeadNil′′] example axiom lemma primed, 95

[HeadNil] example axiom lemma, 100 [T^{h} = T] example axiom, 77 [HeadPair′′] example scheme lemma primed, 100

[HeadPair] example scheme lemma, 101 [∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a}] example scheme, 78 hide identifier ["hide"], 57 hook, 47

i.e.: [x i.e. y] x id est y, 87 I: [x^{I}] x init, 85 i: [x^{i}] x id, 41 id, 31 idempotent, 29 identifier, 10 [identifier(x)] identifier x end identifier, 44 [identifier_{1}(x, y)] identifier one x plus id y end identifier, 45 identifier, Logiweb, 44 if identifier ["if"], 55 if, open, 68 if: [If(x, y, z)] open if x then y else z, 68 in theory x antilemma y says z end antilemma [x antilemma y: z], 95 in theory x antirule y says z end antirule [x antirule y: z], 100 in theory x lemma y says z end lemma [x lemma y: z], 95 in theory x rule y says z end rule [x rule y: z], 100 incompatible, 103 index (of array), 47 infer, 80 inference rule, 78 inherited page aspect, potentially, 61 initial macro state, 60 initial proof state, 106 [inst(x, y)] instantiate x with y end instantiate, 102 [inst^{∗}(x, y)] instantiate star x with y end instantiate, 103 instance, 103 instantiate star x with y end instantiate [inst^{∗}(x, y)], 103 instantiate x with y end instantiate [inst(x, y)], 102 intro * index * pyk * tex * end intro [intro(x, i, p, t)], 70 intro * pyk * tex * end intro [intro(x, p, t)], 70 intro: [intro(x, i, p, t)] intro * index * pyk * tex * end intro, 70 intro: [intro(x, p, t)] intro * pyk * tex * end intro, 70 introduce identifier ["introduce"], 57 introduction, 9

key, 45

[L_{1}] example lemma, 79 lambda identifier ["lambda"], 55 [x ≫ y] because x indeed y qed, 108 lazy, 29 left, flush, 16 lemma, 79 [Lemma x: y] lemma x says y, 95 lemma, rule, 88 lemma, sequent, 84 lemma: [x lemma y: z] in theory x lemma y says z end lemma, 95 let, 69

[z] let x abbreviate y in z, 65 [let_{1}(λx.z, y)] let x by y in z, 69 [let_{1}(x, y)] let one x apply y end let, 69 [let_{2}(x, y)] let two x apply y end let, 69 liberal, 27 lifted, untagged cardinal, 29 [y ≫ z; a] line x because y indeed z end line a, 108 line x because y indeed z end line a [y ≫ z; a], 108 line x premise y end line z [y ⊢ z], 108 line x side condition y end line z [y ⊢⊢ z], 108 Lisp property list, 55 load, 8, 50

[z] locally define x as y end line z, 108 locally define x as y end line z [z], 108 Logiweb identifier, 44 Logiweb sequent calculus, 75

macro aspect, 59 macro aspect ["macro"], 54 macro definition, 59 macro state, 59 macro state, initial, 60 make visible x end visible [x], 68 Map Theory, 76 math * end math, 111 mathematically equal, 25 message, 76 message aspect ["message"], 54 message define x as y end define [x =^{msg} y], 76 message proclamation, 56 metavar x end metavar [\underline{x}], 81 metavariable, 78 metavariables, 81 modus, 86 modus ponens, 86 modus probans, 86

[msg] message, 76 msg: [x =^{msg} y] message define x as y end text end define, 76

name, tex, 111 natural number, 7

[x] macro newline x, 67 [newline x] newline x, 67 newline character, 109 normal form, 24 normalization construct, 30

[occur(x, y, z)] occur x in y substitution z end occur, 103 [occur^{∗}(x, y, z)] occur star x in y substitution z end occur, 103 occur star x in y substitution z end occur [occur^{∗}(x, y, z)], 103 occur x in y substitution z end occur [occur(x, y, z)], 103 off-stage semantics, 34 on-stage semantics, 34 open if, 68 open if x then y else z [If(x, y, z)], 68 operation over, 36 operation, sequent, 84 ordinal number, 29 ordinary variable, 78

p: [p_{0}] proof state, 106 p: [P(x, y, z)] proof expand x state y cache z end expand, 106 p: [P^{∗}(x, y, z)] proof expand list x state y cache z end expand, 106 page aspect, potentially inherited, 61 page bed, 61 page construct, 10, 51 parallel engine, 25 parameter term, 102 parameter term star x stack y seed z end parameter [parm^{∗}(x, y, z)], 102 parameter term x stack y seed z end parameter [parm(x, y, z)], 102 [parm(x, y, z)] parameter term x stack y seed z end parameter, 102 [parm^{∗}(x, y, z)] parameter term star x stack y seed z end parameter, 102 Peano tree, 27 perpetual, 24 [Plus(x, y)] plus x and y end plus, 101 plus, rule, 80 ponens, modus, 86 post identifier ["post"], 57 potentially inherited page aspect, 61 pre identifier ["pre"], 57 predefined concept, 23 premise, 78, 83 [y ⊢ z] line x premise y end line z, 108 priority aspect ["priority"], 54 priority proclamation, 57 [[base →^{prio} x]] priority table x end table, 66 probans, modus, 86 proclaim identifier ["proclaim"], 57 proclamation, 9 proclamation construct, 10 [proof(x, y, z)] proof x term y cache z end proof, 94 [<proof>] the proof aspect, 95 proof [proof], 95 [proof_{2}(x, y)] proof two x term y end proof, 94 proof aspect, 95 proof expander, 104 [Proof of x: y] proof of x read y end proof, 95 proof state, 106 proof state, initial, 106 proof tactic, 104 proof x term y cache z end proof proof(x, y, z), 94 proof, sequent, 84 property list, Lisp, 55 proves: proof(⌈x⌉, ⌈y⌉, base) x proves y, 93 pruning, 60 pure lambda calculus, 23 pyk, 162 pyk aspect, 12 pyk aspect ["pyk"], 54 quote, 41 quote identifier ["quote"], 55

r: [x =^{r} y] x term root equal y, 41 r: [x^{r}] x ref, 41 R: [x^{R}] x root, 41 rack, 47, 50

[rack] example rack, 51 ragged right, 16, 67 [ragged right] ragged right, 67 [ragged right] ragged right expansion, 67 raw, 27 raw test x end test [[x]^{∘}], 75 reduction system, 24 reference, 7, 10 reference cardinal, 31 referencing, 87 [Reflexivity] sequent reflexivity, 102 [Reflexivity_{1}] tactic reflexivity, 105 regular, 32 [∀\underline{a}: ∀\underline{b}: \underline{a} : : \underline{b}^{h} = \underline{a} ⊕ ∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c} ⊕ T : : T = T ⊢ ⊥ ⊥], 88 resolve, 9 retract, 30 retrieve, 9 return [⊥], 26 revelation, 9, 34 right, ragged, 16, 67 root equivalent, 24 root normal form, 24 rule, 78 [rule(x, y)] rule x subcodex y end rule, 99 [rule_{1}(x, y)] rule one x theory y end rule, 99 rule lemma, 88 rule plus, 80 [Rule tactic] rule tactic, 99 rule, inference, 78 rule: [x rule y: z] in theory x rule y says z end rule, 100

s: [x =^{s} y], 84

S: [S(x, y)] sequent eval x term y end eval, 93 S: [S^{+}(x, y)] sequent eval plus x term y end eval, 89 S: [S^{−}(x, y)] seqeval minus x term y end eval, 89 S: [S^{;}(x, y)] seqeval cut x term y end eval, 91 S: [S^{∗}(x, y)] seqeval deref x term y end eval, 89 S: [S^{@}(x, y)] seqeval at x term y end eval, 90 S: [S^{∀}(x, y)] seqeval all x term y end eval, 91 S: [S⊢ ⊢(x, y)] seqeval endorse x term y end eval, 90 S: [S^{⊳} (x, y)] seqeval modus x term y end eval, 89 S: [S^{⊢}(x, y)] seqeval infer x term y end eval, 90 S: [S^{E}(x, y)] seqeval verify x term y end eval, 89 S: [S^{i.e.}(x, y)] seqeval est x term y end eval, 90 S: [S^{I}(x, y)] seqeval init x term y end eval, 89 S: [S_{1}^{+}(x, y, z)] seqeval plus one x term y sequent z end eval, 89 S: [S_{1}^{−}(x, y, z)] seqeval minus one x term y sequent z end eval, 89 S: [S_{1}^{;}(x, y, z)] seqeval cut one x term y forerunner z end eval, 91 S: [S_{1}^{∗}(x, y, z)] seqeval deref one x term y sequent z end eval, 90 S: [S_{1}^{@}(x, y, z)] seqeval at one x term y sequent x end eval, 90 S: [S_{1}^{∀}(x, y, z, u)] seqeval all one x term y variable z sequent u end eval, 91 S: [S⊢ ⊢ ; 1(x, y, z, u)] seqeval endorse one x term y side z sequent u end eval, 90 S: [S_{1}^{⊳} (x, y, z)] seqeval modus one x term y sequent z end eval, 89 S: [S_{1}^{⊢}(x, y, z, u)] seqeval infer one x term y premise z sequent u end eval, 90 S: [S_{1}^{E}(x, y, z)] seqeval verify one x term y sequent z end eval, 89 S: [S_{1}^{i.e.}(x, y, z, u)] seqeval est one x term y name z sequent u end eval, 90 S: [S_{2}^{;}(x, y, z, u)] seqeval cut two x term y sequent u end eval, 91 S: [S_{2}^{∗}(x, y, z, u)] seqeval deref two x term y sequent z def u end eval, 90 S: [S_{2}^{i.e.}(x, y, z, u, v)] seqeval est two x term y name z sequent u def v end eval, 90 scheme, axiom, 78 self-evaluating, 68 semitagged, 33 seqeval all one x term y variable z sequent u end eval [S_{1}^{∀}(x, y, z, u)], 91 seqeval all x term y end eval [S^{∀}(x, y)], 91 seqeval at one x term y sequent z end eval [S_{1}^{@}(x, y, z)], 90 seqeval at x term y end eval [S^{@}(x, y)], 90 seqeval cut one x term y forerunner z end eval [S_{1}^{;}(x, y, z)], 91 seqeval cut two x term y forerunner z sequent u end eval [S_{2}^{;}(x, y, z, u)], 91 seqeval cut x term y end eval [S^{;}(x, y)], 91 seqeval deref one x term y sequent z end eval [S_{1}^{∗}(x, y, z)], 90 seqeval deref two x term y sequent z def u end eval [S_{2}^{∗}(x, y, z, u)], 90 seqeval deref x term y end eval [S^{∗}(x, y)], 89 seqeval endorse one x term y side z sequent u end eval [S⊢ ⊢ ; 1(x, y, z, u)], 90 seqeval endorse x term y end eval [S⊢ ⊢(x, y)], 90 seqeval est one x term y name z sequent u end eval [S_{1}^{i.e.}(x, y, z, u)], 90 seqeval est two x term y name z sequent u def v end eval [S_{2}^{i.e.}(x, y, z, u, v)], 90 seqeval est x term y end eval [S^{i.e.}(x, y)], 90 seqeval infer one x term y premise z sequent u end eval [S_{1}^{⊢}(x, y, z, u)], 90 seqeval infer x term y end eval [S^{⊢}(x, y)], 90 seqeval init x term y end eval [S^{I}(x, y)], 89 seqeval minus one x term y sequent z end eval [S_{1}^{−}(x, y, z)], 89 seqeval minus x term y end eval [S^{−}(x, y)], 89 seqeval modus one x term y sequent z end eval [S_{1}^{⊳} (x, y, z)], 89 seqeval modus x term y end eval [S^{⊳} (x, y)], 89 seqeval plus one x term y sequent z end eval [S_{1}^{+}(x, y, z)], 89 seqeval verify one x term y sequent z end eval [S_{1}^{E}(x, y, z)], 89 seqeval verify x term y end eval [S^{E}(x, y)], 89 sequent, 83 sequent calculus, 75 sequent commutativity [Commutativity], 102 sequent eval plus x term y end eval [S^{+}(x, y)], 89 sequent eval x term y end eval [S(x, y)], 93 sequent operation, 84 sequent proof, 84 sequent reflexivity [Reflexivity], 102 side condition, 83 [y ⊢⊢ z] line x side condition y end line z, 108 singular, 32 stack, 49 statement, 77, 79 statement [stmt], 77 statement aspect, 77 statement define x as y end define [x =^{stmt} y], 77 [<stmt>] the statement aspect, 77

[stmt] statement, 77 stmt: [x =^{stmt} y], 77 strict, 28, 35 strict variable, 37 sub star x set y to z end sub [⟨^{∗}x |y:= z⟩], 82 sub x set y to z end sub [⟨x |y:= z⟩], 82 subcodex, 55 symbol, 10 symbol exists, 52

[T_{E}] example theory, 101 [λc.U^{M}(E(⌈x⌉, T, c))] computably true x end true, 87 [T′_{E}] example theory primed, 78 t: [x ∈_{t} y], 83

T: [x =^{T} y], 83

T: [x ⊆_{T} y], 83 [<tactic>] the tactic aspect, 106 tactic [tactic], 106 tactic aspect, 104 tactic commutativity [Commutativity_{1}], 105 tactic define x as y end define [x =^{tactic} y], 106 tactic reflexivity [Reflexivity_{1}], 105 tactic, conclusion, 107 tactic, proof, 104 tactic: [x =^{tactic} y], 106 tag, 30 tagged cardinal, 30 tagged map, 31 tagged pair, 31 tagged Peano tree, 31 tagged tree, 31 [Tail_{⊕}(x)] tail x end tail, 100 term, parameter, 102 test x end test [[x]^{·}], 74

[tex] tex, 12 tex aspect, 12 tex aspect ["tex"], 54 tex name, 111 texname aspect ["texname"], 54 the empty set [∅], 83 the proof aspect [<proof>], 95 the statement aspect [<stmt>], 77 the tactic aspect [<tactic>], 106 theory, 78 [Theory x] theory x end theory, 101 [theory_{2}(x, y)] theory two x cache y end theory, 101 [theory_{3}(x, y)] theory three x name y end theory, 101 [theory_{4}(x, y, z)] theory four x name var y sum z end theory, 101 transitive bibliography, 50 [Transitivity′′] example rule lemma primed, 100 [Transitivity] example rule lemma, 101 [∀\underline{a}: ∀\underline{b}: ∀\underline{c}: \underline{a} = \underline{b} ⊢ \underline{a} = \underline{c} ⊢ \underline{b} = \underline{c}] example rule, 78 true identifier ["true"], 55 true term, 24 truth normal form, 24 [tuple_{1}(t)], 66 [tuple_{2}(t)], 66 tuple x end tuple [x : : T], 66 type, 36

uncolored, 91 unification, 103 unification algorithm, 103 unify, 103 [unify(x = y, z)] unify x with y substitution z end unify, 104 [unify^{∗}(x = y, z)] unify star x with y substitution z end unify, 104 [unify_{2}(x = y, z)] unify two x with y substitution z end unify, 104 unify star x with y substitution z end unify [unify^{∗}(x = y, z)], 104 unify two x with y substitution z end unify [unify_{2}(x = y, z)], 104 unify x with y substitution z end unify [unify(x = y, z)], 104 unpack, 9 unpack aspect ["unpack"], 54

[V_{1}(c)] verify one c end verify, 96 [V_{2}(c, p)] verify two c proofs p end verify, 96 [V_{3}(c, r, p, d)] verify three c ref r sequents p diagnose d end verify, 97 [V_{4}(c, p)] verify four c premises p end verify, 97 [V_{5}(c, r, a, q)] verify five c ref r array a sequents q end verify, 98 [V_{6}(c, r, p, q)] verify six c ref r list p sequents q end verify, 98 [V_{7}(c, r, i, q)] verify seven c ref r id i sequents q end verify, 98 V: [x^{V}] x verify, 86 V: [x^{V}] x is metavar, 81 v: [x] make visible x end visible, 68 value, 45 value aspect, 25 value aspect ["value"], 54 value proclamation, 55 variable, meta, 78 variable, ordinary, 78 vector, 7 vector hook ["vector"], 51 verification, 86

[verifier] verifier, 96 verify, 9 verify five c ref r array a sequents q end verify [V_{5}(c, r, a, q)] verify five c ref r array a sequents q end verify, 98 verify four c premises p end verify [V_{4}(c, p)], 97 verify one c end verify [V_{1}(c)], 96 verify seven c ref r id i sequents q end verify [V_{7}(c, r, i, q)], 98 verify six c ref r list p sequents q end verify [V_{6}(c, r, p, q)], 98 verify three c ref r sequents p diagnose d end verify [V_{3}(c, r, p, d)], 97 verify two c proofs p end verify [V_{2}(c, p)], 96 visibility, 68

x at y [x @ y], 86 x claim and y [x ∧_{c} y], 73 x claim in y [x ∈_{c} y], 94 x color star y end color [x-color^{∗}(y)], 92 x color y end color [x-color(y)], 91 x comma y [x, y], 66 x curry minus [x^{−}], 87 x curry plus [x^{+}], 87 x cut y [x; y], 87 x debug [x^{d}], 41 x dereference [x^{∗}], 87 x endorse y [x ⊢⊢ y], 80 x first [x^{1}], 32 x free for star y in z [x free for^{∗} y in z], 82 x free for y in z [x free for y in z], 82 x free in star y [x free in^{∗} y], 82 x free in y [x free in y], 82 x id [x^{i}], 41 x id est y [x i.e. y], 87 x infer y [x ⊢ y], 80 x init [x^{I}], 85 x is error [x^{E}], 93 x is metaclosed [x^{C}], 81 x is metaclosed star [x^{C^{∗}}], 81 x is metavar [x^{V}], 81 x less one y [x ≤′ y], 40 x less y [x < y], 39 x less zero y [x <′ y], 40 x macro and y [If(x, y, F)], 69 x macro imply y [If(x, y, T)], 69 x macro or y [If(x, T, y)], 69 x minus one y [x −_{1} y], 40 x minus y [x − y], 40 x minus zero y [x −_{0} y], 40 x modus [x^{⊳} ], 86 x plus one y [x +_{1} y], 39 x plus y [x + y], 39 x plus zero y [x +_{0} y], 39 x prime [x′], 49 x proves y: proof(⌈x⌉, ⌈y⌉, base), 93 x ref [x^{r}], 41 x root [x^{R}], 41 x rule plus y [x ⊕ y], 80 x sequent equal y [x =^{s} y], 84 x set multi y to z end set [x[y⇒z]]t, 48 x set y to z end set [x[y→z]]t, 47 x simple and y [x ˜∧ y], 73 x term in y [x ∈_{t} y], 83 x term minus var y end minus [x\{y}], 83 x term plus var y end plus [x ∪ {y}], 83 x term root equal y [x =^{r} y], 41 x term set equal y [x =^{T} y], 83 x term subset y [x ⊆_{T} y], 83 x term union y [x ∪ y], 83 x times y [x · y], 40 x times zero y [x ·_{0} y], 40 x verify [x^{V}], 86 zero dimensional array, 47

[1] C. Berline and K. Grue. A κ-denotational semantics for Map Theory in ZFC+SI. Theoretical Computer Science, 179(1–2):137–202, jun 1997.

[2] A. Church. The Calculi of Lambda-Conversion. Princeton University Press, 1941.

[3] K. Gödel. Über formal unentscheidbare Sätze der Principia Mathematica und verwandter Systeme I. Monatshefte für Mathematik und Physik, 12(XXXVIII):173–198, 1931.

[4] K. Grue. Map theory. Theoretical Computer Science, 102(1):1–133, jul 1992.

[5] K. Grue. Mathematics and Computation (lecture notes), volume 1–3. DIKU, 7. edition, 2001. http://www.diku.dk/~grue/papers/mac0102/.

[6] K. Grue. Logiweb. In Fairouz Kamareddine, editor, Mathematical Knowledge Management Symposium 2003, volume 93 of Electronic Notes in Theoretical Computer Science, pages 70–101. Elsevier, 2004.

[7] D. Knuth. The TeXbook. Addison Wesley, 1983.

[8] C. P. Wadsworth M. J. Gordon, A. J. Milner. Edinburgh LCF, A mechanised logic of computation, volume 78 of Lecture Notes in Computer Science. Springer-Verlag, 1979.

[9] J. McCarthy. Recursive functions of symbolic expressions and their computation by machine. Communications of the ACM, pages 184–195, 1960.

[10] E. Mendelson. Introduction to Mathematical Logic. Wadsworth and Brooks, 3. edition, 1987.

[11] Guy L. Steele. Common Lisp—The Language. Digital Press, second edition, 1990.