Normalizer for \( \varphi \)-calculus

Command line normalizer of \( \varphi \)-calculus expressions (as produced by the EO compiler).

Throughout the documentation, we refer to 𝜑-calculus as PHI.

This project aims to apply term rewriting techniques to "simplify" an input PHI expression and prepare it for further optimization passes. The simplification procedure will be a form of partial evaluation and normalization (see eo-phi-normalizer rewrite and eo-phi-normalizer dataize).

Contrary to traditional normalization in λ-calculus, we aim at rewriting rules that would help reduce certain metrics of expressions (see eo-phi-normalizer metrics).

See the report on our current progress with metrics.

The eo-phi-normalizer package is available on Hackage.

The latest package Haddock documentation is available on our site.

Installation

Environment requirements

  • OS: Ubuntu 22.04 or macOS 12.
  • stack is installable.
  • eo-phi-normalizer is installable.

Install stack

See the official stack installation documentation.

Install eo-phi-normalizer

Install the eo-phi-normalizer executable globally via stack. Then, the eo-phi-normalizer executable will be available on PATH.

Install eo-phi-normalizer from the repository

Clone and enter the project repository.

git clone https://github.com/objectionary/eo-phi-normalizer --recurse-submodules
cd eo-phi-normalizer

Install eo-phi-normalizer.

export LC_ALL=C.UTF-8
stack install eo-phi-normalizer

Install eo-phi-normalizer from Hackage

You can see all package versions on its Hackage page.

Use the necessary version in the stack install command.

stack update
export LC_ALL=C.UTF-8
stack install --resolver lts-22.16 eo-phi-normalizer-2.1.0

Update eo-phi-normalizer

Run stack install ... as in one of the methods above.

Uninstall eo-phi-normalizer

Learn where stack installs programs.

stack path --programs

Learn how to uninstall a program.

stack uninstall

Quick start

Clone and enter the project repository.

git clone https://github.com/objectionary/eo-phi-normalizer --recurse-submodules
cd eo-phi-normalizer

Install eo-phi-normalizer - see Installation.

Save a PHI program to a file.

cat > celsius.phi <<EOM
{⟦
  c ↦ Φ.org.eolang.float(as-bytes ↦ Φ.org.eolang.bytes(Δ ⤍ 40-39-00-00-00-00-00-00)), // 25.0
  result ↦
    ξ.c.times(x ↦ ⟦ Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD ⟧)  // 1.8
       .plus(x ↦ ⟦ Δ ⤍ 40-40-00-00-00-00-00-00 ⟧), // 32.0
  λ ⤍ Package
⟧}
EOM

Dataize the program recursively.

eo-phi-normalizer dataize --recursive --rules eo-phi-normalizer/test/eo/phi/rules/yegor.yaml \
  --dependency-file 'eo-phi-normalizer/data/0.38.0/org/eolang/float.phi' \
  --dependency-file 'eo-phi-normalizer/data/0.38.0/org/eolang/bytes.phi' \
  celsius.phi
{
  ⟦
    c ↦ ⟦
      Δ ⤍ 40-39-00-00-00-00-00-00
    ⟧,
    result ↦ ⟦
      Δ ⤍ 40-53-40-00-00-00-00-00
    ⟧,
    λ ⤍ Package
  ⟧
}

Pipeline

Install stack

See the official stack installation documentation.

Enter the repository

Clone and enter the project repository.

git clone https://github.com/objectionary/eo-phi-normalizer --recurse-submodules
cd eo-phi-normalizer

Install eo-phi-normalizer

Install eo-phi-normalizer.

export LC_ALL=C.UTF-8
stack install eo-phi-normalizer

Install dependencies

Install yq.

yq --version
yq (https://github.com/mikefarah/yq/) version v4.44.1

Install NodeJS.

node --version
v20.18.0

Install Java.

java --version
openjdk 21.0.5 2024-10-15 LTS
OpenJDK Runtime Environment Zulu21.38+21-CRaC-CA (build 21.0.5+11-LTS)
OpenJDK 64-Bit Server VM Zulu21.38+21-CRaC-CA (build 21.0.5+11-LTS, mixed mode, sharing)

Windows

Install Cygwin.

Make cygpath available on PATH.

Learn about the pipeline

Pipeline stages

The pipeline has several important stages:

  • Rewrite original EO programs into filtered EO programs, leaving only the specified top-level objects (tests).
  • Translate filtered EO programs to initial PHI programs.
  • Translate initial PHI programs to initial EO programs.
  • Test initial EO programs.
  • Normalize initial PHI programs and get normalized PHI programs.
  • Report metrics on initial PHI programs and normalized PHI programs (See Metrics).
  • Translate normalized PHI programs to normalized EO programs.
  • Test normalized EO programs.

Pipeline configuration

The pipeline is configured via the pipeline/config.yaml file.

The configuration file specifies the following:

  • report - Pipeline report configuration.
    • js - Optional path to a JavaScript file that should be inlined into the HTML report.
    • css - Optional path to a CSS file that should be inlined into the HTML report.
    • output - Where to write report versions.
      • html - The file path of the HTML version.
      • json - The file path of the JSON version.
      • markdown - The file path of the GitHub Flavored Markdown version.
    • expected-metrics-change - The expected relative change in metrics w.r.t the initial metrics.
      • dataless - For dataless formations.
      • applications - For applications.
      • formations - For formations.
      • dispatches - For dispatches.
    • expected-improved-programs-percentage - Expected percentage of programs where all metrics changed as expected.
  • test-sets - A list of configurations for sets of test objects (tests).
    • eo - The configuration of the EO part of the test set.
      • original - The file path of the original EO program.
      • enable - A flag to enable tests in the original EO program.
      • include - A list of names of tests in the original EO program that should be included into the filtered EO program.
      • exclude - A list of names of tests in the original EO program that shouldn't be included into the filtered EO program.
      • filtered - The file path of the filtered original EO program.
      • yaml - The file path of the original EO program in the YAML format.
    • phi - The configuration of the PHI part of the test set.
      • initial - The file path of the initial PHI program.
      • normalized - The file path of the normalized PHI program.
      • bindings-path-initial - The path to tests via bindings in the initial PHI program.
      • bindings-path-normalized - The path to tests via bindings in the normalized PHI program.
    • atoms - The configuration of atoms in the test set. The set of enabled atoms is the difference of sets constructed from the enable and disable lists.
      • enable - The list of names of atoms to enable. An empty list is equivalent to a list of all known atoms.
      • disable - The list of names of atoms to disable.

Run the pipeline script

bash ./scripts/pipeline.sh

Explore the pipeline directory

The script will run for several minutes and write the following entries to the pipeline directory:

  • eo-filtered - Filtered EO programs.
  • eo-initial - Initial EO programs.
    • .eoc/4-pull/org/eolang - org.eolang objects (link).
  • eo-normalized - Normalized EO programs.
  • eo-yaml - Filtered EO programs in the YAML format.
  • logs - Logs of some pipeline stages.
  • phi-initial - Initial PHI programs.
    • .eoc/phi/org/eolang - org.eolang objects translated to PHI.
  • phi-normalized - Normalized PHI programs.
  • report - Pipeline reports.
    • report.html - The report in the HTML format.
    • report.json - The report in the JSON format.
    • report.md - The report in the GitHub Flavored Markdown format.

Metrics

PHI grammar

phi-grammar

We count

Object formations

  • Example: ⟦ d ↦ ∅, c ↦ ∅ ⟧

Object applications

  • Example: ξ.b(c ↦ ⟦ ⟧)

Dynamic dispatches

  • Example: ξ.ρ.c

Dataless formations

Definition: \( \Delta \)-depth

\( \Delta \)-depth of an object describes how deep data is in the object when recursively traversing values attached to the object attributes. That is, \( \Delta \)-depth is \( \infty \) for all objects except formations. More specifically:

  1. the \( \Delta \)-depth of a formation with bytes attached to a \( \Delta \)-attribute is \( 1 \);
  2. for a non-empty formation, the \( \Delta \)-depth is:
    1. \( 1 + M \), where \( M \) is the minimal depth among objects attached to attributes of this formation;
    2. \( \infty \) if there are no objects attached to attributes of this formation;
  3. otherwise, the \( \Delta \)-depth of an object is \( \infty \).

Definition: Dataless object

An object is dataless if its \( \Delta \)-depth is greater than 2.

Examples

The following table demonstrates objects with their \( \Delta \)-depths:

metrics

CLI command

See eo-phi-normalizer metrics.

Atoms

The eo-phi-normalizer uses atoms implemented in Haskell. The sections below explain how to update them.

Enter the repository

Clone and enter the project repository.

git clone https://github.com/objectionary/eo-phi-normalizer --recurse-submodules
cd eo-phi-normalizer

Install stack

See the official stack installation documentation.

Update atom definitions

Edit definitions in the list knownAtomsList in the module eo-phi-normalizer/src/Language/EO/Phi/Dataize/Atoms.hs.

Test

Run tests

export LC_ALL=C.UTF-8
stack test

User-defined rules

You can define rewrite rules for the PHI language using YAML and the MetaPHI language that is a superset of PHI.

MetaPHI

See the MetaPHI Labelled BNF in Syntax.cf.

phi-paper rules

Currently, the eo-phi-normalizer supports rules defined in an unpublished paper by Yegor Bugayenko.

Rules

yegor.yaml

The rules are defined in yegor.yaml.

Each rule has the following structure:

  • name - Rule name.
  • description - Rule description.
  • context - (optional) Rule context. A context may contain:
    • global_object - (optional) Global object MetaId.
    • current_object - (optional) Current object MetaId.
  • pattern - Term pattern written in MetaPHI.
    • The pattern must be an object (formation, application, dispatch, etc.)
    • When this term pattern matches a subterm of a PHI term, MetaIds from the term pattern become associated with matching subexpressions of that subterm.
  • result - Substitution result.
    • MetaIds in the subterm pattern get replaced by their associated subexpressions.
  • when - A list of conditions for pattern matching.
    • nf - A list of MetaIds associated with subexpressions that should be in the normal form.
      • An expression is in the normal form when no rule can be applied to that expression.
    • present_attrs - A list of attributes that must be present in subexpression bindings.
      • attrs - A list of attributes. Can include MetaIds.
      • bindings - A list of bindings that must contain these attributes.
    • absent_attrs - A list of attributes that must not be present in subexpression bindings.
      • attrs - A list of attributes. Can include MetaIds.
      • bindings - A list of bindings that must not contain these attributes.
  • tests - A list of unit tests for this rule.
    • name - Test name.
    • input - An initial PHI term.
    • output - The initial PHI term after this rule was applied.
    • matches - Whether the term pattern should match any subterm.

eo-phi-normalizer

See commands supported by the eo-phi-normalizer executable.

eo-phi-normalizer --help
Usage: eo-phi-normalizer COMMAND

  Work with PHI expressions.

Available options:
  -h,--help                Show this help text
  --version                Show version information

Available commands:
  rewrite                  Rewrite a PHI program.
  metrics                  Collect metrics for a PHI program.
  dataize                  Dataize a PHI program.
  pipeline                 Run pipeline-related commands.
  print-rules              Print rules in LaTeX format.
  test                     Run unit tests in given files with user-defined
                           rules.

eo-phi-normalizer rewrite

Environment

Repository

The commands in the following sections access files that are available in the project repository.

Clone and enter the project repository.

git clone https://github.com/objectionary/eo-phi-normalizer --recurse-submodules
cd eo-phi-normalizer

Sample program

Save a PHI program to a file.

cat > celsius.phi <<EOM
{⟦
  c ↦ Φ.org.eolang.float(as-bytes ↦ Φ.org.eolang.bytes(Δ ⤍ 40-39-00-00-00-00-00-00)), // 25.0
  result ↦
    ξ.c.times(x ↦ ⟦ Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD ⟧)  // 1.8
       .plus(x ↦ ⟦ Δ ⤍ 40-40-00-00-00-00-00-00 ⟧), // 32.0
  λ ⤍ Package
⟧}
EOM

CLI

--help

eo-phi-normalizer rewrite --help
Usage: eo-phi-normalizer rewrite [-r|--rules FILE] [-c|--chain] [-j|--json]
                                 [--tex] [-o|--output-file FILE] [-s|--single]
                                 [--max-depth INT] [--max-growth-factor INT]
                                 [FILE] [-d|--dependency-file FILE]

  Rewrite a PHI program.

Available options:
  -r,--rules FILE          FILE with user-defined rules. If unspecified, builtin
                           set of rules is used.
  -c,--chain               Output rewriting steps.
  -j,--json                Output JSON.
  --tex                    Output LaTeX.
  -o,--output-file FILE    Output to FILE. When this option is not specified,
                           output to stdout.
  -s,--single              Output a single expression.
  --max-depth INT          Maximum depth of rules application. Defaults to 10.
  --max-growth-factor INT  The factor by which to allow the input term to grow
                           before stopping. Defaults to 10.
  FILE                     FILE to read input from. When no FILE is specified,
                           read from stdin.
  -d,--dependency-file FILE
                           FILE to read dependencies from (zero or more
                           dependency files allowed).
  -h,--help                Show this help text

--rules FILE

Normalize a 𝜑-expression from celsius.phi using the rules from a given file (e.g. yegor.yaml).

The output may contain multiple numbered results that correspond to different possible rule application sequences (even if the final result is the same).

eo-phi-normalizer rewrite --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
Rule set based on Yegor's draft
Input:
{
  ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
}
====================================================
Result 1 out of 1:
{
  ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
}
----------------------------------------------------

--chain

Use --chain to see numbered normalization steps for each normalization result.

eo-phi-normalizer rewrite --chain --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
Rule set based on Yegor's draft
Input:
{
  ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
}
====================================================
Result 1 out of 1:
[ 1 / 1 ] Normal form: {
  ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
}
----------------------------------------------------

--json

eo-phi-normalizer rewrite --json --chain --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
{
  "input": "{\n  ⟦\n    c ↦ Φ.org.eolang.float (\n      as-bytes ↦ Φ.org.eolang.bytes (\n        Δ ⤍ 40-39-00-00-00-00-00-00\n      )\n    ),\n    result ↦ ξ.c.times (\n      x ↦ ⟦\n        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD\n      ⟧\n    )\n   .plus (\n      x ↦ ⟦\n        Δ ⤍ 40-40-00-00-00-00-00-00\n      ⟧\n    ),\n    λ ⤍ Package\n  ⟧\n}",
  "output": [
    [
      [
        "Normal form",
        "{\n  ⟦\n    c ↦ Φ.org.eolang.float (\n      as-bytes ↦ Φ.org.eolang.bytes (\n        Δ ⤍ 40-39-00-00-00-00-00-00\n      )\n    ),\n    result ↦ ξ.c.times (\n      x ↦ ⟦\n        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD\n      ⟧\n    )\n   .plus (\n      x ↦ ⟦\n        Δ ⤍ 40-40-00-00-00-00-00-00\n      ⟧\n    ),\n    λ ⤍ Package\n  ⟧\n}"
      ]
    ]
  ]
}

--single

eo-phi-normalizer rewrite --single --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
{
  ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
}

--single --json

eo-phi-normalizer rewrite --single --json --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
"{\n  ⟦\n    c ↦ Φ.org.eolang.float (\n      as-bytes ↦ Φ.org.eolang.bytes (\n        Δ ⤍ 40-39-00-00-00-00-00-00\n      )\n    ),\n    result ↦ ξ.c.times (\n      x ↦ ⟦\n        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD\n      ⟧\n    )\n   .plus (\n      x ↦ ⟦\n        Δ ⤍ 40-40-00-00-00-00-00-00\n      ⟧\n    ),\n    λ ⤍ Package\n  ⟧\n}"

--output-file FILE

Redirects the output to file of the given path instead of stdout.

--dependency-file FILE

Injects package dependencies from a given file into the context when transforming the input. Can be used multiple times to inject multiple dependencies.

FILE not specified (read from stdin)

cat celsius.phi | eo-phi-normalizer rewrite --single --json --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml
"{\n  ⟦\n    c ↦ Φ.org.eolang.float (\n      as-bytes ↦ Φ.org.eolang.bytes (\n        Δ ⤍ 40-39-00-00-00-00-00-00\n      )\n    ),\n    result ↦ ξ.c.times (\n      x ↦ ⟦\n        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD\n      ⟧\n    )\n   .plus (\n      x ↦ ⟦\n        Δ ⤍ 40-40-00-00-00-00-00-00\n      ⟧\n    ),\n    λ ⤍ Package\n  ⟧\n}"

eo-phi-normalizer dataize

Dataization is the process through which data is extracted from a given program/object.

Dataization process

To dataize a given program written in \( \varphi \)-calculus, the first step is to normalize it according to the process outlined in eo-phi-normalizer rewrite docs. Then, a single step of dataization is performed according to the following rules in order of priority:

  1. If the object is a formation that contains a \( \Delta \)-binding and no empty bindings, the bytes attached to it are returned
  2. If the object is a formation that contains a \( \lambda \)-binding and no empty bindings, the attached value is evaluated as a known built-in function and its result is returned. Currently, the following functions are supported:
    • Times
    • Plus
    • Package: the existence of this \( \lambda \)-binding is interpreted to mean that all its sibling attributes should be dataized in-place.
  3. If the object is a formation that contains a \( \phi \)-binding and no empty bindings, the result becomes the dataization of its attached object
  4. If the object is an application, the object on which the bindings are applied is dataized and then the application is reapplied on its result. In other words, \( \mathbb{D}\left(obj(a \mapsto b, ...)\right) = \mathbb{D}\left(obj\right)(a \mapsto b, ...) \)
  5. If the object is a dispatch, the object on which the attribute is being dispatched is dataized and then the attribute is dispatched on its result. In other words, \( \mathbb{D}\left(obj.\alpha\right) = \mathbb{D}\left(obj\right).\alpha \)

The full dataization process is achieved by recursively normalizing and dataizing according to the rules above until bytes are reached or the object does not change (in which case the dataization is considered to have failed). Note that dataization assumes that the given set of normalization rules are already proven to be confluent and does not verify claim.

Environment

Save a PHI program to a file.

cat > celsius.phi <<EOM
{⟦
  c ↦ Φ.org.eolang.float(as-bytes ↦ Φ.org.eolang.bytes(Δ ⤍ 40-39-00-00-00-00-00-00)), // 25.0
  result ↦
    ξ.c.times(x ↦ ⟦ Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD ⟧)  // 1.8
       .plus(x ↦ ⟦ Δ ⤍ 40-40-00-00-00-00-00-00 ⟧), // 32.0
  λ ⤍ Package
⟧}
EOM

CLI

--help

eo-phi-normalizer dataize --help
Usage: eo-phi-normalizer dataize [-r|--rules FILE] [FILE]
                                 [-d|--dependency-file FILE]
                                 [-o|--output-file FILE] [--recursive] [--chain]
                                 [--wrap-raw-bytes] [--tex] [--as-package]
                                 [--minimize-stuck-terms]
                                 [--disable-atom ATOM_NAME]
                                 [--enable-atom ATOM_NAME]

  Dataize a PHI program.

Available options:
  -r,--rules FILE          FILE with user-defined rules. If unspecified, builtin
                           set of rules is used.
  FILE                     FILE to read input from. When no FILE is specified,
                           read from stdin.
  -d,--dependency-file FILE
                           FILE to read dependencies from (zero or more
                           dependency files allowed).
  -o,--output-file FILE    Output to FILE. When this option is not specified,
                           output to stdout.
  --recursive              Apply dataization + normalization recursively.
  --chain                  Display all the intermediate steps.
  --wrap-raw-bytes         Wrap raw bytes ⟦ Δ ⤍ 01- ⟧ as Φ.org.eolang.bytes(Δ ⤍
                           01-) in the final output.
  --tex                    Output LaTeX.
  --as-package             Automatically inject (λ → Package) in the program if
                           necessary, to dataize all fields.
  --minimize-stuck-terms   If a dataized (sub)term is stuck (cannot be fully
                           dataized), use the minimal (by size) intermediate
                           result.
  --disable-atom ATOM_NAME Name of an atom to disable.
  --enable-atom ATOM_NAME  Name of an atom to enable.
  -h,--help                Show this help text

--rules FILE

Similar to --rules for the transform subcommand, this argument accepts the path to a YAML file containing the rules to be used in the normalization phase.

--chain

If the --chain argument is passed, all the intermediate steps of normalization + dataization are printed to the console (or the output file if chosen).

eo-phi-normalizer dataize --chain --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
Evaluating lambda 'Package' : ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧

 Dataizing: Φ.org.eolang.float (
  as-bytes ↦ Φ.org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)

 Phi: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ Φ.org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)

 Phi: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)

 Normal form: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)

  Dataizing inside application: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float
   Dataizing inside dispatch: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang
    Dataizing inside dispatch: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org
     Dataizing inside dispatch: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧

     Evaluating lambda 'Package' : ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧

 Dataization changed nothing: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)

 Dataizing: ξ.c.times (
  x ↦ ⟦
    Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
  ⟧
)
. plus (
  x ↦ ⟦
    Δ ⤍ 40-40-00-00-00-00-00-00
  ⟧
)

 xi: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. c.times (
  x ↦ ⟦
    Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
  ⟧
)
. plus (
  x ↦ ⟦
    Δ ⤍ 40-40-00-00-00-00-00-00
  ⟧
)

 DOT: Φ.org.eolang.float (
  as-bytes ↦ Φ.org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)
. times (
  x ↦ ⟦
    Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
  ⟧
)
. plus (
  x ↦ ⟦
    Δ ⤍ 40-40-00-00-00-00-00-00
  ⟧
)

 Phi: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ Φ.org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)
. times (
  x ↦ ⟦
    Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
  ⟧
)
. plus (
  x ↦ ⟦
    Δ ⤍ 40-40-00-00-00-00-00-00
  ⟧
)

 Phi: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)
. times (
  x ↦ ⟦
    Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
  ⟧
)
. plus (
  x ↦ ⟦
    Δ ⤍ 40-40-00-00-00-00-00-00
  ⟧
)

 Normal form: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)
. times (
  x ↦ ⟦
    Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
  ⟧
)
. plus (
  x ↦ ⟦
    Δ ⤍ 40-40-00-00-00-00-00-00
  ⟧
)

  Dataizing inside application: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)
. times (
  x ↦ ⟦
    Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
  ⟧
)
. plus
   Dataizing inside dispatch: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)
. times (
  x ↦ ⟦
    Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
  ⟧
)

    Dataizing inside application: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)
. times
     Dataizing inside dispatch: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)

      Dataizing inside application: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float
       Dataizing inside dispatch: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang
        Dataizing inside dispatch: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org
         Dataizing inside dispatch: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧

         Evaluating lambda 'Package' : ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧

 Dataization changed nothing: ⟦
  c ↦ Φ.org.eolang.float (
    as-bytes ↦ Φ.org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ξ.c.times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧
. org.eolang.float (
  as-bytes ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.bytes (
    Δ ⤍ 40-39-00-00-00-00-00-00
  )
)
. times (
  x ↦ ⟦
    Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
  ⟧
)
. plus (
  x ↦ ⟦
    Δ ⤍ 40-40-00-00-00-00-00-00
  ⟧
)

Dataized 'Package' siblings: ⟦
  c ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.float (
    as-bytes ↦ ⟦
      c ↦ Φ.org.eolang.float (
        as-bytes ↦ Φ.org.eolang.bytes (
          Δ ⤍ 40-39-00-00-00-00-00-00
        )
      ),
      result ↦ ξ.c.times (
        x ↦ ⟦
          Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
        ⟧
      )
     .plus (
        x ↦ ⟦
          Δ ⤍ 40-40-00-00-00-00-00-00
        ⟧
      ),
      λ ⤍ Package
    ⟧
   .org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  ),
  result ↦ ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
 .org.eolang.float (
    as-bytes ↦ ⟦
      c ↦ Φ.org.eolang.float (
        as-bytes ↦ Φ.org.eolang.bytes (
          Δ ⤍ 40-39-00-00-00-00-00-00
        )
      ),
      result ↦ ξ.c.times (
        x ↦ ⟦
          Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
        ⟧
      )
     .plus (
        x ↦ ⟦
          Δ ⤍ 40-40-00-00-00-00-00-00
        ⟧
      ),
      λ ⤍ Package
    ⟧
   .org.eolang.bytes (
      Δ ⤍ 40-39-00-00-00-00-00-00
    )
  )
 .times (
    x ↦ ⟦
      Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
    ⟧
  )
 .plus (
    x ↦ ⟦
      Δ ⤍ 40-40-00-00-00-00-00-00
    ⟧
  ),
  λ ⤍ Package
⟧

--output-file FILE

Redirects the output to file of the given path instead of stdout.

--dependency-file FILE

Injects package dependencies from a given file into the context when dataizing the input. Can be used multiple times to inject multiple dependencies.

--recursive

Applies the normalization+dataization process recursively until it reaches bytes or no longer modifies the object (stalls).

eo-phi-normalizer dataize --recursive --rules eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
{
  ⟦
    c ↦ ⟦
      c ↦ Φ.org.eolang.float (
        as-bytes ↦ Φ.org.eolang.bytes (
          Δ ⤍ 40-39-00-00-00-00-00-00
        )
      ),
      result ↦ ξ.c.times (
        x ↦ ⟦
          Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
        ⟧
      )
     .plus (
        x ↦ ⟦
          Δ ⤍ 40-40-00-00-00-00-00-00
        ⟧
      ),
      λ ⤍ Package
    ⟧
   .org.eolang.float (
      as-bytes ↦ ⟦
        c ↦ Φ.org.eolang.float (
          as-bytes ↦ Φ.org.eolang.bytes (
            Δ ⤍ 40-39-00-00-00-00-00-00
          )
        ),
        result ↦ ξ.c.times (
          x ↦ ⟦
            Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
          ⟧
        )
       .plus (
          x ↦ ⟦
            Δ ⤍ 40-40-00-00-00-00-00-00
          ⟧
        ),
        λ ⤍ Package
      ⟧
     .org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ⟦
      c ↦ Φ.org.eolang.float (
        as-bytes ↦ Φ.org.eolang.bytes (
          Δ ⤍ 40-39-00-00-00-00-00-00
        )
      ),
      result ↦ ξ.c.times (
        x ↦ ⟦
          Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
        ⟧
      )
     .plus (
        x ↦ ⟦
          Δ ⤍ 40-40-00-00-00-00-00-00
        ⟧
      ),
      λ ⤍ Package
    ⟧
   .org.eolang.float (
      as-bytes ↦ ⟦
        c ↦ Φ.org.eolang.float (
          as-bytes ↦ Φ.org.eolang.bytes (
            Δ ⤍ 40-39-00-00-00-00-00-00
          )
        ),
        result ↦ ξ.c.times (
          x ↦ ⟦
            Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
          ⟧
        )
       .plus (
          x ↦ ⟦
            Δ ⤍ 40-40-00-00-00-00-00-00
          ⟧
        ),
        λ ⤍ Package
      ⟧
     .org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    )
   .times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
}

Can be combined with --chain to print all the intermediate steps of both normalization and dataization.

--enable-atom

Enable an atom by name.

eo-phi-normalizer dataize --minimize-stuck-terms --recursive --enable-atom "Lorg_eolang_dataized" --rules eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
{
  ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
}

--disable-atom

Disable an atom by name.

eo-phi-normalizer dataize --minimize-stuck-terms --recursive --disable-atom "Lorg_eolang_dataized" --rules eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
{
  ⟦
    c ↦ Φ.org.eolang.float (
      as-bytes ↦ Φ.org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ξ.c.times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
}

FILE not specified (read from stdin)

If no argument is given for the input file, stdin is consumed until EOF.

cat celsius.phi | eo-phi-normalizer dataize --recursive --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml
{
  ⟦
    c ↦ ⟦
      c ↦ Φ.org.eolang.float (
        as-bytes ↦ Φ.org.eolang.bytes (
          Δ ⤍ 40-39-00-00-00-00-00-00
        )
      ),
      result ↦ ξ.c.times (
        x ↦ ⟦
          Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
        ⟧
      )
     .plus (
        x ↦ ⟦
          Δ ⤍ 40-40-00-00-00-00-00-00
        ⟧
      ),
      λ ⤍ Package
    ⟧
   .org.eolang.float (
      as-bytes ↦ ⟦
        c ↦ Φ.org.eolang.float (
          as-bytes ↦ Φ.org.eolang.bytes (
            Δ ⤍ 40-39-00-00-00-00-00-00
          )
        ),
        result ↦ ξ.c.times (
          x ↦ ⟦
            Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
          ⟧
        )
       .plus (
          x ↦ ⟦
            Δ ⤍ 40-40-00-00-00-00-00-00
          ⟧
        ),
        λ ⤍ Package
      ⟧
     .org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    ),
    result ↦ ⟦
      c ↦ Φ.org.eolang.float (
        as-bytes ↦ Φ.org.eolang.bytes (
          Δ ⤍ 40-39-00-00-00-00-00-00
        )
      ),
      result ↦ ξ.c.times (
        x ↦ ⟦
          Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
        ⟧
      )
     .plus (
        x ↦ ⟦
          Δ ⤍ 40-40-00-00-00-00-00-00
        ⟧
      ),
      λ ⤍ Package
    ⟧
   .org.eolang.float (
      as-bytes ↦ ⟦
        c ↦ Φ.org.eolang.float (
          as-bytes ↦ Φ.org.eolang.bytes (
            Δ ⤍ 40-39-00-00-00-00-00-00
          )
        ),
        result ↦ ξ.c.times (
          x ↦ ⟦
            Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
          ⟧
        )
       .plus (
          x ↦ ⟦
            Δ ⤍ 40-40-00-00-00-00-00-00
          ⟧
        ),
        λ ⤍ Package
      ⟧
     .org.eolang.bytes (
        Δ ⤍ 40-39-00-00-00-00-00-00
      )
    )
   .times (
      x ↦ ⟦
        Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD
      ⟧
    )
   .plus (
      x ↦ ⟦
        Δ ⤍ 40-40-00-00-00-00-00-00
      ⟧
    ),
    λ ⤍ Package
  ⟧
}

eo-phi-normalizer metrics

Metrics

See Metrics for the specification of metrics collected by this command.

Environment

Save a PHI program to a file.

cat > celsius.phi <<EOM
{⟦
  c ↦ Φ.org.eolang.float(as-bytes ↦ Φ.org.eolang.bytes(Δ ⤍ 40-39-00-00-00-00-00-00)), // 25.0
  result ↦
    ξ.c.times(x ↦ ⟦ Δ ⤍ 3F-FC-CC-CC-CC-CC-CC-CD ⟧)  // 1.8
       .plus(x ↦ ⟦ Δ ⤍ 40-40-00-00-00-00-00-00 ⟧), // 32.0
  λ ⤍ Package
⟧}
EOM

CLI

--help

eo-phi-normalizer metrics --help
Usage: eo-phi-normalizer metrics [FILE] [-o|--output-file FILE]
                          [-b|--bindings-path PATH]

  Collect metrics for a PHI program.

Available options:
  FILE                     FILE to read input from. When no FILE is specified,
                           read from stdin.
  -o,--output-file FILE    Output to FILE. When this option is not specified,
                           output to stdout.
  -b,--bindings-path PATH  Report metrics for bindings of a formation accessible
                           in a program by the PATH. When this option is not
                           specified, metrics for bindings are not reported.
                           Example of a PATH: 'org.eolang'.
  -h,--help                Show this help text

FILE

eo-phi-normalizer metrics celsius.phi
{
  "bindings-by-path-metrics": null,
  "program-metrics": {
    "applications": 3,
    "dataless": 6,
    "dispatches": 6,
    "formations": 8
  }
}

FILE not specified (read from stdin)

cat celsius.phi | eo-phi-normalizer metrics
{
  "bindings-by-path-metrics": null,
  "program-metrics": {
    "applications": 3,
    "dataless": 6,
    "dispatches": 6,
    "formations": 8
  }
}

--bindings-path

eo-phi-normalizer metrics --bindings-path org.eolang celsius.phi
{
  "bindings-by-path-metrics": {
    "bindings-metrics": [
      {
        "metrics": {
          "applications": 0,
          "dataless": 3,
          "dispatches": 0,
          "formations": 3
        },
        "name": "float"
      }
    ],
    "path": "org.eolang"
  },
  "program-metrics": {
    "applications": 3,
    "dataless": 6,
    "dispatches": 6,
    "formations": 8
  }
}

eo-phi-normalizer pipeline

This command is used in the pipeline script.

eo-phi-normalizer pipeline prepare-tests

--config

This command reads the pipeline configuration, reads original EO files, filters tests there, and writes them to filtered and yaml files.

source scripts/lib.sh
eo-phi-normalizer pipeline prepare-tests --config "$PIPELINE_CONFIG_FILE"

eo-phi-normalizer pipeline print-dataize-configs

--config, --single-line, --strip-phi-prefix

This commands reads the pipeline configuration and prints configurations for the eo-phi-normalizer dataize.

source scripts/lib.sh
eo-phi-normalizer pipeline print-dataize-configs --single-line --strip-phi-prefix "$PIPELINE_PHI_INITIAL_DIR_RELATIVE/" --config "$PIPELINE_CONFIG_FILE"

eo-phi-normalizer pipeline report

Reports

The eo-phi-normalizer pipeline report command generates reports about initial and normalized PHI programs.

The reports contain detailed information about metrics collected for these programs.

The reports are in HTML, GitHub Flavored Markdown, and JSON formats.

Environment

The command requires that there are:

  • Initial PHI programs
  • Normalized PHI programs
  • A report configuration file

PHI programs

Currently, we translate EO programs and get initial PHI programs.

Next, we normalize these PHI programs and get normalized PHI programs.

Report configuration

The report configuration is stored in the report object in the pipeline configuration file.

CLI

--help

eo-phi-normalizer pipeline report --help
Usage: eo-phi-normalizer pipeline report (-c|--config FILE)

  Generate reports about initial and normalized PHI programs.

Available options:
  -c,--config FILE         The FILE with a report configuration.
  -h,--help                Show this help text

--config

eo-phi-normalizer pipeline report --config pipeline/config.yaml

eo-phi-normalizer test

CLI

--help

eo-phi-normalizer test --help
Usage: eo-phi-normalizer test [-r|--rules FILE]

  Run unit tests in given files with user-defined rules.

Available options:
  -r,--rules FILE          FILE with user-defined rules.
  -h,--help                Show this help text

Run tests in a file

eo-phi-normalizer test --rules eo-phi-normalizer/test/eo/phi/rules/yegor.yaml
User-defined rules unit tests
  Rule set based on Yegor's draft
    xi
      Does not replace ξ inside a subformation [✔]
    DOT
      Should match [✔]
      Shouldn't match [✔]
      Shouldn't match [✔]
      Should apply in subformations [✔]
      Should respect surrounding context [✔]
    DOTrho
      Should match [✔]
    phi
      Attribute does not exist [✔]
      Attribute exists [✔]
      Both attributes do not exist [✔]
    COPY
      Should match [✔]
      Should not match in subformations [✔]
    COPY1
      Should match first void attribute [✔]
    COPY2
      Should match positional arguments [✔]
    EMPTY
      Should match [✔]
      Should not match [✔]
      Should match in subformation [✔]
      Should work with empty formation [✔]
    OVER
      Language.EO.Test.YamlSpec[44:13] [✔]
    STOP
      Accessing nonexistent attribute [✔]
    MISS
      Language.EO.Test.YamlSpec[44:13] [✔]
      Should not match if attr is present [✔]
      Should not match if phi is present [✔]
      Should apply in subformations [✔]
    DD
      Dispatch on bottom is bottom [✔]
      Dispatch on anything else is not touched [✔]
    DC
      Should apply in subformations [✔]

Finished in 0.0062 seconds
27 examples, 0 failures

eo-phi-normalizer print-rules

CLI

--help

eo-phi-normalizer print-rules --help
Usage: eo-phi-normalizer print-rules [-r|--rules FILE] [--tex] [-c|--compact]

  Print rules in LaTeX format.

Available options:
  -r,--rules FILE          FILE with user-defined rules. If unspecified,
                           yegor.yaml is rendered.
  --tex                    Output LaTeX.
  -c,--compact             Print rules, each on a single line.
  -h,--help                Show this help text

Default version

The command below prints to the console rules from yegor.yaml, listing each condition of the rules on a separate line.

rules-latex

eo-phi-normalizer print-rules --tex
\begin{figure*}
\begin{tabular}{rl}
  \rrule{Phi}: & $ Q $ \(\trans\) $ b $ \\\text {if }& $ Q -> b $ \\&not in subformations\\\\
  \rrule{xi}: & $ \xi $ \(\trans\) $ b $ \\\text {if }& $ b $  is the scope of the redex\\&not in subformations\\\\
  \rrule{DOT}: & $ [[ \tau -> b, B ]].\tau $ \(\trans\) $ \mathbb{S}(b, [[ \tau -> b, B ]]) $ \\\text {if }&not in subformations,\\& $ b $  is nf inside formation,\\& $ [[ B ]]\in\mathcal{N} $ ,\\& $ \tau \neq ^ $ \\\\
  \rrule{DOTrho}: & $ [[ ^ -> b, B ]].^ $ \(\trans\) $ b $ \\\text {if }& $ [[ B ]]\in\mathcal{N} $ \\\\
  \rrule{phi}: & $ [[ B ]].\tau $ \(\trans\) $ [[ B ]].@.\tau $ \\\text {if }& $ @ \in B $ ,\\& $ \tau \notin B $ \\\\
  \rrule{COPY}: & $ [[ \tau -> ?, B1 ]]( \tau -> b1, B2 ) $ \(\trans\) $ [[ \tau -> \mathbb{S}(b1, b2), B1 ]]( B2 ) $ \\\text {if }& $ b2 $  is the scope of the redex\\&not in subformations,\\& $ b1\in\mathcal{N} $ \\\\
  \rrule{COPY1}: & $ [[ \tau -> ?, B ]]( 0-> b1 ) $ \(\trans\) $ [[ \tau -> \mathbb{S}(b1, b2), B ]] $ \\\text {if }& $ b2 $  is the scope of the redex\\&not in subformations,\\& $ b1\in\mathcal{N} $ \\\\
  \rrule{COPY2}: & $ [[ \tau1 -> ?, \tau2 -> ?, B ]]( 0-> b1, 1-> b2 ) $ \(\trans\) $ [[ \tau1 -> \mathbb{S}(b1, b3), \tau2 -> \mathbb{S}(b2, b3), B ]] $ \\\text {if }& $ b3 $  is the scope of the redex\\&not in subformations,\\& $ b1\in\mathcal{N} $ ,\\& $ b2\in\mathcal{N} $ \\\\
  \rrule{COPYdelta}: & $ [[ D> ?, B ]]( D> y ) $ \(\trans\) $ [[ D> y, B ]] $ \\\text {if }&not in subformations\\\\
  \rrule{EMPTY}: & $ [[ B1 ]](  ) $ \(\trans\) $ [[ B1 ]] $ \\\\
  \rrule{OVER}: & $ [[ \tau -> b1, B1 ]]( \tau -> b2, B2 ) $ \(\trans\) $ \dead $ \\\\
  \rrule{STOP}: & $ [[ B ]].\tau $ \(\trans\) $ \dead $ \\\text {if }& $ \tau, @, \lambda \notin B $ ,\\& $ ^ \in B $ ,\\& $ [[ B ]]\in\mathcal{N} $ \\\\
  \rrule{MISS}: & $ [[ B1 ]]( \tau -> b, B2 ) $ \(\trans\) $ \dead $ \\\text {if }& $ \tau, @, \lambda \notin B1 $ \\\\
  \rrule{DD}: & $ \dead.\tau $ \(\trans\) $ \dead $ \\\\
  \rrule{DC}: & $ \dead( B ) $ \(\trans\) $ \dead $
\end{tabular}
\end{figure*}

Compact version

The compact version prints rules listing all conditions on a single line.

rules-latex-compact

eo-phi-normalizer print-rules --tex --compact
\begin{figure*}
  \rrule{Phi}:  $ Q $ \(\trans\) $ b $ \quad\text {if } $ Q -> b $ , not in subformations\\\vspace*{0.5em}
  \rrule{xi}:  $ \xi $ \(\trans\) $ b $ \quad\text {if } $ b $  is the scope of the redex, not in subformations\\\vspace*{0.5em}
  \rrule{DOT}:  $ [[ \tau -> b, B ]].\tau $ \(\trans\) $ \mathbb{S}(b, [[ \tau -> b, B ]]) $ \quad\text {if }not in subformations,  $ b $  is nf inside formation,  $ [[ B ]]\in\mathcal{N} $ ,  $ \tau \neq ^ $ \\\vspace*{0.5em}
  \rrule{DOTrho}:  $ [[ ^ -> b, B ]].^ $ \(\trans\) $ b $ \quad\text {if } $ [[ B ]]\in\mathcal{N} $ \\\vspace*{0.5em}
  \rrule{phi}:  $ [[ B ]].\tau $ \(\trans\) $ [[ B ]].@.\tau $ \quad\text {if } $ @ \in B $ ,  $ \tau \notin B $ \\\vspace*{0.5em}
  \rrule{COPY}:  $ [[ \tau -> ?, B1 ]]( \tau -> b1, B2 ) $ \(\trans\) $ [[ \tau -> \mathbb{S}(b1, b2), B1 ]]( B2 ) $ \quad\text {if } $ b2 $  is the scope of the redex, not in subformations,  $ b1\in\mathcal{N} $ \\\vspace*{0.5em}
  \rrule{COPY1}:  $ [[ \tau -> ?, B ]]( 0-> b1 ) $ \(\trans\) $ [[ \tau -> \mathbb{S}(b1, b2), B ]] $ \quad\text {if } $ b2 $  is the scope of the redex, not in subformations,  $ b1\in\mathcal{N} $ \\\vspace*{0.5em}
  \rrule{COPY2}:  $ [[ \tau1 -> ?, \tau2 -> ?, B ]]( 0-> b1, 1-> b2 ) $ \(\trans\) $ [[ \tau1 -> \mathbb{S}(b1, b3), \tau2 -> \mathbb{S}(b2, b3), B ]] $ \quad\text {if } $ b3 $  is the scope of the redex, not in subformations,  $ b1\in\mathcal{N} $ ,  $ b2\in\mathcal{N} $ \\\vspace*{0.5em}
  \rrule{COPYdelta}:  $ [[ D> ?, B ]]( D> y ) $ \(\trans\) $ [[ D> y, B ]] $ \quad\text {if }not in subformations\\\vspace*{0.5em}
  \rrule{EMPTY}:  $ [[ B1 ]](  ) $ \(\trans\) $ [[ B1 ]] $ \\\vspace*{0.5em}
  \rrule{OVER}:  $ [[ \tau -> b1, B1 ]]( \tau -> b2, B2 ) $ \(\trans\) $ \dead $ \\\vspace*{0.5em}
  \rrule{STOP}:  $ [[ B ]].\tau $ \(\trans\) $ \dead $ \quad\text {if } $ \tau, @, \lambda \notin B $ ,  $ ^ \in B $ ,  $ [[ B ]]\in\mathcal{N} $ \\\vspace*{0.5em}
  \rrule{MISS}:  $ [[ B1 ]]( \tau -> b, B2 ) $ \(\trans\) $ \dead $ \quad\text {if } $ \tau, @, \lambda \notin B1 $ \\\vspace*{0.5em}
  \rrule{DD}:  $ \dead.\tau $ \(\trans\) $ \dead $ \\\vspace*{0.5em}
  \rrule{DC}:  $ \dead( B ) $ \(\trans\) $ \dead $
\end{figure*}

Release procedure

Prerequisites

  1. Create an account on Hackage.
  2. Ask one of the package maintainers to make you a new package maintainer.

In the repository

  1. Choose a new release version <version>. The <version> must conform to SemVer.
  2. Draft a new release.
  3. Create a new tag v<version>.
  4. Click Generate release notes.
  5. Create an issue named Release v<version> (example).
  6. List there in the ## Subtasks section what needs to be done for the release.
  7. On the issue page, find Development and click Create a branch ....
  8. Checkout this branch locally using git.
  9. Open CHANGELOG.md
  10. Add a new section at the top of the file before sections for previous versions.
  11. In the section title, specify the version (v<version>) and the release date.
  12. Copy the generated release notes from the release draft into that section.
  13. Format the notes similar to the sections that go below this one.
  14. Commit the changes with a message feat(changelog): add notes for v<version> (replace <version> with the actual version).
  15. In eo-phi-normalizer/package.yaml and eo-phi-normalizer/eo-phi-normalizer.cabal, update the version.
  16. Commit the changes with a message chore(eo-phi-normalizer): bump version <previous-version> <version> (replace the <previous-version> and <version> with the actual versions).
  17. Push changes.
  18. Wait until CI succeeds (see Actions).
  19. Merge changes into master.
  20. Wait until CI succeeds (see Actions).
  21. Return to the page where you drafted the release.
  22. Copy the text from the section about the v<version> in CHANGELOG.md into the release description.
  23. Select Set as the latest release.
  24. Click Publish release.

On Hackage

  1. If the release was successful, go to the package page.
  2. Find there Candidates.
  3. Click on the relevant release candidate.
  4. Publish it.

Contributing

Issues

Check open issues (link).

Issue labels

  • priority N - an issue with the priority N.
    • 1 - The highest priority (the most important issues).
    • 5 - The lowest priority (the least important issues).
  • (scope) - An issue concerning a particular part of the project. Note the parentheses.
  • [non-functional requirement] - An issue concerning a non-functional requirement. Note the square brackets.

Enter the repository

Clone and enter the project repository.

git clone https://github.com/objectionary/eo-phi-normalizer --recurse-submodules
cd eo-phi-normalizer

Install stack

We recommend using stack for quick local development and testing.

Build

Build the project using stack.

export LC_ALL=C.UTF-8
stack build

Test

Run all tests

export LC_ALL=C.UTF-8
stack test

Run

Run the eo-phi-normalizer executable via stack run.

stack run eo-phi-normalizer -- --help
Usage: eo-phi-normalizer COMMAND

  Work with PHI expressions.

Available options:
  -h,--help                Show this help text
  --version                Show version information

Available commands:
  rewrite                  Rewrite a PHI program.
  metrics                  Collect metrics for a PHI program.
  dataize                  Dataize a PHI program.
  pipeline                 Run pipeline-related commands.
  print-rules              Print rules in LaTeX format.
  test                     Run unit tests in given files with user-defined
                           rules.

Or, omit the executable name.

stack run -- --help
Usage: eo-phi-normalizer COMMAND

  Work with PHI expressions.

Available options:
  -h,--help                Show this help text
  --version                Show version information

Available commands:
  rewrite                  Rewrite a PHI program.
  metrics                  Collect metrics for a PHI program.
  dataize                  Dataize a PHI program.
  pipeline                 Run pipeline-related commands.
  print-rules              Print rules in LaTeX format.
  test                     Run unit tests in given files with user-defined
                           rules.

Docs

Math expressions

Use the syntax supported by mdBook - see docs.

mdsh

We use mdsh to document command outputs (see Multiline Shell Code).

You can install mdsh via cargo or nix (link).

prettier

We format docs with prettier.

Run npm i to locally install the prettier version that we use.

Automatic updates

In CI, on the master branch, we run a script to update Markdown files and then we commit changes.

So, no worries if you haven't run mdsh in your PR!

Code quality

Checks in CI

We run fourmolu and hlint checks in CI.

These checks are also implemented as pre-commit hooks.

pre-commit hooks

We use pre-commit hooks to ensure code quality.

Collaborators MUST set up the hooks before commiting any code to our repository.

Set up pre-commit

Single command

pip3 install
pre-commit install
stack install fourmolu
chmod +x scripts/run-fourmolu.sh

Step by step

  1. Install Python 3 (e.g., Python 3.10).

  2. Install pre-commit.

    • Alternatively, run pip3 install.
  3. Install the git hook scripts.

  4. Install fourmolu.

    stack install fourmolu
    
    • You can remove fourmolu later (see SO post)
  5. Make a script executable.

    chmod +x scripts/run-fourmolu.sh
    

pre-commit configs

See docs.

See .pre-commit-config.yaml.

You can run a specific hook (see docs):

pre-commit run -c .pre-commit-config.yaml fourmolu-format --all

pre-commit workflow

  • pre-commit runs before a commit (at the pre-commit phase)

    The pre-commit hook is run first, before you even type in a commit message. It's used to inspect the snapshot that's about to be committed, to see if you've forgotten something, to make sure tests run, or to examine whatever you need to inspect in the code. Exiting non-zero from this hook aborts the commit ...

  • pre-commit stashes (link) unstaged (link) files.

    [WARNING] Unstaged files detected.
    [INFO] Stashing unstaged files to /home/eyjafjallajokull/.cache/pre-commit/patch1705090051-437857.
    
  • pre-commit runs hooks.

  • A hook may exit with an error, e.g.:

    Format Haskell (.hs) files...............................................Failed
    
    - hook id: fourmolu
    - exit code: 102
    - files were modified by this hook
    
    • In case of the fourmolu formatter, it's assumed that formatting a formatted Haskell file doesn't modify it. However, pre-commit runs the fourmolu hook and reports that it has modified some files. This error won't allow you to commit.
  • pre-commit unstashes files.

  • You should stage all changes so that pre-commit does not complain.

    • In case of fourmolu, stage the formatted code regions.
  • Now, you can commit.