Your First Program
This page walks you through the basic workflow of the Fixen compiler: writing a .fix source file, compiling it to Haskell, and inspecting the output.
The Fixen Compiler
Section titled “The Fixen Compiler”The fixen compiler takes a Fixen source file (.fix) and generates a Haskell source file (.hs).
The basic invocation is:
~ $ fixen --output <output.hs> <input.fix>| Argument | Description |
|---|---|
<input.fix> | The Fixen source file to compile (positional argument) |
--output <output.hs> | The output Haskell source file path (required) |
The output file must have a .hs extension, and the input file must have a .fix extension. The compiler validates these and exits with an error message if they do not match.
Debug Flags
Section titled “Debug Flags”The compiler includes several flags for inspecting intermediate representations:
| Flag | Short | Description |
|---|---|---|
--show-ast | -a | Print the parsed Abstract Syntax Tree |
--show-forest | -f | Print the rule forest (the internal IR) |
--show-db | -d | Print the inferred database representation |
--no-color | -c | Suppress colored output |
--no-unicode | -u | Suppress Unicode characters in output |
These are useful when debugging a Fixen program or understanding how the compiler processes your code.
A Minimal Example
Section titled “A Minimal Example”Let us create a simple project that incorporates Fixen programs.
Download: my-project.tar.gz
SHA-256: 9eab6e0ea0994846d4ab4c1c716caa6562acdc7a39a0c73f5b5c40884aa7db09
Project Structure
Section titled “Project Structure”To start, create a cabal project called, say, my-project. The project structure is as follows:
Directorymy-project
- my-project.cabal
Directoryapp
- Main.hs
Directoryfix
- Simple.fix
Dependencies
Section titled “Dependencies”Configure the project to have the following dependencies that are used by Fixen-generated modules:
base(present in virtually every Haskell project)pqueue(for work queues)unordered-containers(facts of a program are stored inHashMaps andHashSets)
For example, we can let my-project.cabal be the following:
cabal-version: 3.0name: my-projectversion: 0.1.0.0build-type: Simplecommon warnings ghc-options: -Wallexecutable my-project import: warnings main-is: Main.hs other-modules: Simple build-depends: base , pqueue , unordered-containers hs-source-dirs: app default-language: GHC2021Writing the Application
Section titled “Writing the Application”We are going to write a simple Fixen program in fix/Simple.fix, then make use of it to perform fixed-point computation
in app/Main.hs. Populate these files with the following content:
module Simple where
rel SimpleRel: String, Intrule: |- SimpleRel "start" 0
query facts: SimpleRel - -This Fixen program defines a single relation SimpleRel consisting of a String and an Int. The only inference rule in this program concludes SimpleRel "start" 0. Finally, the facts query obtains all facts of SimpleRel from the solved fact database.
module Main where
import Simple
main :: IO ()main = do let solved_database = solve [] print (facts solved_database)The main module of the program imports the Simple module which will be generated by Fixen. The module consists of two important functions:
solve, which performs the actual fixed-point computation given a list of starting facts.facts, as defined in thequerydeclaration in the Fixen program we have written.
Our main IO action performs fixed-point computation without any initial facts, then runs the facts query, obtaining every fact derivable from fixed-point inference using solve.
Building and Running
Section titled “Building and Running”Before we run cabal build or cabal run to build/run the Cabal project, we must first get the Fixen compiler to generate the Haskell source that implements the work-queue algorithm that we have specified in fix/Simple.fix. To do so, run the following from the root of the project directory:
~/my-project $ fixen -o app/Simple.hs fix/Simple.fixThis generates a valid Haskell module app/Simple.hs using the definitions in fix/Simple.fix. You can inspect it to see how Fixen translates your relational declarations into Haskell code — including the database layout, the fact type, and the inference rules.
Once this file has been generated, we can proceed to build and run the project:
~/my-project $ cabal run[SimpleRel "start" 0]