8.6 KiB
Geolog DSL Structure
This directory contains example .geolog files that use a richer DSL than the
minimal .chase script language in examples/scripts/.
This README summarizes the Geolog DSL structure as it appears in the examples in this directory. It should be read as a practical, example-driven reference, not as a formal or complete language specification.
At a Glance
- Top-level declarations are
theoryandinstance. - The main kind of type is
Sort. - Symbols can denote sorts, constants, functions, predicates, or nested instances.
- Axioms use sequent-style syntax:
premise |- conclusion. - Instance bodies can be plain literals (
= { ... }) or chase blocks (= chase { ... }). - Function application is postfix, and qualified names use
/.
Informal File Shape
file := { comment | theory_decl | instance_decl }
comment := // ...
theory_decl :=
theory theory_params? Name {
theory_item*
}
instance_decl :=
instance Name : theory_app = {
instance_item*
}
| instance Name : theory_app = chase {
instance_item*
}
In practice, a file is usually a sequence of theory declarations followed by one or more example instances.
Top-Level Declarations
theory
A theory introduces sorts, symbols, and axioms.
theory Graph {
V : Sort;
Edge : [src: V, tgt: V] -> Prop;
}
Theories may also be parameterized.
theory (X : Sort) (Y : Sort) Iso {
fwd : X -> Y;
bwd : Y -> X;
}
theory (N : PetriNet instance) Marking {
token : Sort;
token/of : token -> N/P;
}
Observed parameter forms:
- sort parameters:
(X : Sort) - instance parameters:
(N : PetriNet instance) - dependent instance parameters:
(RP : N ReachabilityProblem instance)
instance
An instance provides concrete elements and assignments for a theory.
instance Triangle : Graph = {
A : V;
B : V;
C : V;
}
Instances may target parameterized theories by writing the arguments before the theory name.
instance MyMap : MyBase Map = { ... }
instance solution0 : ExampleNet problem0 Solution = { ... }
instance AB_Iso : As/a Bs/b Iso = { ... }
Theory Body Items
The examples show the following declaration forms inside a theory body.
Sort declarations
V : Sort;
E : Sort;
This introduces carrier sorts.
Constants or distinguished elements
elem : X;
This introduces a named element of an existing sort.
Functions
src : E -> V;
fwd : X -> Y;
token/of : token -> N/P;
Names may contain /, which is used heavily for structured or qualified names.
Predicates and relations
Unary predicates:
completed : Item -> Prop;
Record-shaped predicates:
Edge : [src: V, tgt: V] -> Prop;
depends : [item: Item, on: Item] -> Prop;
Product-valued functions
Functions may return record-shaped values.
pair_of : A -> [left: B, right: C];
W/src : W -> [firing: F, arc: N/out];
Nested instance slots
Theories can contain fields whose values are themselves instances.
initial_marking : N Marking instance;
trace : N Trace instance;
initial_iso : (trace/input_terminal) (RP/initial_marking/token) Iso instance;
Axioms
Axioms use a sequent-like form.
ax/trans : forall x, y, z : V.
[src: x, tgt: y] Path, [src: y, tgt: z] Path |- [src: x, tgt: z] Path;
An axiom declaration has the observed structure:
name : forall binders. premise |- conclusion;
Formula and Term Syntax
The examples use the following building blocks inside axioms and assignments.
Quantifiers
Universal binders appear after forall.
forall x : X, y : Y.
Existentials appear directly inside conclusions or disjuncts.
exists r : R. r R/data = [x: a, y: b]
exists w : W. w W/src_firing = f, w W/src_arc = arc
Sequents
The central connective is |-, separating premise from conclusion.
premise1, premise2 |- conclusion1, conclusion2;
In the examples:
- commas act as conjunctions
- the left side is the premise
- the right side is the conclusion
Equality
Equality is used for ordinary values and compound values.
ab src = A
r R/data = [x: a, y: b]
x fwd bwd = x
Truth constants
|- true;
|- false;
Disjunction
Disjunction is written as \/.
[item: x, on: y] depends |- x blocked \/ y completed;
Predicate atoms
Unary predicate atoms:
x blocked
y completed
Record-shaped predicate atoms:
[src: x, tgt: y] Edge
[a: x, f: i] id
Postfix application
Function application is postfix and can be chained.
e src
x id
x fwd bwd
w W/src_arc N/out/tgt
This is one of the most distinctive traits of the DSL.
Qualified paths
The slash / is used for qualification and nested access.
Observed examples include:
R/data
N/P
N/out/src
trace/input_terminal
RP/initial_marking/token
ExampleNet/A
Record literals
Records are written with brackets and named fields.
[x: a, y: b]
[firing: f, arc: arc]
The examples also show positional shorthand for record arguments when the field order is known:
[e, e] mul = e;
[cook_dinner, on: buy_groceries] depends;
Field projection
Record-valued terms support field projection.
r R/data .x = a
Instance Body Items
The examples show the following forms inside instance bodies.
Element declarations
a : V;
tok : token;
ab : T;
Function assignments
ab src = A;
tok token/of = ExampleNet/A;
a1 map = MyBase/b1;
Predicate facts
Unary facts:
buy_groceries completed;
Record-shaped facts:
[src: a, tgt: b] Edge;
[item: x, on: y] depends;
Product-valued assignments
a1 pair_of = [left: b1, right: c1];
ot output_terminal/src = [firing: f1, arc: SimpleNet/arc_out];
Nested instance literals
Instance-valued fields can be assigned inline blocks.
initial_marking = {
tok : token;
tok token/of = ExampleNet/A;
};
= { ... } vs = chase { ... }
The examples consistently use two instance forms.
Plain instance
instance Triangle : Graph = {
...
}
This gives a direct structure with only the explicitly listed elements and assignments.
Chase instance
instance Chain : Graph = chase {
...
}
This marks an instance whose contents should be extended by the theory axioms. Examples use this for transitive closure, existential witness generation, and trace/reachability constructions.
Observed Design Patterns
Parameterized theories
Theories can be abstract over:
- a sort, such as
theory (X : Sort) Container - an instance, such as
theory (N : PetriNet instance) Marking - multiple arguments, such as
theory (N : PetriNet instance) (RP : N ReachabilityProblem instance) Solution
Theory application by adjacency
Theory arguments are written before the theory name.
N Marking instance
MyBase Map
ExampleNet problem0 Solution
Nested structure via qualified names
Many examples model dependent structure by naming into earlier declarations.
token/of : token -> N/P;
initial_iso : (trace/input_terminal) (RP/initial_marking/token) Iso instance;
What Seems Outside the File DSL
Some example comments refer to interactive commands such as:
:source
:load
:inspect
:chase
:solve
Those commands appear to belong to an external REPL or tool environment rather
than to the .geolog file grammar itself.
Best Example Files by Feature
transitive_closure.geolog: basic theory, axiom, and= chaseusagegraph.geolog: plain structural instancesmonoid.geolog: postfix application and positional record syntaxtodo_list.geolog: unary predicates and disjunctionsort_param_simple.geolog: sort and instance parametersnested_instance_test.geolog: nested instance-valued fieldsproduct_codomain_test.geolog: record-valued function codomainsfield_projection_test.geolog: field projection syntaxrecord_existential_test.geolog: existential witness creation with recordspetri_net_showcase.geolog: large multi-theory compositionsolver_demo.geolog: satisfiability-oriented axiom patterns
Minimal Example
theory Graph {
V : Sort;
Edge : [src: V, tgt: V] -> Prop;
Path : [src: V, tgt: V] -> Prop;
ax/base : forall x, y : V.
[src: x, tgt: y] Edge |- [src: x, tgt: y] Path;
}
instance Chain : Graph = chase {
a : V;
b : V;
[src: a, tgt: b] Edge;
}
That small example already shows the core structure of the DSL:
- a
theory - sort and predicate declarations
- an axiom written as a sequent
- an
instance - a
chaseblock that asks for closure under the theory axioms