git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge pull request #1307 from hdgarrood/bundle-error-reporting
24eb832Phil Freeman
src/Language/PureScript/Bundle.hs+122−115
@@ -50,17 +50,17 @@ import qualified Paths_purescript as Paths
50data ErrorMessage
50data ErrorMessage
51 = UnsupportedModulePath String
51 = UnsupportedModulePath String
52 | InvalidTopLevel
52 | InvalidTopLevel
53− | UnableToParseModule
53+ | UnableToParseModule String
54 | UnsupportedExport
54 | UnsupportedExport
55− | ErrorInFile FilePath ErrorMessage
55+ | ErrorInModule ModuleIdentifier ErrorMessage
56 deriving Show
56 deriving Show
57
57
58−-- | Modules are either "regular modules" (i.e. those generated by psc-make) or foreign modules.
58+-- | Modules are either "regular modules" (i.e. those generated by psc) or foreign modules.
59−data ModuleType
59+data ModuleType
60− = Regular
60+ = Regular
61− | Foreign
61+ | Foreign
62 deriving (Show, Eq, Ord)
62 deriving (Show, Eq, Ord)
63−
63+
64-- | A module is identified by its module name and its type.
64-- | A module is identified by its module name and its type.
65data ModuleIdentifier = ModuleIdentifier String ModuleType deriving (Show, Eq, Ord)
65data ModuleIdentifier = ModuleIdentifier String ModuleType deriving (Show, Eq, Ord)
66
66
@@ -73,11 +73,11 @@ type Key = (ModuleIdentifier, String)
73
73
74-- | An export is either a "regular export", which exports a name from the regular module we are in,
74-- | An export is either a "regular export", which exports a name from the regular module we are in,
75-- or a reexport of a declaration in the corresponding foreign module.
75-- or a reexport of a declaration in the corresponding foreign module.
76−--
76+--
77−-- Regular exports are labelled, since they might re-export an operator with another name.
77+-- Regular exports are labelled, since they might re-export an operator with another name.
78−data ExportType
78+data ExportType
79− = RegularExport String
79+ = RegularExport String
80− | ForeignReexport
80+ | ForeignReexport
81 deriving (Show, Eq, Ord)
81 deriving (Show, Eq, Ord)
82
82
83-- | There are four types of module element we are interested in:
83-- | There are four types of module element we are interested in:
@@ -89,37 +89,42 @@ data ExportType
89--
89--
90-- Each is labelled with the original AST node which generated it, so that we can dump it back
90-- Each is labelled with the original AST node which generated it, so that we can dump it back
91-- into the output during codegen.
91-- into the output during codegen.
92−data ModuleElement
92+data ModuleElement
93 = Require JSNode String ModuleIdentifier
93 = Require JSNode String ModuleIdentifier
94 | Member JSNode Bool String [JSNode] [Key]
94 | Member JSNode Bool String [JSNode] [Key]
95 | ExportsList [(ExportType, String, JSNode, [Key])]
95 | ExportsList [(ExportType, String, JSNode, [Key])]
96 | Other JSNode
96 | Other JSNode
97 deriving Show
97 deriving Show
98
98
99−-- | A module is just a list of elements of the types listed above.
99+-- | A module is just a list of elements of the types listed above.
100data Module = Module ModuleIdentifier [ModuleElement] deriving Show
100data Module = Module ModuleIdentifier [ModuleElement] deriving Show
101−
101+
102-- | Prepare an error message for consumption by humans.
102-- | Prepare an error message for consumption by humans.
103printErrorMessage :: ErrorMessage -> [String]
103printErrorMessage :: ErrorMessage -> [String]
104printErrorMessage (UnsupportedModulePath s) =
104printErrorMessage (UnsupportedModulePath s) =
105 [ "A CommonJS module has an unsupported name (" ++ show s ++ ")."
105 [ "A CommonJS module has an unsupported name (" ++ show s ++ ")."
106 , "The following file names are supported:"
106 , "The following file names are supported:"
107− , " 1) index.js (psc-make native modules)"
107+ , " 1) index.js (psc native modules)"
108− , " 2) foreign.js (psc-make foreign modules)"
108+ , " 2) foreign.js (psc foreign modules)"
109 ]
109 ]
110printErrorMessage InvalidTopLevel =
110printErrorMessage InvalidTopLevel =
111− [ "Expected a list of source elements at the top level." ]
111+ [ "Expected a list of source elements at the top level." ]
112−printErrorMessage UnableToParseModule =
112+printErrorMessage (UnableToParseModule err) =
113− [ "The module could not be parsed." ]
113+ [ "The module could not be parsed:"
114+ , err
115+ ]
114printErrorMessage UnsupportedExport =
116printErrorMessage UnsupportedExport =
115 [ "An export was unsupported. Exports can be defined in one of two ways: "
117 [ "An export was unsupported. Exports can be defined in one of two ways: "
116 , " 1) exports.name = ..."
118 , " 1) exports.name = ..."
117 , " 2) exports = { ... }"
119 , " 2) exports = { ... }"
118 ]
120 ]
119−printErrorMessage (ErrorInFile filename e) =
121+printErrorMessage (ErrorInModule mid e) =
120− ("Error in file " ++ show filename ++ ":")
122+ ("Error in module " ++ displayIdentifier mid ++ ":")
121 : ""
123 : ""
122 : map (" " ++) (printErrorMessage e)
124 : map (" " ++) (printErrorMessage e)
125+ where
126+ displayIdentifier (ModuleIdentifier name ty) =
127+ name ++ " (" ++ show ty ++ ")"
123
128
124-- | Unpack the node inside a JSNode. This is useful when pattern matching.
129-- | Unpack the node inside a JSNode. This is useful when pattern matching.
125node :: JSNode -> Node
130node :: JSNode -> Node
@@ -128,18 +133,18 @@ node (NT n _ _) = n
128
133
129-- | Calculate the ModuleIdentifier which a require(...) statement imports.
134-- | Calculate the ModuleIdentifier which a require(...) statement imports.
130checkImportPath :: String -> ModuleIdentifier -> S.Set String -> Maybe ModuleIdentifier
135checkImportPath :: String -> ModuleIdentifier -> S.Set String -> Maybe ModuleIdentifier
131−checkImportPath "./foreign" m _ =
136+checkImportPath "./foreign" m _ =
132 Just (ModuleIdentifier (moduleName m) Foreign)
137 Just (ModuleIdentifier (moduleName m) Foreign)
133−checkImportPath name _ names
138+checkImportPath name _ names
134 | name `S.member` names = Just (ModuleIdentifier name Regular)
139 | name `S.member` names = Just (ModuleIdentifier name Regular)
135checkImportPath _ _ _ = Nothing
140checkImportPath _ _ _ = Nothing
136
141
137-- | Compute the dependencies of all elements in a module, and add them to the tree.
142-- | Compute the dependencies of all elements in a module, and add them to the tree.
138−--
143+--
139-- Members and exports can have dependencies. A dependency is of one of the following forms:
144-- Members and exports can have dependencies. A dependency is of one of the following forms:
140--
145--
141-- 1) module.name or member["name"]
146-- 1) module.name or member["name"]
142−--
147+--
143-- where module was imported using
148-- where module was imported using
144--
149--
145-- var module = require("Module.Name");
150-- var module = require("Module.Name");
@@ -149,7 +154,7 @@ checkImportPath _ _ _ = Nothing
149-- where name is the name of a member defined in the current module.
154-- where name is the name of a member defined in the current module.
150withDeps :: Module -> Module
155withDeps :: Module -> Module
151withDeps (Module modulePath es) = Module modulePath (map expandDeps es)
156withDeps (Module modulePath es) = Module modulePath (map expandDeps es)
152− where
157+ where
153 -- | Collects all modules which are imported, so that we can identify dependencies of the first type.
158 -- | Collects all modules which are imported, so that we can identify dependencies of the first type.
154 imports :: [(String, ModuleIdentifier)]
159 imports :: [(String, ModuleIdentifier)]
155 imports = mapMaybe toImport es
160 imports = mapMaybe toImport es
@@ -157,7 +162,7 @@ withDeps (Module modulePath es) = Module modulePath (map expandDeps es)
157 toImport :: ModuleElement -> Maybe (String, ModuleIdentifier)
162 toImport :: ModuleElement -> Maybe (String, ModuleIdentifier)
158 toImport (Require _ nm mid) = Just (nm, mid)
163 toImport (Require _ nm mid) = Just (nm, mid)
159 toImport _ = Nothing
164 toImport _ = Nothing
160−
165+
161 -- | Collects all member names in scope, so that we can identify dependencies of the second type.
166 -- | Collects all member names in scope, so that we can identify dependencies of the second type.
162 boundNames :: [String]
167 boundNames :: [String]
163 boundNames = mapMaybe toBoundName es
168 boundNames = mapMaybe toBoundName es
@@ -173,7 +178,7 @@ withDeps (Module modulePath es) = Module modulePath (map expandDeps es)
173 where
178 where
174 expand (ty, nm, n1, _) = (ty, nm, n1, nub (dependencies modulePath n1))
179 expand (ty, nm, n1, _) = (ty, nm, n1, nub (dependencies modulePath n1))
175 expandDeps other = other
180 expandDeps other = other
176−
181+
177 dependencies :: ModuleIdentifier -> JSNode -> [(ModuleIdentifier, String)]
182 dependencies :: ModuleIdentifier -> JSNode -> [(ModuleIdentifier, String)]
178 dependencies m = everything (++) (mkQ [] toReference)
183 dependencies m = everything (++) (mkQ [] toReference)
179 where
184 where
@@ -195,29 +200,31 @@ withDeps (Module modulePath es) = Module modulePath (map expandDeps es)
195 toReference _ = []
200 toReference _ = []
196
201
197-- | Attempt to create a Module from a Javascript AST.
202-- | Attempt to create a Module from a Javascript AST.
198−--
203+--
199−-- Each type of module element is matched using pattern guards, and everything else is bundled into the
204+-- Each type of module element is matched using pattern guards, and everything else is bundled into the
200-- Other constructor.
205-- Other constructor.
201toModule :: forall m. (Applicative m, MonadError ErrorMessage m) => S.Set String -> ModuleIdentifier -> JSNode -> m Module
206toModule :: forall m. (Applicative m, MonadError ErrorMessage m) => S.Set String -> ModuleIdentifier -> JSNode -> m Module
202−toModule mids mid top
207+toModule mids mid top
203 | JSSourceElementsTop ns <- node top = Module mid <$> mapM toModuleElement ns
208 | JSSourceElementsTop ns <- node top = Module mid <$> mapM toModuleElement ns
204− | otherwise = throwError InvalidTopLevel
209+ | otherwise = err InvalidTopLevel
205− where
210+ where
211+ err = throwError . ErrorInModule mid
212+
206 toModuleElement :: JSNode -> m ModuleElement
213 toModuleElement :: JSNode -> m ModuleElement
207 toModuleElement n
214 toModuleElement n
208 | JSVariables var [ varIntro ] _ <- node n
215 | JSVariables var [ varIntro ] _ <- node n
209− , JSLiteral "var" <- node var
216+ , JSLiteral "var" <- node var
210 , JSVarDecl impN [ eq, req, impP ] <- node varIntro
217 , JSVarDecl impN [ eq, req, impP ] <- node varIntro
211 , JSIdentifier importName <- node impN
218 , JSIdentifier importName <- node impN
212 , JSLiteral "=" <- node eq
219 , JSLiteral "=" <- node eq
213 , JSIdentifier "require" <- node req
220 , JSIdentifier "require" <- node req
214− , JSArguments _ [ impS ] _ <- node impP
221+ , JSArguments _ [ impS ] _ <- node impP
215 , JSStringLiteral _ importPath <- node impS
222 , JSStringLiteral _ importPath <- node impS
216 , Just importPath' <- checkImportPath importPath mid mids
223 , Just importPath' <- checkImportPath importPath mid mids
217 = pure (Require n importName importPath')
224 = pure (Require n importName importPath')
218 toModuleElement n
225 toModuleElement n
219 | JSVariables var [ varIntro ] _ <- node n
226 | JSVariables var [ varIntro ] _ <- node n
220− , JSLiteral "var" <- node var
227+ , JSLiteral "var" <- node var
221 , JSVarDecl declN (eq : decl) <- node varIntro
228 , JSVarDecl declN (eq : decl) <- node varIntro
222 , JSIdentifier name <- node declN
229 , JSIdentifier name <- node declN
223 , JSLiteral "=" <- node eq
230 , JSLiteral "=" <- node eq
@@ -251,11 +258,11 @@ toModule mids mid top
251 = ExportsList <$> mapM toExport (filter (not . isSeparator) (map node props))
258 = ExportsList <$> mapM toExport (filter (not . isSeparator) (map node props))
252 where
259 where
253 toExport :: Node -> m (ExportType, String, JSNode, [Key])
260 toExport :: Node -> m (ExportType, String, JSNode, [Key])
254− toExport (JSPropertyNameandValue name _ [val] ) =
261+ toExport (JSPropertyNameandValue name _ [val] ) =
255− (,,val,[]) <$> exportType (node val)
262+ (,,val,[]) <$> exportType (node val)
256 <*> extractLabel (node name)
263 <*> extractLabel (node name)
257− toExport _ = throwError UnsupportedExport
264+ toExport _ = err UnsupportedExport
258−
265+
259 exportType :: Node -> m ExportType
266 exportType :: Node -> m ExportType
260 exportType (JSMemberDot [f] _ _)
267 exportType (JSMemberDot [f] _ _)
261 | JSIdentifier "$foreign" <- node f
268 | JSIdentifier "$foreign" <- node f
@@ -264,13 +271,13 @@ toModule mids mid top
264 | JSIdentifier "$foreign" <- node f
271 | JSIdentifier "$foreign" <- node f
265 = pure ForeignReexport
272 = pure ForeignReexport
266 exportType (JSIdentifier s) = pure (RegularExport s)
273 exportType (JSIdentifier s) = pure (RegularExport s)
267− exportType _ = throwError UnsupportedExport
274+ exportType _ = err UnsupportedExport
268−
275+
269 extractLabel :: Node -> m String
276 extractLabel :: Node -> m String
270 extractLabel (JSStringLiteral _ nm) = pure nm
277 extractLabel (JSStringLiteral _ nm) = pure nm
271 extractLabel (JSIdentifier nm) = pure nm
278 extractLabel (JSIdentifier nm) = pure nm
272− extractLabel _ = throwError UnsupportedExport
279+ extractLabel _ = err UnsupportedExport
273−
280+
274 isSeparator :: Node -> Bool
281 isSeparator :: Node -> Bool
275 isSeparator (JSLiteral ",") = True
282 isSeparator (JSLiteral ",") = True
276 isSeparator _ = False
283 isSeparator _ = False
@@ -280,9 +287,9 @@ toModule mids mid top
280compile :: [Module] -> [ModuleIdentifier] -> [Module]
287compile :: [Module] -> [ModuleIdentifier] -> [Module]
281compile modules [] = modules
288compile modules [] = modules
282compile modules entryPoints = filteredModules
289compile modules entryPoints = filteredModules
283− where
290+ where
284 (graph, _, vertexFor) = graphFromEdges verts
291 (graph, _, vertexFor) = graphFromEdges verts
285−
292+
286 -- | The vertex set
293 -- | The vertex set
287 verts :: [(ModuleElement, Key, [Key])]
294 verts :: [(ModuleElement, Key, [Key])]
288 verts = do
295 verts = do
@@ -290,12 +297,12 @@ compile modules entryPoints = filteredModules
290 concatMap (toVertices mid) els
297 concatMap (toVertices mid) els
291 where
298 where
292 -- | Create a set of vertices for a module element.
299 -- | Create a set of vertices for a module element.
293− --
300+ --
294 -- Some special cases worth commenting on:
301 -- Some special cases worth commenting on:
295 --
302 --
296 -- 1) Regular exports which simply export their own name do not count as dependencies.
303 -- 1) Regular exports which simply export their own name do not count as dependencies.
297 -- Regular exports which rename and reexport an operator do count, however.
304 -- Regular exports which rename and reexport an operator do count, however.
298− --
305+ --
299 -- 2) Require statements don't contribute towards dependencies, since they effectively get
306 -- 2) Require statements don't contribute towards dependencies, since they effectively get
300 -- inlined wherever they are used inside other module elements.
307 -- inlined wherever they are used inside other module elements.
301 toVertices :: ModuleIdentifier -> ModuleElement -> [(ModuleElement, Key, [Key])]
308 toVertices :: ModuleIdentifier -> ModuleElement -> [(ModuleElement, Key, [Key])]
@@ -306,18 +313,18 @@ compile modules entryPoints = filteredModules
306 toVertex (RegularExport nm, nm1, _, ks) | nm /= nm1 = Just (m, (p, nm1), ks)
313 toVertex (RegularExport nm, nm1, _, ks) | nm /= nm1 = Just (m, (p, nm1), ks)
307 toVertex _ = Nothing
314 toVertex _ = Nothing
308 toVertices _ _ = []
315 toVertices _ _ = []
309−
316+
310 -- | The set of vertices whose connected components we are interested in keeping.
317 -- | The set of vertices whose connected components we are interested in keeping.
311 entryPointVertices :: [Vertex]
318 entryPointVertices :: [Vertex]
312 entryPointVertices = catMaybes $ do
319 entryPointVertices = catMaybes $ do
313 (_, k@(mid, _), _) <- verts
320 (_, k@(mid, _), _) <- verts
314 guard $ mid `elem` entryPoints
321 guard $ mid `elem` entryPoints
315 return (vertexFor k)
322 return (vertexFor k)
316−
323+
317 -- | The set of vertices reachable from an entry point
324 -- | The set of vertices reachable from an entry point
318 reachableSet :: S.Set Vertex
325 reachableSet :: S.Set Vertex
319 reachableSet = S.fromList (concatMap (reachable graph) entryPointVertices)
326 reachableSet = S.fromList (concatMap (reachable graph) entryPointVertices)
320−
327+
321 filteredModules :: [Module]
328 filteredModules :: [Module]
322 filteredModules = map filterUsed modules
329 filteredModules = map filterUsed modules
323 where
330 where
@@ -326,29 +333,29 @@ compile modules entryPoints = filteredModules
326 where
333 where
327 go :: [ModuleElement] -> [ModuleElement]
334 go :: [ModuleElement] -> [ModuleElement]
328 go [] = []
335 go [] = []
329− go (d : Other semi : rest)
336+ go (d : Other semi : rest)
330 | JSLiteral ";" <- node semi
337 | JSLiteral ";" <- node semi
331 , not (isDeclUsed d)
338 , not (isDeclUsed d)
332 = go rest
339 = go rest
333− go (d : rest)
340+ go (d : rest)
334 | not (isDeclUsed d) = go rest
341 | not (isDeclUsed d) = go rest
335 | otherwise = d : go rest
342 | otherwise = d : go rest
336−
343+
337 -- | Filter out the exports for members which aren't used.
344 -- | Filter out the exports for members which aren't used.
338 filterExports :: ModuleElement -> ModuleElement
345 filterExports :: ModuleElement -> ModuleElement
339 filterExports (ExportsList exps) = ExportsList (filter (\(_, nm, _, _) -> isKeyUsed (mid, nm)) exps)
346 filterExports (ExportsList exps) = ExportsList (filter (\(_, nm, _, _) -> isKeyUsed (mid, nm)) exps)
340 filterExports me = me
347 filterExports me = me
341−
348+
342 isDeclUsed :: ModuleElement -> Bool
349 isDeclUsed :: ModuleElement -> Bool
343 isDeclUsed (Member _ _ nm _ _) = isKeyUsed (mid, nm)
350 isDeclUsed (Member _ _ nm _ _) = isKeyUsed (mid, nm)
344 isDeclUsed _ = True
351 isDeclUsed _ = True
345−
352+
346 isKeyUsed :: Key -> Bool
353 isKeyUsed :: Key -> Bool
347− isKeyUsed k
354+ isKeyUsed k
348 | Just me <- vertexFor k = me `S.member` reachableSet
355 | Just me <- vertexFor k = me `S.member` reachableSet
349 | otherwise = False
356 | otherwise = False
350−
357+
351−-- | Topologically sort the module dependency graph, so that when we generate code, modules can be
358+-- | Topologically sort the module dependency graph, so that when we generate code, modules can be
352-- defined in the right order.
359-- defined in the right order.
353sortModules :: [Module] -> [Module]
360sortModules :: [Module] -> [Module]
354sortModules modules = map (\v -> case nodeFor v of (n, _, _) -> n) (reverse (topSort graph))
361sortModules modules = map (\v -> case nodeFor v of (n, _, _) -> n) (reverse (topSort graph))
@@ -356,11 +363,11 @@ sortModules modules = map (\v -> case nodeFor v of (n, _, _) -> n) (reverse (top
356 (graph, nodeFor, _) = graphFromEdges $ do
363 (graph, nodeFor, _) = graphFromEdges $ do
357 m@(Module mid els) <- modules
364 m@(Module mid els) <- modules
358 return (m, mid, mapMaybe getKey els)
365 return (m, mid, mapMaybe getKey els)
359−
366+
360 getKey :: ModuleElement -> Maybe ModuleIdentifier
367 getKey :: ModuleElement -> Maybe ModuleIdentifier
361− getKey (Require _ _ mi) = Just mi
368+ getKey (Require _ _ mi) = Just mi
362 getKey _ = Nothing
369 getKey _ = Nothing
363−
370+
364-- | A module is empty if it contains no exported members (in other words,
371-- | A module is empty if it contains no exported members (in other words,
365-- if the only things left after dead code elimination are module imports and
372-- if the only things left after dead code elimination are module imports and
366-- "other" foreign code).
373-- "other" foreign code).
@@ -374,7 +381,7 @@ isModuleEmpty (Module _ els) = all isElementEmpty els
374 isElementEmpty (Require _ _ _) = True
381 isElementEmpty (Require _ _ _) = True
375 isElementEmpty (Other _) = True
382 isElementEmpty (Other _) = True
376 isElementEmpty _ = False
383 isElementEmpty _ = False
377−
384+
378-- | Generate code for a set of modules, including a call to main().
385-- | Generate code for a set of modules, including a call to main().
379--
386--
380-- Modules get defined on the global PS object, as follows:
387-- Modules get defined on the global PS object, as follows:
@@ -384,10 +391,10 @@ isModuleEmpty (Module _ els) = all isElementEmpty els
384-- ...
391-- ...
385-- })(PS["Module.Name"] = PS["Module.Name"] || {});
392-- })(PS["Module.Name"] = PS["Module.Name"] || {});
386--
393--
387−-- In particular, a module and its foreign imports share the same namespace inside PS.
394+-- In particular, a module and its foreign imports share the same namespace inside PS.
388-- This saves us from having to generate unique names for a module and its foreign imports,
395-- This saves us from having to generate unique names for a module and its foreign imports,
389-- and is safe since a module shares a namespace with its foreign imports in PureScript as well
396-- and is safe since a module shares a namespace with its foreign imports in PureScript as well
390−-- (so there is no way to have overlaps in code generated by psc-make).
397+-- (so there is no way to have overlaps in code generated by psc).
391codeGen :: Maybe String -- ^ main module
398codeGen :: Maybe String -- ^ main module
392 -> String -- ^ namespace
399 -> String -- ^ namespace
393 -> [Module] -- ^ input modules
400 -> [Module] -- ^ input modules
@@ -399,85 +406,85 @@ codeGen optionsMainModule optionsNamespace ms = renderToString (NN (JSSourceElem
399 where
406 where
400 declToJS :: ModuleElement -> [JSNode]
407 declToJS :: ModuleElement -> [JSNode]
401 declToJS (Member n _ _ _ _) = [n]
408 declToJS (Member n _ _ _ _) = [n]
402− declToJS (Other n) = [n]
409+ declToJS (Other n) = [n]
403− declToJS (Require _ nm req) =
410+ declToJS (Require _ nm req) =
404− [ NN (JSVariables (NT (JSLiteral "var") tokenPosnEmpty [ WhiteSpace tokenPosnEmpty "\n " ])
411+ [ NN (JSVariables (NT (JSLiteral "var") tokenPosnEmpty [ WhiteSpace tokenPosnEmpty "\n " ])
405− [ NN (JSVarDecl (sp (JSIdentifier nm))
412+ [ NN (JSVarDecl (sp (JSIdentifier nm))
406 [ sp (JSLiteral "=")
413 [ sp (JSLiteral "=")
407 , moduleReference sp (moduleName req)
414 , moduleReference sp (moduleName req)
408 ])
415 ])
409 ]
416 ]
410 (nt (JSLiteral ";"))) ]
417 (nt (JSLiteral ";"))) ]
411 declToJS (ExportsList exps) = map toExport exps
418 declToJS (ExportsList exps) = map toExport exps
412−
419+
413− where
420+ where
414 toExport :: (ExportType, String, JSNode, [Key]) -> JSNode
421 toExport :: (ExportType, String, JSNode, [Key]) -> JSNode
415 toExport (_, nm, val, _) =
422 toExport (_, nm, val, _) =
416− NN (JSExpression [ NN (JSMemberSquare [ NT (JSIdentifier "exports") tokenPosnEmpty [ WhiteSpace tokenPosnEmpty "\n " ] ]
423+ NN (JSExpression [ NN (JSMemberSquare [ NT (JSIdentifier "exports") tokenPosnEmpty [ WhiteSpace tokenPosnEmpty "\n " ] ]
417− (nt (JSLiteral "["))
424+ (nt (JSLiteral "["))
418 (NN (JSExpression [ nt (JSStringLiteral '"' nm) ]))
425 (NN (JSExpression [ nt (JSStringLiteral '"' nm) ]))
419 (nt (JSLiteral "]")))
426 (nt (JSLiteral "]")))
420 , NN (JSOperator (sp (JSLiteral "=")))
427 , NN (JSOperator (sp (JSLiteral "=")))
421 , reindent val
428 , reindent val
422 , nt (JSLiteral ";")
429 , nt (JSLiteral ";")
423 ])
430 ])
424−
431+
425 reindent :: JSNode -> JSNode
432 reindent :: JSNode -> JSNode
426 reindent (NT n _ _) = sp n
433 reindent (NT n _ _) = sp n
427 reindent nn = nn
434 reindent nn = nn
428−
435+
429 indent :: [JSNode] -> [JSNode]
436 indent :: [JSNode] -> [JSNode]
430 indent = everywhere (mkT squash)
437 indent = everywhere (mkT squash)
431 where
438 where
432 squash (NT n pos ann) = NT n (keepCol pos) (map splat ann)
439 squash (NT n pos ann) = NT n (keepCol pos) (map splat ann)
433 squash nn = nn
440 squash nn = nn
434−
441+
435 splat (CommentA pos s) = CommentA (keepCol pos) s
442 splat (CommentA pos s) = CommentA (keepCol pos) s
436 splat (WhiteSpace pos w) = WhiteSpace (keepCol pos) w
443 splat (WhiteSpace pos w) = WhiteSpace (keepCol pos) w
437 splat ann = ann
444 splat ann = ann
438−
445+
439 keepCol (TokenPn _ _ c) = TokenPn 0 0 (c + 2)
446 keepCol (TokenPn _ _ c) = TokenPn 0 0 (c + 2)
440−
447+
441 prelude :: [JSNode]
448 prelude :: [JSNode]
442− prelude =
449+ prelude =
443 [ NN (JSVariables (NT (JSLiteral "var") tokenPosnEmpty [ CommentA tokenPosnEmpty ("// Generated by psc-bundle " ++ showVersion Paths.version)
450 [ NN (JSVariables (NT (JSLiteral "var") tokenPosnEmpty [ CommentA tokenPosnEmpty ("// Generated by psc-bundle " ++ showVersion Paths.version)
444 , WhiteSpace tokenPosnEmpty "\n"
451 , WhiteSpace tokenPosnEmpty "\n"
445− ])
452+ ])
446− [ NN (JSVarDecl (sp (JSIdentifier optionsNamespace))
453+ [ NN (JSVarDecl (sp (JSIdentifier optionsNamespace))
447 [ sp (JSLiteral "=")
454 [ sp (JSLiteral "=")
448− , NN (JSObjectLiteral (sp (JSLiteral "{"))
455+ , NN (JSObjectLiteral (sp (JSLiteral "{"))
449 []
456 []
450 (sp (JSLiteral "}")))
457 (sp (JSLiteral "}")))
451 ])
458 ])
452− ]
459+ ]
453 (nt (JSLiteral ";")))
460 (nt (JSLiteral ";")))
454 , lf
461 , lf
455 ]
462 ]
456−
463+
457 moduleReference :: (Node -> JSNode) -> String -> JSNode
464 moduleReference :: (Node -> JSNode) -> String -> JSNode
458− moduleReference f mn =
465+ moduleReference f mn =
459− NN (JSMemberSquare [ f (JSIdentifier optionsNamespace) ]
466+ NN (JSMemberSquare [ f (JSIdentifier optionsNamespace) ]
460− (nt (JSLiteral "["))
467+ (nt (JSLiteral "["))
461 (NN (JSExpression [ nt (JSStringLiteral '"' mn) ]))
468 (NN (JSExpression [ nt (JSStringLiteral '"' mn) ]))
462 (nt (JSLiteral "]")))
469 (nt (JSLiteral "]")))
463−
470+
464 wrap :: String -> [JSNode] -> [JSNode]
471 wrap :: String -> [JSNode] -> [JSNode]
465− wrap mn ds =
472+ wrap mn ds =
466− [ NN (JSExpression [ NN (JSExpressionParen (nt (JSLiteral "("))
473+ [ NN (JSExpression [ NN (JSExpressionParen (nt (JSLiteral "("))
467− (NN (JSExpression [ NN (JSFunctionExpression (nt (JSLiteral "function"))
474+ (NN (JSExpression [ NN (JSFunctionExpression (nt (JSLiteral "function"))
468− []
475+ []
469− (nt (JSLiteral "(") ) [nt (JSIdentifier "exports")] (nt (JSLiteral ")"))
476+ (nt (JSLiteral "(") ) [nt (JSIdentifier "exports")] (nt (JSLiteral ")"))
470− (NN (JSBlock [sp (JSLiteral "{")]
477+ (NN (JSBlock [sp (JSLiteral "{")]
471 (lf : ds)
478 (lf : ds)
472 [nl (JSLiteral "}")])))]))
479 [nl (JSLiteral "}")])))]))
473 (nt (JSLiteral ")")))
480 (nt (JSLiteral ")")))
474− , NN (JSArguments (nt (JSLiteral "("))
481+ , NN (JSArguments (nt (JSLiteral "("))
475 [ NN (JSExpression [ moduleReference nt mn
482 [ NN (JSExpression [ moduleReference nt mn
476 , NN (JSOperator (sp (JSLiteral "=")))
483 , NN (JSOperator (sp (JSLiteral "=")))
477 , NN (JSExpressionBinary "||"
484 , NN (JSExpressionBinary "||"
478− [ moduleReference sp mn ]
485+ [ moduleReference sp mn ]
479− (sp (JSLiteral "||"))
486+ (sp (JSLiteral "||"))
480− [ emptyObj ])
487+ [ emptyObj ])
481 ])
488 ])
482 ]
489 ]
483 (nt (JSLiteral ")")))
490 (nt (JSLiteral ")")))
@@ -487,30 +494,30 @@ codeGen optionsMainModule optionsNamespace ms = renderToString (NN (JSSourceElem
487 ]
494 ]
488 where
495 where
489 emptyObj = NN (JSObjectLiteral (sp (JSLiteral "{")) [] (nt (JSLiteral "}")))
496 emptyObj = NN (JSObjectLiteral (sp (JSLiteral "{")) [] (nt (JSLiteral "}")))
490−
497+
491 runMain :: String -> [JSNode]
498 runMain :: String -> [JSNode]
492− runMain mn =
499+ runMain mn =
493− [ NN (JSExpression [ NN (JSMemberDot [ NN (JSMemberSquare [ nl (JSIdentifier optionsNamespace) ]
500+ [ NN (JSExpression [ NN (JSMemberDot [ NN (JSMemberSquare [ nl (JSIdentifier optionsNamespace) ]
494− (nt (JSLiteral "["))
501+ (nt (JSLiteral "["))
495− (NN (JSExpression [ nt (JSStringLiteral '"' mn) ]))
502+ (NN (JSExpression [ nt (JSStringLiteral '"' mn) ]))
496 (nt (JSLiteral "]")))
503 (nt (JSLiteral "]")))
497− ]
504+ ]
498− (nt (JSLiteral "."))
505+ (nt (JSLiteral "."))
499 (nt (JSIdentifier "main")))
506 (nt (JSIdentifier "main")))
500 , NN (JSArguments (nt (JSLiteral "(")) [] (nt (JSLiteral ")")))
507 , NN (JSArguments (nt (JSLiteral "(")) [] (nt (JSLiteral ")")))
501 ])
508 ])
502 , nt (JSLiteral ";")
509 , nt (JSLiteral ";")
503 ]
510 ]
504−
511+
505 nt :: Node -> JSNode
512 nt :: Node -> JSNode
506 nt n = NT n tokenPosnEmpty []
513 nt n = NT n tokenPosnEmpty []
507−
514+
508 lf :: JSNode
515 lf :: JSNode
509 lf = NT (JSLiteral "") tokenPosnEmpty [ WhiteSpace tokenPosnEmpty "\n" ]
516 lf = NT (JSLiteral "") tokenPosnEmpty [ WhiteSpace tokenPosnEmpty "\n" ]
510−
517+
511 sp :: Node -> JSNode
518 sp :: Node -> JSNode
512 sp n = NT n tokenPosnEmpty [ WhiteSpace tokenPosnEmpty " " ]
519 sp n = NT n tokenPosnEmpty [ WhiteSpace tokenPosnEmpty " " ]
513−
520+
514 nl :: Node -> JSNode
521 nl :: Node -> JSNode
515 nl n = NT n tokenPosnEmpty [ WhiteSpace tokenPosnEmpty "\n" ]
522 nl n = NT n tokenPosnEmpty [ WhiteSpace tokenPosnEmpty "\n" ]
516
523
@@ -518,21 +525,21 @@ codeGen optionsMainModule optionsNamespace ms = renderToString (NN (JSSourceElem
518-- This function performs dead code elimination, filters empty modules
525-- This function performs dead code elimination, filters empty modules
519-- and generates and prints the final Javascript bundle.
526-- and generates and prints the final Javascript bundle.
520bundle :: forall m. (Applicative m, MonadError ErrorMessage m)
527bundle :: forall m. (Applicative m, MonadError ErrorMessage m)
521− => [(ModuleIdentifier, String)] -- ^ The input modules. Each module should be javascript rendered from 'Language.PureScript.Make' or @psc-make@.
528+ => [(ModuleIdentifier, String)] -- ^ The input modules. Each module should be javascript rendered from 'Language.PureScript.Make' or @psc@.
522 -> [ModuleIdentifier] -- ^ Entry points. These module identifiers are used as the roots for dead-code elimination
529 -> [ModuleIdentifier] -- ^ Entry points. These module identifiers are used as the roots for dead-code elimination
523 -> Maybe String -- ^ An optional main module.
530 -> Maybe String -- ^ An optional main module.
524 -> String -- ^ The namespace (e.g. PS).
531 -> String -- ^ The namespace (e.g. PS).
525 -> m String
532 -> m String
526bundle inputStrs entryPoints mainModule namespace = do
533bundle inputStrs entryPoints mainModule namespace = do
527 input <- forM inputStrs $ \(ident, js) -> do
534 input <- forM inputStrs $ \(ident, js) -> do
528− ast <- either (const $ throwError UnableToParseModule) pure $ parse js (moduleName ident)
535+ ast <- either (throwError . ErrorInModule ident . UnableToParseModule) pure $ parse js (moduleName ident)
529 return (ident, ast)
536 return (ident, ast)
530
537
531 let mids = S.fromList (map (moduleName . fst) input)
538 let mids = S.fromList (map (moduleName . fst) input)
532−
539+
533 modules <- mapM (fmap withDeps . uncurry (toModule mids)) input
540 modules <- mapM (fmap withDeps . uncurry (toModule mids)) input
534−
541+
535 let compiled = compile modules entryPoints
542 let compiled = compile modules entryPoints
536 sorted = sortModules (filter (not . isModuleEmpty) compiled)
543 sorted = sortModules (filter (not . isModuleEmpty) compiled)
537−
544+
538 return (codeGen mainModule namespace sorted)
545 return (codeGen mainModule namespace sorted)