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