@@ -233,3 +233,85 @@ data JS
233233 -- Raw Javascript (generated when parsing fails for an inline foreign import declaration)
234234 --
235235 | JSRaw String deriving (Show, Eq, Data, Typeable)
236+
237+--
238+-- Traversals
239+--
240+
241+everywhereOnJS :: (JS -> JS) -> JS -> JS
242+everywhereOnJS f = go
243+ where
244+ go :: JS -> JS
245+ go (JSUnary op j) = f (JSUnary op (go j))
246+ go (JSBinary op j1 j2) = f (JSBinary op (go j1) (go j2))
247+ go (JSArrayLiteral js) = f (JSArrayLiteral (map go js))
248+ go (JSIndexer j1 j2) = f (JSIndexer (go j1) (go j2))
249+ go (JSObjectLiteral js) = f (JSObjectLiteral (map (fmap go) js))
250+ go (JSAccessor prop j) = f (JSAccessor prop (go j))
251+ go (JSFunction name args j) = f (JSFunction name args (go j))
252+ go (JSApp j js) = f (JSApp (go j) (map go js))
253+ go (JSConditional j1 j2 j3) = f (JSConditional (go j1) (go j2) (go j3))
254+ go (JSBlock js) = f (JSBlock (map go js))
255+ go (JSVariableIntroduction name j) = f (JSVariableIntroduction name (fmap go j))
256+ go (JSAssignment j1 j2) = f (JSAssignment (go j1) (go j2))
257+ go (JSWhile j1 j2) = f (JSWhile (go j1) (go j2))
258+ go (JSFor name j1 j2 j3) = f (JSFor name (go j1) (go j2) (go j3))
259+ go (JSForIn name j1 j2) = f (JSForIn name (go j1) (go j2))
260+ go (JSIfElse j1 j2 j3) = f (JSIfElse (go j1) (go j2) (fmap go j3))
261+ go (JSReturn js) = f (JSReturn (go js))
262+ go (JSThrow js) = f (JSThrow (go js))
263+ go (JSTypeOf js) = f (JSTypeOf (go js))
264+ go (JSLabel name js) = f (JSLabel name (go js))
265+ go other = f other
266+
267+everywhereOnJSTopDown :: (JS -> JS) -> JS -> JS
268+everywhereOnJSTopDown f = go . f
269+ where
270+ go :: JS -> JS
271+ go (JSUnary op j) = JSUnary op (go (f j))
272+ go (JSBinary op j1 j2) = JSBinary op (go (f j1)) (go (f j2))
273+ go (JSArrayLiteral js) = JSArrayLiteral (map (go . f) js)
274+ go (JSIndexer j1 j2) = JSIndexer (go (f j1)) (go (f j2))
275+ go (JSObjectLiteral js) = JSObjectLiteral (map (fmap (go . f)) js)
276+ go (JSAccessor prop j) = JSAccessor prop (go (f j))
277+ go (JSFunction name args j) = JSFunction name args (go (f j))
278+ go (JSApp j js) = JSApp (go (f j)) (map (go . f) js)
279+ go (JSConditional j1 j2 j3) = JSConditional (go (f j1)) (go (f j2)) (go (f j3))
280+ go (JSBlock js) = JSBlock (map (go . f) js)
281+ go (JSVariableIntroduction name j) = JSVariableIntroduction name (fmap (go . f) j)
282+ go (JSAssignment j1 j2) = JSAssignment (go (f j1)) (go (f j2))
283+ go (JSWhile j1 j2) = JSWhile (go (f j1)) (go (f j2))
284+ go (JSFor name j1 j2 j3) = JSFor name (go (f j1)) (go (f j2)) (go (f j3))
285+ go (JSForIn name j1 j2) = JSForIn name (go (f j1)) (go (f j2))
286+ go (JSIfElse j1 j2 j3) = JSIfElse (go (f j1)) (go (f j2)) (fmap (go . f) j3)
287+ go (JSReturn j) = JSReturn (go (f j))
288+ go (JSThrow j) = JSThrow (go (f j))
289+ go (JSTypeOf j) = JSTypeOf (go (f j))
290+ go (JSLabel name j) = JSLabel name (go (f j))
291+ go other = f other
292+
293+everythingOnJS :: (r -> r -> r) -> (JS -> r) -> JS -> r
294+everythingOnJS (<>) f = go
295+ where
296+ go j@(JSUnary _ j1) = f j <> go j1
297+ go j@(JSBinary _ j1 j2) = f j <> go j1 <> go j2
298+ go j@(JSArrayLiteral js) = foldl (<>) (f j) (map go js)
299+ go j@(JSIndexer j1 j2) = f j <> go j1 <> go j2
300+ go j@(JSObjectLiteral js) = foldl (<>) (f j) (map (go . snd) js)
301+ go j@(JSAccessor _ j1) = f j <> go j1
302+ go j@(JSFunction _ _ j1) = f j <> go j1
303+ go j@(JSApp j1 js) = foldl (<>) (f j <> go j1) (map go js)
304+ go j@(JSConditional j1 j2 j3) = f j <> go j1 <> go j2 <> go j3
305+ go j@(JSBlock js) = foldl (<>) (f j) (map go js)
306+ go j@(JSVariableIntroduction _ (Just j1)) = f j <> go j1
307+ go j@(JSAssignment j1 j2) = f j <> go j1 <> go j2
308+ go j@(JSWhile j1 j2) = f j <> go j1 <> go j2
309+ go j@(JSFor _ j1 j2 j3) = f j <> go j1 <> go j2 <> go j3
310+ go j@(JSForIn _ j1 j2) = f j <> go j1 <> go j2
311+ go j@(JSIfElse j1 j2 Nothing) = f j <> go j1 <> go j2
312+ go j@(JSIfElse j1 j2 (Just j3)) = f j <> go j1 <> go j2 <> go j3
313+ go j@(JSReturn j1) = f j <> go j1
314+ go j@(JSThrow j1) = f j <> go j1
315+ go j@(JSTypeOf j1) = f j <> go j1
316+ go j@(JSLabel _ j1) = f j <> go j1
317+ go other = f other