Annotation of researchv10no/cmd/sml/src/sepcomp/moduleComp.sml, revision 1.1.1.1

1.1       root        1: (* Copyright 1989 by AT&T Bell Laboratories *)
                      2: (* moduleComp.sml *)
                      3: (* Modules compiler for New Jersey ML.   Nick Rothwell, LFCS, January 1989. *)
                      4: (* New version, doing proper lambda nesting for declarations and imports,
                      5:    rather than the old clatty concatenation stuff. *)
                      6: 
                      7: functor ModuleComp(structure Absyn: BAREABSYN
                      8:                     sharing Absyn = BareAbsyn
                      9:                   structure Lambda: LAMBDA
                     10:                   structure Opt: OPT sharing Opt.L = Lambda
                     11:                   structure Machm: CODEGENERATOR
                     12:                  ): MODULE_COMPILER =
                     13:   struct
                     14:     structure Lambda = Lambda
                     15:     structure Absyn = Absyn
                     16: 
                     17:     val bug = ErrorMsg.impossible
                     18: 
                     19:      (* Warning:  if DEBUG is true, then exportFn tends to grab the whole
                     20:         compiler.   --Appel *)
                     21:     val DEBUG = false
                     22: 
                     23:     type lvar = Access.lvar
                     24:     type lexp = Lambda.lexp
                     25:     type code = string
                     26: 
                     27:     fun assert(msg, cond) =
                     28:       if cond then () else bug("assert: " ^ msg)
                     29: 
                     30:     fun pr s = (output std_out s; flush_out std_out)
                     31: 
                     32:     fun debug s = if DEBUG then pr s else ()
                     33: 
                     34: 
                     35:     abstype LambDynModule =
                     36:            LAMBDYNMODULE of {entry: Entry, lvars: lvar list} list
                     37:                        (* These are in reverse order of declaration. *)
                     38:        and CodeDynModule =
                     39:            CODEDYNMODULE of {self: code, subModules: CodeDynModule list}
                     40:                        (* The code is for a function:
                     41:                           "(M1, ..., Mn) -> looker -> array*rubbish"
                     42:                           where each Mi is a "looker -> array*rubbish" *)
                     43: 
                     44:        and Entry = LAMBDAentry of lexp->lexp           (* unclosed *)
                     45:                  | IMPORTentry of CodeDynModule
                     46:     with
                     47:       val emptyDynModule = LAMBDYNMODULE []
                     48: 
                     49:       exception AddDeclaration
                     50:       fun addDeclaration(dec, lvars, LAMBDYNMODULE entries) =
                     51:         let
                     52:          val newEntry =
                     53:            {entry=LAMBDAentry(Translate.transDec dec), lvars=rev lvars}
                     54:         in
                     55:          if !ErrorMsg.anyErrors then
                     56:            raise AddDeclaration
                     57:          else
                     58:            LAMBDYNMODULE(newEntry :: entries)
                     59:        end
                     60: 
                     61:       fun importDynModule(LAMBDYNMODULE inner, LAMBDYNMODULE outer) =
                     62:         LAMBDYNMODULE(inner @ outer)
                     63: 
                     64:       fun abstractDynModule(codeDynModule, lvars) =
                     65:         LAMBDYNMODULE [{entry=IMPORTentry codeDynModule, lvars=lvars}]
                     66: 
                     67:      (* compiler: takes a LambDynModule to a CodeDynModule. We tie together
                     68:         all the lambdas as a set of nested LET declarations. Where we import
                     69:        already-compiled modules, these are abstracted to be arguments to the
                     70:        final lambda expression. *)
                     71: 
                     72:       fun inventLvar name =
                     73:         let
                     74:          val saving = !System.Control.saveLvarNames
                     75:          val _ = (System.Control.saveLvarNames := true)
                     76:          val lvar = Access.namedLvar(Symbol.symbol(name ^ ":"))
                     77:          val _ = (System.Control.saveLvarNames := saving)
                     78:        in
                     79:          lvar
                     80:        end
                     81: 
                     82:      (* Some local lambda-building stuff. This should probably go in a wee
                     83:         structure of its own. *)
                     84: 
                     85:       local
                     86:         open Lambda
                     87:       in
                     88:         fun apply(lvar1, lvar2) = APP(VAR lvar1, VAR lvar2)
                     89: 
                     90:        fun let_1(lvar, exp1, exp2) = APP(FN(lvar, exp2), exp1)
                     91: 
                     92:         fun fn_N(name, lvars, exp) =
                     93:          let
                     94:            val vecLvar = inventLvar name
                     95:            val vecExp = VAR vecLvar
                     96:            fun doit(lv :: rest, n) =
                     97:                  let_1(lv, SELECT(n, vecExp), doit(rest, n+1))
                     98:              | doit(nil, _) = exp
                     99:          in
                    100:            FN(vecLvar, doit(lvars, 0))
                    101:          end
                    102: 
                    103:         fun let_N(name, lvars, exp1, exp2) =
                    104:          APP(fn_N(name, lvars, exp2), exp1)
                    105: 
                    106:        fun record lvars = RECORD(map VAR lvars)
                    107:       end
                    108: 
                    109:      (* foldLambda: takes a list of entries (assumed to be in same order
                    110:        as the actual module declarations), and generates one big lambda.
                    111:        We close it later. foldLambda returns
                    112:        {lambda, imports, importLvars}. *)
                    113: 
                    114:       fun foldLambda({entry=LAMBDAentry thisFn, lvars} :: rest,
                    115:                     looker, allVars
                    116:                    ) =
                    117:            let
                    118:              val {lambda=next, imports, importLvars} =
                    119:                foldLambda(rest, looker, lvars @ allVars)
                    120:            in
                    121:              {lambda=thisFn next,      (* apply this fn->lambda to the
                    122:                                           argument (that's how transDec
                    123:                                           works...) *)
                    124:               imports=imports,
                    125:               importLvars=importLvars
                    126:              }
                    127:            end
                    128: 
                    129:        | foldLambda({entry=IMPORTentry subMod, lvars} :: rest,
                    130:                     looker, allVars
                    131:                    ) =
                    132:            let
                    133:              val modLvar =
                    134:                inventLvar("importModule/" ^ makestring(length rest))
                    135:              val {lambda=next, imports, importLvars} =
                    136:                foldLambda(rest, looker, lvars @ allVars)
                    137:            in
                    138:              {lambda=let_N("importEntry", lvars, apply(modLvar,looker), next),
                    139:               imports=subMod :: imports,
                    140:               importLvars = modLvar :: importLvars
                    141:              }
                    142:            end
                    143: 
                    144:        | foldLambda(nil, _, allVars) =
                    145:            {lambda=record(rev allVars), imports=nil, importLvars=nil}
                    146:                                        (* Make sure the lvars comprising
                    147:                                           the eventual record are the
                    148:                                           right way round!! *)
                    149: 
                    150:      (* codegen compiles a lambda to a machine-code string. *)
                    151: 
                    152:       exception Codegen
                    153:       fun codegen lambda: string =
                    154:          let
                    155:              val _ = debug "codegen...";
                    156:              val executable = Machm.generate lambda
                    157:              val _ = debug("done (" ^ makestring(size executable) ^ ").\n");
                    158:          in
                    159:              if !ErrorMsg.anyErrors then raise Codegen else executable
                    160:          end
                    161: 
                    162:       fun spaces n =
                    163:         let
                    164:           fun spaces'(0, sp) = debug sp
                    165:             | spaces'(n, sp) = spaces'(n-1, " " ^ sp)
                    166:        in
                    167:          spaces'(n, "")
                    168:        end
                    169: 
                    170:       fun printCodeDynModule indent (CODEDYNMODULE{self, subModules}) =
                    171:         (spaces indent;
                    172:         debug("CodeDynModule, self=[..." ^ makestring(size self) ^ "...]\n");
                    173:         spaces indent;
                    174:         debug "sub-modules=(\n";
                    175:         app (printCodeDynModule(indent+3)) subModules;
                    176:         spaces indent;
                    177:         debug ")\n"
                    178:        )
                    179: 
                    180:       val printNums = app (fn i: int => debug(makestring i ^ " "))
                    181: 
                    182:       fun printLambEntry{entry=LAMBDAentry lexpFn, lvars} =
                    183:             (debug "*LAMBDA*\n";
                    184:             MCprint.printLexp(lexpFn(record nil));
                    185:             debug ";\n   lvars=[ ";
                    186:             printNums lvars;
                    187:             debug "].\n"
                    188:            )
                    189:        | printLambEntry{entry=IMPORTentry dyn, lvars} =
                    190:            (debug "*IMPORT*\n";
                    191:             printCodeDynModule 6 dyn;
                    192:             debug "   lvars=[ ";
                    193:             printNums lvars;
                    194:             debug "].\n"
                    195:            )
                    196: 
                    197:       exception CompileDynModule
                    198:       fun compileDynModule opt (LAMBDYNMODULE entries): CodeDynModule =
                    199:        let
                    200:          val _ =
                    201:            if DEBUG then (debug "compileDynModule:\n";
                    202:                           app printLambEntry entries
                    203:                          )
                    204:            else ()
                    205: 
                    206:          val looker = inventLvar "looker"
                    207: 
                    208:          val {lambda=openLambda, imports, importLvars} =
                    209:            foldLambda(rev entries, looker, nil)
                    210:                (* reverse "entries" because a LambDynModule has the most
                    211:                   recent declaration at the front, and we want to nest the
                    212:                   lambda with the old stuff outermost - as well as get the
                    213:                   correct ordering of the lvars in the final result. *)
                    214: 
                    215:          val _ = if !ErrorMsg.anyErrors then raise CompileDynModule else ()
                    216:                (* Just check for any errors during last part of transDec. *)
                    217: 
                    218:          val closedLambda =
                    219:            Opt.bareCloseTop{lambda=openLambda,
                    220:                             looker=looker,
                    221:                             extras=ProcessFile.getCore(),
                    222:                             keepFree=looker :: importLvars
                    223:                            }
                    224:                (* Close the lambda, using the already-generated looker lvar -
                    225:                   this had to be generated in advance, since each imported
                    226:                   module is activated as M(looker). We DON'T want to close
                    227:                   with respect to the modLvars, since we're just about to
                    228:                   lambda-bind these. Keep the looker's lvar free as well,
                    229:                   otherwise it tries to find itself... Gnnnh! *)
                    230: 
                    231:          val finalLambda =
                    232:            fn_N("imports", importLvars, closedLambda)
                    233:                (* That's what we want: "fn (M1, ..., Mn) => fn looker => ..."
                    234:                   where the Mi's we apply to are each a "fn looker => ...".
                    235:                   In fact, I suspect that "imports" and "importLvars" are
                    236:                   both in reverse order, but as long as they're
                    237:                   coherent... *)
                    238: 
                    239:           val _ =
                    240:            if DEBUG then (debug "Final (unopt) lambda:\n";
                    241:                           MCprint.printLexp finalLambda;
                    242:                           debug ".\n"
                    243:                          )
                    244:            else ()
                    245: 
                    246:          val optLambda = opt finalLambda
                    247: 
                    248:          val code =
                    249:            codegen optLambda
                    250:            handle Codegen => raise CompileDynModule
                    251:        in
                    252:          CODEDYNMODULE{self=code, subModules=imports}
                    253:        end
                    254: 
                    255:      (* primeDynModule: returns a "fn lookup => ...result...". If the module
                    256:         doesn't import anything, then we just apply the code to NIL. If the
                    257:        module imports M1...Mn, then we prime these, and build an array of
                    258:        them. *)
                    259: 
                    260:       type object = System.Unsafe.object
                    261:       type looker = lvar -> object
                    262:       type result = object array
                    263:       type module = looker -> result
                    264: 
                    265:       fun primeDynModule(CODEDYNMODULE{self, subModules}): module =
                    266:         let
                    267:          val me: module array -> looker -> result =
                    268:            System.Unsafe.boot self
                    269: 
                    270:          val subModules: module array =
                    271:            arrayoflist(map primeDynModule subModules)
                    272:        in
                    273:          me subModules
                    274:        end
                    275: 
                    276:       fun debugLooker looker =
                    277:         fn lvar: int => (debug("[looker(" ^ makestring lvar ^ ")]\n");
                    278:                         looker lvar
                    279:                        )
                    280: 
                    281:       fun executeDynModule codeDynModule looker: object array =
                    282:        let
                    283:          val _ = debug "priming... "
                    284:          val primed = primeDynModule codeDynModule
                    285:          val _ = debug "executing... "
                    286:          val result = primed(if DEBUG then debugLooker looker else looker)
                    287:          in
                    288:            debug "done\n";
                    289:            result
                    290:          end
                    291:     end
                    292:   end;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.