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

Toggle reinterpreting modules to evaluate private top-level binds #319

Open
theGhostJW opened this issue Aug 30, 2024 · 4 comments
Open
Labels
linear Created by Linear-GitHub Sync

Comments

@theGhostJW
Copy link
Contributor

theGhostJW commented Aug 30, 2024

Describe the feature you’d like to be implemented

Currently if I have evals in place like this:

-- $> hello
hello :: IO ()
hello = T.putStrLn "Hello"

-- $> world
world :: IO ()
world = T.putStrLn "World"

and I kick off ghciwatch

ghciwatch \
  --log-filter info \
  --before-startup-shell 'hpack --force' \
  --restart-glob package.yaml \
  --command 'cabal repl --repl-no-load' \
  --watch src --watch test --watch examples --watch testIntegration \
  --allow-eval --clear --backtrace full

after making a change to the file i get this:

• examples/WebDriverDemo.hs:185:7: hello
[1 of 1] Compiling WebDriverDemo    ( examples/WebDriverDemo.hs, interpreted )
Ok, one module loaded.
Hello
• examples/WebDriverDemo.hs:189:7: world
[1 of 1] Compiling WebDriverDemo    ( examples/WebDriverDemo.hs, interpreted )
Ok, one module loaded.
World

It seems ghci is being reloaded once for prior to each evaluation even though only one change has been made to the file.

It would be great if ghciwatch only reloaded once so I got this (quicker and less noisy):

• examples/WebDriverDemo.hs:185:7: hello
[1 of 1] Compiling WebDriverDemo    ( examples/WebDriverDemo.hs, interpreted )
Ok, one module loaded.
Hello
World

List alternatives to the feature and their pros and cons

No response

Additional context

Current behaviour is slower and noisier than that requested. This is particularly true if you temporarily living with multiple warnings (such as undefined somewhere in code) in this part of the dev cycle.

@github-actions github-actions bot added the linear Created by Linear-GitHub Sync label Aug 30, 2024
@9999years
Copy link
Member

I think this might be unavoidable because interpreting the module is needed to access its top-level binds for the eval feature:

https://github.com/MercuryTechnologies/ghciwatch/blob/main/src/ghci/stdin.rs#L138-L168

Try some of these commands locally and let me know if you can find a way to get it to avoid recompiling the module though?

@theGhostJW
Copy link
Contributor Author

theGhostJW commented Sep 14, 2024

As far as running commands locally goes, this is definitely how ghcid works:

the following is a log from a project I am working on prior to switching to ghciwatch:

Note the warnings etc are logged once first then all the eval results:

ghcid --command 'cabal repl' pyrethrum --allow-eval --clear --no-height-limit '-o ghcid.log' 

Loading cabal repl pyrethrum ...
Warning: The package list for 'hackage.haskell.org' is 82 days old.
Run 'cabal update' to get the latest list of available packages.
Resolving dependencies...
Build profile: -w ghc-9.8.2 -O0
In order, the following will be built (use -v for more details):
 - pyrethrum-0.1.0.0 (interactive) (lib) (configuration changed)
Configuring library for pyrethrum-0.1.0.0...
Preprocessing library for pyrethrum-0.1.0.0...
GHCi, version 9.8.2: https://www.haskell.org/ghc/  :? for help
[ 1 of 36] Compiling ArbitraryIOTest  ( test/ArbitraryIOTest.hs, interpreted )
[ 2 of 36] Compiling AuxFiles         ( src/AuxFiles.hs, interpreted )

..... and many more

134 | mkFixture = \case
    | ^^^^^^^^^
examples/PyrethrumBase.hs:141:1-6: warning: [GHC-40910] [-Wunused-top-binds]
    Defined but not used: ‘mkHook’
    |
141 | mkHook = \case
    | ^^^^^^
examples/PyrethrumBase.hs:155:1-6: warning: [GHC-40910] [-Wunused-top-binds]
    Defined but not used: ‘mkNode’
    |
155 | mkNode = \case
    | ^^^^^^
examples/PyrethrumBase.hs:165:1-9: warning: [GHC-40910] [-Wunused-top-binds]
    Defined but not used: ‘mkTestRun’
    |
165 | mkTestRun tr = mkNode <$> tr
    | ^^^^^^^^^
examples/PyrethrumDemoTest.hs:6:17-19: warning: [GHC-38856] [-Wunused-imports]
    The import of ‘Out’ from module ‘DSL.Out’ is redundant
  |
6 | import DSL.Out (Out, out)
  |                 ^^^
examples/PyrethrumDemoTest.hs:7:24-27: warning: [GHC-38856] [-Wunused-imports]
    The import of ‘:>’ from module ‘Effectful’ is redundant
  |
7 | import Effectful (Eff, (:>))
  |                        ^^^^
test/SuiteRuntimePropTest.hs:(26,1)-(35,2): warning: [GHC-38856] [-Wunused-imports]
    The import of ‘Verbose, Verbose’
    from module ‘Test.Tasty.Falsify’ is redundant
   |
26 | import Test.Tasty.Falsify (
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^...

..... and many more
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:14:1
$> unit_simple_pass
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:18:1
$> unit_simple_fail
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:22:1
$> unit_nested_pass_fail
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:86:1
$> unit_nested_threaded_chk_thread_count
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:157:1
$> unit_empty_thread_hooks
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:188:1
$> unit_pass_prob_pregen
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:192:1
$> unit_pass_prob_no_pregen
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:209:1
$> unit_prop_test_fail_template_wrong_result
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:236:1
$> unit_prop_fail_each_after_out_of_order
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:254:1
$> unit_prop_fail_each_after_out_of_order1
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:272:1
$> unit_prop_fail_each_after
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:297:1
$> unit_missing_setup
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:311:1
$> unit_wrong_result
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:343:1
$> unit_fail_wrong_counts
unit_fail_wrong_counts
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:374:1
$> unit_missing_hooks
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:402:1
$> unit_wrong_failure_path
 
/home/theghostjw/pyrethrum/pyrethrum/test/SuiteRuntimeTest.hs:436:1
$> unit_once_failure_missing

example code is here: https://github.com/theGhostJW/pyrethrum/blob/ghcid-play/test/SuiteRuntimeTest.hs

This is just a branch of a reasonably big project. I can cut this down to a minimal example if that would be useful

@9999years
Copy link
Member

ghcid doesn't let you access unexported top-level bindings in eval comments, so it doesn't have to reinterpret the modules under inspection. Maybe I could have a toggle for this?

@theGhostJW
Copy link
Contributor Author

So if I understand you correctly you are saying that the behviour of ghcid comes with an extra limitation in that "private" functions are not able to be evaluated. Its not a limitation I've noticed before because I usually develop in fully open modules and then restrict the exports when the api of the module is bedded down. By that time I'm done with this type of stubbing anyway.

If this is the case I think a toggle would be awesome. Different users will prefer different behaviour at different stages.

@9999years 9999years changed the title Only reload once for multiple evals Toggle reinterpreting modules to evaluate private top-level binds Sep 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
linear Created by Linear-GitHub Sync
Projects
None yet
Development

No branches or pull requests

2 participants