Skip to content

Commit 2c68e66

Browse files
committed
new function named manual to ease haskell core support
1 parent 7e8148a commit 2c68e66

3 files changed

Lines changed: 103 additions & 23 deletions

File tree

CHANGES

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
// release history with features and fixed and open bugs
22

3+
new features implemented in master branch but not part of the latest release
4+
* new language: haskell core (write high level haskell and see the core ast)
5+
36
0.4.1
47
* distinguish between source positions and spans
58

69
0.4
710
* allowed jumping from text location to corresponding tree (and back)
811
* removed dependency on glade, now using gtk3
12+
* manual parser selection in language menu
913

1014
0.3
1115
* removed dynamical extension of languages. The library (see astview.cabal) offers

src/core/Language/Astview/DataTree.hs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module Language.Astview.DataTree
88
,dataToAst
99
,dataToAstSimpl
1010
,removeSubtrees
11+
,manual
1112
) where
1213

1314
import Data.Generics (Data
@@ -20,10 +21,30 @@ import Data.Tree (Tree(..))
2021
import Data.Maybe(isNothing,isJust)
2122
import Language.Astview.Language
2223

23-
dataToAst :: (Data t) => (forall span.Data span => span -> Maybe SrcSpan)
24-
-> (forall st . Typeable st => st -> Bool)
25-
-> t -> Ast
26-
dataToAst getSrcLoc pIgnore = Ast . annotateWithPaths . delegateSrcLoc . removeSubtrees isEmpty . removeNothings . worker where
24+
-- |uses the tree builder to get a tree and then runs the usual update and
25+
-- path annotation functions.
26+
--
27+
-- 'manual' is a more flexible version of 'dataToAst', but in most cases
28+
-- 'dataToAst' is the function of choice.
29+
-- Use 'manual' only if the tree builder function has to differ from the default
30+
-- defined in 'dataToAst' (see 'Language.Astview.Languages.HaskellCore' for an
31+
-- example).
32+
manual :: (t -> Tree (Maybe AstNode)) -- ^tree builder
33+
-> t
34+
-> Ast
35+
manual f =
36+
Ast . annotateWithPaths . delegateSrcLoc . removeSubtrees isEmpty . removeNothings . f
37+
38+
-- |creates an 'Ast' from the input term by using the constructor names
39+
-- of node labels and keeping the structure. We try to associate source
40+
-- locations to nodes by applying the source location selector at every subtree.
41+
-- We ignore a whole subtree if the filter predicate holds (useful if meta Data
42+
-- like source locations should not be visible in the 'Ast').
43+
dataToAst :: (Data t)
44+
=> (forall span.Data span => span -> Maybe SrcSpan) -- ^ source location selector
45+
-> (forall st. Typeable st => st -> Bool) -- ^ filter predicate
46+
-> t -> Ast
47+
dataToAst getSrcLoc pIgnore t = manual worker t where
2748

2849
worker :: (Data t,Typeable t) => t -> Tree (Maybe AstNode)
2950
worker term | pIgnore term = Node Nothing []
@@ -44,9 +65,10 @@ dataToAst getSrcLoc pIgnore = Ast . annotateWithPaths . delegateSrcLoc . removeS
4465
-- annotations) from the ast. Just give one example value of the annotation
4566
-- type to this function and all values of this type are being discarded from
4667
-- the ast.
47-
dataToAstIgnoreByExample :: (Data t,Typeable t,Typeable b,Data b)
48-
=> (forall a . (Data a,Typeable a) => a -> Maybe SrcSpan)
49-
-> b -> t -> Ast
68+
dataToAstIgnoreByExample :: (Data t,Typeable t,Typeable ig,Data ig)
69+
=> (forall a . (Data a,Typeable a) => a -> Maybe SrcSpan) -- ^ source location selector
70+
-> ig -- ^all values of this type will be missing in 'Ast'
71+
-> t -> Ast
5072
dataToAstIgnoreByExample getLoc igExample = dataToAst getLoc ignore where
5173
ignore t = equalTypes t igExample
5274

@@ -57,7 +79,9 @@ dataToAstSimpl = dataToAst (const Nothing) (const False)
5779

5880
-- * helper functions
5981

60-
-- |every node will be annotated with its path.
82+
-- |Every node will be annotated with its path, beginning with @[0]@ for root
83+
-- node. Don't manually annotate paths during creation of 'Ast's, instead
84+
-- use a default (e.g. @[]@) and add paths by 'annotateWithPaths' afterwards.
6185
annotateWithPaths :: Tree AstNode -> Tree AstNode
6286
annotateWithPaths = f [0] where
6387
f :: [Int] -> Tree AstNode -> Tree AstNode
Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
module Language.Astview.Languages.HaskellCore (haskellCore) where
22
import Prelude hiding (span)
3-
import Data.Generics (Data,extQ)
3+
4+
import Data.Tree(Tree(Node))
5+
import Data.Generics (Data,Typeable,extQ,ext1Q,gmapQ,showConstr,toConstr,typeOf)
46
import Data.Generics.Zipper(toZipper,down',query)
57

68
import Language.Astview.Language hiding (parse)
7-
import Language.Astview.DataTree (dataToAstIgnoreByExample)
9+
import Language.Astview.DataTree (manual)
810

911
import Parser
1012
import Lexer hiding (getDynFlags, getSrcLoc, buffer)
1113
import qualified DynFlags as GHC
1214
import Outputable
13-
import qualified SrcLoc
1415
import FastString
1516
import StringBuffer
1617
import qualified GHC
18+
import qualified SrcLoc as GHC
19+
import qualified Outputable as GHC
20+
import qualified RdrName as GHC
21+
import qualified OccName as GHC
1722

1823
import GHC.Paths (libdir)
1924

@@ -25,34 +30,33 @@ haskellCore = Language "HaskellCore" "Haskell" [".hs"] parsehs
2530
parsehs :: String -> Either Error Ast
2631
parsehs s =
2732
case runParser s parseModule of
28-
POk _ parsed -> Right (dataToAstIgnoreByExample getSrcLoc (undefined :: SrcSpan) parsed)
33+
POk _ parsed -> Right (coreToAst parsed)
2934
PFailed ss msg -> Left $ makeError ss (showSDocUnsafe msg)
3035

31-
makeError :: SrcLoc.SrcSpan -> String -> Error
36+
makeError :: GHC.SrcSpan -> String -> Error
3237
makeError ss s =
3338
case ss of
34-
SrcLoc.RealSrcSpan real -> ErrLocation (ghcss2ss real) s
39+
GHC.RealSrcSpan real -> ErrLocation (ghcss2ss real) s
3540
_ -> ErrMessage s
3641

3742

38-
ghcss2ss :: SrcLoc.RealSrcSpan -> SrcSpan
43+
ghcss2ss :: GHC.RealSrcSpan -> SrcSpan
3944
ghcss2ss real
40-
= let start = SrcLoc.realSrcSpanStart real
41-
end = SrcLoc.realSrcSpanEnd real
42-
in span (SrcLoc.srcLocLine start)
43-
(SrcLoc.srcLocCol start)
44-
(SrcLoc.srcLocLine end)
45-
(SrcLoc.srcLocCol end)
45+
= let start = GHC.realSrcSpanStart real
46+
end = GHC.realSrcSpanEnd real
47+
in span (GHC.srcLocLine start)
48+
(GHC.srcLocCol start)
49+
(GHC.srcLocLine end)
50+
(GHC.srcLocCol end)
4651

4752
runParser :: String -> P a -> ParseResult a
4853
runParser str parser = unP parser parseState
4954
where
5055
filename = "<interactive>"
51-
location = SrcLoc.mkRealSrcLoc (mkFastString filename) 1 1
56+
location = GHC.mkRealSrcLoc (mkFastString filename) 1 1
5257
buffer = stringToStringBuffer str
5358
parseState = mkPState (unsafePerformIO getDynFlags) buffer location
5459

55-
5660
getDynFlags :: IO GHC.DynFlags
5761
getDynFlags =
5862
GHC.defaultErrorHandler GHC.defaultFatalMessager GHC.defaultFlushOut $
@@ -67,3 +71,51 @@ getSrcLoc t = down' (toZipper t) >>= query (def `extQ` atSpan) where
6771
atSpan :: GHC.SrcSpan -> Maybe SrcSpan
6872
atSpan (GHC.RealSrcSpan ss) = Just $ ghcss2ss ss
6973
atSpan _ = Nothing
74+
75+
-- * typed ast to untyped ast
76+
77+
coreToAst :: (Data t,Typeable t) => t -> Ast
78+
coreToAst = manual worker where
79+
worker :: (Data t,Typeable t) => t -> Tree (Maybe AstNode)
80+
worker term
81+
| term `equalTypes` (undefined :: GHC.SrcSpan) = Node Nothing []
82+
| otherwise = (gdefault `ext1Q` atL `extQ` atRdrName `extQ` atOccName `extQ` atString) term where
83+
84+
atString :: String -> Tree (Maybe AstNode)
85+
atString s = Node (Just $ AstNode s Nothing [] Identificator) []
86+
87+
atRdrName :: GHC.RdrName -> Tree (Maybe AstNode)
88+
atRdrName rdr = Node (Just $ AstNode (rdrName2String rdr) (getSrcLoc rdr) [] Identificator) []
89+
90+
atOccName :: GHC.OccName -> Tree (Maybe AstNode)
91+
atOccName o = Node (Just $ AstNode (GHC.occNameString o) (getSrcLoc o) [] Identificator) []
92+
93+
atL :: (Typeable t, Data t) => GHC.GenLocated GHC.SrcSpan t -> Tree (Maybe AstNode)
94+
atL (GHC.L _ a) = worker a
95+
96+
gdefault :: (Typeable t,Data t) => t -> Tree (Maybe AstNode)
97+
gdefault x = Node (Just n) cs where
98+
99+
n :: AstNode
100+
n = AstNode (showConstr $ toConstr x) (getSrcLoc x) [] Operation
101+
102+
cs = gmapQ worker x
103+
104+
rdrName2String :: GHC.RdrName -> String
105+
rdrName2String r =
106+
case GHC.isExact_maybe r of
107+
Just n -> showGhc n
108+
Nothing ->
109+
case r of
110+
GHC.Unqual _occ -> GHC.occNameString $ GHC.rdrNameOcc r
111+
GHC.Qual modname _occ -> GHC.moduleNameString modname ++ "."
112+
++ GHC.occNameString (GHC.rdrNameOcc r)
113+
GHC.Orig _ _ -> error "GHC.Orig introduced after renaming"
114+
GHC.Exact _ -> error "GHC.Exact introduced after renaming"
115+
116+
showGhc :: (GHC.Outputable a) => a -> String
117+
showGhc = GHC.showPpr GHC.unsafeGlobalDynFlags
118+
119+
-- |returns whether both values are of the same type
120+
equalTypes :: (Typeable b1,Typeable b2) => b1 -> b2 -> Bool
121+
equalTypes t1 t2 = typeOf t1 == typeOf t2

0 commit comments

Comments
 (0)