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