Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Diff of /sml/trunk/src/cm/bootstrap/btcompile.sml
ViewVC logotype

Diff of /sml/trunk/src/cm/bootstrap/btcompile.sml

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 369, Sun Jul 4 12:55:20 1999 UTC revision 592, Mon Apr 3 07:04:12 2000 UTC
# Line 6  Line 6 
6   *   *
7   * Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)   * Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)
8   *)   *)
9  functor BootstrapCompileFn (structure MachDepVC: MACHDEP_VC  local
10                              val os: SMLofNJ.SysInfo.os_kind) :> sig      structure EM = GenericVC.ErrorMsg
11        structure E = GenericVC.Environment
12        structure SE = GenericVC.StaticEnv
13        structure PS = GenericVC.PersStamps
14        structure GG = GroupGraph
15        structure DG = DependencyGraph
16    in
17    functor BootstrapCompileFn
18                (structure MachDepVC : MACHDEP_VC
19                 val os : SMLofNJ.SysInfo.os_kind
20                 val load_plugin : SrcPath.context -> string -> bool) :> sig
21      val make' : string option -> bool      val make' : string option -> bool
22      val make : unit -> bool      val make : unit -> bool
     val deliver' : string option -> bool  
     val deliver : unit -> bool  
23      val reset : unit -> unit      val reset : unit -> unit
24        val symval : string -> { get: unit -> int option, set: int option -> unit }
25  end = struct  end = struct
   
     structure EM = GenericVC.ErrorMsg  
     structure E = GenericVC.Environment  
     structure SE = GenericVC.CMStaticEnv  
     structure BE = GenericVC.BareEnvironment  
     structure PS = GenericVC.PersStamps  
     structure CoerceEnv = GenericVC.CoerceEnv  
26      structure SSV = SpecificSymValFn (structure MachDepVC = MachDepVC      structure SSV = SpecificSymValFn (structure MachDepVC = MachDepVC
27                                        val os = os)                                        val os = os)
28      structure P = OS.Path      structure P = OS.Path
29      structure F = OS.FileSys      structure F = OS.FileSys
30        structure BF = MachDepVC.Binfile
31    
32        val arch = MachDepVC.architecture
33        val osname = FilenamePolicy.kind2name os
34        val archos = concat [arch, "-", osname]
35    
36      (* Since the bootstrap compiler never executes any of the code      fun init_servers (GG.GROUP { grouppath, ... }) =
37       * it produces, we don't need any dynamic values.  Therefore,          Servers.cmb { archos = archos,
38       * we create RecompPersstate (but not FullPersstate!) and                        root = SrcPath.descr grouppath }
39       * instantiate Recomp as well as RecompTraversal.        | init_servers GG.ERRORGROUP = ()
      * Since RecompPersstate is not part of any surrounding FullPersstate,  
      * function "discard_value" simply does nothing. *)  
     structure RecompPersstate =  
         RecompPersstateFn (structure MachDepVC = MachDepVC  
                            val discard_code = true  
                            fun stable_value_present i = false  
                            fun new_smlinfo i = ())  
40    
41      structure Recomp = RecompFn (structure PS = RecompPersstate)      structure StabModmap = StabModmapFn ()
     structure RT = CompileGenericFn (structure CT = Recomp)  
42    
43      fun recomp gp g = isSome (RT.group gp g)      structure Compile = CompileFn (structure MachDepVC = MachDepVC
44                                       structure StabModmap = StabModmap
45                                       val compile_there =
46                                           Servers.compile o SrcPath.descr)
47    
48        structure BFC = BfcFn (structure MachDepVC = MachDepVC)
49    
50      (* instantiate Stabilize... *)      (* instantiate Stabilize... *)
51      structure Stabilize =      structure Stabilize =
52          StabilizeFn (fun bn2statenv gp i = #1 (#stat (valOf (RT.bnode gp i)))          StabilizeFn (structure MachDepVC = MachDepVC
53                       fun warmup (i, p) = ()                       structure StabModmap = StabModmap
54                       val recomp = recomp                       fun recomp gp g = let
55                       val transfer_state = RecompPersstate.transfer_state)                           val { store, get } = BFC.new ()
56                             val _ = init_servers g
57                             val { group, ... } =
58                                 Compile.newTraversal (fn _ => fn _ => (),
59                                                       store, g)
60                         in
61                             case Servers.withServers (fn () => group gp) of
62                                 NONE => NONE
63                               | SOME _ => SOME get
64                         end
65                         val getII = Compile.getII)
66    
67        structure VerifyStable = VerStabFn (structure Stabilize = Stabilize)
68    
69      (* ... and Parse *)      (* ... and Parse *)
70      structure Parse = ParseFn (structure Stabilize = Stabilize      structure Parse = ParseFn (structure Stabilize = Stabilize
71                                 val pending = AutoLoad.getPending)                                 structure StabModmap = StabModmap
72                                   val evictStale = Compile.evictStale
73                                   fun pending () = SymbolMap.empty)
74    
75      (* copying an input file to an output file safely... *)      fun mkBootList g = let
76      fun copyFile (oi, ci, oo, co, inp, outp, eof) (inf, outf) = let          fun listName p =
77          fun workIn is = let              case P.fromString p of
78              fun workOut os = let                  { vol = "", isAbs = false, arcs = _ :: arc1 :: arcn } => let
79                  val N = 4096                      fun win32name () =
80                  fun loop () =                          concat (arc1 ::
81                      if eof is then () else (outp (os, inp (is, N)); loop ())                                  foldr (fn (a, r) => "\\" :: a :: r) [] arcn)
82              in              in
83                  loop ()                      case os of
84                            SMLofNJ.SysInfo.WIN32 => win32name ()
85                          | _ => P.toString { isAbs = false, vol = "",
86                                              arcs = arc1 :: arcn }
87              end              end
88                  | _ => raise Fail ("BootstrapCompile:listName: bad name: " ^ p)
89          in          in
90              SafeIO.perform { openIt = fn () => oo outf,          MkBootList.group listName g
                              closeIt = co,  
                              work = workOut,  
                              cleanup = fn () =>  
                                  (F.remove outf handle _ => ()) }  
91          end          end
92    
93        local
94            fun internal_reset () =
95                (Compile.reset ();
96                 Parse.reset ();
97                 StabModmap.reset ())
98        in
99            fun reset () =
100                (Say.vsay ["[CMB reset]\n"];
101                 internal_reset ())
102            val checkDirbase = let
103                val prev = ref NONE
104                fun ck db =
105                    (case !prev of
106                         NONE => prev := SOME db
107                       | SOME db' =>
108                         if db = db' then ()
109                         else (Say.vsay ["[new dirbase is `", db,
110                                         "'; CMB reset]\n"];
111                               internal_reset ();
112                               prev := SOME db))
113      in      in
114          SafeIO.perform { openIt = fn () => oi inf,              ck
115                           closeIt = ci,          end
                          work = workIn,  
                          cleanup = fn () => () }  
116      end      end
117    
118      val copyTextFile =      fun mk_compile { deliver, root, dirbase = dbopt, paranoid } = let
         copyFile (TextIO.openIn, TextIO.closeIn,  
                   AutoDir.openTextOut, TextIO.closeOut,  
                   TextIO.inputN, TextIO.output, TextIO.endOfStream)  
   
     val copyBinFile =  
         copyFile (BinIO.openIn, BinIO.closeIn,  
                   AutoDir.openBinOut, BinIO.closeOut,  
                   BinIO.inputN, BinIO.output, BinIO.endOfStream)  
119    
120      fun compile deliver dbopt = let          val _ = StabModmap.reset ()
121    
122          val dirbase = getOpt (dbopt, BtNames.dirbaseDefault)          val dirbase = getOpt (dbopt, BtNames.dirbaseDefault)
123            val _ = checkDirbase dirbase
124          val pcmodespec = BtNames.pcmodespec          val pcmodespec = BtNames.pcmodespec
125          val initgspec = BtNames.initgspec          val initgspec = BtNames.initgspec
126          val maingspec = BtNames.maingspec          val maingspec = BtNames.maingspec
127    
128          val arch = MachDepVC.architecture          val bindir = concat [dirbase, BtNames.bin_infix, archos]
129          val osname = FilenamePolicy.kind2name os          val bootdir = concat [dirbase, BtNames.boot_infix, archos]
         val bindir = concat [dirbase, ".bin.", arch, "-", osname]  
         val bootdir = concat [dirbase, ".boot.", arch, "-", osname]  
130    
131          fun listName (p, copy) =          val keep_going = #get StdConfig.keep_going ()
             case P.fromString p of  
                 { vol = "", isAbs = false, arcs = arc0 :: arc1 :: arcn } => let  
                     fun win32name () =  
                         concat (arc1 ::  
                                 foldr (fn (a, r) => "\\" :: a :: r) [] arcn)  
                     fun doCopy () = let  
                         val bootpath =  
                             P.toString { isAbs = false, vol = "",  
                                          arcs = bootdir :: arc1 :: arcn }  
                     in  
                         copyBinFile (p, bootpath)  
                     end  
                 in  
                     if copy andalso arc0 = bindir then doCopy () else ();  
                     case os of  
                         SMLofNJ.SysInfo.WIN32 => win32name ()  
                       | _ => P.toString { isAbs = false, vol = "",  
                                           arcs = arc1 :: arcn }  
                 end  
               | _ => raise Fail "BootstrapCompile:listName: bad name"  
   
         val keep_going = EnvConfig.getSet StdConfig.keep_going NONE  
132    
133          val ctxt = SrcPath.cwdContext ()          val ctxt = SrcPath.cwdContext ()
134    
135          val pidfile = P.joinDirFile { dir = bootdir, file = "RTPID" }          val listfile = P.joinDirFile { dir = bootdir, file = BtNames.bootlist }
136          val listfile = P.joinDirFile { dir = bootdir, file = "BOOTLIST" }          val pidmapfile = P.joinDirFile { dir = bootdir, file = BtNames.pidmap }
137    
138          val pcmode = PathConfig.new ()          val pcmode = PathConfig.new ()
139          val _ = PathConfig.processSpecFile (pcmode, pcmodespec)          val _ = PathConfig.processSpecFile (pcmode, pcmodespec)
# Line 134  Line 141 
141          fun stdpath s = SrcPath.standard pcmode { context = ctxt, spec = s }          fun stdpath s = SrcPath.standard pcmode { context = ctxt, spec = s }
142    
143          val initgspec = stdpath initgspec          val initgspec = stdpath initgspec
144          val maingspec = stdpath maingspec          val maingspec =
145                case root of
146          val cmifile = valOf (SrcPath.reAnchoredName (initgspec, bootdir))                  NONE => stdpath maingspec
147              handle Option => raise Fail "BootstrapCompile: cmifile"                | SOME r => SrcPath.fromDescr pcmode r
148    
149          val fnpolicy =          val fnpolicy =
150              FilenamePolicy.separate { bindir = bindir, bootdir = bootdir }              FilenamePolicy.separate { bindir = bindir, bootdir = bootdir }
151                  { arch = arch, os = os }                  { arch = arch, os = os }
152    
153          fun mkParam { primconf, pervasive, pervcorepids }          val param =
154                      { corenv } =              { fnpolicy = fnpolicy,
             { primconf = primconf,  
               fnpolicy = fnpolicy,  
155                pcmode = pcmode,                pcmode = pcmode,
156                symenv = SSV.env,                symval = SSV.symval,
157                keep_going = keep_going,                keep_going = keep_going }
               pervasive = pervasive,  
               corenv = corenv,  
               pervcorepids = pervcorepids }  
158    
159          val emptydyn = E.dynamicPart E.emptyEnv          val emptydyn = E.dynamicPart E.emptyEnv
160    
161          (* first, build an initial GeneralParam.info, so we can          (* first, build an initial GeneralParam.info, so we can
162           * deal with the pervasive env and friends... *)           * deal with the pervasive env and friends... *)
163    
         val primconf = Primitive.primEnvConf  
         val mkInitParam = mkParam { primconf = primconf,  
                                     pervasive = E.emptyEnv,  
                                     pervcorepids = PidSet.empty }  
   
         val param_nocore = mkInitParam { corenv = BE.staticPart BE.emptyEnv }  
   
164          val groupreg = GroupReg.new ()          val groupreg = GroupReg.new ()
165          val errcons = EM.defaultConsumer ()          val errcons = EM.defaultConsumer ()
166          val ginfo_nocore = { param = param_nocore, groupreg = groupreg,          val ginfo = { param = param, groupreg = groupreg, errcons = errcons }
167                               errcons = errcons }  
168            fun mk_main_compile arg = let
169    
170          fun main_compile arg = let              val { pervasive = perv_n, others, src } = arg
             val { rts, core, pervasive, primitives, binpaths } = arg  
171    
172                fun recompInitGroup () = let
173              val ovldR = GenericVC.Control.overloadKW              val ovldR = GenericVC.Control.overloadKW
174              val savedOvld = !ovldR              val savedOvld = !ovldR
175              val _ = ovldR := true              val _ = ovldR := true
176                    val sbnode = Compile.newSbnodeTraversal ()
177    
178              (* here we build a new gp -- the one that uses the freshly                  val perv_fsbnode = (NONE, perv_n)
              * brewed pervasive env, core env, and primitives *)  
             val core = valOf (RT.sbnode ginfo_nocore core)  
             val corenv =  CoerceEnv.es2bs (#1 (#stat core))  
             val core_sym = #1 (#sym core)  
   
             (* The following is a bit of a hack (but corenv is a hack anyway):  
              * As soon as we have core available, we have to patch the  
              * ginfo to include the correct corenv (because virtually  
              * everybody else needs access to corenv). *)  
             val param_justcore = mkInitParam { corenv = corenv }  
             val ginfo_justcore = { param = param_justcore, groupreg = groupreg,  
                                    errcons = errcons }  
   
             fun rt n = valOf (RT.sbnode ginfo_justcore n)  
             val rts = rt rts  
             val pervasive = rt pervasive  
   
             fun sn2pspec (name, n) = let  
                 val { stat = (s, sp), sym = (sy, syp), ctxt, bfc } = rt n  
                 val env =  
                     E.mkenv { static = s, symbolic = sy, dynamic = emptydyn }  
                 val pidInfo = { statpid = sp, sympid = syp, ctxt = ctxt }  
             in  
                 { name = name, env = env, pidInfo = pidInfo }  
             end  
   
             val pspecs = map sn2pspec primitives  
   
             val _ = ovldR := savedOvld  
   
             (* This is a hack but must be done for both the symbolic  
              * and later the dynamic part of the core environment:  
              * we must include these parts in the pervasive env. *)  
             val perv_sym = E.layerSymbolic (#1 (#sym pervasive), core_sym)  
179    
180              val param =                  fun rt n = valOf (sbnode ginfo n)
181                  mkParam { primconf = Primitive.configuration pspecs,                  val pervasive = rt perv_n
182                            pervasive = E.mkenv { static = #1 (#stat pervasive),  
183                                                  symbolic = perv_sym,                  fun rt2ie (n, ii: IInfo.info) = let
184                                                  dynamic = emptydyn },                      val s = #statenv ii ()
185                            pervcorepids =                      val (dae, mkDomain) = Statenv2DAEnv.cvt s
                             PidSet.addList (PidSet.empty,  
                                             [#2 (#stat pervasive),  
                                              #2 (#sym pervasive),  
                                              #2 (#stat core)]) }  
                         { corenv = corenv }  
             val stab =  
                 if deliver then SOME true else NONE  
186          in          in
187              case Parse.parse NONE param stab maingspec of                      (* Link path info = NONE, will be reset at import
188                  NONE => false                       * time (in members.sml). *)
189                | SOME (g, gp) =>                      { ie = ((NONE, n), dae), mkDomain = mkDomain }
190                      if recomp gp g then let                  end
191                          val rtspid = PS.toHex (#2 (#stat rts))  
192                          fun writeList s = let                  fun add_exports (n, exports) = let
193                              fun add ((p, flag), l) = let                      val { ie, mkDomain } = rt2ie (n, rt n)
194                                  val n = listName (p, true)                      fun ins_ie (sy, m) = SymbolMap.insert (m, sy, ie)
195                              in                  in
196                                  if flag then n :: l else l                      SymbolSet.foldl ins_ie exports (mkDomain ())
197                              end                  end
198                              fun transcribe (p, NONE) = listName (p, true)  
199                                | transcribe (p, SOME (off, desc)) =                  val special_exports = let
200                                  concat [listName (p, false),                      fun mkie (n, rtn) = #ie (rt2ie (n, rtn))
201                                          "@", Int.toString off, ":", desc]                  in
202                              val bootstrings =                      SymbolMap.insert (SymbolMap.empty,
203                                  foldr add (map transcribe (MkBootList.group g))                                        PervAccess.pervStrSym,
204                                        binpaths                                        mkie (perv_n, pervasive))
205                              fun show str =                  end
206                                  (TextIO.output (s, str);              in
207                                   TextIO.output (s, "\n"))                  GG.GROUP { exports = foldl add_exports special_exports others,
208                               kind = GroupGraph.LIB { wrapped = StringSet.empty,
209                                                       subgroups = [] },
210                               required = StringSet.singleton "primitive",
211                               grouppath = initgspec,
212                               sublibs = [] }
213                    before (ovldR := savedOvld)
214                end
215    
216                (* just go and load the stable init group or signal failure *)
217                fun loadInitGroup () = let
218                    val lsarg =
219                        { getGroup = fn _ => raise Fail "CMB: initial getGroup",
220                          anyerrors = ref false }
221                          in                          in
222                              app show bootstrings                  case Stabilize.loadStable ginfo lsarg initgspec of
223                        NONE => NONE
224                      | SOME (g as GG.GROUP { exports, ... }) => SOME g
225                      | SOME GG.ERRORGROUP => NONE
226                          end                          end
227    
228                (* Don't try to load the stable init group. Instead, recompile
229                 * directly. *)
230                fun dontLoadInitGroup () = let
231                    val g0 = recompInitGroup ()
232                    val stabarg = { group = g0, anyerrors = ref false }
233                      in                      in
234                        if deliver then                        if deliver then
235                         (SafeIO.perform { openIt = fn () =>                      case Stabilize.stabilize ginfo stabarg of
236                                             AutoDir.openTextOut pidfile,                          SOME g => g
237                                           closeIt = TextIO.closeOut,                        | NONE => raise Fail "CMB: cannot stabilize init group"
238                                           work = fn s =>                  else g0
239                                             TextIO.output (s, rtspid ^ "\n"),              end
240                                           cleanup = fn () =>  
241                                             OS.FileSys.remove pidfile              (* Try loading the init group from the stable file if possible;
242                                             handle _ => () };               * recompile if loading fails *)
243                          SafeIO.perform { openIt = fn () =>              fun tryLoadInitGroup () =
244                    case loadInitGroup () of
245                        SOME g => g
246                      | NONE => dontLoadInitGroup ()
247    
248                (* Ok, now, based on "paranoid" and stable verification,
249                 * call the appropriate function(s) to get the init group. *)
250                val init_group =
251                    if paranoid then let
252                        val export_nodes = perv_n :: others
253                        val ver_arg = (initgspec, export_nodes, [],
254                                       SrcPathSet.empty)
255                        val em = StableMap.empty
256                    in
257                        if VerifyStable.verify' ginfo em ver_arg then
258                            tryLoadInitGroup ()
259                        else dontLoadInitGroup ()
260                    end
261                    else tryLoadInitGroup ()
262    
263    
264                val stab = if deliver then SOME true else NONE
265    
266                val gr = GroupReg.new ()
267                val _ = GroupReg.register gr (initgspec, src)
268    
269                val parse_arg =
270                    { load_plugin = load_plugin,
271                      gr = gr,
272                      param = param,
273                      stabflag = stab,
274                      group = maingspec,
275                      init_group = init_group,
276                      paranoid = paranoid }
277            in
278                Servers.dirbase dirbase;
279                case Parse.parse parse_arg of
280                    NONE => NONE
281                  | SOME (g, gp) => let
282                        fun thunk () = let
283                            val _ = init_servers g
284                            fun store _ = ()
285                            val { group = recomp, ... } =
286                                Compile.newTraversal (fn _ => fn _ => (), store, g)
287                            val res =
288                                Servers.withServers (fn () => recomp gp)
289                        in
290                            if isSome res then let
291                                val { l = bootitems, ss } = mkBootList g
292                                val stablelibs = Reachable.stableLibsOf g
293                                fun inSet bi = StableSet.member (ss, bi)
294                                val frontiers =
295                                    SrcPathMap.map (Reachable.frontier inSet)
296                                                   stablelibs
297                                fun writeBootList s = let
298                                    fun wr str = TextIO.output (s, str ^ "\n")
299                                    val numitems = length bootitems
300                                    fun biggerlen (s, n) = Int.max (size s, n)
301                                    val maxlen = foldl biggerlen 0 bootitems
302                                in
303                                    wr (concat ["%", Int.toString numitems,
304                                                " ", Int.toString maxlen]);
305                                    app wr bootitems
306                                end
307                                fun writePid s i = let
308                                    val sn = BinInfo.stablename i
309                                    val os = BinInfo.offset i
310                                    val descr = BinInfo.describe i
311                                    val bfc = BFC.getStable
312                                        { stable = sn, offset = os, descr = descr }
313                                in
314                                    case BF.exportPidOf bfc of
315                                        NONE => ()
316                                      | SOME pid =>
317                                            (TextIO.output (s, " ");
318                                             TextIO.output (s, PS.toHex pid))
319                                end
320                                fun writePidLine s (p, set) =
321                                    if StableSet.isEmpty set then ()
322                                    else (TextIO.output (s, SrcPath.descr p);
323                                          StableSet.app (writePid s) set;
324                                          TextIO.output (s, "\n"))
325                                fun writePidMap s =
326                                    SrcPathMap.appi (writePidLine s) frontiers
327                            in
328                                if deliver then
329                                    (SafeIO.perform
330                                     { openIt = fn () =>
331                                             AutoDir.openTextOut listfile,                                             AutoDir.openTextOut listfile,
332                                           closeIt = TextIO.closeOut,                                           closeIt = TextIO.closeOut,
333                                           work = writeList,                                     work = writeBootList,
334                                           cleanup = fn () =>                                     cleanup = fn _ =>
335                                             OS.FileSys.remove listfile                                             OS.FileSys.remove listfile
336                                             handle _ => () };                                             handle _ => () };
337                          copyTextFile (SrcPath.osstring initgspec, cmifile);                                   SafeIO.perform
338                          Say.say ["Runtime System PID is: ", rtspid, "\n"])                                   { openIt = fn () =>
339                                           AutoDir.openTextOut pidmapfile,
340                                       closeIt = TextIO.closeOut,
341                                       work = writePidMap,
342                                       cleanup = fn _ =>
343                                           OS.FileSys.remove pidmapfile
344                                           handle _ => () };
345                                     Say.say
346                                          ["New boot directory has been built.\n"])
347                        else ();                        else ();
348                        true                        true
349                      end                      end
350                      else false                      else false
351          end handle Option => (RT.reset (); false)                      end
352                    in
353                        SOME ((g, gp, pcmode), thunk)
354                    end
355            end handle Option => (Compile.reset (); NONE)
356                     (* to catch valOf failures in "rt" *)                     (* to catch valOf failures in "rt" *)
357      in      in
358          case BuildInitDG.build ginfo_nocore initgspec of          case BuildInitDG.build ginfo initgspec of
359              SOME x => main_compile x              SOME x => mk_main_compile x
360            | NONE => false            | NONE => NONE
361        end
362    
363        fun compile dbopt =
364            case mk_compile { deliver = true, root = NONE,
365                              dirbase = dbopt, paranoid = true } of
366                NONE => false
367              | SOME (_, thunk) => thunk ()
368    
369        local
370            fun slave (dirbase, root) =
371                case mk_compile { deliver = false, root = SOME root,
372                                  dirbase = SOME dirbase, paranoid = false } of
373                    NONE => NONE
374                  | SOME ((g, gp, pcmode), _) => let
375                        val trav = Compile.newSbnodeTraversal () gp
376                        fun trav' sbn = isSome (trav sbn)
377                    in
378                        SOME (g, trav', pcmode)
379                    end
380        in
381            val _ = CMBSlaveHook.init archos slave
382      end      end
383    
384      val make' = compile false      val make' = compile
385      fun make () = make' NONE      fun make () = make' NONE
386      val deliver' = compile true      val symval = SSV.symval
     fun deliver () = deliver' NONE  
     fun reset () =  
         (RecompPersstate.reset ();  
          RT.resetAll ();  
          Recomp.reset ();  
          Parse.reset ())  
387  end  end
388    end (* local *)

Legend:
Removed from v.369  
changed lines
  Added in v.592

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0