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