1
1
mirror of https://github.com/anoma/juvix.git synced 2024-09-11 08:15:41 +03:00
Commit Graph

1348 Commits

Author SHA1 Message Date
Łukasz Czajka
86e8458b9f
JuvixReg recursors (#2641)
* Implements JuvixReg recursors, which will allow to implement JuvixReg
transformations more succinctly and effectively.
* Adds a transformation framework to JuvixReg.
* Adds identity transformation tests.
* Depends on #2635
2024-02-19 08:58:19 +00:00
Paul Cadman
a1264643b2
Correctly resolve the visibility annotations of NameSpaceEntries (#2657)
See the bug report for context.

* Closes #2656
2024-02-16 18:26:01 +01:00
Paul Cadman
dc0498902f
Transitively register local modules in ScoperState (#2655)
This PR fixes a TODO in the scoper code. We need to transitively
register local modules when checking an import.


* Closes #2654
2024-02-16 14:09:49 +00:00
Łukasz Czajka
a110297a69
JuvixReg interpreter (#2635)
* Closes #2577 
* Adds the `juvix dev reg run file.jvr` command.
* Adds interpreter tests.
2024-02-15 10:46:19 +01:00
Jan Mas Rovira
3e680da057
Effect benchmarks (#2640)
# Overview
This pr implements a simple benchmark suite to compare the efficiency of
[`effectful-core`](https://hackage.haskell.org/package/effectful-core)
and [`polysemy`](https://hackage.haskell.org/package/polysemy).

I've implemented the suite with the help of
[`tasty-bench`](https://hackage.haskell.org/package/tasty-bench). It is
a simple benchmarking library that has minimal dependencies and it can
be run with a default main using the same cli options as our
[`tasty`](https://hackage.haskell.org/package/tasty) test suite.

# How to run

```
stack run juvixbench
```

If you only want to run a particular benchmark:
```
stack run juvixbench -- -p "/Output/"
```

# Results
The results show that `effectful` is the clear winner, in some cases it
is extremely close to the raw version.

## State
This benchmark adds the first 2 ^ 22 first naturals:
```
countRaw :: Natural -> Natural
countRaw = go 0
  where
    go :: Natural -> Natural -> Natural
    go acc = \case
      0 -> acc
      m -> go (acc + m) (pred m)
```

Results:
```
   State
      Eff State (Static): OK
        25.2 ms ± 2.4 ms
      Sem State:          OK
        2.526 s ± 5.1 ms
      Raw State:          OK
        22.3 ms ± 1.5 ms
``` 

## Output
This benchmark collects the first 2 ^ 21 naturals in a list and adds
them.

```
countdownRaw :: Natural -> Natural
countdownRaw = sum' . reverse . go []
  where
    go :: [Natural] -> Natural -> [Natural]
    go acc = \case
      0 -> acc
      m -> go (m : acc) (pred m)
```

Results:
```
      Eff Output (Dynamic): OK
        693  ms ±  61 ms
      Eff Accum (Static):   OK
        553  ms ±  36 ms
      Sem Output:           OK
        2.606 s ±  91 ms
      Raw Output:           OK
        604  ms ±  26 ms
```

## Reader (First Order)
Repeats a constant in a list and adds it. The effects based version ask
the constant value in each iteration.

```
countRaw :: Natural -> Natural
countRaw = sum' . go []
  where
    go :: [Natural] -> Natural -> [Natural]
    go acc = \case
      0 -> acc
      m -> go (c : acc) (pred m)
```

Results:
```
    Reader (First order)
      Eff Reader (Static): OK
        103  ms ± 6.9 ms
      Sem Reader:          OK
        328  ms ±  31 ms
      Raw Reader:          OK
        106  ms ± 1.9 ms
```

## Reader (Higher Order)
Adds the first 2 ^ 21 naturals. The effects based version use `local`
(from the `Reader`) effect to pass down the argument that counts the
iterations.

```
countRaw :: Natural -> Natural
countRaw = sum' . go []
  where
    go :: [Natural] -> Natural -> [Natural]
    go acc = \case
      0 -> acc
      m -> go (m : acc) (pred m)
```

Results: 
```
    Reader (Higher order)
      Eff Reader (Static): OK
        720  ms ±  56 ms
      Sem Reader:          OK
        2.094 s ± 182 ms
      Raw Reader:          OK
        154  ms ± 2.2 ms
```

## Embed IO 
Opens a temporary file and appends a character to it a number of times.
```
countRaw :: Natural -> IO ()
countRaw n =
  withSystemTempFile "tmp" $ \_ h -> go h n
  where
    go :: Handle -> Natural -> IO ()
    go h = \case
      0 -> return ()
      a -> hPutChar h c >> go h (pred a)
```

Results: 
```
   Embed IO
      Raw IO:       OK
        464  ms ±  12 ms
      Eff RIO:      OK
        487  ms ± 3.5 ms
      Sem Embed IO: OK
        582  ms ±  33 ms
```
2024-02-14 15:12:39 +01:00
Jan Mas Rovira
97030f8cb4
Use EmbedIO instead of Embed IO (#2645)
- ⚠️ Depends on #2644 

The `effectful` library does not support the `Embed` effect out of the
box. However, it offers `IOE`, which is equivalent to `Embed IO` from
polysemy. In preparation to a possible migration to `effectful`, this pr
hides the general `Embed` effect from the prelude and it exports a
specialized `EmbedIO` in its place.
2024-02-13 18:00:01 +00:00
Jan Mas Rovira
77ed3697fb
Remove redundant Embed effect in the scoper (#2644)
see #2645
2024-02-13 13:14:37 +01:00
Jan Mas Rovira
c8da68d3db
Remove redundant embed @IO (#2637)
Since we upgraded to ghc-9.8.1 and dropped the dependency on
[with-utf8](https://hackage.haskell.org/package/with-utf8), the function
`writeFileEnsureLn` no longer has the constraint `MonadMask m`, so the
`embed @IO` has become redundant
2024-02-12 20:15:10 +01:00
Jan Mas Rovira
d09f15226e
Effectful Output (#2625)
This pr replaces the `Writer` effect with a more fitting `Output` effect
in the Juvix Tree evaluator.
2024-02-12 18:51:49 +01:00
Łukasz Czajka
da676114be
Style improvements (#2642)
* This PR provides minor coding style improvement, addressing the
comments in the review of #2617
2024-02-12 17:01:15 +01:00
Paul Cadman
e3044c4fb1
Fix linux static binary build workflow (#2634)
The alpine abstract packages clang/llvm now meet minimum version
requirements in the Docker container we're using for the linux static
build.

The llvm package must now be installed separately to get the `llvm-ar`
tool.
2024-02-12 10:25:44 +00:00
Jan Mas Rovira
50a62f6182
Fix bugs in the Nockma prettyprinter and parser (#2632)
This pr addresses a number of problems.

1. It fixes a bug where paths were annotated as operations rather than
paths in the parser.
2. It fixes a bug that happened when unfolding cells in the pretty
printer in order to minimize delimiters. It caused the stdlibcall hints
to be ignored for the unfolded arguments.
3. In order to properly test this, we can't ignore the hints for the Eq
instance, so I've changed that.
4. I've introduced the class NockmaEq for nockma semantic equality. This
is used in the evaluator as well as in the semantic tests.
5. I've added a bigger test. I found these bugs while working with this
file.
2024-02-09 14:59:42 +01:00
Paul Cadman
672004c2f9
Add jvt files to extra-source-files (#2628)
If this line is omitted then the project cannot be built with cabal
2024-02-09 12:42:42 +00:00
Łukasz Czajka
ed15e57d8a
JuvixReg parser and pretty printer (#2617)
* Closes #2578 
* Implements JuvixReg parser and pretty printer.
* Adds the `juvix dev reg read file.jvr` command.
* Adds the `reg` target to the `compile` commands.
* Adds tests for the JuvixReg parser.
2024-02-09 12:19:29 +01:00
Jan Mas Rovira
5dfafe00d2
Add nockma as a valid target for the tree compile command (#2630)
This allows us to do `juvix dev tree compile --target nockma test.jvt`.
The pipeline was already implemented, this pr only adds the
`TargetNockma` to the list of supported backends so that the cli
recognizes it.
2024-02-08 19:18:58 +01:00
Jan Mas Rovira
fe606176f6
Parse nockma atomVoid (#2631) 2024-02-08 17:13:37 +01:00
Paul Cadman
1edddfb32d
Use pow2 function from Anoma/Nock stdlib (#2629)
This PR introduces the `pow2` function from the Anoma/Nock stdlib,
replacing the 'Builtin function' version we wrote in the Tree->Nockma
translation. This will be more efficient because it will be jetted in
Anoma.

## New Anoma/nockma stdlib locations

The Nock stdlib now has multiple layers. We now use a Nock term to
to fetch each stdlib symbol's code because this can be obtained from
Urbit's dojo,

for example:

    > =>  anoma  !=(add)
    [9 20 0 15]

where `anoma` is the symbol where the anoma stdlib is loaded.

The stdlib is the Nock code associated with
6a4e15fe9c/hoon/anoma.hoon

## Tests

This commit also adds unit tests for the stdlib / appendRights
functions. The tests use the evaluator with 'interceptStdlibCalls' both
enabled and disabled.
2024-02-08 11:22:25 +00:00
Jan Mas Rovira
8dfe2baa93
Effectful Juvix tree evaluator (#2623)
This pr implements two additional versions of the Juvix Tree evaluator.
Now we have
1. The raw implementation that does not use effects. It throws Haskell
exceptions for errors. It uses `unsafePerformIO` for traces. It relies
on bang patterns to force strictness and guarantee the expected order of
execution (for traces). Avoiding effects allows for improved execution
efficiency.
2. [`polysemy`](https://hackage.haskell.org/package/polysemy-1.9.1.3)
based implementation.
3.
[`effectful-core`](https://hackage.haskell.org/package/effectful-core)
based implementation.

One can specify which evaluator to use thus:
```
juvix dev tree eval --evaluator XXX test.jvt
```
where XXX is one of `raw`, `polysemy`, `effectful`.

# Preliminary benchmarks

More thorough benchmarks should be run, but here are some preliminary
results:

## Test032 (Fibonacci 20)
I've adapted test032 so that it main is a single call to fibonacci of
20.

Command:
```
hyperfine --warmup 2 --runs 10 'juvix dev tree eval test032.jvt --evaluator polysemy' 'juvix dev tree eval test032.jvt --evaluator raw' 'juvix dev tree eval test032.jvt --evaluator e
ffectful'
```

Output:
```
Benchmark 1: juvix dev tree eval test032.jvt --evaluator polysemy
  Time (mean ± σ):      2.133 s ±  0.040 s    [User: 2.113 s, System: 0.016 s]
  Range (min … max):    2.088 s …  2.227 s    10 runs

Benchmark 2: juvix dev tree eval test032.jvt --evaluator raw
  Time (mean ± σ):     308.7 ms ±  13.8 ms    [User: 293.6 ms, System: 14.1 ms]
  Range (min … max):   286.5 ms … 330.1 ms    10 runs

Benchmark 3: juvix dev tree eval test032.jvt --evaluator effectful
  Time (mean ± σ):     366.0 ms ±   2.8 ms    [User: 345.4 ms, System: 19.4 ms]
  Range (min … max):   362.5 ms … 372.6 ms    10 runs

Summary
  juvix dev tree eval test032.jvt --evaluator raw ran
    1.19 ± 0.05 times faster than juvix dev tree eval test032.jvt --evaluator effectful
    6.91 ± 0.34 times faster than juvix dev tree eval test032.jvt --evaluator polysemy
```

## Test034 (Higher-order function composition)

A modified version of test034 where main defined as `call[exp](3, 12)`

Command:
```
hyperfine --warmup 2 --runs 10 'juvix dev tree eval test034.jvt --evaluator polysemy' 'juvix dev tree eval test034.jvt --evaluator raw' 'juvix dev tree eval test034.jvt --evaluator effectful'
```

Output:
```
Benchmark 1: juvix dev tree eval test034.jvt --evaluator polysemy
  Time (mean ± σ):      7.025 s ±  0.184 s    [User: 6.518 s, System: 0.469 s]
  Range (min … max):    6.866 s …  7.327 s    10 runs

Benchmark 2: juvix dev tree eval test034.jvt --evaluator raw
  Time (mean ± σ):     835.6 ms ±   7.4 ms    [User: 757.2 ms, System: 75.9 ms]
  Range (min … max):   824.7 ms … 847.4 ms    10 runs

Benchmark 3: juvix dev tree eval test034.jvt --evaluator effectful
  Time (mean ± σ):      1.578 s ±  0.010 s    [User: 1.427 s, System: 0.143 s]
  Range (min … max):    1.563 s …  1.595 s    10 runs

Summary
  juvix dev tree eval test034.jvt --evaluator raw ran
    1.89 ± 0.02 times faster than juvix dev tree eval test034.jvt --evaluator effectful
    8.41 ± 0.23 times faster than juvix dev tree eval test034.jvt --evaluator polysemy
```

## Test036 (Streams without memoization)
A modified version of test036 where main defined as `call[nth](700,
call[primes]())`

Command:
```
hyperfine --warmup 2 --runs 5 'juvix dev tree eval test036.jvt --evaluator polysemy' 'juvix dev tree eval test036.jvt --evaluator raw' 'juvix dev tree eval test036.jvt --evaluator effectful'
```

Output:
```
Benchmark 1: juvix dev tree eval test036.jvt --evaluator polysemy
  Time (mean ± σ):      1.993 s ±  0.026 s    [User: 1.946 s, System: 0.043 s]
  Range (min … max):    1.969 s …  2.023 s    5 runs

Benchmark 2: juvix dev tree eval test036.jvt --evaluator raw
  Time (mean ± σ):     137.5 ms ±   7.1 ms    [User: 127.5 ms, System: 8.9 ms]
  Range (min … max):   132.8 ms … 149.8 ms    5 runs

Benchmark 3: juvix dev tree eval test036.jvt --evaluator effectful
  Time (mean ± σ):     329.0 ms ±   7.3 ms    [User: 289.3 ms, System: 37.4 ms]
  Range (min … max):   319.9 ms … 336.0 ms    5 runs

Summary
  juvix dev tree eval test036.jvt --evaluator raw ran
    2.39 ± 0.13 times faster than juvix dev tree eval test036.jvt --evaluator effectful
   14.50 ± 0.77 times faster than juvix dev tree eval test036.jvt --evaluator polysemy
```
2024-02-08 10:53:40 +01:00
Jan Mas Rovira
652c0e8eb2
Add -XBangPatterns to the justfile (#2627) 2024-02-08 08:31:11 +00:00
Jan Mas Rovira
57bedc0d8c
Remove BangPattern pragmas (#2626)
`BangPatterns` is already enabled by
[`GHC2021`](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html#extension-GHC2021),
so it makes sense to remove the pragmas and add the corresponding flag
to ormolu
2024-02-07 11:46:13 +00:00
Jan Mas Rovira
13f64afbc1
upgrade to Ghc 9.8.1 (#2624)
This PR updates the stackage LTS resolver to `nightly-2024-02-06` which
uses GHC 9.8.1

## Upgrade notes

You will need to update your HLS to
[2.6.0.0](https://github.com/haskell/haskell-language-server/releases/tag/2.6.0.0),
this release contains support for GHC 9.8.1

## Fixes

### `haskeline` / `repline`

We have removed the custom haskeline / repline forks used in the build.
This is because we had trouble overriding haskeline as it is bundled
with GHC and the stackage resolver uses this bundled version. We were
using a custom fork of haskeline to implement
[mapInputT_](15c0685c91/app/Commands/Repl.hs (L409))
in the Juvix REPL, required to implement error handling. This requires
private API from the Haskeline library.

Instead of using a custom fork we use TemplateHaskell to obtain access
to the private API we need. See
[DarkArts.hs](15c0685c91/src/Juvix/Prelude/DarkArts.hs)
and
[HaskelineJB.hs](15c0685c91/app/HaskelineJH.hs).

To obtain access to the private API, we adapted a method from [a Tweag
blogpost](https://www.tweag.io/blog/2021-01-07-haskell-dark-arts-part-i/)
and [repo](https://github.com/tweag/th-jailbreak) - updating it for GHC
9.8.1.

### `aeson-better-errors`

The `aeson-better-errors` library has not been updated to work with
`mtl-2.3.0` so it cannot work with the new stackage resolver. We are
using a [fork](https://github.com/Vekhir/aeson-better-errors.git) which
has been updated.

We should consider replacing this library in future, see
https://github.com/anoma/juvix/issues/2621

###  `path`

The `path` library now includes API `splitDrive` and `dropDrive` so we
can remove our versions of those functions from the prelude.

### `with-utf8`

We no longer need to depend on `with-utf8`. We were using this package
for UTF-8 versions of `readFile` and `writeFile` APIs. These APIs are
now available in the `text` package.

### Compiler warnings

GHC 9.8.1 introduces several new compiler warnings. 

* We have suppressed `missing-role-annotations` and
`missing-poly-kind-signatures`
* We added our own versions of `head` and `tail` to work around the new
`partial-tx` warning introduced for those functions in `Data.List`.
* We fixed up the code to avoid the
[term-variable-capture](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/using-warnings.html#ghc-flag--Wterm-variable-capture)
warning.
2024-02-07 09:47:48 +00:00
Łukasz Czajka
795212b092
JuvixTree validation (#2616)
* Validation (type checking) of JuvixTree. Similar to JuvixAsm
validation, will help with debugging.
* Depends on #2608
2024-02-06 15:46:55 +01:00
Jan Mas Rovira
10e2a23239
Translation from Juvix Tree to Nockma (#2614)
This PR replaces the JuvixAsm -> Nockma translation with a JuvixTree ->
Nockma translation.

We can now enable some of the JuvixTree tests that did not work with
JuvixAsm->Nockma because they were too slow.


## Notes

We have changed [test031: temp stack with
branching](22ee87f0e7/tests/Tree/positive/test031.jvt)
to avoid using negative numbers (because negative integers are not
supported in Nockma).

Three tree tests trace/output lists. Lists are serialised differently by
the asm and nockma pretty printers so they cannot share a single test
output file. We have created separate nockma output files for these
tests (see eg.
[test028.nockma.out](22ee87f0e7/tests/Tree/positive/out/test028.nockma.out)).

* Closes https://github.com/anoma/juvix/issues/2606

---------

Co-authored-by: Paul Cadman <git@paulcadman.dev>
Co-authored-by: Lukasz Czajka <lukasz@heliax.dev>
2024-02-06 08:33:14 +00:00
Olivier Benz
5a878827f2
Use images from Quay (#2620)
I now mirror the *GHC musl* images to both Docker Hub and Quay:

* https://hub.docker.com/r/benz0li/ghc-musl
* https://quay.io/repository/benz0li/ghc-musl

Docker Hub imposes a rate limit. Quay, on the other hand, does not.

This also ensures the long-term availability of these images.
2024-02-05 11:42:07 +00:00
Jan Mas Rovira
3005772f09
Replace egrep with grep -E (#2618)
Quoting the [release notes of gnu
`grep-3.8`](https://lists.gnu.org/archive/html/info-gnu/2022-09/msg00001.html)

>   The egrep and fgrep commands, which have been deprecated since
  release 2.5.3 (2007), now warn that they are obsolescent and should
  be replaced by grep -E and grep -F.

In order to fix the warning, I've replaced all instances of `egrep` with
`grep -E`
2024-02-05 10:27:46 +01:00
Paul Cadman
262966d745
Add a justfile to perform project install, test, clean, format tasks (#2615)
This PR adds a https://github.com/casey/just

```
$ just
Available recipes:
    build *opts  # Build the project. `build runtime` builds only the runtime.
    clean *opts  # Clean the project. `clean runtime` cleans only the runtime. `clean juvix-build` cleans only juvix-build dirs.
    format *opts # Formats all Haskell files in the project. `format changed` formats only changed files. `format FILES` formats individual files.
    install      # Install juvix
    test *filter # Run the tests in the project. Use the filter arg to set a Tasty pattern.
```

---------

Co-authored-by: Jan Mas Rovira <janmasrovira@gmail.com>
2024-02-02 12:48:14 +01:00
Łukasz Czajka
9322e5d21f
JuvixTree REPL (#2608)
* JuvixTree REPL
* Depends on #2601
2024-02-01 17:50:09 +00:00
Łukasz Czajka
7b0a11d570
JuvixTree negative evaluation tests (#2601)
* Adds negative tests for the JuvixTree evaluator
* Depends on #2600 
* Depends on #2599 
* Depends on #2598 
* Depends on #2597 
* Depends on #2596 
* Depends on #2595 
* Depends on #2594 
* Depends on #2590
2024-02-01 12:58:38 +00:00
Łukasz Czajka
b433eb48cb
Location info in JuvixTree nodes (#2600) 2024-01-31 22:11:44 +00:00
Łukasz Czajka
8956e51b33
Options for juvix dev tree read (#2599)
* Adds the `--transforms`, `--eval` and `--no-print` options to the
`juvix dev tree read` command.
* Depends on #2598 
* Depends on #2597 
* Depends on #2596 
* Depends on #2595 
* Depends on #2594 
* Depends on #2590
2024-01-31 15:17:14 +01:00
Paul Cadman
ab887e3138
Store syntax aliases in serialized scoper infotable (#2605)
This PR fixes an issue with importing `syntax alias` and using them from
another module:

Say you have a module defining a syntax alias:

```
module SyntaxAlias;

import Stdlib.Prelude open;

syntax alias MyNat := Nat;
```

and another which imports / uses it:

```
module test073;

import SyntaxAlias open;

main : MyNat := 11;
```

The compiler crashed with the following error:

```
^?!): empty Fold
            CallStack (from HasCallStack):
              error, called at src/Lens/Micro.hs:711:28 in microlens-0.4.13.1-ARwI8t2x86cAxRs56XPcG1:Lens.Micro
              ^?!, called at src/Juvix/Compiler/Concrete/Translation/FromParsed/Analysis/Scoping.hs:565:29 in juvix-0.5.5-G7jC6MbkbsJGkMT9u4BkYQ:Juvix.Compiler.Concrete.Translation.FromParsed.Analysis.Scoping
```

We fix this by adding the aliases to the store's [scoper info
table](6649209d26/src/Juvix/Compiler/Store/Scoped/Data/InfoTable.hs (L14))
and then use it to initialise the scoper state when scoping a module.
2024-01-31 11:56:09 +00:00
Jan Mas Rovira
84b0e5605f
Use writeFileEnsureLn in place of writeFile (#2604)
Now we guarantee that whenever we write a file there is a newline
character at the end, which is a [Unix
convention](https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_205).

The juvix prelude now exports `writeFileEnsureLn` and it no longer
exports `writeFile`. If at some point we need the behaviour of
`writeFile` I'd suggest that we export it renamed as `writeFileVerbatim`
or something similar.
2024-01-31 11:15:17 +01:00
Łukasz Czajka
dc54bbb2c2
JuvixTree smoke tests (#2598)
* Adds smoke tests for `juvix dev tree` CLI commands.
* Fixes a bug with printing JuvixAsm.
* Depends on #2597 
* Depends on #2596 
* Depends on #2595 
* Depends on #2594 
* Depends on #2590
2024-01-31 08:33:52 +00:00
Łukasz Czajka
15c223d0f1
Filter out unreachable functions in JuvixTree (#2597)
* Adds the `FilterUnreachable` transformation in JuvixTree.
* Depends on #2596 
* Depends on #2595 
* Depends on #2594 
* Depends on #2590 
* Depends on #2589 
* Depends on #2587
2024-01-30 20:01:07 +00:00
Łukasz Czajka
4651d1eafe
Compute temporary stack height in JuvixTree (#2596) 2024-01-30 18:34:36 +00:00
Łukasz Czajka
1153f6b338
JuvixTree "apply" transformation (#2595)
* Moves the "apply" transformation from JuivxAsm to JuvixTree. This
transformation removes the `CallClosures` nodes.
* Makes Nockma compilation tests use JuvixTree instead of JuvixAsm
files.
* Depends on #2594 
* Depends on #2590
* Depends on #2589 
* Depends on #2587
2024-01-30 15:46:10 +00:00
Jan Mas Rovira
4c5050ccae
Remove redundant QuasiQuotes pragmas (#2603)
We already have `QuasiQuotes` in the default extensions list.
2024-01-30 10:08:07 +01:00
Łukasz Czajka
a5bfba6c1c
JuvixTree recursors and transformation framework (#2594)
* Generalizes JuvixCore map and fold recursors to work also for
JuvixTree.
* Adds a transformation framework to JuvixTree.
* Adds identity trasformation tests for JuvixTree.
* Depends on #2590 
* Depends on #2589 
* Depends on #2587
2024-01-29 16:43:08 +00:00
Jan Mas Rovira
21a5568985
Add dev nockma format command (#2593)
Useful for formatting nockma code. 
Usage:
```
juvix dev nockma format input.nockma
```
The formatted code is printed to stdout.
2024-01-29 13:36:53 +01:00
Łukasz Czajka
6649209d26
Add the juvix dev tree compile command (#2590)
* Adds the `juvix dev tree compile` CLI command.
* Depends on #2589 
* Depends on #2587 
* Depends on #2583
2024-01-27 08:54:57 +01:00
Paul Cadman
df9b17d74f
Fix generation and evaluation of Nock isCell op (#2602)
This PR fixes the generation and evaluation of the Nock isCell op.

As we can see from its
[definition](https://developers.urbit.org/reference/nock/definition),
the isCell op (Nock 3) evaluates its argument:

```
*[a 3 b]            ?*[a b]
```

Previously we were not evaluating the argument before checking if it is
an atom/cell.

Co-authored-by: Jan Mas Rovira <janmasrovira@gmail.com>
2024-01-26 19:37:47 +00:00
Łukasz Czajka
0073d04f89
JuvixTree evaluator (#2589)
* Implements JuvixTree evaluator
* Adds JuvixTree evaluation tests
* Adds the `juvix dev tree eval` command
* Depends on #2587 
* Depends on #2583
2024-01-25 19:11:45 +00:00
Łukasz Czajka
c95fcb38c8
JuvixTree tests (#2587)
* Implements a translation from JuvixAsm to JuvixTree. It does not work
in general, but works for all code generated from Juvix and all JuvixAsm
tests.
* Adds the `juvix dev tree from-asm` command.
* Adds tests automatically converted from JuvixAsm tests.
* Depends on #2583
2024-01-25 18:02:06 +00:00
Paul Cadman
06d459695d
Use Anoma compatible Nockma serialization of Bools and List-like data structures (#2591)
This PR changes the Nockma representation of builtin Bool and list-like
types to make them compatible with Anoma.

True and False are now compiled to the Nockma atoms 0 and 1
respectively.

For inductive types that have exactly two constructors, one of arity
zero and one of arity two, we compile the arity zero constructor to
Nockma zero, and the arity two constructor to a Nockma cell. In
particular a Juvix stdlib List will be compiled to an Anoma/Nockma list.
This is necessary for compatibility with the layout of resource and
resource logic types in Anoma.

In tests we avoid using the StackRef memory reference because it will be
removed as part of the JuvixTree work.

---------

Co-authored-by: Łukasz Czajka <62751+lukaszcz@users.noreply.github.com>
2024-01-24 15:16:04 +00:00
Łukasz Czajka
e5ea085f1c
JuvixTree parser and pretty printer (#2583)
This PR implements:
* JuvixTree parser.
* JuvixTree pretty printer.
* `juvix dev tree read file.jvt` command which reads and pretty prints a
JuvixTree file.
* The `tree` target in the `compile` command.
* Removal of `StackRef` in JuvixAsm. This makes JuvixAsm more consistent
with JuvixTree and simplifies the data structures. `StackRef` is not
needed for compilation from Core.

Tests for the parser will appear in a separate PR, when I implement an
automatic translation of JuvixAsm to JuvixTree files.

---------

Co-authored-by: Paul Cadman <git@paulcadman.dev>
Co-authored-by: Jan Mas Rovira <janmasrovira@gmail.com>
2024-01-24 12:45:39 +01:00
Jan Mas Rovira
510490a5bf
Support MemRepTuple in the Nockma backend (#2586)
We can represent Anoma types like
[resource](e18e50e3c3/hoon/resource-machine.hoon (L7))
as Juvix records.

The Nockma encoding of types uses Nockma 'tuples' where each component
of the tuple holds a value of a field. So for Juvix->Anoma integration
it is convenient to compile values of record types as Nockma tuples.

We already have the concept of representing constructors of inductive
types that have only one non-zero-field constructor in the compiler, see
[`MemRepTuple`](1147e1fce1/src/Juvix/Compiler/Tree/Language/Rep.hs (L13)).

In this PR, as part of the Nockma step, we mark constructors that
satisfy the requirements of the `MemRepTuple` translation as such. Then
we use a tuple encoding for those constructors.

---------

Co-authored-by: Paul Cadman <git@paulcadman.dev>
2024-01-23 14:36:19 +01:00
Jan Mas Rovira
8005089dc5
Improved errors for nockma eval (#2585)
This is needed if we want to debug nockma in a more sane manner.

Evaluation errors now include an evaluation trace (with source locations
when present). It looks like this:

![image](https://github.com/anoma/juvix/assets/5511599/4a553035-f56e-4f7c-bb69-9a2aeb41afcb)
2024-01-23 09:37:06 +00:00
Jan Mas Rovira
1147e1fce1
Unqualify language import in nockma parser (#2584) 2024-01-22 09:20:38 +00:00
Jan Mas Rovira
39d176e643
Fast nockma eval (#2580)
Adds annotations to cells to indicate that it is a call to the stdlib
and might be evaluated faster in the Haskell evaluator.

The syntax for stdlib calls is as follows:
```
[stdlib@add args@<args-term> <left-term> <right-term>]
```
where `add` is the name of the function being called, `<args-term>` is a
nockma term that points to the position of the arguments, and
`<left-term>` and `<right-term>` are the actual components of the cell.
2024-01-19 12:01:58 +01:00
Łukasz Czajka
91ba586336
Factor the JuvixCore -> JuvixAsm translation into JuvixCore -> JuvixTree -> JuvixAsm (#2581)
This PR:
* introduces the JuvixTree language which is like JuvixAsm except that
instead of the value stack there is an applicative structure,
* refactors the JuvixCore -> JuvixAsm translation into JuvixCore ->
JuvixTree -> JuvixAsm.

JuvixAsm is a bit too low level for efficient compilation to Nock.
Translating the value stack explicitly is a bad idea and it's
unnecessary, because the value stack just represents an applicative
structure which can be represented directly in Nock. It's possible, but
cumbersome and unnecessary, to recover the applicative structure from
JuvixAsm code. It's better to have a bit more high-level JuvixTree
language which still retains the explicit applicative structure.
2024-01-18 15:36:44 +01:00