/**
* 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)\ )