+fun makeEmacsKeywords infiles =
+ let
+ val (_, infiles) = Order.order NONE infiles
+ val G = foldl (fn (fname, G) => check' G fname) Env.empty infiles
+
+ fun annotate_decl d =
+ case d of
+ DVal (name, NONE, e) =>
+ (case Env.lookupVal G name of
+ NONE => d
+ | SOME t => DVal (name, SOME t, e))
+ | _ => d
+
+ fun doFile (file, acc) =
+ let
+ val (_, decls, _) = Parse.parse file
+
+ fun isAction evs (t, _) =
+ case t of
+ TAction (_, r1, r2) =>
+ let
+ fun enrich (r, evs) =
+ StringMap.foldli (fn (ev, _, evs) =>
+ StringSet.add (evs, ev))
+ evs r
+ in
+ SOME (enrich (r2, enrich (r1, evs)))
+ end
+ | TArrow (_, t) => isAction evs t
+ | TNested (_, t) => isAction evs t
+ | TUnif (_, ref (SOME t)) => isAction evs t
+ | _ => NONE
+ in
+ foldl (fn ((d, _, _), (types, contexts, actions, vals, evs)) =>
+ case annotate_decl d of
+ DExternType s => (s :: types, contexts, actions, vals, evs)
+ | DExternVal (s, t) =>
+ (case isAction evs t of
+ SOME evs => (types, contexts, s :: actions, vals, evs)
+ | NONE => (types, contexts, actions, s :: vals, evs))
+ | DVal (s, NONE, _) => (types, contexts, actions, s :: vals, evs)
+ | DVal (s, SOME t, _) =>
+ (case isAction evs t of
+ SOME evs => (types, contexts, s :: actions, vals, evs)
+ | NONE => (types, contexts, actions, s :: vals, evs))
+ | DContext s => (types, s :: contexts, actions, vals, evs))
+ acc decls
+ end
+
+ val (types, contexts, actions, vals, evs) =
+ foldl doFile ([], [], [], [], StringSet.empty) infiles
+
+ fun printKind (ident, syms) =
+ (print "(defconst domtool-";
+ print ident;
+ print "-regexp\n (domtool-syms-re";
+ app (fn s => (print " \""; print s; print "\"")) syms;
+ print ")\n \"A regexp that matches Domtool ";
+ print ident;
+ print " from the standard library.\")\n\n")
+ in
+ printKind ("types", types);
+ printKind ("contexts", contexts);
+ printKind ("actions", actions);
+ printKind ("vals", vals);
+ printKind ("env-vars", StringSet.listItems evs)
+ end
+