1
1
mirror of https://github.com/anoma/juvix.git synced 2024-12-15 10:03:22 +03:00
Commit Graph

106 Commits

Author SHA1 Message Date
Paul Cadman
7a9b21a4f8
External package dependencies (#2272)
This PR adds external git dependency support to the Juvix package
format.

## New dependency Git item

You can now add a `git` block to the dependencies list:

```yaml
name: HelloWorld
main: HelloWorld.juvix
dependencies:
  - .juvix-build/stdlib
  - git:
      url: https://my.git.repo
      name: myGitRepo
      ref: main
version: 0.1.0
```

Git block required fields:
* `url`: The URL of the git repository
* `ref`: The git reference that should be checked out
* `name`: The name for the dependency. This is used to name the
directory of the clone, it is required. Perhaps we could come up with a
way to automatically name the clone directory. Current ideas are to
somehow encode the URL / ref combination or use a UUID. However there's
some value in having the clone directory named in a friendly way.

NB:
* The values of the `name` fields must be unique among the git blocks in
the dependencies list.

## Behaviour

When dependencies for a package are registered, at the beginning of the
compiler pipeline, all remote dependencies are processed:

1. If it doesn't already exist, the remote dependency is cloned to
`.juvix-build/deps/$name`
2. `git fetch` is run in the clone
3. `git checkout` at the specified `ref` is run in the clone

The clone is then processed by the PathResolver in the same way as path
dependencies.

NB:
* Remote dependencies of transitive dependencies are also processed.
* The `git fetch` step is required for the case where the remote is
updated. In this case we want the user to be able to update the `ref`
field.

## Errors

1. Missing fields in the Git dependency block are YAML parse errors
2. Duplicate `name` values in the dependencies list is an error thrown
when the package file is processed
3. The `ref` doesn't exist in the clone or the clone directory is
otherwise corrupt. An error with a suggestion to `juvix clean` is given.
The package file path is used as the location in the error message.
4. Other `git` command errors (command not found, etc.), a more verbose
error is given with the arguments that were passed to the git command.

## Future work

1. Add an offline mode
2. Add a lock file mechanism that resolves branch/tag git refs to commit
hashes

* closes https://github.com/anoma/juvix/issues/2083

---------

Co-authored-by: Jan Mas Rovira <janmasrovira@gmail.com>
2023-09-01 12:37:06 +01:00
Jan Mas Rovira
34719bbc4d
Report termination errors after typechecking (#2318)
- Closes #2293.
- Closes #2319 

I've added an effect for termination. It keeps track of which functions
failed the termination checker, which is run just after translating to
Internal. During typechecking, non-terminating functions are not
normalized. After typechecking, if there is at least one function which
failed the termination checker, an error is reported.
Additionally, we now properly check for termination of functions defined
in a let expression in the repl.
2023-08-30 16:38:59 +02:00
Jan Mas Rovira
491f7f7508
Update ci to use ormolu 0.5.3.0 and reformat project (#2313)
Updates ormolu to 0.5.3.0 and formats the project
2023-08-25 17:37:23 +01:00
Jan Mas Rovira
ef16b45ca6
Aliasing (#2301)
- Closes #2188.

This pr introduces a new syntactical statement for defining aliases:
```
syntax alias newName := oldName;
```
where `oldName` can be any name in the expression namespace. Fixity and
module aliases are not supported at the moment.

- The `newName` does not inherit the fixity of `oldName`. We have agreed
that the goal is to inherit the fixity of `oldName` except if `newName`
has a fixity statement, but this will be done in a separate pr as it
requires #2310.
2023-08-25 15:28:58 +02:00
Łukasz Czajka
2baad15a41 Remove old function syntax (#2305)
* Enables new function syntax in local let-declarations
* Closes #2251
2023-08-24 16:24:47 +02:00
Łukasz Czajka
8095e52c21
Check for incomparable precedences (#2289)
Give an error when there are two operators with incomparable precedences
instead of linearising the ordering arbitrarily.
2023-08-16 16:33:29 +02:00
Łukasz Czajka
eebe961321
User-friendly operator declaration syntax (#2270)
* Closes #1964 

Adds the possibility to define operator fixities. They live in a
separate namespace. Standard library defines a few in
`Stdlib.Data.Fixity`:
```

syntax fixity rapp {arity: binary, assoc: right};
syntax fixity lapp {arity: binary, assoc: left, same: rapp};
syntax fixity seq {arity: binary, assoc: left, above: [lapp]};

syntax fixity functor {arity: binary, assoc: right};

syntax fixity logical {arity: binary, assoc: right, above: [seq]};
syntax fixity comparison {arity: binary, assoc: none, above: [logical]};

syntax fixity pair {arity: binary, assoc: right};
syntax fixity cons {arity: binary, assoc: right, above: [pair]};

syntax fixity step {arity: binary, assoc: right};
syntax fixity range {arity: binary, assoc: right, above: [step]};

syntax fixity additive {arity: binary, assoc: left, above: [comparison, range, cons]};
syntax fixity multiplicative {arity: binary, assoc: left, above: [additive]};

syntax fixity composition {arity: binary, assoc: right, above: [multiplicative]};
```

The fixities are identifiers in a separate namespace (different from
symbol and module namespaces). They can be exported/imported and then
used in operator declarations:
```
import Stdlib.Data.Fixity open;

syntax operator && logical;
syntax operator || logical;
syntax operator + additive;
syntax operator * multiplicative;
```
2023-08-09 18:15:51 +02:00
Jan Mas Rovira
98b3621ae1
Record patterns (#2271)
- Closes #2269 

Example:
```
type Sum (A B : Type) :=
  | inj1 {
      fst : A;
      snd : B
    }
  | inj2 {
      fst : A;
      snd2 : B
    };

sumSwap {A B : Type} : Sum A B -> Sum B A
  | inj1@{fst; snd := y} := inj2 y fst
  | inj2@{snd2 := y; fst := fst} := inj1 y fst;
```
2023-08-08 16:01:20 +02:00
Jan Mas Rovira
f7382caeac
Record updates (#2263)
- Closes #1642.

This pr introduces syntax for convenient record updates.
Example:
```
type Triple (A B C : Type) :=
  | mkTriple {
      fst : A;
      snd : B;
      thd : C;
    };

main : Triple Nat Nat Nat;
main :=
  let
    p : Triple Nat Nat Nat := mkTriple 2 2 2;
    p' :
      Triple Nat Nat Nat :=
        p @Triple{
          fst := fst + 1;
          snd := snd * 3
        };
    f : Triple Nat Nat Nat -> Triple Nat Nat Nat := (@Triple{fst := fst * 10});
  in f p';
```
We write `@InductiveType{..}` to update the contents of a record. The
`@` is used for parsing. The `InductiveType` symbol indicates the type
of the record update. Inside the braces we have a list of `fieldName :=
newValue` items separated by semicolon. The `fieldName` is bound in
`newValue` with the old value of the field. Thus, we can write something
like `p @Triple{fst := fst + 1;}`.

Record updates `X@{..}` are parsed as postfix operators with higher
priority than application, so `f x y @X{q := 1}` is equivalent to `f x
(y @X{q := 1})`.

It is possible the use a record update with no argument by wrapping the
update in parentheses. See `f` in the above example.
2023-08-07 12:35:36 +02:00
Jan Mas Rovira
f38123c550
Adt syntax (#2262)
- merge #2260  first

Allows constructors to be defined using Haskell-like Adt syntax.
E.g.
```
module Adt;

type Bool :=
  | true
  | false;

type Pair (A B : Type) :=
  | mkPair A B;

type Nat :=
  | zero
  | suc Nat;
```

---------

Co-authored-by: Paul Cadman <git@paulcadman.dev>
2023-08-01 13:39:43 +01:00
Jan Mas Rovira
65b000999d
Separate modules namespace (#2257) 2023-07-26 09:59:50 +02:00
Jan Mas Rovira
2d666fd82c
Named arguments (#2250)
- closes #1991 

This pr implements named arguments as described in #1991. It does not
yet implement optional arguments, which should be added in a later pr as
they are not required for record syntax.

# Syntax Overview

Named arguments are a convenient mehcanism to provide arguments, where
we give the arguments by name instead of by position. Anything with a
type signature can have named arguments, i.e. functions, types,
constructors and axioms.

For instance, if we have (note that named arguments can also appear on
the rhs of the `:`):
```
fun : {A B : Type} (f : A -> B) : (x : A) -> B := ... ;
```
With the traditional positional application, we would write
```
fun suc zero
```
With named arguments we can write the following:
1. `fun (f := suc) (x := zero)`.
2. We can change the order: `fun (x := zero) (f := suc)`.
3. We can group the arguments: `fun (x := zero; f := suc)`.
4. We can partially apply functions with named arguments: `fun (f :=
suc) zero`.
5. We can provide implicit arguments analogously (with braces): `fun {A
:= Nat; B := Nat} (f := suc; x := zero)`.
6. We can skip implicit arguments: `fun {B := Nat} (f := suc; x :=
zero)`.

What we cannot do:
1. Skip explicit arguments. E.g. `fun (x := zero)`.
2. Mix explicit and implicit arguments in the same group. E.g. `fun (A
:= Nat; f := suc)`
3. Provide explicit and implicit arguments in different order. E.g. `fun
(f := suc; x := zero) {A := Nat}`.
2023-07-18 10:32:34 +01:00
Jan Mas Rovira
2c8a364143
New syntax for function definitions (#2243)
- Closes #2060
- Closes #2189


- This pr adds support for the syntax described in #2189. It does not
drop support for the old syntax.

It is possible to automatically translate juvix files to the new syntax
by using the formatter with the `--new-function-syntax` flag. E.g.

```
juvix format --in-place --new-function-syntax
```
# Syntax changes
Type signatures follow this pattern:
```
f (a1 : Expr) .. (an : Expr) : Expr
```
where each `ai` is a non-empty list of symbols. Braces are used instead
of parentheses when the argument is implicit.

Then, we have these variants:
1. Simple body. After the signature we have `:= Expr;`.
2. Clauses. The function signature is followed by a non-empty sequence
of clauses. Each clause has the form:
```
| atomPat .. atomPat := Expr
```
# Mutual recursion
Now identifiers **do not need to be defined before they are used**,
making it possible to define mutually recursive functions/types without
any special syntax.
There are some exceptions to this. We cannot forward reference a symbol
`f` in some statement `s` if between `s` and the definition of `f` there
is one of the following statements:
1. Local module
2. Import statement
3. Open statement

I think it should be possible to drop the restriction for local modules
and import statements
2023-07-10 19:57:55 +02:00
Jan Mas Rovira
d69d8c6eca
Remove abstract (#2219)
- Closes #2002 
- Closes #1690 
- Closes #2224
- Closes #2237
2023-06-30 15:01:46 +02:00
Jan Mas Rovira
f4aa70b13d
Finish the new pretty printing algorithm and delete the old one (#2151)
- Closes #2128 
- Closes #2161 

This pr fully implements the monadic pretty printer based on
`ExactPrint`, which respects comments. Until now, comments inside
expressions were printed after the current statement. Now they are
printed in the correct place, except when a comment occurs before
something that we don't store its location. E.g. parentheses,
semicolons, braces, colons, etc. I proposed that we irone out this issue
in a separate pr.

Since the old non-monadic algorithm is no longer necessary, I removed
it.
2023-06-02 13:02:35 +02:00
Łukasz Czajka
d08d8ce7eb
Add the format pragma (#2150)
* Closes #2117
2023-05-31 23:30:59 +02:00
Jan Mas Rovira
88c5dabb6d
Add Semigroup instance for AnsiText (#2140)
`AnsiText` is a type that represents some text that can be printed with
`Ansi` formatting annotations, or as plain text. It is expected that it
should have a `Semigroup` instance. This pr adds that.

---------

Co-authored-by: Paul Cadman <git@paulcadman.dev>
2023-05-31 08:53:08 +01:00
Łukasz Czajka
e9284b3ef6
Iterator syntax (#2126)
* Closes #1992 

A function identifier `fun` can be declared as an iterator with
```
syntax iterator fun;
```
For example:
```haskell
syntax iterator for;
for : {A B : Type} -> (A -> B -> A) -> A -> List B -> List A;
for f acc nil := acc;
for f acc (x :: xs) := for (f acc x) xs;
```
Iterator application syntax allows for a finite number of initializers
`acc := a` followed by a finite number of ranges `x in xs`. For example:
```
for (acc := 0) (x in lst) acc + x
```
The number of initializers plus the number of ranges must be non-zero.

An iterator application
```
fun (acc1 := a1; ..; accn := an) (x1 in b1; ..; xk in bk) body
```
gets desugared to
```
fun \{acc1 .. accn x1 .. xk := body} a1 .. an b1 .. bk
```
The `acc1`, ..., `accn`, `x1`, ..., `xk` can be patterns.

The desugaring works on a purely syntactic level. Without further
restrictions, it is not checked if the number of initializers/ranges
matches the type of the identifier. The restrictions on the number of
initializers/ranges can be specified in iterator declaration:
```
syntax iterator fun {init: n, range: k};
syntax iterator for {init: 1, range: 1};
syntax iterator map {init: 0, range: 1};
```
The attributes (`init`, `range`) in between braces are parsed as YAML to
avoid inventing and parsing a new attribute language. Both attributes
are optional.
2023-05-30 15:30:11 +02:00
Jan Mas Rovira
ab83749a86
Scope check symbols inside using {..} and hiding {..} (#2108)
- Closes #2089 

Now the symbols inside `using {..}` and `hiding {..}` are properly
scoped, which means that they will be properly colored and will have
goto information. If the referenced module does not contain a symbol in
the list, an error will be thrown.
2023-05-22 11:41:13 +02:00
Jan Mas Rovira
9b1011b8ad
Add syntax for Judoc blocks (#2102)
- Closes #2050 

This pr adds the possibility to give judoc documentation in blocks
delimited by `{--` and `--}`.
- Inside these blocks, normal comments are disabled.
- It is allowed to have multiple blocks associated with the same
identifier, e.g.
```
{-- an axiom --}
{-- of type ;Type; --}
axiom a : Type;
```
- Nested blocks are *not* allowed.
- Blocks can be empty: `{-- --}`.
- The formatter respects line breaks inside blocks.
- The formatter normalizes whitespace at both ends of the block to a
single whitespace.
2023-05-19 14:05:32 +02:00
Jan Mas Rovira
a164083b70
Modify open import syntax (#2098) 2023-05-17 11:08:48 +02:00
Jan Mas Rovira
b0c566f52d
Partial incremental highlighting (#2053) 2023-05-10 13:09:48 +02:00
Łukasz Czajka
c31e373c88
Add: pragma support (#1997)
* Closes #1965 
* Implements the `unroll` pragma to control the unrolling depth on a
per-function basis.
* Implements parsing of the `inline` pragma.

---------

Co-authored-by: janmasrovira <janmasrovira@gmail.com>
2023-04-26 15:26:13 +02:00
janmasrovira
15b29bca69
Qualified imports (#2004) 2023-04-14 17:37:23 +02:00
janmasrovira
5de0026d83
Add juvix global project under xdg directory and other improvements (#1963)
Co-authored-by: Paul Cadman <git@paulcadman.dev>
2023-04-13 11:27:39 +02:00
janmasrovira
90a7a5e7e0
Fix REPL state to include enough information to rerun the pipeline (#1911)
Previously we were:
* discarding the types table 
* discarding the name ids state
after processing an expression in the REPL.

For example evaluating:
```
let even : _; odd : _; odd zero := false; odd (suc n) := not (even n); even zero := true; even (suc n) := not (odd n) in even 10
```
would loop in the REPL.

We noticed that the `n` in `suc n` was being given type `Type` instead
of `Nat`. This was because the name id given to n was incorrect, the
REPL started using name ids from 0 again.

We fixed this issue by storing information, including the types table
and name ids state in the Artifacts data structure that is returned when
we run the pipeline for the first time. This information is then used
when we call functions to compile / type check REPL expressions.

---------

Co-authored-by: Paul Cadman <git@paulcadman.dev>
2023-03-30 13:39:27 +02:00
Łukasz Czajka
1eadbc4f81
Remove the old C backend (#1862)
* Depends on PR #1832 
* Closes #1799 
* Removes Backend.C.Translation.FromInternal
* Removes `foreign` and `compile` blocks
* Removes unused test files
* Removes the old C runtime
* Removes other dead code
2023-03-14 17:22:32 +01:00
janmasrovira
098c256da8
Allow shadowing local variables with let function definitions (#1847)
Co-authored-by: Paul Cadman <git@paulcadman.dev>
2023-02-22 10:26:54 +01:00
janmasrovira
764c6faa80
Improve comma formatting (#1842)
- Closes #1837
2023-02-14 15:27:11 +00:00
Łukasz Czajka
45aa415b71
Short syntax for sequences of function and datatype parameters (#1809) 2023-02-06 19:01:54 +01:00
janmasrovira
929a8658ac
Special syntax for case (#1800)
- Closes #1716

---------

Co-authored-by: Paul Cadman <git@paulcadman.dev>
2023-02-06 14:53:35 +01:00
janmasrovira
38622b28d1
Allow type signatures to have a body (#1785)
- Closes #1637.

A function type signature is now allowed to have a body. This is valid
for both top level and let definitions.
```
not : Bool -> Bool := λ {
 | true := false
 | false := true
};
```
2023-01-31 08:46:53 +00:00
janmasrovira
447f2f1dcf
Keep regular comments in html output (#1766)
- Fixes #1723 
- It refactors parsing/scoping so that the scoper does not need to read
files or parse any module. Instead, the parser takes care of parsing all
the imported modules transitively.
2023-01-27 13:24:28 +01:00
janmasrovira
88ab622353
Print comments when pretty printing concrete syntax (#1737) 2023-01-24 16:15:24 +01:00
Jonathan Cubides
807b3b1770
Update CI to install Smoke, Github actions, and Makefile fixes (#1735)
This PR adds some maintenance at different levels to the CI config, the
Make file, and formatting.

- Most of the actions used by the CI related to haskell, ormolu, hlint
and pre-commit have been updated because Github requires NodeJS 16. This
change removes all the old warnings related to nodeJs.
In the case of ormolu, the new version makes us format some files that
were not formatted before, similarly with hlint.
- The CI has been updated to use the latest version of the Smoke testing
framework, which introduced installation of the dependencies for Linux
(libicu66) and macOS (icu4c) in the CI. In the case of macOS, the CI
uses a binary for smoke. For Linux, we use stack to build smoke from the
source. The source here is in a fork of [the official Smoke
repo](https://github.com/SamirTalwar/smoke). Such includes some
features/changes that are not yet in the official repo.

- The Makefile runs the ormolu and hlint targets using as a path for the
binaries the environment variables ORMOLU and HLINT. Thus, export those
variables in your environment before running `make check,` `make format`
or `make hlint`. Otherwise, the Makefile will use the binaries provided
by `stack`.

Co-authored-by: Paul Cadman <git@paulcadman.dev>
2023-01-24 11:50:23 +01:00
janmasrovira
f7205915a5
Typecheck let expressions (#1712) 2023-01-17 09:41:07 +01:00
Jonathan Cubides
5b495681c6
Compiler output (#1705)
Add a global flag `--output-dir to specify where to put the compiler output.
2023-01-06 17:54:13 +01:00
Jonathan Cubides
d48e3bd16a
Allow optional pipe before the first constructor for inductive type declarations (#1699) 2023-01-05 11:28:54 +01:00
janmasrovira
af63c36574
Support basic dependencies (#1622) 2022-12-20 13:05:40 +01:00
Paul Cadman
a3b2aa6940
Add translation from Internal to Core (#1567) 2022-11-07 14:47:56 +01:00
Murray
5cea26ac7f
Improve As-Pattern parsing (#1603)
* Allow naming nullary constructors without using parentheses
* Negative test cases
2022-11-03 10:02:22 +01:00
Paul Cadman
9e7a8a98d4
Support go to definition for the standard library (#1592)
* Remove ParserParams

ParserParams is only used to record the root of the project, which is
used to prefix source file paths. However source file paths are always
absolute so this is not required.

* Add GetAbsPath to Files effect

The Files effect is not responsible for resolving a relative module
path into an absolute path on disk. This will allow us to resolve
relative module paths to alternative paths, for example to point to the
standard library on disk.

* Files effect getAbsPath returns paths within the registered standard
library

This means that the standard library can exist on disk at a different
location to the Juvix project.

A command line flag --stdlib-path can be specified to point to a
standard library, otherwise the embedded standard library is written to
disk at $PROJ_DIR/.juvix-build/stdlib and this is used instead.

* Recreate stdlib dir only when juvix version changes

* Add UpdateStdlib to the Files effect

* Add comment for stdlibOrFile

* Remove spurious import
2022-10-19 15:55:16 +01:00
janmasrovira
2062d3d8e5
Properly newline expressions in the pretty printer (#1581) 2022-10-18 17:38:31 +02:00
Paul Cadman
504b5ec799
Rename builtin natural to nat and boolean to bool (#1588) 2022-10-14 18:42:03 +02:00
Paul Cadman
be5e2b9f2a
Add builtin boolean (#1582)
builtin boolean
inductive MyBool {
  myTrue : Bool;
  myFalse : Bool;
};

The first constructor is mapped to primitive true and the second
constructor is mapped to primitive false.

This also adds compilation of builtin boolean in the legacy backend as
this was trivial to implement.
2022-10-13 14:03:49 +01:00
janmasrovira
60d4f0433a
Refactor CLI (#1527) 2022-09-14 16:16:15 +02:00
Łukasz Czajka
708a4032c6
Add an option to show name ids in errors (#1486) 2022-09-01 13:22:32 +02:00
janmasrovira
bcaf319b90
Add --stdin flag (#1459) 2022-08-19 16:57:07 +02:00
Jonathan Cubides
01a44e436d
Refactor (#1420)
* Big refactor in process

* remove unnecessary functions from the prelude

* remove comments
2022-08-03 13:20:40 +02:00
janmasrovira
a47ade818a
add name and version to juvix.yaml (#1422)
* add name and version to package.yaml

* allow empty juvix.yaml file
2022-07-29 13:35:48 +02:00