# Geolog Surface Syntax Reference This document describes the surface syntax of Geolog. For examples, see `examples/geolog/`. ## Lexical Elements ### Identifiers ``` identifier := [a-zA-Z_][a-zA-Z0-9_]* ``` ### Paths Paths use `/` as a separator (not `.`), which allows `.` for field projection: ``` path := identifier ('/' identifier)* ``` Examples: `P`, `in/src`, `ax/refl` ### Keywords ``` namespace theory instance query Sort Prop forall exists ``` ### Operators and Punctuation ``` : -> = |- \/ . , ; { } [ ] ( ) ``` ## Declarations A Geolog file consists of declarations: ``` file := declaration* declaration := namespace | theory | instance | query ``` ### Namespace ``` namespace identifier; ``` Currently a no-op; reserved for future module system. ### Theory ```ebnf theory := 'theory' params? identifier '{' theory_item* '}' params := param_group+ param_group := '(' param (',' param)* ')' param := identifier ':' type_expr theory_item := sort_decl | function_decl | axiom_decl | field_decl ``` #### Sort Declaration ``` identifier ':' 'Sort' ';' ``` Example: `P : Sort;` #### Function Declaration ``` path ':' type_expr '->' type_expr ';' ``` Examples: ``` src : E -> V; // Unary function mul : [x: M, y: M] -> M; // Binary function (product domain) ``` #### Relation Declaration Relations are functions to `Prop`: ``` path ':' type_expr '->' 'Prop' ';' ``` Example: ``` leq : [x: X, y: X] -> Prop; // Binary relation ``` #### Axiom Declaration ``` path ':' 'forall' quantified_vars '.' premises '|-' conclusion ';' quantified_vars := (var_group (',' var_group)*)? // May be empty! var_group := identifier (',' identifier)* ':' type_expr premises := formula (',' formula)* // May be empty ``` Examples: ``` // No premises (Horn clause with empty body) ax/refl : forall x : X. |- [x: x, y: x] leq; // With premises ax/trans : forall x : X, y : X, z : X. [x: x, y: y] leq, [x: y, y: z] leq |- [x: x, y: z] leq; // Empty quantifier - unconditional axiom // Useful for asserting existence without preconditions ax/nonempty : forall . |- exists x : X.; ``` ### Instance ```ebnf instance := 'instance' identifier ':' type_expr '=' instance_body instance_body := '{' instance_item* '}' | 'chase' '{' instance_item* '}' instance_item := element_decl | equation | nested_instance ``` Using `= chase { ... }` runs the chase algorithm during elaboration, automatically deriving facts from axioms. The chase supports: - **Existential conclusions**: Creates fresh elements for `∃` in axiom conclusions - **Equality conclusions**: Uses congruence closure to track element equivalences - **Fixpoint iteration**: Runs until no new facts can be derived Equality saturation enables termination for theories with unit laws (like Categories) that would otherwise loop forever. #### Element Declaration ``` identifier ':' type_expr ';' ``` Example: `A : V;` — declares element `A` of sort `V` #### Equation ``` term '=' term ';' ``` Example: `ab src = A;` — asserts that applying `src` to `ab` yields `A` #### Nested Instance (syntax parsed but not fully elaborated) ``` identifier '=' '{' instance_item* '}' ';' ``` ## Type Expressions ```ebnf type_expr := 'Sort' | 'Prop' | path | record_type | app_type | arrow_type | instance_type record_type := '[' (field (',' field)*)? ']' field := identifier ':' type_expr // Named field | type_expr // Positional: gets name "0", "1", etc. app_type := type_expr type_expr // Juxtaposition arrow_type := type_expr '->' type_expr instance_type := type_expr 'instance' ``` Examples: ``` Sort // The universe of sorts Prop // Propositions V // A named sort [x: M, y: M] // Product type with named fields [M, M] // Product type with positional fields ("0", "1") [M, on: M] // Mixed: first positional, second named M -> M // Function type PetriNet instance // Instance of a theory N PetriNet instance // Parameterized: N is a PetriNet instance ``` ## Terms ```ebnf term := path | record | paren_term | application | projection record := '[' (entry (',' entry)*)? ']' entry := identifier ':' term // Named entry | term // Positional: gets name "0", "1", etc. paren_term := '(' term ')' application := term term // Postfix! 'x f' means 'f(x)' projection := term '.' identifier // Record projection ``` **Important**: Geolog uses **postfix** function application. | Geolog | Traditional | |--------|-------------| | `x f` | `f(x)` | | `[x: a, y: b] mul` | `mul(a, b)` | | `x f g` | `g(f(x))` | This matches categorical composition: morphisms compose left-to-right. Examples: ``` A // Variable/element reference ab src // Apply src to ab [x: a, y: b] mul // Apply mul to record (named fields) [a, b] mul // Apply mul to record (positional) [a, on: b] rel // Mixed: positional first, named second x f g // Composition: g(f(x)) r .field // Project field from record r ``` **Note on positional fields**: Positional fields are assigned names "0", "1", etc. When matching against a relation defined with named fields (e.g., `rel : [x: M, y: M] -> Prop`), positional fields are matched by position: "0" matches the first field, "1" the second, etc. This allows mixing positional and named syntax: `[a, y: b] rel` is equivalent to `[x: a, y: b] rel`. ## Formulas ```ebnf formula := atomic | exists | disjunction | paren_formula atomic := equality | relation_app equality := term '=' term relation_app := term identifier // 'x R' means R(x) exists := 'exists' quantified_vars '.' formulas? // Body may be empty (= True) formulas := formula (',' formula)* disjunction := formula ('\/' formula)+ paren_formula := '(' formula ')' ``` **Conjunction** is implicit: premises in axioms separated by `,` form a conjunction. Examples: ``` x = y // Equality [x: a, y: b] leq // Relation application exists z : X. [x: x, y: z] leq // Existential with condition exists z : X. // Existential with empty body (= exists z. True) phi \/ psi // Disjunction ``` ## Comments Line comments start with `//`: ``` // This is a comment P : Sort; // Inline comment ``` ## Complete Example ```geolog // Directed graph theory theory Graph { V : Sort; E : Sort; src : E -> V; tgt : E -> V; } // A triangle: A → B → C → A instance Triangle : Graph = { A : V; B : V; C : V; ab : E; ab src = A; ab tgt = B; bc : E; bc src = B; bc tgt = C; ca : E; ca src = C; ca tgt = A; } ``` ## Grammar Summary (EBNF) ```ebnf file := declaration* declaration := 'namespace' ident ';' | 'theory' params? ident '{' theory_item* '}' | 'instance' ident ':' type '=' '{' instance_item* '}' | 'query' ident ':' type '=' formula params := ('(' param (',' param)* ')')+ param := ident ':' type theory_item := ident ':' 'Sort' ';' | path ':' type '->' type ';' | path ':' 'forall' qvars '.' formulas '|-' formula ';' qvars := (ident (',' ident)* ':' type) (',' ...)* formulas := formula (',' formula)* instance_item := ident ':' type ';' | term '=' term ';' | ident '=' '{' instance_item* '}' ';' type := 'Sort' | 'Prop' | path | '[' fields ']' | type type | type '->' type | type 'instance' fields := (ident ':' type) (',' ...)* term := path | '[' entries ']' | '(' term ')' | term term | term '.' ident entries := (ident ':' term) (',' ...)* formula := term '=' term | term ident | 'exists' qvars '.' formula | formula '\/' formula | '(' formula ')' path := ident ('/' ident)* ident := [a-zA-Z_][a-zA-Z0-9_]* ``` ## Example Files The `examples/geolog/` directory contains working examples: | File | Description | |------|-------------| | `graph.geolog` | Simple directed graph theory with vertices and edges | | `preorder.geolog` | Preorder (reflexive, transitive relation) with discrete/chain instances | | `transitive_closure.geolog` | **Demonstrates chase algorithm** - computes reachability | | `monoid.geolog` | Algebraic monoid theory with associativity axiom | | `petri_net.geolog` | Petri net formalization with places, transitions, marking | | `petri_net_showcase.geolog` | **Full showcase** - parameterized theories, nested instances, cross-references | | `todo_list.geolog` | Task management example with dependencies | | `solver_demo.geolog` | Solver demonstration with reachability queries | | `relalg_simple.geolog` | Simple RelAlgIR query plan examples | ### Running Examples ```bash # Start REPL with an example cargo run -- examples/geolog/graph.geolog # Or load interactively cargo run :source examples/geolog/transitive_closure.geolog :inspect Chain :chase Chain # Computes transitive closure! ```