All file paths below are repo-relative, not local workspace paths. The main sources are `geolog-lang/src/Geolog/IR.hs` and `geolog-lang/src/Geolog/Lower.hs`.
## Where the IR sits
The current pipeline is:
1. Source text is lexed and parsed.
2. The elaborator builds a typed core representation.
3.`lowerTop` lowers that elaborated theory into `I.FlatTheory`.
4. Tests pretty-print the lowered form as `table ...` and `law ...` declarations.
The lowering entry point is `geolog-lang/src/Geolog/Lower.hs`, via `lowerTop`, which calls `lower`, then `lowerEntry`, then `finishTheory`.
-`Path = [QName]`: a hierarchical name like `["M","mul"]`, pretty-printed as `M.mul`.
-`ColType` is the type of a column. `EntityType Path` means the column refers to rows from another entity/table, `PrimType PrimInt | PrimString` covers builtin scalars, and `Tuple [(QName, ColType)]` supports structured values.
-`Table` contains `columns :: [ColType]` and `primaryKey :: Maybe [Int]`.
-`Term` supports literals, variables, projections like `x.field`, and record construction.
-`Atom` contains `table :: Path`, `rowId :: Maybe Term`, and `values :: Map Int Term`.
-`Prop` and `Law` provide a small logic language for atoms, equality, conjunction, disjunction, and universally quantified Horn-style laws.
-`FlatTheory` is the final lowered package with `tables :: Map Path Table` and `laws :: Map Path Law`.
See `geolog-lang/src/Geolog/IR.hs` for the concrete definitions.
`liftOnShared` copies shared outer variables into the current row shape so that dependencies become relationally explicit. This is why tables like `D.mul` contain both `M.car` arguments and displayed-car columns.
See `liftOnShared` in `geolog-lang/src/Geolog/Lower.hs`.
### 5. References generate join information
When a local path is used as:
- an attribute, lowering creates a `PiColumn`
- a value, lowering creates a `JoinColumn`
In both cases it also accumulates foreign-key-style atoms in `?fkeys`. Those atoms are later assembled into explicit laws.
See `lowerAttrNeutral` and `lowerArgNeutral` in `geolog-lang/src/Geolog/Lower.hs`.
## Why there are `foreignKeys` and `total` laws
Each lowered table may carry generated laws.
### `foreignKeys`
`makeFkeys` says: if a row exists in table `p`, then the rows it depends on must also exist.
So the IR is not just an AST for queries. It is the bridge from elaborated dependent syntax to a database-shaped form that later evaluation code can consume.
The IR looks good as a first compiler pass, but not yet as a complete runtime model.
What already looks solid:
- It matches the direction described in the other notes: theories become tables plus laws.
- It already lowers nontrivial dependent structure into a relational form.
- It makes important constraints explicit, especially `foreignKeys` and `total`.
- It gives Geolog a plausible backend-neutral compiled form between elaboration and evaluation.
What still looks missing:
- explicit runtime state for the chase
- fresh witness generation for existential conclusions
- branch or world tracking for disjunction
- equality-class or term-merging machinery
- provenance and scheduling information
So the current IR is best seen as a lowered theory IR, not yet a full chase-runtime IR.
If the project keeps this design, the natural next step is probably a second layer above `FlatTheory` for runtime execution state. That layer would hold current facts, branch identity, fresh-name allocation, equality information, and evaluation metadata.
`docs/lecture3.tex` has a `Query IR` section header but no content yet, so the code above is currently the most concrete description of the actual intermediate representation.