[project @ 2000-11-21 16:42:58 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
55         -- optimisation opts
56         opt_DoSemiTagging,
57         opt_FoldrBuildOn,
58         opt_LiberateCaseThreshold,
59         opt_StgDoLetNoEscapes,
60         opt_UnfoldCasms,
61         opt_UsageSPOn,
62         opt_UnboxStrictFields,
63         opt_SimplNoPreInlining,
64         opt_SimplDoEtaReduction,
65         opt_SimplDoLambdaEtaExpansion,
66         opt_SimplCaseOfCase,
67         opt_SimplCaseMerge,
68         opt_SimplPedanticBottoms,
69         opt_SimplExcessPrecision,
70
71         -- Unfolding control
72         opt_UF_HiFileThreshold,
73         opt_UF_CreationThreshold,
74         opt_UF_UseThreshold,
75         opt_UF_FunAppDiscount,
76         opt_UF_KeenessFactor,
77         opt_UF_UpdateInPlace,
78         opt_UF_CheapOp,
79         opt_UF_DearOp,
80
81         -- misc opts
82         opt_InPackage,
83         opt_EmitCExternDecls,
84         opt_EnsureSplittableC,
85         opt_GranMacros,
86         opt_HiVersion,
87         opt_HistorySize,
88         opt_IgnoreAsserts,
89         opt_IgnoreIfacePragmas,
90         opt_NoHiCheck,
91         opt_OmitBlackHoling,
92         opt_OmitInterfacePragmas,
93         opt_NoPruneTyDecls,
94         opt_NoPruneDecls,
95         opt_Static,
96         opt_Unregisterised
97     ) where
98
99 #include "HsVersions.h"
100
101 import Array    ( array, (//) )
102 import GlaExts
103 import IOExts   ( IORef, readIORef )
104 import Constants        -- Default values for some flags
105 import Util
106 import FastTypes
107 import Config
108
109 import Maybes           ( firstJust )
110 import Panic            ( panic )
111
112 #if __GLASGOW_HASKELL__ < 301
113 import ArrBase  ( Array(..) )
114 #else
115 import PrelArr  ( Array(..) )
116 #endif
117 \end{code}
118
119 %************************************************************************
120 %*                                                                      *
121 \subsection{Command-line options}
122 %*                                                                      *
123 %************************************************************************
124
125 The hsc command-line options are split into two categories:
126
127   - static flags
128   - dynamic flags
129
130 Static flags are represented by top-level values of type Bool or Int,
131 for example.  They therefore have the same value throughout the
132 invocation of hsc.
133
134 Dynamic flags are represented by an abstract type, DynFlags, which is
135 passed into hsc by the compilation manager for every compilation.
136 Dynamic flags are those that change on a per-compilation basis,
137 perhaps because they may be present in the OPTIONS pragma at the top
138 of a module.
139
140 Other flag-related blurb:
141
142 A list of {\em ToDo}s is things to be done in a particular part of
143 processing.  A (fictitious) example for the Core-to-Core simplifier
144 might be: run the simplifier, then run the strictness analyser, then
145 run the simplifier again (three ``todos'').
146
147 There are three ``to-do processing centers'' at the moment.  In the
148 main loop (\tr{main/Main.lhs}), in the Core-to-Core processing loop
149 (\tr{simplCore/SimplCore.lhs), and in the STG-to-STG processing loop
150 (\tr{simplStg/SimplStg.lhs}).
151
152 %************************************************************************
153 %*                                                                      *
154 \subsection{Datatypes associated with command-line options}
155 %*                                                                      *
156 %************************************************************************
157
158 \begin{code}
159 data SwitchResult
160   = SwBool      Bool            -- on/off
161   | SwString    FAST_STRING     -- nothing or a String
162   | SwInt       Int             -- nothing or an Int
163 \end{code}
164
165 \begin{code}
166 data CoreToDo           -- These are diff core-to-core passes,
167                         -- which may be invoked in any order,
168                         -- as many times as you like.
169
170   = CoreDoSimplify      -- The core-to-core simplifier.
171         (SimplifierSwitch -> SwitchResult)
172                         -- Each run of the simplifier can take a different
173                         -- set of simplifier-specific flags.
174   | CoreDoFloatInwards
175   | CoreDoFloatOutwards Bool    -- True <=> float lambdas to top level
176   | CoreLiberateCase
177   | CoreDoPrintCore
178   | CoreDoStaticArgs
179   | CoreDoStrictness
180   | CoreDoWorkerWrapper
181   | CoreDoSpecialising
182   | CoreDoUSPInf
183   | CoreDoCPResult
184   | CoreDoGlomBinds
185   | CoreCSE
186
187   | CoreDoNothing        -- useful when building up lists of these things
188 \end{code}
189
190 \begin{code}
191 data StgToDo
192   = StgDoStaticArgs
193   | StgDoLambdaLift
194   | StgDoMassageForProfiling  -- should be (next to) last
195   -- There's also setStgVarInfo, but its absolute "lastness"
196   -- is so critical that it is hardwired in (no flag).
197   | D_stg_stats
198 \end{code}
199
200 \begin{code}
201 data SimplifierSwitch
202   = MaxSimplifierIterations Int
203   | SimplInlinePhase Int
204   | DontApplyRules
205   | NoCaseOfCase
206   | SimplLetToCase
207 \end{code}
208
209 %************************************************************************
210 %*                                                                      *
211 \subsection{Dynamic command-line options}
212 %*                                                                      *
213 %************************************************************************
214
215 \begin{code}
216 data DynFlag
217
218    -- debugging flags
219    = Opt_D_dump_absC
220    | Opt_D_dump_asm
221    | Opt_D_dump_cpranal
222    | Opt_D_dump_deriv
223    | Opt_D_dump_ds
224    | Opt_D_dump_flatC
225    | Opt_D_dump_foreign
226    | Opt_D_dump_inlinings
227    | Opt_D_dump_occur_anal
228    | Opt_D_dump_parsed
229    | Opt_D_dump_realC
230    | Opt_D_dump_rn
231    | Opt_D_dump_simpl
232    | Opt_D_dump_simpl_iterations
233    | Opt_D_dump_spec
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_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_DictsStrict                 = lookUp  SLIT("-fdicts-strict")
410 opt_IrrefutableTuples           = lookUp  SLIT("-firrefutable-tuples")
411 opt_MaxContextReductionDepth    = lookup_def_int "-fcontext-stack" mAX_CONTEXT_REDUCTION_DEPTH
412 opt_NumbersStrict               = lookUp  SLIT("-fnumbers-strict")
413 opt_Parallel                    = lookUp  SLIT("-fparallel")
414 opt_SMP                         = lookUp  SLIT("-fsmp")
415
416 -- optimisation opts
417 opt_DoSemiTagging               = lookUp  SLIT("-fsemi-tagging")
418 opt_FoldrBuildOn                = lookUp  SLIT("-ffoldr-build-on")
419 opt_LiberateCaseThreshold       = lookup_def_int "-fliberate-case-threshold" (10::Int)
420 opt_StgDoLetNoEscapes           = lookUp  SLIT("-flet-no-escape")
421 opt_UnfoldCasms                 = lookUp SLIT("-funfold-casms-in-hi-file")
422 opt_UsageSPOn                   = lookUp  SLIT("-fusagesp-on")
423 opt_UnboxStrictFields           = lookUp  SLIT("-funbox-strict-fields")
424
425 {-
426    The optional '-inpackage=P' flag tells what package
427    we are compiling this module for.
428    The Prelude, for example is compiled with '-package prelude'
429 -}
430 opt_InPackage                   = case lookup_str "-inpackage=" of
431                                     Just p  -> _PK_ p
432                                     Nothing -> SLIT("Main")     -- The package name if none is specified
433
434 opt_EmitCExternDecls            = lookUp  SLIT("-femit-extern-decls")
435 opt_EnsureSplittableC           = lookUp  SLIT("-fglobalise-toplev-names")
436 opt_GranMacros                  = lookUp  SLIT("-fgransim")
437 opt_HiVersion                   = read cProjectVersionInt :: Int
438 opt_HistorySize                 = lookup_def_int "-fhistory-size" 20
439 opt_IgnoreAsserts               = lookUp  SLIT("-fignore-asserts")
440 opt_IgnoreIfacePragmas          = lookUp  SLIT("-fignore-interface-pragmas")
441 opt_NoHiCheck                   = lookUp  SLIT("-fno-hi-version-check")
442 opt_OmitBlackHoling             = lookUp  SLIT("-dno-black-holing")
443 opt_OmitInterfacePragmas        = lookUp  SLIT("-fomit-interface-pragmas")
444
445 -- Simplifier switches
446 opt_SimplNoPreInlining          = lookUp SLIT("-fno-pre-inlining")
447         -- NoPreInlining is there just to see how bad things
448         -- get if you don't do it!
449 opt_SimplDoEtaReduction         = lookUp SLIT("-fdo-eta-reduction")
450 opt_SimplDoLambdaEtaExpansion   = lookUp SLIT("-fdo-lambda-eta-expansion")
451 opt_SimplCaseOfCase             = lookUp SLIT("-fcase-of-case")
452 opt_SimplCaseMerge              = lookUp SLIT("-fcase-merge")
453 opt_SimplPedanticBottoms        = lookUp SLIT("-fpedantic-bottoms")
454 opt_SimplExcessPrecision        = lookUp SLIT("-fexcess-precision")
455
456 -- Unfolding control
457 opt_UF_HiFileThreshold          = lookup_def_int "-funfolding-interface-threshold" (45::Int)
458 opt_UF_CreationThreshold        = lookup_def_int "-funfolding-creation-threshold"  (45::Int)
459 opt_UF_UseThreshold             = lookup_def_int "-funfolding-use-threshold"       (8::Int)     -- Discounts can be big
460 opt_UF_FunAppDiscount           = lookup_def_int "-funfolding-fun-discount"        (6::Int)     -- It's great to inline a fn
461 opt_UF_KeenessFactor            = lookup_def_float "-funfolding-keeness-factor"    (1.5::Float)
462 opt_UF_UpdateInPlace            = lookUp  SLIT("-funfolding-update-in-place")
463
464 opt_UF_CheapOp  = ( 1 :: Int)   -- Only one instruction; and the args are charged for
465 opt_UF_DearOp   = ( 4 :: Int)
466                         
467 opt_NoPruneDecls                = lookUp SLIT("-fno-prune-decls")
468 opt_NoPruneTyDecls              = lookUp SLIT("-fno-prune-tydecls")
469 opt_Static                      = lookUp SLIT("-static")
470 opt_Unregisterised              = lookUp SLIT("-funregisterised")
471 \end{code}
472
473 %************************************************************************
474 %*                                                                      *
475 \subsection{List of static hsc flags}
476 %*                                                                      *
477 %************************************************************************
478
479 \begin{code}
480 isStaticHscFlag f =
481   f `elem` [
482         "fauto-sccs-on-all-toplevs",
483         "fauto-sccs-on-exported-toplevs",
484         "fauto-sccs-on-individual-cafs",
485         "fauto-sccs-on-dicts",
486         "fscc-profiling",
487         "fticky-ticky",
488         "fall-strict",
489         "fdicts-strict",
490         "firrefutable-tuples",
491         "fnumbers-strict",
492         "fparallel",
493         "fsmp",
494         "fsemi-tagging",
495         "ffoldr-build-on",
496         "flet-no-escape",
497         "funfold-casms-in-hi-file",
498         "fusagesp-on",
499         "funbox-strict-fields",
500         "femit-extern-decls",
501         "fglobalise-toplev-names",
502         "fgransim",
503         "fignore-asserts",
504         "fignore-interface-pragmas",
505         "fno-hi-version-check",
506         "fno-implicit-prelude",
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}