Skip to content

Commit

Permalink
Merge pull request #373 from github/multi-component-repl
Browse files Browse the repository at this point in the history
Multi component repl
  • Loading branch information
robrix authored Nov 1, 2019
2 parents 1f796bd + 7683376 commit 2a13455
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 92 deletions.
31 changes: 0 additions & 31 deletions .ghci

This file was deleted.

31 changes: 31 additions & 0 deletions .ghci.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-- Consider copying this to your ~/.ghc/ghci.conf file:

-- Pretty-printing
:set -ignore-package pretty-simple -package pretty-simple
:def! pretty \ _ -> pure ":set -interactive-print Text.Pretty.Simple.pPrint"
:def! no-pretty \ _ -> pure ":set -interactive-print System.IO.print"
:def! r \_ -> pure ":reload\n:pretty"

-- Turn on some language extensions you use a lot
:seti -XFlexibleContexts -XOverloadedStrings -XTypeApplications

-- Break on errors
:seti -fbreak-on-error

-- Automatically show the code around breakpoints
:set stop :list

-- Use a cyan lambda as the prompt
:set prompt "\ESC[1;36m\STXλ \ESC[m\STX"

-- Better errors
:set -ferror-spans -freverse-errors -fprint-expanded-synonyms

-- Path-local ghci history
:set -flocal-ghci-history

-- Better typed holes
:set -funclutter-valid-hole-fits -fabstract-refinement-hole-fits -frefinement-level-hole-fits=2

-- Enable pretty-printing immediately
:pretty
70 changes: 70 additions & 0 deletions .ghci.semantic
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
-- GHCI settings for semantic, collected by running cabal repl -v and checking out the flags cabal passes to ghc.
-- These live here instead of script/repl for ease of commenting.
-- These live here instead of .ghci so cabal repl remains unaffected.

-- Basic verbosity
:set -v1

-- No optimizations
:set -O0

-- Compile to object code
:set -fwrite-interface -fobject-code

-- Write build products to dist-repl (so that we don’t clobber 'cabal build' outputs)
:set -outputdir dist-repl/build/x86_64-osx/ghc-8.6.5/semantic-0.8.0.0/build
:set -odir dist-repl/build/x86_64-osx/ghc-8.6.5/semantic-0.8.0.0/build
:set -hidir dist-repl/build/x86_64-osx/ghc-8.6.5/semantic-0.8.0.0/build
:set -stubdir dist-repl/build/x86_64-osx/ghc-8.6.5/semantic-0.8.0.0/build

-- Look for autogen’d files in dist-repl
:set -idist-repl/build/x86_64-osx/ghc-8.6.5/semantic-0.8.0.0/build/autogen

-- Load all our sources… remember to keep this up to date when we add new packages!
-- But don’t add semantic-source, it’s important that we get that from hackage.
:set -isemantic-analysis/src
:set -isemantic-ast/src
:set -isemantic-core/src
:set -isemantic-java/src
:set -isemantic-json/src
:set -isemantic-python/src
:set -isemantic-tags/src
:set -iapp
:set -isrc
:set -ibench
:set -itest

-- Default language mode & extensions
:set -XHaskell2010
:set -XStrictData

-- Warnings for compiling .hs files
:set -Weverything
:set -Wno-all-missed-specialisations
:set -Wno-implicit-prelude
:set -Wno-missed-specialisations
:set -Wno-missing-import-lists
:set -Wno-missing-local-signatures
:set -Wno-monomorphism-restriction
:set -Wno-name-shadowing
:set -Wno-safe
:set -Wno-unsafe
:set -Wno-star-is-type
-- Bonus: silence “add these modules to your .cabal file” warnings for files we :load
:set -Wno-missing-home-modules

-- Don’t fail on warnings when in the repl
:set -Wwarn

-- Warnings for code written in the repl
:seti -Weverything
:seti -Wno-all-missed-specialisations
:seti -Wno-implicit-prelude
:seti -Wno-missed-specialisations
:seti -Wno-missing-import-lists
:seti -Wno-missing-local-signatures
:seti -Wno-monomorphism-restriction
:seti -Wno-name-shadowing
:seti -Wno-safe
:seti -Wno-unsafe
:seti -Wno-star-is-type
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ profiles
cabal.project.local*
dist
dist-newstyle
dist-repl
.ghci
.ghc.environment.*
.ghci_history

Expand Down
82 changes: 21 additions & 61 deletions docs/💡ProTip!.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,27 @@ _Voilà!_ You’re now looking at the source code for the datatype generated fro

## GHCi

The Haskell interactive repl (GHCi) allows you to quickly typecheck your work and test out ideas interactively. It’s always worth having a repl open, but we’ve particularly tuned some workflows, e.g. semantic assignment development, for the repl.
The Haskell interactive repl (GHCi) allows you to quickly typecheck your work and test out ideas interactively. It’s always worth having a repl open, and we’ve particularly tuned some workflows for the repl.

[pretty-printing]: pretty-printing
Full docs for ghci can be found in the [user’s guide][ghci user’s guide].

[ghci user’s guide]: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html

### Configuration

We configure `ghci` with defaults & macros for use with `semantic` via the [`.ghci` file][] at the project root, and you can further customize its behaviour via the `~/.ghci` file.
### Multiple components

Full docs for ghci can be found in the [user’s guide][ghci user’s guide].
`semantic` consists of multiple packages and components, which makes it somewhat challenging to load into `ghci` using e.g. `cabal repl`. To help that, we provide [`script/repl`][] to automate working with multiple components & packages. Unlike when using `cabal repl`, after loading you will need to explicitly `:load` (at least some of) the sources you need to work with. For example, when working in the main `semantic` package, almost everything can be loaded with `:load Semantic.CLI`, since the `Semantic.CLI` module ultimately depends on just about everything else in the repo.

[ghci user’s guide]: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html
[`.ghci` file]: https://github.com/github/semantic/blob/master/.ghci
This script is also set up to store intermediate build products in a separate `dist-repl` dir to avoid colliding with normal builds.

[`script/repl`]: https://github.com/github/semantic/blob/master/script/repl


### Configuration

`ghci` can be configured with scripts containing Haskell statements and repl commands. By default, the `~/.ghc/ghci.conf` file will be loaded, as well as a `.ghci` file in the working directory, if any. We don’t currently provide such for use with `semantic`, but we do provide a [`.ghci.sample`][] file which we suggest copying to `~/.ghc/ghci.conf` for better typed holes, pretty-printing via `pretty-simple`, and a simple prompt.

[`.ghci.sample`]: https://github.com/github/semantic/blob/master/.ghci.sample


### Managing history
Expand All @@ -178,9 +186,9 @@ maxHistorySize: Nothing

### Pretty-printing

By default, GHCi prints the results of expressions using their `Show` instances, which can be particularly difficult to read for large recursive structures like `Term`s and `Diff`s. The project’s [`.ghci` file][] provides `:pretty` & `:no-pretty` macros which respectively enable & disable colourized, pretty-printed formatting of result values instead. These macros depend on the the `pretty-show` & `hscolour` packages.
By default, GHCi prints the results of expressions using their `Show` instances, which can be particularly difficult to read for large recursive structures like `Term`s and `Diff`s. The project’s [`.ghci.sample`][] file provides `:pretty` & `:no-pretty` macros which respectively enable & disable colourized, pretty-printed formatting of result values instead. These macros depend on the the `pretty-simple` package.

Since `:reload`ing resets local bindings, the [`.ghci` file][] also provides a convenient `:r` macro which reloads and then immediately re-enables `:pretty`.
Since `:reload`ing resets local bindings, the file also provides a convenient `:r` macro which reloads and then immediately re-enables `:pretty`.

You can use `:pretty` & `:no-pretty` like so:

Expand All @@ -203,60 +211,12 @@ You can use `:pretty` & `:no-pretty` like so:
```


### Working in Assignment

When working in assignment, some setup is required. This macro automates that by automatically importing the necessary modules and outputs an example command. If you provide the language you are working with as an optional parameter, the example command is formatted for that language's specific needs (parser, example file extension, etc.).

The macro is defined as:

```
:{
assignmentExample lang = case lang of
"Python" -> mk "py" "python"
"Go" -> mk "go" "go"
"Ruby" -> mk "rb" "ruby"
"JavaScript" -> mk "js" "typescript"
"TypeScript" -> mk "ts" "typescript"
"Haskell" -> mk "hs" "haskell"
"Markdown" -> mk "md" "markdown"
"JSON" -> mk "json" "json"
_ -> mk "" ""
where mk fileExtension parser = putStrLn ("example: fmap (() <$) . runTask . parse " ++ parser ++ "Parser =<< Semantic.Util.blob \"example." ++ fileExtension ++ "\"") >> return ("import Parsing.Parser\nimport Semantic.Task\nimport Semantic.Util")
:}
:def assignment assignmentExample
```

And is invoked in GHCi like:

```
λ :assignment Python
```

The output produces a one line expression assuming the syntax to assign is in a file named `example` with the relevant programming language extension:

```haskell
quieterm <$> parseFile pythonParser "example.py"
```


### Inspecting TreeSitter ASTs

Inspecting the parse tree from TreeSitter can be helpful for debugging. In GHCi, the command below allows viewing the TreeSitter production name of each node in the TreeSitter AST:

```haskell
import TreeSitter.Java
fmap nodeSymbol <$> parseFile javaASTParser "example.java"
```


### Using Threadscope
## Using Threadscope

Threadscope is a tool for profiling the multi-threaded performance of Haskell programs. It allows us to see how work is shared across processors and identify performance issues related to garbage collection or bottlenecks in our processes.

To install threadscope:

1. Download a prebuilt binary from https://github.com/haskell/ThreadScope/releases .
2. `chmod a+x` the result of extracting the release.
3. `brew install gtk+ gtk-mac-integration`.
4. profit.
1. Download a prebuilt binary from https://github.com/haskell/ThreadScope/releases
2. `chmod a+x` the result of extracting the release
3. `brew install gtk+ gtk-mac-integration`
15 changes: 15 additions & 0 deletions script/repl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
# Usage: script/repl [ARGS...]
# Run a repl session capable of loading all of the packages and their individual components. Any passed arguments, e.g. module names or flags, will be passed to ghci.

set -e

cd $(dirname "$0")/..

repl_builddir=dist-repl

if [[ ! -d $repl_builddir ]]; then
echo "$repl_builddir does not exist, first run 'cabal repl --builddir=$repl_builddir', exit, and then re-run $0"
else
cabal exec --builddir=$repl_builddir ghci -- -ghci-script=.ghci.semantic $@
fi

0 comments on commit 2a13455

Please sign in to comment.