/** * This module defines generic strategies for packing a * set of modules reachable from a root module and for * flattening a set of modules into a single program. * * Module systems allow the definition of a program to be * split into separate units stored in separate files. For * languages that do not support separate compilation (such * as grammar formalisms) these separate units need to be * combined to create the whole program. * * Aspects of module packing and flattening * * - finding the module associated with the module name * - doing something with the module, i.e., adding it to the result * - finding the imports in a module * - keeping track of which modules have already been inlined */ module strategy/pack/common imports term/string strategy/pack/graph rules PackInit : root -> (root, (), []) strategies /** * Packing a module consists of collecting all modules into * a single file. */ pack(parser, imp) = PackInit; graph-nodes(Fst; parser, get-imports(imp), \ (n,x,xs) -> [x|xs] \ ) get-imports(imp) = collect(imp); concat rules WriteMod(getname, write, ext) : mod -> <write>(<add-extension>(<getname>mod, <ext>()), mod) strategies /** * Unpacking is the reverse of packing, i.e., writing each module * in a list of modules to a separate file. */ unpack(wrapper: (term -> term) * term -> term, getname, ext) = wrapper(WriteMod(getname, WriteToTextFile, ext)) strategies /** * <flatten> (root, mods)| produces a flattened version of the root module. */ flatten(imp, nameeq, getcontent) = \ (root, mods) -> (root, mods, []) \; graph-nodes(lookup(nameeq), get-imports(imp), \ (_,x,y) -> <conc>(<getcontent>x, y)\ )