1-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
2-- All rights reserved.
3--
4-- Redistribution and use in source and binary forms, with or without
5-- modification, are permitted provided that the following conditions are
6-- met:
7--
8--     - Redistributions of source code must retain the above copyright
9--       notice, this list of conditions and the following disclaimer.
10--
11--     - Redistributions in binary form must reproduce the above copyright
12--       notice, this list of conditions and the following disclaimer in
13--       the documentation and/or other materials provided with the
14--       distribution.
15--
16--     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
17--       names of its contributors may be used to endorse or promote products
18--       derived from this software without specific prior written permission.
19--
20-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32)package "BOOT"
33
34DEFPARAMETER($getUnexposedOperations, true)
35
36--% Functions for manipulating MODEMAP DATABASE
37
38augLisplibModemapsFromCategory(form is [op,:argl], body, signature,
39                               domainShell) ==
40  sl := [["$",:"*1"],:[[a,:p] for a in argl
41    for p in rest $PatternVariableList]]
42  form:= SUBLIS(sl,form)
43  body:= SUBLIS(sl,body)
44  signature:= SUBLIS(sl,signature)
45  opAlist:= SUBLIS(sl, domainShell.(1)) or return nil
46  nonCategorySigAlist:=
47    mkAlistOfExplicitCategoryOps substitute("*1","$",body)
48  domainList:=
49    [[a,m] for a in rest form for m in rest signature |
50      isCategoryForm(m)]
51  catPredList:= [['ofCategory,:u] for u in [["*1",form],:domainList]]
52  for (entry:= [[op,sig,:.],pred,sel]) in opAlist |
53    member(sig,LASSOC(op,nonCategorySigAlist)) repeat
54      pred':= MKPF([pred,:catPredList],'AND)
55      modemap:= [["*1",:sig],[pred',sel]]
56      $lisplibModemapAlist:=
57        [[op,:interactiveModemapForm modemap],:$lisplibModemapAlist]
58
59augmentLisplibModemapsFromFunctor(form,opAlist,signature) ==
60  form:= [formOp,:argl]:= formal2Pattern form
61  opAlist:= formal2Pattern opAlist
62  signature:= formal2Pattern signature
63  nonCategorySigAlist:=
64    mkAlistOfExplicitCategoryOps first signature or return nil
65  for (entry:= [[op,sig,:.],pred,sel]) in opAlist |
66    or/[(sig in catSig) for catSig in
67      allLASSOCs(op,nonCategorySigAlist)] repeat
68        skip:=
69          argl and CONTAINED("$",rest sig) => 'SKIP
70          nil
71        sel:= substitute(form,"$",sel)
72        patternList:= listOfPatternIds sig
73        --get relevant predicates
74        predList:=
75          [[a,m] for a in argl for m in rest signature
76            | MEMQ(a,$PatternVariableList)]
77        sig:= substitute(form,"$",sig)
78        pred':= MKPF([pred,:[mkDatabasePred y for y in predList]],'AND)
79        l:=listOfPatternIds predList
80        if "OR"/[null MEMQ(u,l) for u in argl] then
81          sayMSG ['"cannot handle modemap for",:bright op,
82                          '"by pattern match" ]
83          skip:= 'SKIP
84        modemap:= [[form,:sig],[pred',sel,:skip]]
85        $lisplibModemapAlist:= [[op,:interactiveModemapForm modemap],
86          :$lisplibModemapAlist]
87
88saveUsersHashTable() ==
89  erase_lib(['USERS, 'DATABASE])
90  stream:= writeLib('USERS,'DATABASE)
91  for k in MSORT HKEYS $usersTb repeat
92    rwrite(k, HGET($usersTb, k), stream)
93  RSHUT stream
94
95saveDependentsHashTable() ==
96  erase_lib(['DEPENDENTS, 'DATABASE])
97  stream:= writeLib('DEPENDENTS,'DATABASE)
98  for k in MSORT HKEYS $depTb repeat
99    rwrite(k, HGET($depTb, k), stream)
100  RSHUT stream
101
102save_browser_data() ==
103    buildLibdb(false)
104    dbSplitLibdb()
105    mkUsersHashTable()
106    saveUsersHashTable()
107    mkDependentsHashTable()
108    saveDependentsHashTable()
109
110getUsersOfConstructor(con) ==
111  stream := readLib('USERS, 'DATABASE)
112  val := rread_list(con, stream)
113  RSHUT stream
114  val
115
116getDependentsOfConstructor(con) ==
117  stream := readLib('DEPENDENTS, 'DATABASE)
118  val := rread_list(con, stream)
119  RSHUT stream
120  val
121
122orderPredicateItems(pred1,sig,skip) ==
123  pred:= signatureTran pred1
124  pred is ["AND",:l] => orderPredTran(l,sig,skip)
125  pred
126
127orderPredTran(oldList,sig,skip) ==
128  lastPreds:=nil
129  --(1) make two kinds of predicates appear last:
130  -----  (op *target ..) when *target does not appear later in sig
131  -----  (isDomain *1 ..)
132  for pred in oldList repeat
133    ((pred is [op,pvar,.] and MEMQ(op,'(isDomain ofCategory))
134       and pvar=first sig and not (pvar in rest sig)) or
135        (not skip and pred is ['isDomain,pvar,.] and pvar="*1")) =>
136          oldList:=delete(pred,oldList)
137          lastPreds:=[pred,:lastPreds]
138--sayBrightlyNT "lastPreds="
139--pp lastPreds
140
141  --(2a) lastDependList=list of all variables that lastPred forms depend upon
142  lastDependList := "UNIONQ"/[listOfPatternIds x for x in lastPreds]
143--sayBrightlyNT "lastDependList="
144--pp lastDependList
145
146  --(2b) dependList=list of all variables that isDom/ofCat forms depend upon
147  dependList :=
148    "UNIONQ"/[listOfPatternIds y for x in oldList |
149      x is ['isDomain,.,y] or x is ['ofCategory,.,y]]
150--sayBrightlyNT "dependList="
151--pp dependList
152
153  --(3a) newList= list of ofCat/isDom entries that don't depend on
154  for x in oldList repeat
155    if (x is ['ofCategory,v,body]) or (x is ['isDomain,v,body]) then
156      indepvl:=listOfPatternIds v
157      depvl:=listOfPatternIds body
158    else
159      indepvl := listOfPatternIds x
160      depvl := nil
161    (INTERSECTIONQ(indepvl,dependList) = nil)
162        and INTERSECTIONQ(indepvl,lastDependList) =>
163      somethingDone := true
164      lastPreds := [:lastPreds,x]
165      oldList := delete(x,oldList)
166--if somethingDone then
167--  sayBrightlyNT "Again lastPreds="
168--  pp lastPreds
169--  sayBrightlyNT "Again oldList="
170--  pp oldList
171
172  --(3b) newList= list of ofCat/isDom entries that don't depend on
173  while oldList repeat
174    for x in oldList repeat
175      if (x is ['ofCategory,v,body]) or (x is ['isDomain,v,body]) then
176        indepvl:=listOfPatternIds v
177        depvl:=listOfPatternIds body
178      else
179        indepvl := listOfPatternIds x
180        depvl := nil
181      (INTERSECTIONQ(indepvl,dependList) = nil) =>
182        dependList:= setDifference(dependList,depvl)
183        newList:= [:newList,x]
184--  sayBrightlyNT "newList="
185--  pp newList
186
187  --(4) noldList= what is left over
188    (noldList:= setDifference(oldList,newList)) = oldList =>
189--    sayMSG '"NOTE: Parameters to domain have circular dependencies"
190      newList := [:newList,:oldList]
191      return nil
192    oldList:=noldList
193--  sayBrightlyNT "noldList="
194--  pp noldList
195
196  for pred in newList repeat
197    if pred is ['isDomain,x,y] or x is ['ofCategory,x,y] then
198      ids:= listOfPatternIds y
199      if and/[id in fullDependList for id in ids] then
200        fullDependList:= insertWOC(x,fullDependList)
201      fullDependList:= UNIONQ(fullDependList,ids)
202
203  newList:=[:newList,:lastPreds]
204
205--substitute (isDomain ..) forms as completely as possible to avoid false paths
206  newList := isDomainSubst newList
207  answer := [['AND,:newList],:INTERSECTIONQ(fullDependList,sig)]
208--sayBrightlyNT '"answer="
209--pp answer
210
211isDomainSubst u == main where
212  main ==
213    u is [head,:tail] =>
214      nhead :=
215        head is ['isDomain,x,y] => ['isDomain,x,fn(y,tail)]
216        head
217      [nhead,:isDomainSubst rest u]
218    u
219  fn(x,alist) ==
220    atom x =>
221      IDENTP x and MEMQ(x,$PatternVariableList) and (s := findSub(x,alist)) => s
222      x
223    [first x, :[fn(y, alist) for y in rest x]]
224  findSub(x,alist) ==
225    null alist => nil
226    alist is [['isDomain,y,z],:.] and x = y => z
227    findSub(x,rest alist)
228
229signatureTran pred ==
230  atom pred => pred
231  pred is ['has, D, catForm] and isCategoryForm(catForm) =>
232    ['ofCategory,D,catForm]
233  [signatureTran p for p in pred]
234
235interactiveModemapForm mm ==
236  --  create modemap form for use by the interpreter.  This function
237  --  replaces all specific domains mentioned in the modemap with pattern
238  --  variables, and predicates
239  mm := replaceVars(COPY mm,$PatternVariableList,$FormalMapVariableList)
240  [pattern:=[dc,:sig],pred] := mm
241  pred := [fn x for x in pred] where fn x ==
242    x is [a,b,c] and a ~= 'isFreeFunction and atom c => [a,b,[c]]
243    x
244--pp pred
245  [mmpat, patternAlist, partial, patvars] :=
246    modemapPattern(pattern,sig)
247--pp [pattern, mmpat, patternAlist, partial, patvars]
248  [pred,domainPredicateList] :=
249    substVars(pred,patternAlist,patvars)
250--pp [pred,domainPredicateList]
251  [pred,:dependList]:=
252    fixUpPredicate(pred,domainPredicateList,partial,rest mmpat)
253--pp [pred,dependList]
254  [cond, :.] := pred
255  [mmpat, cond]
256
257modemapPattern(mmPattern,sig) ==
258  --  Returns a list of the pattern of a modemap, an Alist of the
259  --  substitutions made, a boolean flag indicating whether
260  --  the result type is partial, and a list of unused pattern variables
261  patternAlist := nil
262  mmpat := nil
263  patvars := $PatternVariableList
264  partial := false
265  for xTails in tails mmPattern repeat
266    x := first xTails
267    if x is ['Union,dom,tag] and tag = '"failed" and xTails=sig then
268      x := dom
269      partial := true
270    patvar := rassoc(x,patternAlist)
271    not null patvar => mmpat := [patvar,:mmpat]
272    patvar := first patvars
273    patvars := rest patvars
274    mmpat := [patvar,:mmpat]
275    patternAlist := [[patvar,:x],:patternAlist]
276  [NREVERSE mmpat,patternAlist,partial,patvars]
277
278substVars(pred,patternAlist,patternVarList) ==
279  --make pattern variable substitutions
280  domainPredicates := nil
281  for [[patVar,:value],:.] in tails patternAlist repeat
282    pred := substitute(patVar,value,pred)
283    patternAlist := NSUBST(patVar, value, patternAlist)
284    domainPredicates := substitute(patVar,value,domainPredicates)
285    if not MEMQ(value,$FormalMapVariableList) then
286      domainPredicates := [["isDomain",patVar,value],:domainPredicates]
287  everything := [pred,patternAlist,domainPredicates]
288  for var in $FormalMapVariableList repeat
289    CONTAINED(var,everything) =>
290      replacementVar := first patternVarList
291      patternVarList := rest patternVarList
292      pred := substitute(replacementVar,var,pred)
293      domainPredicates := substitute(replacementVar,var,domainPredicates)
294  [pred, domainPredicates]
295
296fixUpPredicate(predClause, domainPreds, partial, sig) ==
297  --  merge the predicates in predClause and domainPreds into a
298  --  single predicate
299  [predicate, fn, :skip] := predClause
300  if first predicate = "AND" then
301    predicates := APPEND(domainPreds,rest predicate)
302  else if predicate ~= MKQ "T"
303--was->then predicates:= REVERSE [predicate, :domainPreds]
304       then predicates:= [predicate, :domainPreds]
305       else predicates := domainPreds or [predicate]
306  if #predicates > 1 then
307    pred := ["AND",:predicates]
308    [pred,:dependList]:=orderPredicateItems(pred,sig,skip)
309  else
310    pred := orderPredicateItems(first predicates,sig,skip)
311    dependList:= if pred is ['isDomain,pvar,[.]] then [pvar] else nil
312  pred := moveORsOutside pred
313  if partial then pred := ["partial", :pred]
314  [[pred, fn, :skip],:dependList]
315
316moveORsOutside p ==
317  p is ['AND,:q] =>
318    q := [moveORsOutside r for r in q]
319    x := or/[r for r in q | r is ['OR,:s]] =>
320        moveORsOutside(['OR, :[['AND, :substitute(t, x, q)] for t in rest x]])
321    ['AND,:q]
322  p
323
324replaceVars(x,oldvars,newvars) ==
325  --  replace every identifier in oldvars with the corresponding
326  --  identifier in newvars in the expression x
327  for old in oldvars for new in newvars repeat
328    x := substitute(new,old,x)
329  x
330
331getDomainFromMm mm ==
332  -- Returns the Domain (or package or category) of origin from a pattern
333  -- modemap
334  [., cond] := mm
335  if cond is ['partial, :c] then cond := c
336  condList :=
337    cond is ['AND, :cl] => cl
338    cond is ['OR, ['AND, :cl],:.] => cl  --all cl's should give same info
339    [cond]
340  val :=
341    for condition in condList repeat
342      condition is ['isDomain, "*1", dom] => return opOf dom
343      condition is ['ofCategory, "*1", cat] and _
344          not(member(opOf cat, ["finiteAggregate", "shallowlyMutable", _
345               "arbitraryPrecision", "canonicalUnitNormal"]))_
346             => return opOf cat
347  null val =>
348    keyedSystemError("S2GE0016",
349      ['"getDomainFromMm",'"Can't find domain in modemap condition"])
350  val
351
352getFirstArgTypeFromMm mm ==
353  -- Returns the type of the first argument or nil
354  [pats, cond] := mm
355  [.,.,:args] := pats
356  null args => nil
357  arg1 := first args
358  if cond is ['partial, :c] then cond := c
359  condList :=
360    cond is ['AND, :cl] => cl
361    cond is ['OR, ['AND, :cl],:.] => cl  --all cl's should give same info
362    [cond]
363  type := nil
364  for condition in condList while not type repeat
365      if condition is ['isDomain, a1, dom] and a1=arg1 then type := dom
366  type
367
368isFreeFunctionFromMm mm ==
369  -- This returns true is the modemap represents a free function, ie,
370  -- one not coming from a domain or category.
371  [., cond] := mm
372  isFreeFunctionFromMmCond cond
373
374isFreeFunctionFromMmCond cond ==
375  -- This returns true is the modemap represents a free function, ie,
376  -- one not coming from a domain or category.
377  if cond is ['partial, :c] then cond := c
378  condList :=
379    cond is ['AND, :cl] => cl
380    cond is ['OR, ['AND, :cl],:.] => cl  --all cl's should give same info
381    [cond]
382  iff := false
383  for condition in condList while not iff repeat
384      if condition is ['isFreeFunction, :.] then iff := true
385  iff
386
387getAllModemapsFromDatabase(op,nargs) ==
388  $getUnexposedOperations: local := true
389  startTimingProcess 'diskread
390  ans := getSystemModemaps(op,nargs)
391  stopTimingProcess 'diskread
392  ans
393
394getModemapsFromDatabase(op,nargs) ==
395  $getUnexposedOperations: local := false
396  startTimingProcess 'diskread
397  ans := getSystemModemaps(op,nargs)
398  stopTimingProcess 'diskread
399  ans
400
401getSystemModemaps(op,nargs) ==
402  mml:= GETDATABASE(op,'OPERATION) =>
403    mms := NIL
404    for (x := [[.,:sig],.]) in mml repeat
405      (NUMBERP nargs) and (nargs ~= #QCDR sig) => 'iterate
406      $getUnexposedOperations or isFreeFunctionFromMm(x) or
407        isExposedConstructor(getDomainFromMm(x)) => mms := [x,:mms]
408      'iterate
409    mms
410  nil
411
412mkAlistOfExplicitCategoryOps target ==
413  if target is ['add,a,:l] then
414    target:=a
415  target is ['Join,:l] =>
416    "union"/[mkAlistOfExplicitCategoryOps cat for cat in l]
417  target is ['CATEGORY,.,:l] =>
418    l:= flattenSignatureList ['PROGN,:l]
419    u:=
420      [[atomizeOp op,:sig] for x in l | x is ['SIGNATURE,op,sig,:.]]
421            where
422              atomizeOp op ==
423                atom op => op
424                op is [a] => a
425                keyedSystemError("S2GE0016",
426                  ['"mkAlistOfExplicitCategoryOps",'"bad signature"])
427    opList:= REMDUP ASSOCLEFT u
428    [[x,:fn(x,u)] for x in opList] where
429      fn(op,u) ==
430        u is [[a,:b],:c] => (a=op => [b,:fn(op,c)]; fn(op,c))
431  isCategoryForm(target) => nil
432  keyedSystemError("S2GE0016",
433    ['"mkAlistOfExplicitCategoryOps",'"bad signature"])
434
435flattenSignatureList(x) ==
436  atom x => nil
437  x is ['SIGNATURE,:.] => [x]
438  x is ['IF,cond,b1,b2] =>
439     append(flattenSignatureList b1, flattenSignatureList b2)
440  x is ['PROGN,:l] =>
441     ll:= []
442     for x in l repeat
443        x is ['SIGNATURE,:.] => ll:=cons(x,ll)
444        ll:= append(flattenSignatureList x,ll)
445     ll
446  nil
447
448mkDatabasePred [a,t] ==
449  isCategoryForm(t) => ['ofCategory, a, t]
450  ['ofType,a,t]
451
452formal2Pattern x ==
453  SUBLIS(pairList($FormalMapVariableList,rest $PatternVariableList),x)
454
455updateDatabase(fname,cname,systemdir?) ==
456 -- for now in NRUNTIME do database update only if forced
457  not $forceDatabaseUpdate => nil
458  clearClams()
459  clearAllSlams []
460  if constructor? cname then
461    if GET(cname, 'LOADED) then
462      clearConstructorCaches()
463
464REMOVER(lst,item) ==
465  --destructively removes item from lst
466  not PAIRP lst =>
467    lst=item => nil
468    lst
469  first lst=item => rest lst
470  RPLNODE(lst,REMOVER(first lst,item),REMOVER(rest lst,item))
471
472allLASSOCs(op,alist) ==
473  [value for [key,:value] in alist | key = op]
474
475--% Miscellaneous Stuff
476
477getOplistForConstructorForm (form := [op,:argl]) ==
478  --  The new form is an op-Alist which has entries (<op> . signature-Alist)
479  --    where signature-Alist has entries (<signature> . item)
480  --      where item has form (<slotNumber> <condition> <kind>)
481  --        where <kind> =  ELT | CONST | (XLAM..) ..
482  pairlis:= [[fv,:arg] for fv in $FormalMapVariableList for arg in argl]
483  opAlist := getOperationAlistFromLisplib op
484  [:getOplistWithUniqueSignatures(op,pairlis,signatureAlist)
485      for [op,:signatureAlist] in opAlist]
486
487getOplistWithUniqueSignatures(op,pairlis,signatureAlist) ==
488  alist:= nil
489  for [sig, :[slotNumber, pred, kind]] in signatureAlist repeat
490      key := SUBLIS(pairlis, [op, sig])
491      term := assoc(key, alist)
492      if null term then
493          alist := cons([key, pred, [kind, nil, slotNumber]], alist)
494      else
495          value := rest term
496          oldpred := first value
497          newpred :=
498              oldpred = true or pred = true => true
499              oldpred = pred => oldpred
500              oldpred is ['OR, :predl] =>
501                  member(pred, predl) => oldpred
502                  ['OR, pred, :predl]
503              ['OR, pred, oldpred]
504          RPLACA(value, newpred)
505  alist
506
507--% Exposure Group Code
508
509dropPrefix(fn) ==
510  member(fn.0,[char "?",char "-",char "+"]) => SUBSTRING(fn,1,nil)
511  fn
512
513DEFPARAMETER($globalExposureHash, nil)
514
515initExposureHash() ==
516    $globalExposureHash := MAKE_HASHTABLE('EQUAL)
517    for grdata in $globalExposureGroupAlist repeat
518        group := first(grdata)
519        alist := rest(grdata)
520        for pair in alist repeat
521            name := first(pair)
522            ogr := HGET($globalExposureHash, name)
523            HPUT($globalExposureHash, name, [group, :ogr])
524
525isExposedConstructor name ==
526  -- this function checks the local exposure data in the frame to
527  -- see if the given constructor is exposed. The format of
528  -- $localExposureData is a vector with
529  --   slot 0: list of groups exposed in the frame
530  --   slot 1: list of constructors explicitly exposed
531  --   slot 2: list of constructors explicitly hidden
532  -- check if it is explicitly hidden
533  MEMQ(name,'(Union Record Mapping)) => true
534  MEMQ(name,$localExposureData.2) => false
535  -- check if it is explicitly exposed
536  MEMQ(name,$localExposureData.1) => true
537  -- check if it is in an exposed group
538  found := NIL
539  if null($globalExposureHash) then
540      initExposureHash()
541  exd := HGET($globalExposureHash, name)
542  for g in $localExposureData.0 while not found repeat
543      null(g in exd) => 'iterate
544      found := true
545  found
546
547displayExposedGroups() ==
548  sayKeyedMsg("S2IZ0049A",[$interpreterFrameName])
549  if null $localExposureData.0
550    then centerAndHighlight '"there are no exposed groups"
551    else for g in $localExposureData.0 repeat
552      centerAndHighlight g
553
554displayExposedConstructors() ==
555  sayKeyedMsg("S2IZ0049B",NIL)
556  if null $localExposureData.1
557    then centerAndHighlight
558      '"there are no explicitly exposed constructors"
559    else for c in $localExposureData.1 repeat
560      centerAndHighlight c
561
562displayHiddenConstructors() ==
563  sayKeyedMsg("S2IZ0049C",NIL)
564  if null $localExposureData.2
565    then centerAndHighlight
566      '"there are no explicitly hidden constructors"
567    else for c in $localExposureData.2 repeat
568      centerAndHighlight c
569
570getOperationAlistFromLisplib x ==
571    u := GETDATABASE(x, 'OPERATIONALIST)
572    --  u := removeZeroOneDestructively u
573    null u => u          -- this can happen for Object
574    CAAR u = '_$unique => rest u
575    f := addConsDB '(NIL T ELT)
576    for [op, :sigList] in u repeat
577        for items in tails sigList repeat
578            [sig, :r] := first items
579            if r is [., :s] then
580                if s is [., :t] then
581                    if t is [.] then nil
582                    else RPLACD(s, QCDDR f)
583                else RPLACD(r, QCDR f)
584            else RPLACD(first items, f)
585            RPLACA(items, addConsDB first items)
586    u and markUnique u
587
588markUnique x ==
589    u := first x
590    RPLACA(x, '(_$unique))
591    RPLACD(x, [u, :rest x])
592    rest x
593
594--=======================================================================
595--          Creation of System Sig/Pred Vectors & Hash Tables
596--=======================================================================
597
598addConsDB x == x
599