I try to visualize an existing Haskell code base with SourceGraph.
SourceGraph mycabal.cabal
But all I get are error messages like this:
Could not parse source file ./src/mysource.hs
SourceGraph: Could not find data file templates/default.html
Any hints what to do or where to look for documentation?
The only documentation I have found so far is this one: http://code.haskell.org/~ivanm/Sample_SourceGraph/SourceGraph/SourceGraph.html which unfortunately only consists of catchy images but with no hints how to produce them.
Regarding your immediate question, it seems like the best documentation here is the source: http://code.haskell.org/SourceGraph/
I tried it on a repository of my own, and ran into the parsing issue, too. This is haskell-src-exts failing to parse a module. The following patch shows the actual error:
--- Parsing.hs 2013-02-14 12:59:34.000000000 +0100
+++ ../SourceGraph-0.7.0.5-fixed/Parsing.hs 2014-04-08 20:49:54.000000000 +0200
## -64,7 +64,7 ##
parseFile :: FileContents -> Either FilePath Module
parseFile (p,f) = case (parseFileContentsWithMode mode f) of
(ParseOk hs) -> Right hs
- _ -> Left p
+ x -> Left $ p ++ ": " ++ show x
where
mode = defaultParseMode { parseFilename = p
, fixities = Nothing
It turns out that most of my failing modules failed because "MultiParamTypeClasses is not enabled". This is apparently haskell-src-exts being rightfully strict, while ghc is happy without the MultiParamTypeClasses extension: https://github.com/haskell-suite/haskell-src-exts/issues/29
So as a quick fix, try adding
{-# LANGUAGE MultiParamTypeClasses #-}
at the top of your failing modules.
Just ran into a similar issue, so I thought I'd document here what I did. I put my changes in a patch file.
https://gist.github.com/ivanperez-keera/b398ce71a22e8a4849f3
cabal sandbox init
cabal unpack SourceGraph
wget https://gist.githubusercontent.com/ivanperez-keera/b398ce71a22e8a4849f3/raw/bf26ffc45564934c0f175e7619ded8a299a9b7d5/verbose-sourcegraph.patch
cd SourceGraph-0.7.0.6/
patch -i ../verbose-sourcegraph.patch
cd ..
cabal install SourceGraph-0.7.0.6/
Most of the "errors" in my files where due to bang patterns and multi param type classes. There must be a better solution to make SourceGraph's parse mode default to the same as GHC.
Related
I'm trying to build my project and I'm running into a really strange problem. I got my friend to install Haskell with Chocolatey and when he goes to compile my project with cabal build and cabal run project he runs into the following error that I just don't have:
Expr.hs:103:1: error:
Type applications in patterns are not yet supported
|
103 | evalVal env val #(HInteger _) = return $ val
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I assumed that the cabal file would take care of dependencies but obviously not. A cursory search as well proves fruitless because I can't even find another instance of someone having the same error.
I'm not sure if the problem is due to him being on ghc 9.0.1 and cabal 3.4 and I'm on ghc 8.8.3 and cabal 3.2 or if it's due to different operating systems, his being Windows and I OSX.
My worry is that if I upgrade my ghc and cabal versions then I will run into this error and I'll have to reinstall everything which was messy and difficult the first time
It turns out that was a change in GHC 9.0: Whitespace-sensitive !, ~, #, and $
it's the second point there:
f # x = y
Before: value binding that binds both f and x to y using an as-pattern
After: infix function named (#)
To restore the old behavior, remove the leading and trailing whitespace around #, like so:
f#x = x
So if you change it to
evalVal env val#(HInteger _) = return $ val
it should work for both compilers
[Update: Turns out this was a GHC bug and it is now fixed, slated for the 8.6.4 release: https://ghc.haskell.org/trac/ghc/ticket/16104#comment:8 ]
I'm trying to port a core plugin to GHC 8.6.3, which was last working fine with GHC 8.4 series. Unfortunately, I'm running into issues. Wondering if pluging programming requirements have changed, or is this a regression in GHC itself. I boiled it down to the following example and would like some guidance on how to make this work:
I have the following in file TestPlugin.hs:
{-# LANGUAGE TemplateHaskell #-}
module TestPlugin (plugin) where
import GhcPlugins
import Data.Bits
plugin :: Plugin
plugin = defaultPlugin {installCoreToDos = install}
where install _ todos = return (test : todos)
test = CoreDoPluginPass "Test" check
check :: ModGuts -> CoreM ModGuts
check m = do mbN <- thNameToGhcName 'complement
case mbN of
Just _ -> liftIO $ putStrLn "Found complement!"
Nothing -> error "Failed to locate complement"
return m
And I have a very simple Test.hs file:
{-# OPTIONS_GHC -fplugin TestPlugin #-}
main :: IO ()
main = return ()
With GHC-8.4.2, I have:
$ ghc-8.4.2 --make -package ghc -c TestPlugin.hs
[1 of 1] Compiling TestPlugin ( TestPlugin.hs, TestPlugin.o )
$ ghc-8.4.2 -package ghc -c Test.hs
Found complement!
But with GHC 8.6.3, I get:
$ ghc-8.6.3 --make -package ghc -c TestPlugin.hs
[1 of 1] Compiling TestPlugin ( TestPlugin.hs, TestPlugin.o )
$ ghc-8.6.3 -package ghc -c Test.hs
ghc: panic! (the 'impossible' happened)
(GHC version 8.6.3 for x86_64-apple-darwin):
Failed to locate complement
The problem goes away if I change Test.hs to:
{-# OPTIONS_GHC -fplugin TestPlugin #-}
import Data.Bits -- Should not be required in the client code!
main :: IO ()
main = return ()
That is, if I explicitly import Data.Bits. But tis is quite undesirable, since Test.hs is client code and the users of the plugin have no reason to import all bunch of modules the plugin might need for its own purposes. (In practice, this would require clients to import a whole bunch of irrelevant modules; quite unworkable and not maintainable.)
I've found the following stack-overflow ticket, which seems to suffer from a similar problem: How to replicate the behaviour of 'name in a TH splice However, the answer suggested there is just not OK in this case (and perhaps wasn't really OK there either) since it would require unnecessary changes to client code in my case that is just not reasonable to expect. (Perhaps #JoachimBretner has an idea?) I've also filed this as a GHC ticket (https://ghc.haskell.org/trac/ghc/ticket/16104#ticket), but feedback from the stack-overflow community is greatly appreciated.
Should I be coding my plugin differently? Or is this a GHC regression?
Not a direct answer, but when I need to “hard-code” a name in a GHC plugin, I don’t use TH. Instead, I use findImportedModule and lookupOrig to look it up, e.g. as in
lookupJDITyCon :: TcPluginM Class
lookupJDITyCon = do
Found _ md <- findImportedModule jdiModule Nothing
jdiTcNm <- lookupOrig md (mkTcOcc "JustDoIt")
tcLookupClass jdiTcNm
where
jdiModule = mkModuleName "GHC.JustDoIt"
from the code of my ghc-justdoit plugin.
I use Template Haskell names when the user needs to mention names, e.g. in splices or annotations, that I want to pick up in the plugin. This is what I do in inspection-testing. I discuss this a bit in the appendix of the Inspection Testing paper.
If I have the following in my package.yaml file:
default-extensions:
- LambdaCase
I am able to compile my project which makes use of the LambdaCase syntax like this:
myFunction = \case
Nothing -> "empty"
Just x -> x
However, if the project is run with stack runghc, the LambdaCase extension is not respected.
My project has about 200 modules, so I would rather not have to add {-# LANGUAGE LambdaCase #-} to the top of every file.
Is there a way to enable a project-wide GHC extension with stack runghc analogously to the package-wide default-extensions property in package.yaml?
Yes, stack should probably have some better support for this -
see https://github.com/commercialhaskell/stack/issues/3338 .
I'd say the summary is that stack runghc came before stack ghci, it's ended up having a much simpler meaning that does not take cabal files into account at all. Not sure how to make things consistent and intuitive on the commandline without changing the meaning of runghc.
In that issue, I describe a hacky workaround. Copying it here:
Here's a workaround for now. Put the following in ~/.local/bin/stack-run-ghc.sh and make it user executable:
#/bin/sh
ghc $(echo "$*" | sed 's/--interactive//g')
This takes the arguments, removes --interactive, and calls ghc. With this, I can build stack using ghc via the following:
stack ghci --with-ghc stack-run-ghc.sh --ghci-options src/main/Main.hs
When parsing haskell source files that contain #define and #if, parseFileContentsWithMode gets confused and throws an error about the hash. I tried to include MagicHash and CPP in the extension list (extns, see below) but that didn't work. I can't really change the source files because there are a lot of them.
getModule extns filePath program = fromParseResult $ parseFileContentsWithMode mode program
where
bangPatternsExt = map parseExtension extns
mode = ParseMode filePath Haskell2010 bangPatternsExt False False
The parser failed at:
#if __GLASGOW_HASKELL__ >= 612
instance Lift ModName where
lift = lift . modString
Haskell-src-exts doesn't support CPP natively (there is no issue in the GitHub issue tracker for that, but an old one on trac at http://trac.haskell.org/haskell-src-exts/ticket/27).
You can look at solution or workarounds for haskell-src-exts parsing modules with CPP failing for workarounds (using cpphs).
There is also a package called hse-cpp (https://hackage.haskell.org/package/hse-cpp) that looks like it can run cpphs for you, but I haven't used it, and it doesn't seem to get updated a lot.
What's the best way to iterate over all the modules (files) in a given package? Concretely, suppose I have
an executable called "runThis"
a cabal package P with files F1.hs, F2.hs, ..., Fn.hs
Whats the easiest way to execute:
runThis F1.hs
runThis F2.hs
...
runThis Fn.hs
?
I thought I might try --with-compiler but that fails with
cabal: The program ghc version >=6.4 is required but the version of runThis
(The other option looks like tweaking the Setup.lhs -- but ideally I'd like to hijack the build process and use "runThis" instead of, say, ghc)
Thanks!
From Duncan Coutts' email:
Question: How to add the preprocessor? I have tried
main =
defaultMainWithHooks
simpleUserHooks{hookedPreProcessors=[("foo",transformation)]}
transformation :: BuildInfo -> LocalBuildInfo -> PreProcessor
That looks right. Here's how to complete it (example taken from the
Cabal haddock docs for the PreProcess module):
transformation _ _ =
PreProcessor {
platformIndependent = True,
runPreProcessor =
mkSimplePreProcessor $ \inFile outFile verbosity -> do
fail $ "transformation: " ++ inFile ++ " " ++ outFile
}
and it works fine:
runghc Setup.hs build
Preprocessing library foo-1.0...
Setup.hs: transformation: Abc.foo dist/build/Abc.hs
But under which circumstances will this function be called? Up to now
I have not succeeded in making cabal call this function.
It calls it when it goes and looks for the module Abc (ie Abc.hs
or .lhs), and since if does not find it, it'll check through the list of
preprocessors and go looking for the corresponding files, ie Abc.foo.