1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
12 , Binop.Associativity(..)
13 , Binop.Precedence(..)
20import Control.Monad (foldM)
21import qualified Data.ByteString as B
22import qualified Data.List as List
24import qualified Data.Map as Map
25import qualified Data.Text as Text
26import qualified Data.Text.Encoding as Text
28import qualified AST.Canonical as Can
29import qualified AST.Module.Name as ModuleName
30import qualified AST.Utils.Binop as Binop
31import qualified Data.OneOrMore as OneOrMore
32import qualified Elm.Compiler.Module as Module
33import qualified Elm.Compiler.Type as Type
34import qualified Elm.Compiler.Type.Extract as Extract
35import qualified Elm.Name as N
36import qualified Json.Decode as D
37import qualified Json.Encode as E
38import Json.Encode ((==>))
39import qualified Reporting.Annotation as A
40import qualified Reporting.Error as Error
41import qualified Reporting.Error.Docs as E
42import qualified Reporting.Region as R
43import qualified Reporting.Result as Result
44import Parse.Primitives (Parser)
45import qualified Parse.Primitives as P
46import qualified Parse.Primitives.Symbol as Symbol
47import qualified Parse.Primitives.Variable as Var
48import qualified Parse.Primitives.Whitespace as W
59toDict :: [Module] -> Documentation
61 Map.fromList (map toPair modules)
65toPair :: Module -> (N.Name, Module)
66toPair modul@(Module name _ _ _ _ _) =
78 , _unions :: Map.Map N.Name Union
79 , _aliases :: Map.Map N.Name Alias
80 , _values :: Map.Map N.Name Value
81 , _binops :: Map.Map N.Name Binop
85type Comment = Text.Text
88data Alias = Alias Comment [N.Name] Type.Type
89data Union = Union Comment [N.Name] [(N.Name, [Type.Type])]
90data Value = Value Comment Type.Type
91data Binop = Binop Comment Type.Type Binop.Associativity Binop.Precedence
95-- JSON ENCODE / DECODE
98encode :: Module -> E.Value
99encode (Module name comment unions aliases values binops) =
101 [ "name" ==> Module.encode name
102 , "comment" ==> E.text comment
103 , "unions" ==> E.list encodeUnion (Map.toList unions)
104 , "aliases" ==> E.list encodeAlias (Map.toList aliases)
105 , "values" ==> E.list encodeValue (Map.toList values)
106 , "binops" ==> E.list encodeBinop (Map.toList binops)
110decoder :: D.Decoder Error Module
113 <$> D.field "name" Module.decoder
114 <*> D.field "comment" D.text
115 <*> D.field "unions" (dictDecoder union)
116 <*> D.field "aliases" (dictDecoder alias)
117 <*> D.field "values" (dictDecoder value)
118 <*> D.field "binops" (dictDecoder binop)
121dictDecoder :: D.Decoder Error a -> D.Decoder Error (Map.Map N.Name a)
122dictDecoder entryDecoder =
123 Map.fromList <$> D.list (named entryDecoder)
126named :: D.Decoder Error a -> D.Decoder Error (N.Name, a)
129 <$> D.field "name" D.text
142encodeUnion :: (N.Name, Union) -> E.Value
143encodeUnion (name, Union comment args cases) =
145 [ "name" ==> E.text name
146 , "comment" ==> E.text comment
147 , "args" ==> E.list E.text args
148 , "cases" ==> E.list encodeCase cases
152union :: D.Decoder Error Union
155 <$> D.field "comment" D.text
156 <*> D.field "args" (D.list D.text)
157 <*> D.field "cases" (D.list caseDecoder)
160encodeCase :: ( N.Name, [Type.Type] ) -> E.Value
161encodeCase ( tag, args ) =
162 E.list id [ E.text tag, E.list Type.encode args ]
165caseDecoder :: D.Decoder Error ( N.Name, [Type.Type] )
169 <*> D.index 1 (D.list typeDecoder)
176encodeAlias :: (N.Name, Alias) -> E.Value
177encodeAlias ( name, Alias comment args tipe) =
179 [ "name" ==> E.text name
180 , "comment" ==> E.text comment
181 , "args" ==> E.list E.text args
182 , "type" ==> Type.encode tipe
186alias :: D.Decoder Error Alias
189 <$> D.field "comment" D.text
190 <*> D.field "args" (D.list D.text)
191 <*> D.field "type" typeDecoder
198encodeValue :: (N.Name, Value) -> E.Value
199encodeValue (name, Value comment tipe) =
201 [ "name" ==> E.text name
202 , "comment" ==> E.text comment
203 , "type" ==> Type.encode tipe
207value :: D.Decoder Error Value
210 <$> D.field "comment" D.text
211 <*> D.field "type" typeDecoder
218encodeBinop :: (N.Name, Binop) -> E.Value
219encodeBinop (name, Binop comment tipe assoc prec) =
221 [ "name" ==> E.text name
222 , "comment" ==> E.text comment
223 , "type" ==> Type.encode tipe
224 , "associativity" ==> encodeAssoc assoc
225 , "precedence" ==> encodePrec prec
229binop :: D.Decoder Error Binop
232 <$> D.field "comment" D.text
233 <*> D.field "type" typeDecoder
234 <*> D.field "associativity" assocDecoder
235 <*> D.field "precedence" precDecoder
242encodeAssoc :: Binop.Associativity -> E.Value
245 Binop.Left -> E.text "left"
246 Binop.Non -> E.text "non"
247 Binop.Right -> E.text "right"
250assocDecoder :: D.Decoder Error Binop.Associativity
254 "left" -> D.succeed Binop.Left
255 "non" -> D.succeed Binop.Non
256 "right" -> D.succeed Binop.Right
257 _ -> D.fail BadAssociativity
264encodePrec :: Binop.Precedence -> E.Value
265encodePrec (Binop.Precedence n) =
269precDecoder :: D.Decoder Error Binop.Precedence
271 Binop.Precedence <$> D.int
278fromModule :: Can.Module -> Result.Result i w Error.Error Module
279fromModule (Can.Module name docs exports decls unions aliases binops effects) =
281 Can.ExportEverything ->
282 Result.throw $ Error.Docs $ E.ImplicitExposing
284 Can.Export exportDict ->
287 Result.throw $ Error.Docs $ E.NoDocs
289 Just (A.At region (Can.Docs overview comments)) ->
290 do names <- parseOverview region overview
291 Result.mapError Error.Docs $
292 do checkNames exportDict names
293 let types = gatherTypes decls Map.empty
295 (addExport (Info comments types unions aliases binops effects))
296 (emptyModule name overview)
297 (Map.toList exportDict)
300emptyModule :: ModuleName.Canonical -> B.ByteString -> Module
301emptyModule (ModuleName.Canonical _ name) overview =
302 Module name (Text.decodeUtf8 overview) Map.empty Map.empty Map.empty Map.empty
309type LName = A.Located N.Name
312parseOverview :: R.Region -> B.ByteString -> Result.Result i w Error.Error [LName]
313parseOverview (R.Region (R.Position row col) _) overview =
314 case P.runAt row (col + 3) (chompOverview []) overview of
316 Result.throw (Error.Syntax err)
322chompOverview :: [LName] -> Parser [LName]
324 do isDocs <- W.chompUntilDocs
326 then chompOverviewHelp names
330chompOverviewHelp :: [LName] -> Parser [LName]
331chompOverviewHelp names =
332 do pos <- P.getPosition
333 (W.SPos spos) <- W.whitespace
335 then chompOverview names
336 else chompOverview =<< chompDocs names
339chompDocs :: [LName] -> Parser [LName]
341 do name <- P.addLocation (P.oneOf [ Var.lower, Var.upper, chompBinop ])
344 [ do P.checkSpace spos
347 chompDocs (name:names)
348 , return (name:names)
352chompBinop :: Parser N.Name
365 Result.Result i w E.Error a
369 Map.Map N.Name (OneOrMore.OneOrMore R.Region)
372checkNames :: Map.Map N.Name (A.Located Can.Export) -> [LName] -> Result i w ()
373checkNames exports names =
374 do docs <- Map.traverseWithKey isUnique (List.foldl' addName Map.empty names)
375 let overlap = Map.size (Map.intersection docs exports)
376 if Map.size exports == overlap && overlap == Map.size docs
379 do _ <- Map.traverseWithKey onlyInDocs (Map.difference docs exports)
380 _ <- Map.traverseWithKey onlyInExports (Map.difference exports docs)
384addName :: Dups -> LName -> Dups
385addName dict (A.At region name) =
386 Map.insertWith OneOrMore.more name (OneOrMore.one region) dict
389isUnique :: N.Name -> OneOrMore.OneOrMore R.Region -> Result i w R.Region
390isUnique name regions =
392 OneOrMore.One region ->
395 OneOrMore.More _ _ ->
396 let (r1:r2:_) = OneOrMore.toList regions in
397 Result.throw (E.Duplicate name r1 r2)
400onlyInDocs :: N.Name -> R.Region -> Result i w a
401onlyInDocs name region =
402 Result.throw $ E.OnlyInDocs name region
405onlyInExports :: N.Name -> A.Located Can.Export -> Result i w a
406onlyInExports name (A.At region _) =
407 Result.throw $ E.OnlyInExports name region
416 { _iComments :: Map.Map N.Name Comment
418 , _iUnions :: Map.Map N.Name Can.Union
419 , _iAliases :: Map.Map N.Name Can.Alias
420 , _iBinops :: Map.Map N.Name Can.Binop
421 , _iEffects :: Can.Effects
425addExport :: Info -> Module -> (N.Name, A.Located Can.Export) -> Result i w Module
426addExport info (Module n c us as_ vs bs) (name, A.At region export) =
429 do tipe <- getType name info
430 comment <- getComment region name info
432 let newValues = Map.insert name (Value comment tipe) vs
433 Result.ok $ Module n c us as_ newValues bs
436 do let (Can.Binop_ assoc prec realName) = _iBinops info ! name
437 tipe <- getType realName info
438 comment <- getComment region realName info
440 let newBinops = Map.insert name (Binop comment tipe assoc prec) bs
441 Result.ok $ Module n c us as_ vs newBinops
444 do let (Can.Alias tvars tipe _) = _iAliases info ! name
445 comment <- getComment region name info
447 let newAliases = Map.insert name (Alias comment tvars (Extract.fromType tipe)) as_
448 Result.ok $ Module n c us newAliases vs bs
450 Can.ExportUnionOpen ->
451 do let (Can.Union tvars ctors _ _) = _iUnions info ! name
452 comment <- getComment region name info
454 let newUnions = Map.insert name (Union comment tvars (map dector ctors)) us
455 Result.ok $ Module n c newUnions as_ vs bs
457 Can.ExportUnionClosed ->
458 do let (Can.Union tvars _ _ _) = _iUnions info ! name
459 comment <- getComment region name info
461 let newUnions = Map.insert name (Union comment tvars []) us
462 Result.ok $ Module n c newUnions as_ vs bs
468getComment :: R.Region -> N.Name -> Info -> Result i w Comment
469getComment region name info =
470 case Map.lookup name (_iComments info) of
472 Result.throw (E.NoComment name region)
478getType :: N.Name -> Info -> Result i w Type.Type
480 case _iValues info ! name of
481 A.At defRegion Nothing ->
482 Result.throw (E.NoAnnotation name defRegion)
484 A.At _ (Just tipe) ->
485 Result.ok (Extract.fromType tipe)
488dector :: Can.Ctor -> (N.Name, [Type.Type])
489dector (Can.Ctor name _ _ args) =
490 ( name, map Extract.fromType args )
498 Map.Map N.Name (A.Located (Maybe Can.Type))
501gatherTypes :: Can.Decls -> Types -> Types
502gatherTypes decls types =
504 Can.Declare def subDecls ->
505 gatherTypes subDecls (addDef types def)
507 Can.DeclareRec defs subDecls ->
508 gatherTypes subDecls (List.foldl' addDef types defs)
510 Can.SaveTheEnvironment ->
514addDef :: Types -> Can.Def -> Types
517 Can.Def (A.At region name) _ _ ->
518 Map.insert name (A.At region Nothing) types
520 Can.TypedDef (A.At region name) _ typedArgs _ resultType ->
523 foldr Can.TLambda resultType (map snd typedArgs)
525 Map.insert name (A.At region (Just tipe)) types
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list