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

SCM Repository

[smlnj] Annotation of /sml/trunk/src/cm/main/cm-boot.sml
ViewVC logotype

Annotation of /sml/trunk/src/cm/main/cm-boot.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 676 - (view) (download)

1 : blume 375 (*
2 :     * This is the module that actually puts together the contents of the
3 : blume 587 * structure CM that people find in smlnj/cm/full.cm. A "minimal" structure
4 : blume 375 * CM is defined in CmHook, but it needs to be initialized at bootstrap
5 : blume 495 * time.
6 : blume 375 *
7 :     * Copyright (c) 1999 by Lucent Bell Laboratories
8 :     *
9 :     * author: Matthias Blume (blume@cs.princeton.edu)
10 :     *)
11 :     functor LinkCM (structure HostMachDepVC : MACHDEP_VC) = struct
12 :    
13 :     datatype envrequest = AUTOLOAD | BARE
14 :    
15 :     local
16 :     structure E = GenericVC.Environment
17 : blume 569 structure DE = DynamicEnv
18 : blume 375 structure SE = GenericVC.StaticEnv
19 :     structure ER = GenericVC.EnvRef
20 :     structure S = GenericVC.Symbol
21 :     structure EM = GenericVC.ErrorMsg
22 :     structure BF = HostMachDepVC.Binfile
23 : blume 380 structure P = OS.Path
24 :     structure F = OS.FileSys
25 : blume 451 structure DG = DependencyGraph
26 : blume 587 structure GG = GroupGraph
27 : blume 375
28 :     val os = SMLofNJ.SysInfo.getOSKind ()
29 : blume 464 val my_archos =
30 :     concat [HostMachDepVC.architecture, "-", FilenamePolicy.kind2name os]
31 : blume 375
32 :     structure SSV =
33 :     SpecificSymValFn (structure MachDepVC = HostMachDepVC
34 :     val os = os)
35 :    
36 :     val emptydyn = E.dynamicPart E.emptyEnv
37 : blume 569 val system_values = ref (SrcPathMap.empty: E.dynenv SrcPathMap.map)
38 : blume 375
39 : blume 588 structure StabModmap = StabModmapFn ()
40 :    
41 : blume 400 structure Compile =
42 : blume 448 CompileFn (structure MachDepVC = HostMachDepVC
43 : blume 588 structure StabModmap = StabModmap
44 : blume 464 val compile_there = Servers.compile o SrcPath.descr)
45 : blume 400
46 : blume 537 structure BFC =
47 :     BfcFn (structure MachDepVC = HostMachDepVC)
48 :    
49 : blume 399 structure Link =
50 :     LinkFn (structure MachDepVC = HostMachDepVC
51 : blume 537 structure BFC = BFC
52 : blume 399 val system_values = system_values)
53 : blume 375
54 :     structure AutoLoad = AutoLoadFn
55 : blume 399 (structure C = Compile
56 : blume 403 structure L = Link
57 :     structure BFC = BFC)
58 : blume 375
59 : blume 537 val mkBootList = #l o MkBootList.group (fn p => p)
60 :    
61 : blume 587 fun init_servers (GG.GROUP { grouppath, ... }) =
62 : blume 464 Servers.cm { archos = my_archos, project = SrcPath.descr grouppath }
63 : blume 587 | init_servers GG.ERRORGROUP = ()
64 : blume 456
65 : blume 399 fun recomp_runner gp g = let
66 : blume 456 val _ = init_servers g
67 : blume 403 fun store _ = ()
68 :     val { group, ... } = Compile.newTraversal (Link.evict, store, g)
69 : blume 399 in
70 : blume 450 isSome (Servers.withServers (fn () => group gp))
71 :     before Link.cleanup gp
72 : blume 399 end
73 : blume 375
74 :     (* This function combines the actions of "recompile" and "exec".
75 :     * When successful, it combines the results (thus forming a full
76 :     * environment) and adds it to the toplevel environment. *)
77 : blume 587 fun make_runner _ _ GG.ERRORGROUP = false
78 :     | make_runner add_bindings gp (g as GG.GROUP grec) = let
79 :     val { required = rq, ... } = grec
80 :     val { store, get } = BFC.new ()
81 :     val _ = init_servers g
82 :     val { group = c_group, ... } =
83 :     Compile.newTraversal (Link.evict, store, g)
84 :     val { group = l_group, ... } = Link.newTraversal (g, get)
85 :     in
86 :     case Servers.withServers (fn () => c_group gp) of
87 :     NONE => false
88 :     | SOME { stat, sym} =>
89 : blume 537 (* Before executing the code, we announce the privileges
90 : blume 399 * that are being invoked. (For the time being, we assume
91 :     * that everybody has every conceivable privilege, but at
92 :     * the very least we announce which ones are being made
93 :     * use of.) *)
94 : blume 400 (Link.cleanup gp;
95 : blume 399 if StringSet.isEmpty rq then ()
96 :     else Say.say ("$Execute: required privileges are:\n" ::
97 :     map (fn s => (" " ^ s ^ "\n")) (StringSet.listItems rq));
98 :     case l_group gp of
99 : blume 375 NONE => false
100 : blume 518 | SOME dyn =>
101 :     (if add_bindings then
102 :     let val delta = E.mkenv { static = stat,
103 :     symbolic = sym,
104 :     dynamic = dyn }
105 :     val base = #get ER.topLevel ()
106 : blume 587 val new = E.concatEnv (delta, base)
107 : blume 518 in
108 :     #set ER.topLevel new;
109 :     Say.vsay ["[New bindings added.]\n"]
110 :     end
111 :     else ();
112 :     true))
113 : blume 587 end
114 : blume 375
115 :     val al_greg = GroupReg.new ()
116 :    
117 :     (* Instantiate the stabilization mechanism. *)
118 :     structure Stabilize =
119 : blume 403 StabilizeFn (structure MachDepVC = HostMachDepVC
120 : blume 588 structure StabModmap = StabModmap
121 : blume 403 fun recomp gp g = let
122 :     val { store, get } = BFC.new ()
123 : blume 456 val _ = init_servers g
124 : blume 403 val { group, ... } =
125 :     Compile.newTraversal (Link.evict, store, g)
126 :     in
127 : blume 450 case Servers.withServers (fn () => group gp) of
128 : blume 403 NONE => NONE
129 :     | SOME _ => SOME get
130 :     end
131 :     val getII = Compile.getII)
132 : blume 375
133 :     (* Access to the stabilization mechanism is integrated into the
134 :     * parser. I'm not sure if this is the cleanest way, but it works
135 :     * well enough. *)
136 :     structure Parse = ParseFn (structure Stabilize = Stabilize
137 : blume 588 structure StabModmap = StabModmap
138 : blume 537 fun evictStale () =
139 :     (Compile.evictStale ();
140 :     Link.evictStale ())
141 : blume 375 val pending = AutoLoad.getPending)
142 :    
143 :     local
144 : blume 592 type kernelValues = { init_group : GG.group }
145 : blume 375
146 :     val fnpolicy = FilenamePolicy.colocate
147 :     { os = os, arch = HostMachDepVC.architecture }
148 :    
149 :     val theValues = ref (NONE: kernelValues option)
150 :    
151 :     in
152 : blume 666 val penv = SrcPath.newEnv ()
153 : blume 645
154 : blume 377 (* cancelling anchors cannot affect the order of existing paths
155 :     * (it may invalidate some paths; but all other ones stay as
156 :     * they are) *)
157 : blume 666 fun setAnchor a v = SrcPath.set_anchor (penv, a, v)
158 : blume 377 (* same goes for reset because it just cancels all anchors... *)
159 : blume 666 fun resetPathConfig () = SrcPath.reset_anchors penv
160 : blume 569 (* get the current binding for an anchor *)
161 : blume 666 fun getAnchor a () = SrcPath.get_anchor (penv, a)
162 : blume 375
163 : blume 525 fun mkStdSrcPath s =
164 : blume 666 SrcPath.file
165 :     (SrcPath.standard { err = fn s => raise Fail s, env = penv }
166 :     { context = SrcPath.cwd (), spec = s })
167 : blume 525
168 : blume 479 fun getPending () = let
169 : blume 375 fun one (s, _) = let
170 :     val nss = Symbol.nameSpaceToString (Symbol.nameSpace s)
171 :     val n = Symbol.name s
172 :     in
173 : blume 479 concat [" ", nss, " ", n, "\n"]
174 : blume 375 end
175 :     in
176 : blume 479 map one (SymbolMap.listItemsi (AutoLoad.getPending ()))
177 : blume 375 end
178 :    
179 :     fun initPaths () = let
180 : blume 433 val lpcth = #get StdConfig.local_pathconfig ()
181 : blume 375 val p = case lpcth () of
182 :     NONE => []
183 :     | SOME f => [f]
184 : blume 433 val p = #get StdConfig.pathcfgspec () :: p
185 : blume 666 fun processOne f = SrcPath.processSpecFile (penv, f)
186 : blume 375 handle _ => ()
187 :     in
188 : blume 676 app processOne p;
189 :     SrcPath.sync ()
190 : blume 375 end
191 :    
192 : blume 537 fun getTheValues () = valOf (!theValues)
193 :     handle Option => raise Fail "CMBoot: theParam not initialized"
194 :    
195 : blume 375 fun param () = let
196 : blume 537 val v = getTheValues ()
197 : blume 375 in
198 : blume 537 { fnpolicy = fnpolicy,
199 : blume 666 penv = penv,
200 : blume 433 symval = SSV.symval,
201 : blume 592 keep_going = #get StdConfig.keep_going () }
202 : blume 375 end
203 :    
204 : blume 537 val init_group = #init_group o getTheValues
205 :    
206 : blume 507 fun dropPickles () =
207 :     if #get StdConfig.conserve_memory () then
208 :     Parse.dropPickles ()
209 :     else ()
210 :    
211 : blume 537 fun parse_arg (gr, sflag, p) =
212 :     { load_plugin = load_plugin, gr = gr, param = param (),
213 : blume 569 stabflag = sflag, group = p,
214 :     init_group = init_group (), paranoid = false }
215 : blume 537
216 :     and autoload s = let
217 : blume 525 val p = mkStdSrcPath s
218 : blume 375 in
219 : blume 537 (case Parse.parse (parse_arg (al_greg, NONE, p)) of
220 : blume 505 NONE => false
221 :     | SOME (g, _) =>
222 : blume 537 (AutoLoad.register (GenericVC.EnvRef.topLevel, g);
223 :     true))
224 : blume 507 before dropPickles ()
225 : blume 375 end
226 :    
227 : blume 578 and run mkSrcPath sflag f s = let
228 :     val p = mkSrcPath s
229 : blume 537 val gr = GroupReg.new ()
230 : blume 375 in
231 : blume 537 (case Parse.parse (parse_arg (gr, sflag, p)) of
232 : blume 505 NONE => false
233 :     | SOME (g, gp) => f gp g)
234 : blume 507 before dropPickles ()
235 : blume 375 end
236 :    
237 : blume 578 and load_plugin context x = let
238 : blume 518 val _ = Say.vsay ["[attempting to load plugin ", x, "]\n"]
239 : blume 643 fun badname s = Say.say ["[bad plugin name: ", s, "]\n"]
240 : blume 578 fun mkSrcPath s =
241 : blume 666 SrcPath.file
242 :     (SrcPath.standard { env = penv, err = badname }
243 :     { context = context, spec = s })
244 : blume 518 val success =
245 : blume 578 run mkSrcPath NONE (make_runner false) x handle _ => false
246 : blume 518 in
247 :     if success then
248 :     Say.vsay ["[plugin ", x, " loaded successfully]\n"]
249 :     else
250 :     Say.vsay ["[unable to load plugin ", x, "]\n"];
251 :     success
252 :     end
253 :    
254 : blume 666 fun cwd_load_plugin x = load_plugin (SrcPath.cwd ()) x
255 : blume 578
256 : blume 449 fun stabilize_runner gp g = true
257 :    
258 : blume 578 fun stabilize recursively =
259 :     run mkStdSrcPath (SOME recursively) stabilize_runner
260 :     val recomp = run mkStdSrcPath NONE recomp_runner
261 :     val make = run mkStdSrcPath NONE (make_runner true)
262 : blume 449
263 : blume 642
264 :     fun sources archos group = let
265 :     val policy =
266 :     case archos of
267 :     NONE => fnpolicy
268 :     | SOME ao => FilenamePolicy.colocate_generic ao
269 : blume 666 fun sourcesOf ((p, gth, _), (v, a)) =
270 : blume 642 if SrcPathSet.member (v, p) then (v, a)
271 :     else
272 :     let val v = SrcPathSet.add (v, p)
273 : blume 652 in case gth () of
274 : blume 642 GG.ERRORGROUP => (v, a)
275 :     | GG.GROUP { kind, sources, ... } => let
276 :     fun add (p, x, a) =
277 :     StringMap.insert
278 :     (a, SrcPath.osstring p, x)
279 :     val a = SrcPathMap.foldli add a sources
280 :     fun sg subgroups =
281 :     foldl sourcesOf (v, a) subgroups
282 :     in
283 :     case kind of
284 :     GG.LIB { kind, version } =>
285 :     (case kind of
286 :     GG.STABLE _ => let
287 :     val file = SrcPath.osstring p
288 :     val (a, x) =
289 :     StringMap.remove (a, file)
290 :     val sfile =
291 :     FilenamePolicy.mkStableName
292 :     policy (p, version)
293 :     in
294 :     (v,
295 :     StringMap.insert (a, sfile, x))
296 :     end
297 :     | GG.DEVELOPED d => sg (#subgroups d))
298 :     | GG.NOLIB n => sg (#subgroups n)
299 :     end
300 :     end
301 : blume 632 val p = mkStdSrcPath group
302 :     val gr = GroupReg.new ()
303 :     in
304 :     (case Parse.parse (parse_arg (gr, NONE, p)) of
305 : blume 642 SOME (g, _) => let
306 :     val (_, sm) =
307 : blume 666 sourcesOf ((p, fn () => g, []),
308 : blume 642 (SrcPathSet.empty,
309 :     StringMap.singleton
310 :     (SrcPath.osstring p,
311 :     { class = "cm",
312 :     derived = false })))
313 :     fun add (s, { class, derived }, l) =
314 :     { file = s, class = class, derived = derived } :: l
315 : blume 632 in
316 : blume 642 SOME (StringMap.foldli add [] sm)
317 :     end
318 :     | _ => NONE)
319 : blume 632 before dropPickles ()
320 :     end
321 :    
322 : blume 537 (* I would have liked to express this using "run", but "run"
323 :     * thinks it has to return a bool... *)
324 :     fun mk_standalone sflag s = let
325 :     val p = mkStdSrcPath s
326 :     val gr = GroupReg.new ()
327 :     in
328 :     (case Parse.parse (parse_arg (gr, sflag, p)) of
329 :     NONE => NONE
330 :     | SOME (g, gp) =>
331 :     if isSome sflag orelse recomp_runner gp g then
332 :     SOME (mkBootList g)
333 :     else NONE)
334 :     before dropPickles ()
335 :     end
336 :    
337 : blume 518 fun slave () = let
338 : blume 537 val gr = GroupReg.new ()
339 :     fun parse p = Parse.parse (parse_arg (gr, NONE, p))
340 : blume 518 in
341 : blume 666 Slave.slave { penv = penv,
342 : blume 518 parse = parse,
343 : blume 480 my_archos = my_archos,
344 :     sbtrav = Compile.newSbnodeTraversal,
345 :     make = make }
346 : blume 518 end
347 : blume 456
348 : blume 518 fun al_ginfo () = { param = param (),
349 :     groupreg = al_greg,
350 :     errcons = EM.defaultConsumer () }
351 :    
352 :     val al_manager =
353 :     AutoLoad.mkManager { get_ginfo = al_ginfo,
354 :     dropPickles = dropPickles }
355 :    
356 :     fun al_manager' (ast, _, ter) = al_manager (ast, ter)
357 :    
358 : blume 375 fun reset () =
359 : blume 399 (Compile.reset ();
360 :     Link.reset ();
361 : blume 375 AutoLoad.reset ();
362 :     Parse.reset ();
363 : blume 588 SmlInfo.reset ();
364 :     StabModmap.reset ())
365 : blume 375
366 : blume 569 fun initTheValues (bootdir, de, er, autoload_postprocess) = let
367 : blume 375 val _ = let
368 :     fun listDir ds = let
369 :     fun loop l =
370 : blume 380 case F.readDir ds of
371 : blume 375 "" => l
372 :     | x => loop (x :: l)
373 :     in
374 :     loop []
375 :     end
376 :     val fileList = SafeIO.perform
377 : blume 380 { openIt = fn () => F.openDir bootdir,
378 :     closeIt = F.closeDir,
379 : blume 375 work = listDir,
380 : blume 459 cleanup = fn _ => () }
381 : blume 380 fun isDir x = F.isDir x handle _ => false
382 : blume 375 fun subDir x = let
383 : blume 380 val d = P.concat (bootdir, x)
384 : blume 375 in
385 :     if isDir d then SOME (x, d) else NONE
386 :     end
387 :     val pairList = List.mapPartial subDir fileList
388 : blume 666 fun sa (x, d) = SrcPath.set_anchor (penv, x, SOME d)
389 : blume 375 in
390 : blume 666 app sa pairList
391 : blume 375 end
392 : blume 569
393 :     val pidmapfile = P.concat (bootdir, BtNames.pidmap)
394 :     fun readpidmap s = let
395 :     fun loop m = let
396 :     fun enter (d, pids) = let
397 :     fun enter1 (hexp, e) =
398 :     case GenericVC.PersStamps.fromHex hexp of
399 :     SOME p => (DE.bind (p, DE.look de p, e)
400 :     handle DE.Unbound => e)
401 :     | NONE => e
402 :     in
403 : blume 666 SrcPathMap.insert (m, SrcPath.decode penv d,
404 : blume 569 foldl enter1 emptydyn pids)
405 :     end
406 :     in
407 :     case TextIO.inputLine s of
408 :     "" => m
409 :     | line => (case String.tokens Char.isSpace line of
410 :     d :: pids => loop (enter (d, pids))
411 :     | _ => loop m)
412 :     end
413 :     in
414 :     system_values := loop SrcPathMap.empty
415 :     end
416 :    
417 :     val _ =
418 :     SafeIO.perform { openIt = fn () => TextIO.openIn pidmapfile,
419 :     closeIt = TextIO.closeIn,
420 :     work = readpidmap,
421 :     cleanup = fn _ => () }
422 :    
423 : blume 525 val initgspec = mkStdSrcPath BtNames.initgspec
424 : blume 537 val ginfo = { param = { fnpolicy = fnpolicy,
425 : blume 666 penv = penv,
426 : blume 433 symval = SSV.symval,
427 : blume 592 keep_going = false },
428 : blume 375 groupreg = GroupReg.new (),
429 :     errcons = EM.defaultConsumer () }
430 : blume 537 fun loadInitGroup () =
431 : blume 666 Stabilize.loadStable
432 :     { getGroup = fn _ =>
433 :     raise Fail "CMBoot: initial getGroup",
434 :     anyerrors = ref false }
435 :     (ginfo, initgspec, NONE, [])
436 : blume 375 in
437 : blume 537 case loadInitGroup () of
438 :     NONE => raise Fail "CMBoot: unable to load init group"
439 :     | SOME init_group => let
440 :     val _ = Compile.reset ()
441 :     val _ = Link.reset ()
442 : blume 375
443 : blume 537 val { exports = ctm, ... } =
444 :     Compile.newTraversal (fn _ => fn _ => (),
445 :     fn _ => (),
446 :     init_group)
447 :     val { exports = ltm, ... } = Link.newTraversal
448 :     (init_group, fn _ => raise Fail "init: get bfc?")
449 :    
450 :     fun getSymTrav (tr_m, sy) =
451 :     case SymbolMap.find (tr_m, sy) of
452 :     NONE => raise Fail "init: bogus init group (1)"
453 :     | SOME tr => tr
454 :    
455 : blume 592 val perv_ct = getSymTrav (ctm, PervAccess.pervStrSym)
456 :     val perv_lt = getSymTrav (ltm, PervAccess.pervStrSym)
457 : blume 537
458 :     fun doTrav t =
459 :     case t ginfo of
460 :     SOME r => r
461 :     | NONE => raise Fail "init: bogus init group (2)"
462 :    
463 :     val { stat = pervstat, sym = pervsym } = doTrav perv_ct
464 :     val pervdyn = doTrav perv_lt
465 :    
466 :     val pervasive = E.mkenv { static = pervstat,
467 :     symbolic = pervsym,
468 :     dynamic = pervdyn }
469 :    
470 : blume 495 fun bare_autoload x =
471 :     (Say.say
472 :     ["!* ", x,
473 :     ": \"autoload\" not available, using \"make\"\n"];
474 :     make x)
475 :     val bare_preload =
476 :     Preload.preload { make = make,
477 :     autoload = bare_autoload }
478 :     val standard_preload =
479 :     Preload.preload { make = make, autoload = autoload }
480 : blume 375 in
481 : blume 592 #set ER.pervasive pervasive;
482 : blume 587 #set ER.topLevel E.emptyEnv;
483 : blume 592 theValues := SOME { init_group = init_group };
484 : blume 375 case er of
485 :     BARE =>
486 : blume 495 (bare_preload BtNames.bare_preloads;
487 : blume 569 system_values := SrcPathMap.empty;
488 : blume 495 NONE)
489 : blume 375 | AUTOLOAD =>
490 :     (HostMachDepVC.Interact.installCompManager
491 :     (SOME al_manager');
492 : blume 495 standard_preload BtNames.standard_preloads;
493 : blume 507 (* unconditionally drop all library pickles *)
494 :     Parse.dropPickles ();
495 : blume 495 SOME (autoload_postprocess ()))
496 : blume 375 end
497 :     end
498 :     end
499 :     in
500 : blume 495 fun init (bootdir, de, er) = let
501 :     fun procCmdLine () = let
502 :     val autoload = ignore o autoload
503 :     val make = ignore o make
504 :     fun p (f, ("sml" | "sig"), mk) = HostMachDepVC.Interact.useFile f
505 :     | p (f, "cm", mk) = mk f
506 :     | p (f, e, mk) = Say.say ["!* unable to process `", f,
507 :     "' (unknown extension `", e, "')\n"]
508 :     fun arg ("-a", _) = autoload
509 :     | arg ("-m", _) = make
510 :     | arg (f, mk) =
511 :     (p (f,
512 :     String.map Char.toLower (getOpt (OS.Path.ext f, "<none>")),
513 :     mk);
514 :     mk)
515 :     in
516 :     case SMLofNJ.getArgs () of
517 :     ["@CMslave"] => (#set StdConfig.verbose false; slave ())
518 :     | l => ignore (foldl arg autoload l)
519 :     end
520 : blume 448 in
521 : blume 569 initTheValues (bootdir, de, er,
522 :     fn () => (Cleanup.install initPaths;
523 :     procCmdLine))
524 : blume 448 end
525 : blume 479
526 :     structure CM :> CM = struct
527 :     type 'a controller = { get : unit -> 'a, set : 'a -> unit }
528 :    
529 :     structure Anchor = struct
530 : blume 569 fun anchor a = { get = getAnchor a, set = setAnchor a }
531 : blume 479 val reset = resetPathConfig
532 :     end
533 :    
534 :     structure Control = struct
535 :     val keep_going = StdConfig.keep_going
536 :     val verbose = StdConfig.verbose
537 :     val parse_caching = StdConfig.parse_caching
538 :     val warn_obsolete = StdConfig.warn_obsolete
539 :     val debug = StdConfig.debug
540 : blume 505 val conserve_memory = StdConfig.conserve_memory
541 : blume 479 end
542 :    
543 :     structure Library = struct
544 : blume 666 type lib = SrcPath.file
545 : blume 479 val known = Parse.listLibs
546 :     val descr = SrcPath.descr
547 :     val osstring = SrcPath.osstring
548 :     val dismiss = Parse.dismissLib
549 : blume 632 fun unshare lib = (Link.unshare lib; dismiss lib)
550 : blume 479 end
551 :    
552 :     structure State = struct
553 :     val synchronize = SrcPath.sync
554 :     val reset = reset
555 :     val pending = getPending
556 :     end
557 :    
558 :     structure Server = struct
559 :     type server = Servers.server
560 : blume 666 fun start x = Servers.start x
561 :     before SrcPath.scheduleNotification ()
562 : blume 479 val stop = Servers.stop
563 :     val kill = Servers.kill
564 :     val name = Servers.name
565 :     end
566 :    
567 :     val autoload = autoload
568 :     val make = make
569 :     val recomp = recomp
570 :     val stabilize = stabilize
571 :    
572 : blume 642 val sources = sources
573 : blume 632
574 : blume 479 val symval = SSV.symval
575 : blume 578 val load_plugin = cwd_load_plugin
576 : blume 537 val mk_standalone = mk_standalone
577 : blume 479 end
578 : blume 525
579 : blume 578 structure Tools = ToolsFn (val load_plugin = cwd_load_plugin
580 : blume 666 val penv = penv)
581 : blume 578
582 :     val load_plugin = load_plugin
583 : blume 375 end
584 :     end

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