[project @ 2000-11-07 13:12:21 by simonpj]
[ghc-hetmet.git] / ghc / compiler / main / CmdLineOpts.lhs
1 %
2 % (c) The University of Glasgow, 1996-2000
3 %
4 \section[CmdLineOpts]{Things to do with command-line options}
5
6 \begin{code}
7
8 module CmdLineOpts (
9         CoreToDo(..),
10         SimplifierSwitch(..), isAmongSimpl,
11         StgToDo(..),
12         SwitchResult(..),
13         HscLang(..),
14         DynFlag(..),    -- needed non-abstractly by DriverFlags
15         DynFlags(..),
16
17         v_Static_hsc_opts,
18
19         intSwitchSet,
20         switchIsOn,
21         isStaticHscFlag,
22
23         opt_PprStyle_NoPrags,
24         opt_PprUserLength,
25         opt_PprStyle_Debug,
26
27         dopt,
28
29         -- other dynamic flags
30         dopt_CoreToDo,
31         dopt_StgToDo,
32         dopt_HscLang,
33         dopt_OutName,
34
35         -- profiling opts
36         opt_AutoSccsOnAllToplevs,
37         opt_AutoSccsOnExportedToplevs,
38         opt_AutoSccsOnIndividualCafs,
39         opt_AutoSccsOnDicts,
40         opt_SccProfilingOn,
41         opt_DoTickyProfiling,
42
43         -- language opts
44         opt_AllStrict,
45         opt_DictsStrict,
46         opt_MaxContextReductionDepth,
47         opt_IrrefutableTuples,
48         opt_NumbersStrict,
49         opt_Parallel,
50         opt_SMP,
51
52         -- optimisation opts
53         opt_DoSemiTagging,
54         opt_FoldrBuildOn,
55         opt_LiberateCaseThreshold,
56         opt_StgDoLetNoEscapes,
57         opt_UnfoldCasms,
58         opt_UsageSPOn,
59         opt_UnboxStrictFields,
60         opt_SimplNoPreInlining,
61         opt_SimplDoEtaReduction,
62         opt_SimplDoLambdaEtaExpansion,
63         opt_SimplCaseOfCase,
64         opt_SimplCaseMerge,
65         opt_SimplPedanticBottoms,
66         opt_SimplExcessPrecision,
67
68         -- Unfolding control
69         opt_UF_HiFileThreshold,
70         opt_UF_CreationThreshold,
71         opt_UF_UseThreshold,
72         opt_UF_FunAppDiscount,
73         opt_UF_KeenessFactor,
74         opt_UF_UpdateInPlace,
75         opt_UF_CheapOp,
76         opt_UF_DearOp,
77
78         -- misc opts
79         opt_InPackage,
80         opt_EmitCExternDecls,
81         opt_EnsureSplittableC,
82         opt_GranMacros,
83         opt_HiVersion,
84         opt_HistorySize,
85         opt_IgnoreAsserts,
86         opt_IgnoreIfacePragmas,
87         opt_NoHiCheck,
88         opt_OmitBlackHoling,
89         opt_OmitInterfacePragmas,
90         opt_NoPruneTyDecls,
91         opt_NoPruneDecls,
92         opt_Static,
93         opt_Unregisterised,
94         opt_Verbose
95     ) where
96
97 #include "HsVersions.h"
98
99 import Array    ( array, (//) )
100 import GlaExts
101 import IOExts   ( IORef, readIORef )
102 import Constants        -- Default values for some flags
103 import Util
104 import FastTypes
105
106 import Maybes           ( firstJust )
107 import Panic            ( panic )
108
109 #if __GLASGOW_HASKELL__ < 301
110 import ArrBase  ( Array(..) )
111 #else
112 import PrelArr  ( Array(..) )
113 #endif
114 \end{code}
115
116 %************************************************************************
117 %*                                                                      *
118 \subsection{Command-line options}
119 %*                                                                      *
120 %************************************************************************
121
122 The hsc command-line options are split into two categories:
123
124   - static flags
125   - dynamic flags
126
127 Static flags are represented by top-level values of type Bool or Int,
128 for example.  They therefore have the same value throughout the
129 invocation of hsc.
130
131 Dynamic flags are represented by an abstract type, DynFlags, which is
132 passed into hsc by the compilation manager for every compilation.
133 Dynamic flags are those that change on a per-compilation basis,
134 perhaps because they may be present in the OPTIONS pragma at the top
135 of a module.
136
137 Other flag-related blurb:
138
139 A list of {\em ToDo}s is things to be done in a particular part of
140 processing.  A (fictitious) example for the Core-to-Core simplifier
141 might be: run the simplifier, then run the strictness analyser, then
142 run the simplifier again (three ``todos'').
143
144 There are three ``to-do processing centers'' at the moment.  In the
145 main loop (\tr{main/Main.lhs}), in the Core-to-Core processing loop
146 (\tr{simplCore/SimplCore.lhs), and in the STG-to-STG processing loop
147 (\tr{simplStg/SimplStg.lhs}).
148
149 %************************************************************************
150 %*                                                                      *
151 \subsection{Datatypes associated with command-line options}
152 %*                                                                      *
153 %************************************************************************
154
155 \begin{code}
156 data SwitchResult
157   = SwBool      Bool            -- on/off
158   | SwString    FAST_STRING     -- nothing or a String
159   | SwInt       Int             -- nothing or an Int
160 \end{code}
161
162 \begin{code}
163 data CoreToDo           -- These are diff core-to-core passes,
164                         -- which may be invoked in any order,
165                         -- as many times as you like.
166
167   = CoreDoSimplify      -- The core-to-core simplifier.
168         (SimplifierSwitch -> SwitchResult)
169                         -- Each run of the simplifier can take a different
170                         -- set of simplifier-specific flags.
171   | CoreDoFloatInwards
172   | CoreDoFloatOutwards Bool    -- True <=> float lambdas to top level
173   | CoreLiberateCase
174   | CoreDoPrintCore
175   | CoreDoStaticArgs
176   | CoreDoStrictness
177   | CoreDoWorkerWrapper
178   | CoreDoSpecialising
179   | CoreDoUSPInf
180   | CoreDoCPResult
181   | CoreDoGlomBinds
182   | CoreCSE
183
184   | CoreDoNothing        -- useful when building up lists of these things
185 \end{code}
186
187 \begin{code}
188 data StgToDo
189   = StgDoStaticArgs
190   | StgDoLambdaLift
191   | StgDoMassageForProfiling  -- should be (next to) last
192   -- There's also setStgVarInfo, but its absolute "lastness"
193   -- is so critical that it is hardwired in (no flag).
194   | D_stg_stats
195 \end{code}
196
197 \begin{code}
198 data SimplifierSwitch
199   = MaxSimplifierIterations Int
200   | SimplInlinePhase Int
201   | DontApplyRules
202   | NoCaseOfCase
203   | SimplLetToCase
204 \end{code}
205
206 %************************************************************************
207 %*                                                                      *
208 \subsection{Dynamic command-line options}
209 %*                                                                      *
210 %************************************************************************
211
212 \begin{code}
213 data DynFlag
214
215    -- debugging flags
216    = Opt_D_dump_all
217    | Opt_D_dump_most
218    | Opt_D_dump_absC
219    | Opt_D_dump_asm
220    | Opt_D_dump_cpranal
221    | Opt_D_dump_deriv
222    | Opt_D_dump_ds
223    | Opt_D_dump_flatC
224    | Opt_D_dump_foreign
225    | Opt_D_dump_inlinings
226    | Opt_D_dump_occur_anal
227    | Opt_D_dump_parsed
228    | Opt_D_dump_realC
229    | Opt_D_dump_rn
230    | Opt_D_dump_simpl
231    | Opt_D_dump_simpl_iterations
232    | Opt_D_dump_spec
233    | Opt_D_dump_stg
234    | Opt_D_dump_stranal
235    | Opt_D_dump_tc
236    | Opt_D_dump_types
237    | Opt_D_dump_rules
238    | Opt_D_dump_usagesp
239    | Opt_D_dump_cse
240    | Opt_D_dump_worker_wrapper
241    | Opt_D_show_passes
242    | Opt_D_dump_rn_trace
243    | Opt_D_dump_rn_stats
244    | Opt_D_dump_stix
245    | Opt_D_dump_simpl_stats
246    | Opt_D_source_stats
247    | Opt_D_verbose_core2core
248    | Opt_D_verbose_stg2stg
249    | Opt_D_dump_hi_diffs
250    | Opt_D_dump_minimal_imports
251    | Opt_DoCoreLinting
252    | Opt_DoStgLinting
253    | Opt_DoUSPLinting
254
255    | Opt_WarnDuplicateExports
256    | Opt_WarnHiShadows
257    | Opt_WarnIncompletePatterns
258    | Opt_WarnMissingFields
259    | Opt_WarnMissingMethods
260    | Opt_WarnMissingSigs
261    | Opt_WarnNameShadowing
262    | Opt_WarnOverlappingPatterns
263    | Opt_WarnSimplePatterns
264    | Opt_WarnTypeDefaults
265    | Opt_WarnUnusedBinds
266    | Opt_WarnUnusedImports
267    | Opt_WarnUnusedMatches
268    | Opt_WarnDeprecations
269
270    -- language opts
271    | Opt_AllowOverlappingInstances
272    | Opt_AllowUndecidableInstances
273    | Opt_GlasgowExts
274    | Opt_Generics
275    | Opt_NoImplicitPrelude 
276
277    -- misc
278    | Opt_ReportCompile
279    deriving (Eq)
280
281 data DynFlags = DynFlags {
282   coreToDo   :: [CoreToDo],
283   stgToDo    :: [StgToDo],
284   hscLang    :: HscLang,
285   hscOutName :: String,  -- name of the file in which to place output
286   flags      :: [DynFlag]
287  }
288
289 dopt :: DynFlag -> DynFlags -> Bool
290 dopt f dflags  = f `elem` (flags dflags)
291
292 dopt_CoreToDo :: DynFlags -> [CoreToDo]
293 dopt_CoreToDo = coreToDo
294
295 dopt_StgToDo :: DynFlags -> [StgToDo]
296 dopt_StgToDo = stgToDo
297
298 dopt_OutName :: DynFlags -> String
299 dopt_OutName = hscOutName
300
301 data HscLang
302   = HscC
303   | HscAsm
304   | HscJava
305   | HscInterpreted
306     deriving Eq
307
308 dopt_HscLang :: DynFlags -> HscLang
309 dopt_HscLang = hscLang
310 \end{code}
311
312 %************************************************************************
313 %*                                                                      *
314 \subsection{Classifying command-line options}
315 %*                                                                      *
316 %************************************************************************
317
318 \begin{code}
319 -- v_Statis_hsc_opts is here to avoid a circular dependency with
320 -- main/DriverState.
321 GLOBAL_VAR(v_Static_hsc_opts, [], [String])
322
323 lookUp           :: FAST_STRING -> Bool
324 lookup_int       :: String -> Maybe Int
325 lookup_def_int   :: String -> Int -> Int
326 lookup_def_float :: String -> Float -> Float
327 lookup_str       :: String -> Maybe String
328
329 unpacked_static_opts = unsafePerformIO (readIORef v_Static_hsc_opts)
330 packed_static_opts   = map _PK_ unpacked_static_opts
331
332 lookUp     sw = sw `elem` packed_static_opts
333         
334 lookup_str sw = firstJust (map (startsWith sw) unpacked_static_opts)
335
336 lookup_int sw = case (lookup_str sw) of
337                   Nothing -> Nothing
338                   Just xx -> Just (read xx)
339
340 lookup_def_int sw def = case (lookup_str sw) of
341                             Nothing -> def              -- Use default
342                             Just xx -> read xx
343
344 lookup_def_float sw def = case (lookup_str sw) of
345                             Nothing -> def              -- Use default
346                             Just xx -> read xx
347
348
349 {-
350  Putting the compiler options into temporary at-files
351  may turn out to be necessary later on if we turn hsc into
352  a pure Win32 application where I think there's a command-line
353  length limit of 255. unpacked_opts understands the @ option.
354
355 unpacked_opts :: [String]
356 unpacked_opts =
357   concat $
358   map (expandAts) $
359   map _UNPK_ argv  -- NOT ARGV any more: v_Static_hsc_opts
360   where
361    expandAts ('@':fname) = words (unsafePerformIO (readFile fname))
362    expandAts l = [l]
363 -}
364 \end{code}
365
366 %************************************************************************
367 %*                                                                      *
368 \subsection{Static options}
369 %*                                                                      *
370 %************************************************************************
371
372 \begin{code}
373 -- debugging opts
374 opt_PprStyle_NoPrags            = lookUp  SLIT("-dppr-noprags")
375 opt_PprStyle_Debug              = lookUp  SLIT("-dppr-debug")
376 opt_PprUserLength               = lookup_def_int "-dppr-user-length" 5 --ToDo: give this a name
377
378 -- profiling opts
379 opt_AutoSccsOnAllToplevs        = lookUp  SLIT("-fauto-sccs-on-all-toplevs")
380 opt_AutoSccsOnExportedToplevs   = lookUp  SLIT("-fauto-sccs-on-exported-toplevs")
381 opt_AutoSccsOnIndividualCafs    = lookUp  SLIT("-fauto-sccs-on-individual-cafs")
382 opt_AutoSccsOnDicts             = lookUp  SLIT("-fauto-sccs-on-dicts")
383 opt_SccProfilingOn              = lookUp  SLIT("-fscc-profiling")
384 opt_DoTickyProfiling            = lookUp  SLIT("-fticky-ticky")
385
386 -- language opts
387 opt_AllStrict                   = lookUp  SLIT("-fall-strict")
388 opt_DictsStrict                 = lookUp  SLIT("-fdicts-strict")
389 opt_IrrefutableTuples           = lookUp  SLIT("-firrefutable-tuples")
390 opt_MaxContextReductionDepth    = lookup_def_int "-fcontext-stack" mAX_CONTEXT_REDUCTION_DEPTH
391 opt_NumbersStrict               = lookUp  SLIT("-fnumbers-strict")
392 opt_Parallel                    = lookUp  SLIT("-fparallel")
393 opt_SMP                         = lookUp  SLIT("-fsmp")
394
395 -- optimisation opts
396 opt_DoSemiTagging               = lookUp  SLIT("-fsemi-tagging")
397 opt_FoldrBuildOn                = lookUp  SLIT("-ffoldr-build-on")
398 opt_LiberateCaseThreshold       = lookup_def_int "-fliberate-case-threshold" (10::Int)
399 opt_StgDoLetNoEscapes           = lookUp  SLIT("-flet-no-escape")
400 opt_UnfoldCasms                 = lookUp SLIT("-funfold-casms-in-hi-file")
401 opt_UsageSPOn                   = lookUp  SLIT("-fusagesp-on")
402 opt_UnboxStrictFields           = lookUp  SLIT("-funbox-strict-fields")
403
404 {-
405    The optional '-inpackage=P' flag tells what package
406    we are compiling this module for.
407    The Prelude, for example is compiled with '-package prelude'
408 -}
409 opt_InPackage                   = case lookup_str "-inpackage=" of
410                                     Just p  -> _PK_ p
411                                     Nothing -> SLIT("Main")     -- The package name if none is specified
412
413 opt_EmitCExternDecls            = lookUp  SLIT("-femit-extern-decls")
414 opt_EnsureSplittableC           = lookUp  SLIT("-fglobalise-toplev-names")
415 opt_GranMacros                  = lookUp  SLIT("-fgransim")
416 opt_HiVersion                   = lookup_def_int "-fhi-version=" 0 -- what version we're compiling.
417 opt_HistorySize                 = lookup_def_int "-fhistory-size" 20
418 opt_IgnoreAsserts               = lookUp  SLIT("-fignore-asserts")
419 opt_IgnoreIfacePragmas          = lookUp  SLIT("-fignore-interface-pragmas")
420 opt_NoHiCheck                   = lookUp  SLIT("-fno-hi-version-check")
421 opt_OmitBlackHoling             = lookUp  SLIT("-dno-black-holing")
422 opt_OmitInterfacePragmas        = lookUp  SLIT("-fomit-interface-pragmas")
423
424 -- Simplifier switches
425 opt_SimplNoPreInlining          = lookUp SLIT("-fno-pre-inlining")
426         -- NoPreInlining is there just to see how bad things
427         -- get if you don't do it!
428 opt_SimplDoEtaReduction         = lookUp SLIT("-fdo-eta-reduction")
429 opt_SimplDoLambdaEtaExpansion   = lookUp SLIT("-fdo-lambda-eta-expansion")
430 opt_SimplCaseOfCase             = lookUp SLIT("-fcase-of-case")
431 opt_SimplCaseMerge              = lookUp SLIT("-fcase-merge")
432 opt_SimplPedanticBottoms        = lookUp SLIT("-fpedantic-bottoms")
433 opt_SimplExcessPrecision        = lookUp SLIT("-fexcess-precision")
434
435 -- Unfolding control
436 opt_UF_HiFileThreshold          = lookup_def_int "-funfolding-interface-threshold" (45::Int)
437 opt_UF_CreationThreshold        = lookup_def_int "-funfolding-creation-threshold"  (45::Int)
438 opt_UF_UseThreshold             = lookup_def_int "-funfolding-use-threshold"       (8::Int)     -- Discounts can be big
439 opt_UF_FunAppDiscount           = lookup_def_int "-funfolding-fun-discount"        (6::Int)     -- It's great to inline a fn
440 opt_UF_KeenessFactor            = lookup_def_float "-funfolding-keeness-factor"    (1.5::Float)
441 opt_UF_UpdateInPlace            = lookUp  SLIT("-funfolding-update-in-place")
442
443 opt_UF_CheapOp  = ( 1 :: Int)   -- Only one instruction; and the args are charged for
444 opt_UF_DearOp   = ( 4 :: Int)
445                         
446 opt_NoPruneDecls                = lookUp SLIT("-fno-prune-decls")
447 opt_NoPruneTyDecls              = lookUp SLIT("-fno-prune-tydecls")
448 opt_Static                      = lookUp SLIT("-static")
449 opt_Unregisterised              = lookUp SLIT("-funregisterised")
450 opt_Verbose                     = lookUp SLIT("-v")
451 \end{code}
452
453 %************************************************************************
454 %*                                                                      *
455 \subsection{List of static hsc flags}
456 %*                                                                      *
457 %************************************************************************
458
459 \begin{code}
460 isStaticHscFlag f =
461   f `elem` [
462         "fauto-sccs-on-all-toplevs",
463         "fauto-sccs-on-exported-toplevs",
464         "fauto-sccs-on-individual-cafs",
465         "fauto-sccs-on-dicts",
466         "fscc-profiling",
467         "fticky-ticky",
468         "fall-strict",
469         "fdicts-strict",
470         "firrefutable-tuples",
471         "fnumbers-strict",
472         "fparallel",
473         "fsmp",
474         "fsemi-tagging",
475         "ffoldr-build-on",
476         "flet-no-escape",
477         "funfold-casms-in-hi-file",
478         "fusagesp-on",
479         "funbox-strict-fields",
480         "femit-extern-decls",
481         "fglobalise-toplev-names",
482         "fgransim",
483         "fignore-asserts",
484         "fignore-interface-pragmas",
485         "fno-hi-version-check",
486         "fno-implicit-prelude",
487         "dno-black-holing",
488         "fomit-interface-pragmas",
489         "fno-pre-inlining",
490         "fdo-eta-reduction",
491         "fdo-lambda-eta-expansion",
492         "fcase-of-case",
493         "fcase-merge",
494         "fpedantic-bottoms",
495         "fexcess-precision",
496         "funfolding-update-in-place",
497         "freport-compile",
498         "fno-prune-decls",
499         "fno-prune-tydecls",
500         "static",
501         "funregisterised",
502         "v" ]
503   || any (flip prefixMatch f) [
504         "fcontext-stack",
505         "fliberate-case-threshold",
506         "fhi-version=",
507         "fhistory-size",
508         "funfolding-interface-threshold",
509         "funfolding-creation-threshold",
510         "funfolding-use-threshold",
511         "funfolding-fun-discount",
512         "funfolding-keeness-factor"
513      ]
514 \end{code}
515
516 %************************************************************************
517 %*                                                                      *
518 \subsection{Switch ordering}
519 %*                                                                      *
520 %************************************************************************
521
522 These things behave just like enumeration types.
523
524 \begin{code}
525 instance Eq SimplifierSwitch where
526     a == b = tagOf_SimplSwitch a ==# tagOf_SimplSwitch b
527
528 instance Ord SimplifierSwitch where
529     a <  b  = tagOf_SimplSwitch a <# tagOf_SimplSwitch b
530     a <= b  = tagOf_SimplSwitch a <=# tagOf_SimplSwitch b
531
532
533 tagOf_SimplSwitch (SimplInlinePhase _)          = _ILIT(1)
534 tagOf_SimplSwitch (MaxSimplifierIterations _)   = _ILIT(2)
535 tagOf_SimplSwitch DontApplyRules                = _ILIT(3)
536 tagOf_SimplSwitch SimplLetToCase                = _ILIT(4)
537 tagOf_SimplSwitch NoCaseOfCase                  = _ILIT(5)
538
539 -- If you add anything here, be sure to change lAST_SIMPL_SWITCH_TAG, too!
540
541 lAST_SIMPL_SWITCH_TAG = 5
542 \end{code}
543
544 %************************************************************************
545 %*                                                                      *
546 \subsection{Switch lookup}
547 %*                                                                      *
548 %************************************************************************
549
550 \begin{code}
551 isAmongSimpl :: [SimplifierSwitch] -> SimplifierSwitch -> SwitchResult
552 isAmongSimpl on_switches                -- Switches mentioned later occur *earlier*
553                                         -- in the list; defaults right at the end.
554   = let
555         tidied_on_switches = foldl rm_dups [] on_switches
556                 -- The fold*l* ensures that we keep the latest switches;
557                 -- ie the ones that occur earliest in the list.
558
559         sw_tbl :: Array Int SwitchResult
560         sw_tbl = (array (0, lAST_SIMPL_SWITCH_TAG) -- bounds...
561                         all_undefined)
562                  // defined_elems
563
564         all_undefined = [ (i, SwBool False) | i <- [0 .. lAST_SIMPL_SWITCH_TAG ] ]
565
566         defined_elems = map mk_assoc_elem tidied_on_switches
567     in
568     -- (avoid some unboxing, bounds checking, and other horrible things:)
569 #if __GLASGOW_HASKELL__ < 405
570     case sw_tbl of { Array bounds_who_needs_'em stuff ->
571 #else
572     case sw_tbl of { Array _ _ stuff ->
573 #endif
574     \ switch ->
575         case (indexArray# stuff (tagOf_SimplSwitch switch)) of
576 #if __GLASGOW_HASKELL__ < 400
577           Lift v -> v
578 #elif __GLASGOW_HASKELL__ < 403
579           (# _, v #) -> v
580 #else
581           (# v #) -> v
582 #endif
583     }
584   where
585     mk_assoc_elem k@(MaxSimplifierIterations lvl)
586         = (iBox (tagOf_SimplSwitch k), SwInt lvl)
587     mk_assoc_elem k@(SimplInlinePhase n)
588         = (iBox (tagOf_SimplSwitch k), SwInt n)
589     mk_assoc_elem k
590         = (iBox (tagOf_SimplSwitch k), SwBool True) -- I'm here, Mom!
591
592     -- cannot have duplicates if we are going to use the array thing
593     rm_dups switches_so_far switch
594       = if switch `is_elem` switches_so_far
595         then switches_so_far
596         else switch : switches_so_far
597       where
598         sw `is_elem` []     = False
599         sw `is_elem` (s:ss) = (tagOf_SimplSwitch sw) ==# (tagOf_SimplSwitch s)
600                             || sw `is_elem` ss
601 \end{code}
602
603
604 %************************************************************************
605 %*                                                                      *
606 \subsection{Misc functions for command-line options}
607 %*                                                                      *
608 %************************************************************************
609
610
611 \begin{code}
612 switchIsOn :: (switch -> SwitchResult) -> switch -> Bool
613
614 switchIsOn lookup_fn switch
615   = case (lookup_fn switch) of
616       SwBool False -> False
617       _            -> True
618
619 intSwitchSet :: (switch -> SwitchResult)
620              -> (Int -> switch)
621              -> Maybe Int
622
623 intSwitchSet lookup_fn switch
624   = case (lookup_fn (switch (panic "intSwitchSet"))) of
625       SwInt int -> Just int
626       _         -> Nothing
627 \end{code}
628
629 \begin{code}
630 startsWith :: String -> String -> Maybe String
631 -- startsWith pfx (pfx++rest) = Just rest
632
633 startsWith []     str = Just str
634 startsWith (c:cs) (s:ss)
635   = if c /= s then Nothing else startsWith cs ss
636 startsWith  _     []  = Nothing
637
638 endsWith  :: String -> String -> Maybe String
639 endsWith cs ss
640   = case (startsWith (reverse cs) (reverse ss)) of
641       Nothing -> Nothing
642       Just rs -> Just (reverse rs)
643 \end{code}