[project @ 2000-12-14 12:52:40 by sewardj]
[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_InterpSyn
247    | Opt_D_dump_BCOs
248    | Opt_D_source_stats
249    | Opt_D_verbose_core2core
250    | Opt_D_verbose_stg2stg
251    | Opt_D_dump_hi
252    | Opt_D_dump_hi_diffs
253    | Opt_D_dump_minimal_imports
254    | Opt_DoCoreLinting
255    | Opt_DoStgLinting
256    | Opt_DoUSPLinting
257
258    | Opt_WarnDuplicateExports
259    | Opt_WarnHiShadows
260    | Opt_WarnIncompletePatterns
261    | Opt_WarnMissingFields
262    | Opt_WarnMissingMethods
263    | Opt_WarnMissingSigs
264    | Opt_WarnNameShadowing
265    | Opt_WarnOverlappingPatterns
266    | Opt_WarnSimplePatterns
267    | Opt_WarnTypeDefaults
268    | Opt_WarnUnusedBinds
269    | Opt_WarnUnusedImports
270    | Opt_WarnUnusedMatches
271    | Opt_WarnDeprecations
272
273    -- language opts
274    | Opt_AllowOverlappingInstances
275    | Opt_AllowUndecidableInstances
276    | Opt_GlasgowExts
277    | Opt_Generics
278    | Opt_NoImplicitPrelude 
279
280    -- misc
281    | Opt_ReportCompile
282    deriving (Eq)
283
284 data DynFlags = DynFlags {
285   coreToDo   :: [CoreToDo],
286   stgToDo    :: [StgToDo],
287   hscLang    :: HscLang,
288   hscOutName :: String,  -- name of the file in which to place output
289   verbosity  :: Int,     -- verbosity level
290   flags      :: [DynFlag]
291  }
292
293 defaultDynFlags = DynFlags {
294   coreToDo = [], stgToDo = [], 
295   hscLang = HscC, hscOutName = "", 
296   verbosity = 0, flags = []
297   }
298
299 {- 
300     Verbosity levels:
301         
302     0   |   print errors & warnings only
303     1   |   minimal verbosity: print "compiling M ... done." for each module.
304     2   |   equivalent to -dshow-passes
305     3   |   equivalent to existing "ghc -v"
306     4   |   "ghc -v -ddump-most"
307     5   |   "ghc -v -ddump-all"
308 -}
309
310 dopt :: DynFlag -> DynFlags -> Bool
311 dopt f dflags  = f `elem` (flags dflags)
312
313 dopt_CoreToDo :: DynFlags -> [CoreToDo]
314 dopt_CoreToDo = coreToDo
315
316 dopt_StgToDo :: DynFlags -> [StgToDo]
317 dopt_StgToDo = stgToDo
318
319 dopt_OutName :: DynFlags -> String
320 dopt_OutName = hscOutName
321
322 data HscLang
323   = HscC
324   | HscAsm
325   | HscJava
326   | HscInterpreted
327     deriving (Eq, Show)
328
329 dopt_HscLang :: DynFlags -> HscLang
330 dopt_HscLang = hscLang
331 \end{code}
332
333 %************************************************************************
334 %*                                                                      *
335 \subsection{Classifying command-line options}
336 %*                                                                      *
337 %************************************************************************
338
339 \begin{code}
340 -- v_Statis_hsc_opts is here to avoid a circular dependency with
341 -- main/DriverState.
342 GLOBAL_VAR(v_Static_hsc_opts, [], [String])
343
344 lookUp           :: FAST_STRING -> Bool
345 lookup_int       :: String -> Maybe Int
346 lookup_def_int   :: String -> Int -> Int
347 lookup_def_float :: String -> Float -> Float
348 lookup_str       :: String -> Maybe String
349
350 unpacked_static_opts = unsafePerformIO (readIORef v_Static_hsc_opts)
351 packed_static_opts   = map _PK_ unpacked_static_opts
352
353 lookUp     sw = sw `elem` packed_static_opts
354         
355 lookup_str sw = firstJust (map (startsWith sw) unpacked_static_opts)
356
357 lookup_int sw = case (lookup_str sw) of
358                   Nothing -> Nothing
359                   Just xx -> Just (read xx)
360
361 lookup_def_int sw def = case (lookup_str sw) of
362                             Nothing -> def              -- Use default
363                             Just xx -> read xx
364
365 lookup_def_float sw def = case (lookup_str sw) of
366                             Nothing -> def              -- Use default
367                             Just xx -> read xx
368
369
370 {-
371  Putting the compiler options into temporary at-files
372  may turn out to be necessary later on if we turn hsc into
373  a pure Win32 application where I think there's a command-line
374  length limit of 255. unpacked_opts understands the @ option.
375
376 unpacked_opts :: [String]
377 unpacked_opts =
378   concat $
379   map (expandAts) $
380   map _UNPK_ argv  -- NOT ARGV any more: v_Static_hsc_opts
381   where
382    expandAts ('@':fname) = words (unsafePerformIO (readFile fname))
383    expandAts l = [l]
384 -}
385 \end{code}
386
387 %************************************************************************
388 %*                                                                      *
389 \subsection{Static options}
390 %*                                                                      *
391 %************************************************************************
392
393 \begin{code}
394 -- debugging opts
395 opt_PprStyle_NoPrags            = lookUp  SLIT("-dppr-noprags")
396 opt_PprStyle_Debug              = lookUp  SLIT("-dppr-debug")
397 opt_PprStyle_RawTypes           = lookUp  SLIT("-dppr-rawtypes")
398 opt_PprUserLength               = lookup_def_int "-dppr-user-length" 5 --ToDo: give this a name
399
400 -- profiling opts
401 opt_AutoSccsOnAllToplevs        = lookUp  SLIT("-fauto-sccs-on-all-toplevs")
402 opt_AutoSccsOnExportedToplevs   = lookUp  SLIT("-fauto-sccs-on-exported-toplevs")
403 opt_AutoSccsOnIndividualCafs    = lookUp  SLIT("-fauto-sccs-on-individual-cafs")
404 opt_AutoSccsOnDicts             = lookUp  SLIT("-fauto-sccs-on-dicts")
405 opt_SccProfilingOn              = lookUp  SLIT("-fscc-profiling")
406 opt_DoTickyProfiling            = lookUp  SLIT("-fticky-ticky")
407
408 -- language opts
409 opt_AllStrict                   = lookUp  SLIT("-fall-strict")
410 opt_NoMonomorphismRestriction   = lookUp  SLIT("-fno-monomorphism-restriction")
411 opt_DictsStrict                 = lookUp  SLIT("-fdicts-strict")
412 opt_IrrefutableTuples           = lookUp  SLIT("-firrefutable-tuples")
413 opt_MaxContextReductionDepth    = lookup_def_int "-fcontext-stack" mAX_CONTEXT_REDUCTION_DEPTH
414 opt_NumbersStrict               = lookUp  SLIT("-fnumbers-strict")
415 opt_Parallel                    = lookUp  SLIT("-fparallel")
416 opt_SMP                         = lookUp  SLIT("-fsmp")
417
418 -- optimisation opts
419 opt_DoSemiTagging               = lookUp  SLIT("-fsemi-tagging")
420 opt_FoldrBuildOn                = lookUp  SLIT("-ffoldr-build-on")
421 opt_LiberateCaseThreshold       = lookup_def_int "-fliberate-case-threshold" (10::Int)
422 opt_StgDoLetNoEscapes           = lookUp  SLIT("-flet-no-escape")
423 opt_UnfoldCasms                 = lookUp SLIT("-funfold-casms-in-hi-file")
424 opt_UsageSPOn                   = lookUp  SLIT("-fusagesp-on")
425 opt_UnboxStrictFields           = lookUp  SLIT("-funbox-strict-fields")
426
427 {-
428    The optional '-inpackage=P' flag tells what package
429    we are compiling this module for.
430    The Prelude, for example is compiled with '-package prelude'
431 -}
432 opt_InPackage                   = case lookup_str "-inpackage=" of
433                                     Just p  -> _PK_ p
434                                     Nothing -> SLIT("Main")     -- The package name if none is specified
435
436 opt_EmitCExternDecls            = lookUp  SLIT("-femit-extern-decls")
437 opt_EnsureSplittableC           = lookUp  SLIT("-fglobalise-toplev-names")
438 opt_GranMacros                  = lookUp  SLIT("-fgransim")
439 opt_HiVersion                   = read cProjectVersionInt :: Int
440 opt_HistorySize                 = lookup_def_int "-fhistory-size" 20
441 opt_IgnoreAsserts               = lookUp  SLIT("-fignore-asserts")
442 opt_IgnoreIfacePragmas          = lookUp  SLIT("-fignore-interface-pragmas")
443 opt_NoHiCheck                   = lookUp  SLIT("-fno-hi-version-check")
444 opt_OmitBlackHoling             = lookUp  SLIT("-dno-black-holing")
445 opt_OmitInterfacePragmas        = lookUp  SLIT("-fomit-interface-pragmas")
446
447 -- Simplifier switches
448 opt_SimplNoPreInlining          = lookUp SLIT("-fno-pre-inlining")
449         -- NoPreInlining is there just to see how bad things
450         -- get if you don't do it!
451 opt_SimplDoEtaReduction         = lookUp SLIT("-fdo-eta-reduction")
452 opt_SimplDoLambdaEtaExpansion   = lookUp SLIT("-fdo-lambda-eta-expansion")
453 opt_SimplCaseOfCase             = lookUp SLIT("-fcase-of-case")
454 opt_SimplCaseMerge              = lookUp SLIT("-fcase-merge")
455 opt_SimplPedanticBottoms        = lookUp SLIT("-fpedantic-bottoms")
456 opt_SimplExcessPrecision        = lookUp SLIT("-fexcess-precision")
457
458 -- Unfolding control
459 opt_UF_HiFileThreshold          = lookup_def_int "-funfolding-interface-threshold" (45::Int)
460 opt_UF_CreationThreshold        = lookup_def_int "-funfolding-creation-threshold"  (45::Int)
461 opt_UF_UseThreshold             = lookup_def_int "-funfolding-use-threshold"       (8::Int)     -- Discounts can be big
462 opt_UF_FunAppDiscount           = lookup_def_int "-funfolding-fun-discount"        (6::Int)     -- It's great to inline a fn
463 opt_UF_KeenessFactor            = lookup_def_float "-funfolding-keeness-factor"    (1.5::Float)
464 opt_UF_UpdateInPlace            = lookUp  SLIT("-funfolding-update-in-place")
465
466 opt_UF_CheapOp  = ( 1 :: Int)   -- Only one instruction; and the args are charged for
467 opt_UF_DearOp   = ( 4 :: Int)
468                         
469 opt_NoPruneDecls                = lookUp SLIT("-fno-prune-decls")
470 opt_NoPruneTyDecls              = lookUp SLIT("-fno-prune-tydecls")
471 opt_Static                      = lookUp SLIT("-static")
472 opt_Unregisterised              = lookUp SLIT("-funregisterised")
473 \end{code}
474
475 %************************************************************************
476 %*                                                                      *
477 \subsection{List of static hsc flags}
478 %*                                                                      *
479 %************************************************************************
480
481 \begin{code}
482 isStaticHscFlag f =
483   f `elem` [
484         "fauto-sccs-on-all-toplevs",
485         "fauto-sccs-on-exported-toplevs",
486         "fauto-sccs-on-individual-cafs",
487         "fauto-sccs-on-dicts",
488         "fscc-profiling",
489         "fticky-ticky",
490         "fall-strict",
491         "fdicts-strict",
492         "firrefutable-tuples",
493         "fnumbers-strict",
494         "fparallel",
495         "fsmp",
496         "fsemi-tagging",
497         "ffoldr-build-on",
498         "flet-no-escape",
499         "funfold-casms-in-hi-file",
500         "fusagesp-on",
501         "funbox-strict-fields",
502         "femit-extern-decls",
503         "fglobalise-toplev-names",
504         "fgransim",
505         "fignore-asserts",
506         "fignore-interface-pragmas",
507         "fno-hi-version-check",
508         "dno-black-holing",
509         "fomit-interface-pragmas",
510         "fno-pre-inlining",
511         "fdo-eta-reduction",
512         "fdo-lambda-eta-expansion",
513         "fcase-of-case",
514         "fcase-merge",
515         "fpedantic-bottoms",
516         "fexcess-precision",
517         "funfolding-update-in-place",
518         "freport-compile",
519         "fno-prune-decls",
520         "fno-prune-tydecls",
521         "static",
522         "funregisterised"
523         ]
524   || any (flip prefixMatch f) [
525         "fcontext-stack",
526         "fliberate-case-threshold",
527         "fhistory-size",
528         "funfolding-interface-threshold",
529         "funfolding-creation-threshold",
530         "funfolding-use-threshold",
531         "funfolding-fun-discount",
532         "funfolding-keeness-factor"
533      ]
534 \end{code}
535
536 %************************************************************************
537 %*                                                                      *
538 \subsection{Switch ordering}
539 %*                                                                      *
540 %************************************************************************
541
542 These things behave just like enumeration types.
543
544 \begin{code}
545 instance Eq SimplifierSwitch where
546     a == b = tagOf_SimplSwitch a ==# tagOf_SimplSwitch b
547
548 instance Ord SimplifierSwitch where
549     a <  b  = tagOf_SimplSwitch a <# tagOf_SimplSwitch b
550     a <= b  = tagOf_SimplSwitch a <=# tagOf_SimplSwitch b
551
552
553 tagOf_SimplSwitch (SimplInlinePhase _)          = _ILIT(1)
554 tagOf_SimplSwitch (MaxSimplifierIterations _)   = _ILIT(2)
555 tagOf_SimplSwitch DontApplyRules                = _ILIT(3)
556 tagOf_SimplSwitch SimplLetToCase                = _ILIT(4)
557 tagOf_SimplSwitch NoCaseOfCase                  = _ILIT(5)
558
559 -- If you add anything here, be sure to change lAST_SIMPL_SWITCH_TAG, too!
560
561 lAST_SIMPL_SWITCH_TAG = 5
562 \end{code}
563
564 %************************************************************************
565 %*                                                                      *
566 \subsection{Switch lookup}
567 %*                                                                      *
568 %************************************************************************
569
570 \begin{code}
571 isAmongSimpl :: [SimplifierSwitch] -> SimplifierSwitch -> SwitchResult
572 isAmongSimpl on_switches                -- Switches mentioned later occur *earlier*
573                                         -- in the list; defaults right at the end.
574   = let
575         tidied_on_switches = foldl rm_dups [] on_switches
576                 -- The fold*l* ensures that we keep the latest switches;
577                 -- ie the ones that occur earliest in the list.
578
579         sw_tbl :: Array Int SwitchResult
580         sw_tbl = (array (0, lAST_SIMPL_SWITCH_TAG) -- bounds...
581                         all_undefined)
582                  // defined_elems
583
584         all_undefined = [ (i, SwBool False) | i <- [0 .. lAST_SIMPL_SWITCH_TAG ] ]
585
586         defined_elems = map mk_assoc_elem tidied_on_switches
587     in
588     -- (avoid some unboxing, bounds checking, and other horrible things:)
589 #if __GLASGOW_HASKELL__ < 405
590     case sw_tbl of { Array bounds_who_needs_'em stuff ->
591 #else
592     case sw_tbl of { Array _ _ stuff ->
593 #endif
594     \ switch ->
595         case (indexArray# stuff (tagOf_SimplSwitch switch)) of
596 #if __GLASGOW_HASKELL__ < 400
597           Lift v -> v
598 #elif __GLASGOW_HASKELL__ < 403
599           (# _, v #) -> v
600 #else
601           (# v #) -> v
602 #endif
603     }
604   where
605     mk_assoc_elem k@(MaxSimplifierIterations lvl)
606         = (iBox (tagOf_SimplSwitch k), SwInt lvl)
607     mk_assoc_elem k@(SimplInlinePhase n)
608         = (iBox (tagOf_SimplSwitch k), SwInt n)
609     mk_assoc_elem k
610         = (iBox (tagOf_SimplSwitch k), SwBool True) -- I'm here, Mom!
611
612     -- cannot have duplicates if we are going to use the array thing
613     rm_dups switches_so_far switch
614       = if switch `is_elem` switches_so_far
615         then switches_so_far
616         else switch : switches_so_far
617       where
618         sw `is_elem` []     = False
619         sw `is_elem` (s:ss) = (tagOf_SimplSwitch sw) ==# (tagOf_SimplSwitch s)
620                             || sw `is_elem` ss
621 \end{code}
622
623
624 %************************************************************************
625 %*                                                                      *
626 \subsection{Misc functions for command-line options}
627 %*                                                                      *
628 %************************************************************************
629
630
631 \begin{code}
632 switchIsOn :: (switch -> SwitchResult) -> switch -> Bool
633
634 switchIsOn lookup_fn switch
635   = case (lookup_fn switch) of
636       SwBool False -> False
637       _            -> True
638
639 intSwitchSet :: (switch -> SwitchResult)
640              -> (Int -> switch)
641              -> Maybe Int
642
643 intSwitchSet lookup_fn switch
644   = case (lookup_fn (switch (panic "intSwitchSet"))) of
645       SwInt int -> Just int
646       _         -> Nothing
647 \end{code}
648
649 \begin{code}
650 startsWith :: String -> String -> Maybe String
651 -- startsWith pfx (pfx++rest) = Just rest
652
653 startsWith []     str = Just str
654 startsWith (c:cs) (s:ss)
655   = if c /= s then Nothing else startsWith cs ss
656 startsWith  _     []  = Nothing
657
658 endsWith  :: String -> String -> Maybe String
659 endsWith cs ss
660   = case (startsWith (reverse cs) (reverse ss)) of
661       Nothing -> Nothing
662       Just rs -> Just (reverse rs)
663 \end{code}