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 normalizer transform and normalizer dataize).

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

See the report on our current progress with metrics.

The normalizer package is available on Hackage.

The latest package Haddock documentation is available on our site.

Installation

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

Install from the repository

Clone and enter the project repository.

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

Install normalizer.

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

Install from Hackage

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

Update

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

Uninstall

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/normalizer --recurse-submodules
cd normalizer

Install 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.

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

Enter the repository

Clone and enter the project repository.

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

Install normalizer

Install normalizer.

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

Install dependencies

Install yq.

yq --version

Install NodeJS.

node --version

Install Java.

java --version

Windows

Install Cygwin.

Make cygpath available on PATH.

Learn about the pipeline

Pipeline stages

The pipeline has several important stages:

  • Transform 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.
  • 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 an EO 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
      • 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.

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.

Normalizer

See commands supported by the normalizer executable.

normalizer --help
Usage: normalizer COMMAND

  Work with PHI expressions.

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

Available commands:
  transform                Transform a PHI program.
  metrics                  Collect metrics for a PHI program.
  dataize                  Dataize a PHI program.
  report                   Generate reports about initial and normalized PHI
                           programs.

normalizer transform

MetaPHI

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

See the MetaPHI Labelled BNF in Syntax.cf.

phi-paper rules

Currently, the PHI normalizer supports rules defined in an unpublished paper by Yegor Bugayenko.

Rules

yegor.yaml

These rules translated to MetaPHI are 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.
    • 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 shoud be in normal form.
    • 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.

Normal form

An expression is in normal form when no rule can be applied to that expression.

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/normalizer --recurse-submodules
cd 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

normalizer transform --help
Usage: normalizer transform (-r|--rules FILE) [-c|--chain] [-j|--json]
                            [-o|--output-file FILE] [-s|--single]
                            [--max-depth INT] [--max-growth-factor INT] [FILE]
                            [-d|--dependency-file FILE]

  Transform a PHI program.

Available options:
  -r,--rules FILE          FILE with user-defined rules. Must be specified.
  -c,--chain               Output transformation steps.
  -j,--json                Output JSON.
  -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).

normalizer transform --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.

normalizer transform --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

normalizer transform --json --chain --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
{
  "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 ⟧ }",
  "output": [
    [
      [
        "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 ⟧ }"
      ]
    ]
  ]
}

--single

normalizer transform --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

normalizer transform --single --json --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 ⟧ }"

--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 | normalizer transform --single --json --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml
"{ ⟦ 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 ⟧ }"

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 normalizer transform 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

normalizer dataize --help
Usage: normalizer dataize (-r|--rules FILE) [FILE] [-d|--dependency-file FILE]
                          [-o|--output-file FILE] [--recursive] [--chain]
                          [--tex]

  Dataize a PHI program.

Available options:
  -r,--rules FILE          FILE with user-defined rules. Must be specified.
  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.
  --tex                    Output LaTeX.
  -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).

normalizer dataize --chain --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
Dataizing inside phi: ξ.c.times (x ↦ ⟦ Δ ⤍ 01-01-00-00-00-00-00-00-00-07-CD-CC-CC-CC-CC-CC-1C-FF-FF-FF-FF-FF-FF-FF-CC ⟧).plus (x ↦ ⟦ Δ ⤍ 01-01-00-00-00-00-00-00-00-07-00-00-00-00-00-00-10-FF-FF-FF-FF-FF-FF-FF-D1 ⟧)
Dataizing inside application: ξ.c.times (x ↦ ⟦ Δ ⤍ 01-01-00-00-00-00-00-00-00-07-CD-CC-CC-CC-CC-CC-1C-FF-FF-FF-FF-FF-FF-FF-CC ⟧).plus
Dataizing inside dispatch: ξ.c.times (x ↦ ⟦ Δ ⤍ 01-01-00-00-00-00-00-00-00-07-CD-CC-CC-CC-CC-CC-1C-FF-FF-FF-FF-FF-FF-FF-CC ⟧)
Dataizing inside application: ξ.c.times
Dataizing inside dispatch: ξ.c
Dataizing inside dispatch: ξ
Nothing to dataize: ξ

--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).

normalizer dataize --recursive --rules eo-phi-normalizer/test/eo/phi/rules/yegor.yaml celsius.phi
Φ.org.eolang.float (as-bytes ↦ Φ.org.eolang.bytes (Δ ⤍ 01-01-00-00-00-00-00-00-00-07-00-00-00-00-00-00-19-FF-FF-FF-FF-FF-FF-FF-D0)).times (x ↦ ⟦ Δ ⤍ 01-01-00-00-00-00-00-00-00-07-CD-CC-CC-CC-CC-CC-1C-FF-FF-FF-FF-FF-FF-FF-CC ⟧).plus (x ↦ ⟦ Δ ⤍ 01-01-00-00-00-00-00-00-00-07-00-00-00-00-00-00-10-FF-FF-FF-FF-FF-FF-FF-D1 ⟧)

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

FILE not specified (read from stdin)

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

cat celsius.phi | normalizer dataize --recursive --rules ./eo-phi-normalizer/test/eo/phi/rules/yegor.yaml
Φ.org.eolang.float (as-bytes ↦ Φ.org.eolang.bytes (Δ ⤍ 01-01-00-00-00-00-00-00-00-07-00-00-00-00-00-00-19-FF-FF-FF-FF-FF-FF-FF-D0)).times (x ↦ ⟦ Δ ⤍ 01-01-00-00-00-00-00-00-00-07-CD-CC-CC-CC-CC-CC-1C-FF-FF-FF-FF-FF-FF-FF-CC ⟧).plus (x ↦ ⟦ Δ ⤍ 01-01-00-00-00-00-00-00-00-07-00-00-00-00-00-00-10-FF-FF-FF-FF-FF-FF-FF-D1 ⟧)

normalizer metrics

PHI grammar

phi-grammar

Metrics

We count:

Object formations

  • ⟦ d ↦ ∅, c ↦ ∅ ⟧

Object applications

  • ξ.b(c ↦ ⟦ ⟧)

Dynamic dispatches

  • ξ.ρ.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

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

normalizer metrics --help
Usage: 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

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 | normalizer metrics
{
  "bindings-by-path-metrics": null,
  "program-metrics": {
    "applications": 3,
    "dataless": 6,
    "dispatches": 6,
    "formations": 8
  }
}

--bindings-path

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
  }
}

normalizer report

Reports

The 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 file

A report configuration file has several attributes:

  • input
    • js - Optional path to a JavaScript file that should be inlined into an HTML report.
      • If no path is specified, normalizer will use report/main.js from the eo-phi-normalizer package.
    • css - Optional path to a CSS file that should be inlined into an HTML report.
      • If no path is specified, normalizer will use report/styles.css from the eo-phi-normalizer package.
  • output
    • html - Optional path to an HTML report.
      • If no path is specified, the HTML report won't be generated.
    • json - Optional path to a JSON report.
      • If no path is specified, the JSON report won't be generated.
    • markdown - Optional path to a GitHub Flavored Markdown report.
      • If no path is specified, the GitHub Flavored Markdown report won't be generated.
  • expected-metrics-change - Specifies expected changes of metrics for normalized PHI programs relative to the initial PHI programs. Values represent (metric_initial - metric_normalized) / metric_ initial. Attributes:
    • dataless
    • applications
    • formations
    • dispatches
  • items
    • phi - path to an initial PHI program.
    • phi-normalized - path to a normalized PHI program.
      • The normalized PHI program should correspond to the initial PHI program.
    • bindings-path-phi - path to bindings of a formation in the initial PHI program.
      • org.eolang corresponds to a formation Φ.org.eolang.
    • bindings-path-phi-normalized - path to bindings of a formation in the normalized PHI program.
      • org.eolang corresponds to a formation Φ.org.eolang.

Sample report configuration file

The normalizer repository contains the report/config.yaml report configuration file.

Click to view the file
{{#include ../../../../report/config.yaml}}

CLI

--help

normalizer report --help
Usage: normalizer 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

Provide a report configuration file (see Report configuration file).

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/normalizer --recurse-submodules
cd normalizer

Install stack

We recommend using stack for quick local development and testing.

Build

Build the project using stack.

stack build

Run

Run the normalizer executable via stack run.

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

  Work with PHI expressions.

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

Available commands:
  transform                Transform a PHI program.
  metrics                  Collect metrics for a PHI program.
  dataize                  Dataize a PHI program.
  report                   Generate reports about initial and normalized PHI
                           programs.
  prepare-pipeline-tests   Prepare EO test files for the pipeline.

Or, omit the executable name.

stack run -- --help
Usage: normalizer COMMAND

  Work with PHI expressions.

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

Available commands:
  transform                Transform a PHI program.
  metrics                  Collect metrics for a PHI program.
  dataize                  Dataize a PHI program.
  report                   Generate reports about initial and normalized PHI
                           programs.
  prepare-pipeline-tests   Prepare EO test files for the pipeline.

Test

Run all tests

stack test

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.