Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dhalli, an interactive REPL for Dhall #266

Merged
merged 11 commits into from
Feb 16, 2018

Conversation

ocharles
Copy link
Member

This commit introduces dhalli, a fairly minimal Dhall REPL that supports:

  • Evalution of Dhall expressions along with import resolution
  • Type inspection of abritrary expressions
  • Syntax highlighting and pretty printing for output
  • Persistent bindings with :let
  • One-expression lookup with an implicit "it" binding

This commit splits out the pretty printing logic from Dhall.Core into its own
module. Dhall.Core actually relies on some "internal" pretty printing functions,
so pretty printing has been moved to Dhall.Pretty.Internal - Dhall.Pretty
exposes the public facing interface.
This commit introduces dhalli, a fairly minimal Dhall REPL that supports:

* Evalution of Dhall expressions along with import resolution
* Type inspection of abritrary expressions
* Syntax highlighting and pretty printing for output
* Persistent bindings with :let
* One-expression lookup with an implicit "it" binding
@ocharles
Copy link
Member Author

I've based this on the semantic pretty printing branch, as I want syntax highlighting for output.

@Gabriella439
Copy link
Collaborator

@ocharles: Note that this still needs to resolve the merge conflicts from the original pretty-printing branch

@Gabriella439
Copy link
Collaborator

Now that the other branches are merged, could you merge master into this branch to reduce the diff?

dhalli/Main.hs Outdated


data Env = Env
{ envBindings :: StrictMap.Map Dhall.Text Binding
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dhall bindings should probably be an ordered association list (i.e. [(Text, Binding)]) like the Context. The reason order matters is so that x@n references to shadowed variables work correctly

In other words, something like this should work:

> :let x = True
> :let x = False
> x@1
Bool

True

The other reason you want to do this is to avoid bugs such as the following:

> :let x = 1
> :let y = x : Integer
> :let x = True

If you used a Map for that then the second x would override the first x and you would turn y from a well-typed to an ill-typed term.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you used a Map for that then the second x would override the first x and you would turn y from a well-typed to an ill-typed term.

That's not quite true, as expressions are normalized before putting them into the environment. So in this case, you'd add (x, 1), then (y, 1), then replace (x, True).

You're otherwise right though, so I'll make that change.

dhalli/Main.hs Outdated

return
( Dhall.normalize
( StrictMap.foldlWithKey'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more accurate way to do this and to correctly take into account variable shadowing and variable capture is to create a nested let expression from the previous bindings and normalize that.

dhalli/Main.hs Outdated
normalize loaded

t <-
typeCheck expr
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to type-check the expression before normalization, otherwise the expression can diverge

dhalli/Main.hs Outdated
( Expr.Annot ( Expr.Var ( Dhall.V varName 0 ) ) t )

addBinding _ =
error ":let should be of the form `:let x = y`"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want to use liftIO . fail instead of error. The issue with error is that it is not evaluation-safe:

error message `seq` () = error message
fail  message `seq` () = ()

dhall.cabal Outdated
@@ -147,6 +147,22 @@ Executable dhall
Other-Modules:
Paths_dhall

Executable dhalli
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps call this dhall-repl instead

dhalli/Main.hs Outdated


greeter :: MonadIO m => m ()
greeter =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would skip the greeter. I try to keep the tooling minimal and unintrusive

dhalli/Main.hs Outdated
=> Repline.Options m
options =
[ ( "type", dontCrash . typeOf )
, ( "let", dontCrash . addBinding )
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another useful option would be save:

> :save ./x = 1
> ./x
Integer

1

@ocharles
Copy link
Member Author

I've addressed all your suggestions except for :save. There's probably a lot of things that could be added, but I think we can work those out in a separate PR.

@Gabriella439
Copy link
Collaborator

Thanks! This looks amazing :)

@Gabriella439 Gabriella439 merged commit 7f29209 into dhall-lang:master Feb 16, 2018
@ocharles ocharles deleted the ollie/dhalli branch February 16, 2018 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants