1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

root/1.4.x/src/interp/define.boot @ 2275

Revision 2275, 76.9 KB (checked in by dos-reis, 22 months ago)
  • interp/define.boot (NRTgetLookupFunction): Take an environment argument. Adjust caller. (NRTextendsCategory1): Likewise. (extendsCategory): Likewise. (extendsCategoryBasic): Likewise. (catExtendsCat?): Likewise.
Line 
1-- Copyright (c) 1991-2002, The Numerical Algorithms Group Ltd.
2-- All rights reserved.
3-- Copyright (C) 2007-2011, Gabriel Dos Reis.
4-- All rights reserved.
5--
6-- Redistribution and use in source and binary forms, with or without
7-- modification, are permitted provided that the following conditions are
8-- met:
9--
10--     - Redistributions of source code must retain the above copyright
11--       notice, this list of conditions and the following disclaimer.
12--
13--     - Redistributions in binary form must reproduce the above copyright
14--       notice, this list of conditions and the following disclaimer in
15--       the documentation and/or other materials provided with the
16--       distribution.
17--
18--     - Neither the name of The Numerical Algorithms Group Ltd. nor the
19--       names of its contributors may be used to endorse or promote products
20--       derived from this software without specific prior written permission.
21--
22-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34import nruncomp
35import g_-error
36import database
37import modemap
38
39namespace BOOT
40
41module define where
42  compDefine: (%Form,%Mode,%Env) -> %Maybe %Triple
43  compSubDomain: (%Form,%Mode,%Env) -> %Maybe %Triple
44  compCapsule: (%Form, %Mode, %Env) -> %Maybe %Triple
45  compJoin: (%Form,%Mode,%Env) -> %Maybe %Triple
46  compAdd: (%Form, %Mode, %Env) -> %Maybe %Triple
47  compCategory: (%Form,%Mode,%Env) -> %Maybe %Triple
48
49
50--%
51
52$newCompCompare := false
53
54++ List of mutable domains.
55$mutableDomains := nil
56
57++ True if the current constructor being compiled instantiates
58++ mutable domains or packages.  Default is `false'.
59$mutableDomain := false
60
61++ when non nil, holds the declaration number of a function in a capsule.
62$suffix := nil
63
64$doNotCompileJustPrint := false
65
66++ stack of pending capsule function definitions.
67$capsuleFunctionStack := []
68
69$functionStats := nil
70$functorStats := nil
71
72$lisplibCategory := nil
73$lisplibAncestors := nil
74$lisplibAbbreviation := nil
75$CheckVectorList := []
76$pairlis := []
77$functorTarget := nil
78$condAlist := []
79$uncondAlist := []
80$NRTslot1PredicateList := []
81$NRTattributeAlist := []
82$NRTslot1Info := nil
83$NRTdeltaListComp := []
84$template := nil
85$signature := nil
86$isOpPackageName := false
87$lookupFunction := nil
88$byteAddress := nil
89$byteVec := nil
90$lisplibSlot1 := nil
91$sigAlist := []
92$predAlist := []
93$argumentConditionList := []
94$finalEnv := nil
95$initCapsuleErrorCount := nil
96$CapsuleModemapFrame := nil
97$CapsuleDomainsInScope := nil
98$signatureOfForm := nil
99$addFormLhs := nil
100$lisplibSuperDomain := nil
101$sigList := []
102$atList := []
103
104++ List of declarations appearing as side conditions of a where-expression.
105$whereDecls := nil
106
107++ True if the current functor definition refines a domain.
108$subdomain := false
109
110--%
111
112compDefineAddSignature: (%Form,%Sig,%Env) -> %Env
113
114
115--%
116
117--=======================================================================
118--            Generate Code to Create Infovec
119--=======================================================================
120getInfovecCode() ==
121--Function called by compDefineFunctor1 to create infovec at compile time
122  ['LIST,
123    MKQ makeDomainTemplate $template,
124      MKQ makeCompactDirect $NRTslot1Info,
125        MKQ NRTgenFinalAttributeAlist(),
126          NRTmakeCategoryAlist(),
127            MKQ $lookupFunction]
128
129--=======================================================================
130--         Generation of Domain Vector Template (Compile Time)
131--=======================================================================
132makeDomainTemplate vec ==   
133--NOTES: This function is called at compile time to create the template
134--  (slot 0 of the infovec); called by getInfovecCode from compDefineFunctor1
135  newVec := newShell # vec
136  for index in 0..maxIndex vec repeat
137    item := vectorRef(vec,index)
138    null item => nil
139    vectorRef(newVec,index) :=
140      item isnt [.,:.] => item
141      cons? first item => makeGoGetSlot(item,index)
142      item   
143  $byteVec := "append"/reverse! $byteVec
144  newVec
145 
146makeGoGetSlot(item,index) ==
147--NOTES: creates byte vec strings for LATCH slots
148--these parts of the $byteVec are created first; see also makeCompactDirect
149  [sig,whereToGo,op,:flag] := item
150  n := #sig - 1
151  newcode := [n,whereToGo,:makeCompactSigCode sig,index]
152  $byteVec := [newcode,:$byteVec]
153  curAddress := $byteAddress
154  $byteAddress := $byteAddress + n + 4
155  [curAddress,:op]
156 
157--=======================================================================
158--                Generate OpTable at Compile Time
159--=======================================================================
160--> called by getInfovecCode (see top of this file) from compDefineFunctor1
161makeCompactDirect u ==
162  $predListLength :local := # $NRTslot1PredicateList
163  $byteVecAcc: local := nil
164  [nam,[addForm,:opList]] := u
165  --pp opList
166  d := [[op,y] for [op,:items] in opList | y := makeCompactDirect1(op,items)]
167  $byteVec := [:$byteVec,:"append"/reverse! $byteVecAcc]
168  LIST2VEC ("append"/d)
169 
170makeCompactDirect1(op,items) ==
171--NOTES: creates byte codes for ops implemented by the domain
172    curAddress := $byteAddress
173    $op: local := op  --temp hack by RDJ 8/90 (see orderBySubsumption)
174    newcodes :=
175      "append"/[u for y in orderBySubsumption items | u := fn y] or return nil
176    $byteVecAcc := [newcodes,:$byteVecAcc]
177    curAddress
178 where fn y ==
179  [sig,:r] := y
180  r = ['Subsumed] =>
181    n := #sig - 1
182    $byteAddress := $byteAddress + n + 4
183    [n,0,:makeCompactSigCode sig,0]  --always followed by subsuming signature
184    --identified by a 0 in slot position
185  if r is [n,:s] then
186    slot :=
187      n is [p,:.] => p  --the rest is linenumber of function definition
188      n
189    predCode :=
190      s is [pred,:.] => predicateBitIndex pred
191      0
192  --> drop items which are not present (predCode = -1)
193  predCode = -1 => return nil
194  --> drop items with nil slots if lookup function is incomplete
195  if null slot then
196     $lookupFunction is 'lookupIncomplete => return nil
197     slot := 1   --signals that operation is not present
198  n := #sig - 1
199  $byteAddress := $byteAddress + n + 4
200  res := [n,predCode,:makeCompactSigCode sig,slot]
201  res
202 
203orderBySubsumption items ==
204  acc := subacc := nil
205  for x in items repeat
206    not ($op in '(Zero One)) and x is [.,.,.,'Subsumed] =>
207      subacc := [x,:subacc]
208    acc := [x,:acc]
209  y := z := nil
210  for [a,b,:.] in subacc | b repeat   
211  --NOTE: b = nil means that the signature a will appear in acc, that this
212  --  entry is be ignored (e.g. init: -> $ in ULS)
213    while (u := assoc(b,subacc)) repeat b := second u
214    u := assoc(b,acc) or systemError nil
215    if null second u then u := [first u,1] --mark as missing operation
216    y := [[a,'Subsumed],u,:y] --makes subsuming signature follow one subsumed
217    z := insert(b,z)  --mark a signature as already present
218  [:y,:[w for (w := [c,:.]) in acc | not listMember?(c,z)]] --add those not subsuming
219 
220makeCompactSigCode sig == [fn for x in sig] where
221  fn() ==
222    x is "$$" => 2
223    x is "$" => 0
224    not integer? x =>
225      systemError ['"code vector slot is ",x,'"; must be number"]
226    x
227 
228--=======================================================================
229--               Generate Slot 4 Constructor Vectors
230--=======================================================================
231NRTmakeCategoryAlist() ==
232  $depthAssocCache: local := hashTable 'EQ
233  $catAncestorAlist: local := nil
234  pcAlist := [:[[x,:"T"] for x in $uncondAlist],:$condAlist]
235  $levelAlist: local := depthAssocList [CAAR x for x in pcAlist]
236  opcAlist := reverse! SORTBY(function NRTcatCompare,pcAlist)
237  newPairlis := [[5 + i,:b] for [.,:b] in $pairlis for i in 1..]
238  slot1 := [[a,:k] for [a,:b] in applySubst($pairlis,opcAlist)
239                   | (k := predicateBitIndex b) ~= -1]
240  slot0 := [hasDefaultPackage opOf a for [a,:b] in slot1]
241  sixEtc := [5 + i for i in 1..#$pairlis]
242  formals := ASSOCRIGHT $pairlis
243  for x in slot1 repeat
244    x.first := applySubst(pairList(['$,:formals],["$$",:sixEtc]),first x)
245  -----------code to make a new style slot4 -----------------
246  predList := ASSOCRIGHT slot1  --is list of predicate indices
247  maxPredList := "MAX"/predList
248  catformvec := ASSOCLEFT slot1
249  maxElement := "MAX"/$byteVec
250  ['CONS, ['makeByteWordVec2,MAX(maxPredList,1),MKQ predList],
251    ['CONS, MKQ LIST2VEC slot0,
252      ['CONS, MKQ LIST2VEC [encodeCatform x for x in catformvec],
253        ['makeByteWordVec2,maxElement,MKQ $byteVec]]]]
254  --NOTE: this is new form: old form satisfies vector? CDDR form
255
256encodeCatform x ==
257  k := NRTassocIndex x => k
258  x isnt [.,:.] or rest x isnt [.,:.] => x
259  [first x,:[encodeCatform y for y in rest x]]
260 
261NRTcatCompare [catform,:pred] == LASSOC(first catform,$levelAlist)
262 
263hasDefaultPackage catname ==
264  defname := makeDefaultPackageName symbolName catname
265  constructor? defname => defname
266  nil
267 
268 
269--=======================================================================
270--              Compute the lookup function (complete or incomplete)
271--=======================================================================
272NRTgetLookupFunction(domform,exCategory,addForm,env) ==
273  domform := applySubst($pairlis,domform)
274  addForm := applySubst($pairlis,addForm)
275  $why: local := nil
276  addForm isnt [.,:.] => 'lookupComplete
277  NRTextendsCategory1(domform,exCategory,getExportCategory addForm,env) =>
278    'lookupIncomplete
279  [u,msg,:v] := $why
280  SAY '"--------------non extending category----------------------"
281  sayPatternMsg('"%1p of category %2p", [domform,u])
282  if v ~= nil then
283    sayPatternMsg('"%1b %2p",[msg,first v])
284  else
285    sayPatternMsg('"%1b",[msg])
286  SAY '"----------------------------------------------------------"
287  'lookupComplete
288
289getExportCategory form ==
290  [op,:argl] := form
291  op is 'Record => ['RecordCategory,:argl]
292  op is 'Union => ['UnionCategory,:argl]
293  op is 'Enumeration => ['EnumerationCategory,:argl]
294  op is 'Mapping => ['MappingCategory,:argl]
295  [[.,target,:tl],:.] := getConstructorModemapFromDB op
296  applySubst(pairList($FormalMapVariableList,argl),target)
297 
298NRTextendsCategory1(domform,exCategory,addForm,env) ==
299  addForm is ["%Comma",:r] =>
300    and/[extendsCategory(domform,exCategory,x,env) for x in r]
301  extendsCategory(domform,exCategory,addForm,env)
302
303--=======================================================================
304--         Compute if a domain constructor is forgetful functor
305--=======================================================================
306extendsCategory(dom,u,v,env) ==
307  --does category u extend category v (yes iff u contains everything in v)
308  --is dom of category u also of category v?
309  u=v => true
310  v is ["Join",:l] => and/[extendsCategory(dom,u,x,env) for x in l]
311  v is ["CATEGORY",.,:l] => and/[extendsCategory(dom,u,x,env) for x in l]
312  v is ["SubsetCategory",cat,d] =>
313    extendsCategory(dom,u,cat,env) and isSubset(dom,d,env)
314  v := substSlotNumbers(v,$template,$functorForm)
315  extendsCategoryBasic(dom,u,v,env) => true
316  $why :=
317    v is ['SIGNATURE,op,sig] => [u,['"  has no ",:formatOpSignature(op,sig)]]
318    [u,'" has no",v]
319  nil
320 
321extendsCategoryBasic(dom,u,v,env) ==
322  v is ['IF,p,['ATTRIBUTE,c],.] =>
323    uVec := compMakeCategoryObject(u,env).expr
324    cons? c and isCategoryForm(c,env) =>
325      LASSOC(c,second categoryHierarchy uVec) is [=p,:.]
326    LASSOC(c,categoryAttributes uVec) is [=p,:.]
327  u is ["Join",:l] => or/[extendsCategoryBasic(dom,x,v,env) for x in l]
328  u = v => true
329  isCategoryForm(v,env) => catExtendsCat?(u,v,env)
330  v is ['SIGNATURE,op,sig] =>
331    uVec := compMakeCategoryObject(u,env).expr
332    or/[categoryRef(uVec,i) is [[=op,=sig],:.] for i in 6..maxIndex uVec]
333  u is ['CATEGORY,.,:l] =>
334    v is ['IF,:.] => listMember?(v,l)
335    false
336  false
337 
338catExtendsCat?(u,v,env) ==
339  u = v => true
340  uvec := compMakeCategoryObject(u,env).expr
341  slot4 := categoryHierarchy uvec
342  prinAncestorList := first slot4
343  listMember?(v,prinAncestorList) => true
344  vOp := KAR v
345  if similarForm := assoc(vOp,prinAncestorList) then
346    PRINT u
347    sayBrightlyNT '"   extends "
348    PRINT similarForm
349    sayBrightlyNT '"   but not "
350    PRINT v
351  or/[catExtendsCat?(x,v,env) for x in ASSOCLEFT second slot4]
352 
353substSlotNumbers(form,template,domain) ==
354  form is [op,:.] and
355    symbolMember?(op,allConstructors()) => expandType(form,template,domain)
356  form is ['SIGNATURE,op,sig] =>
357    ['SIGNATURE,op,[substSlotNumbers(x,template,domain) for x in sig]]
358  form is ['CATEGORY,k,:u] =>
359    ['CATEGORY,k,:[substSlotNumbers(x,template,domain) for x in u]]
360  expandType(form,template,domain)
361 
362expandType(lazyt,template,domform) ==
363  lazyt isnt [.,:.] => expandTypeArgs(lazyt,template,domform)
364  [functorName,:argl] := lazyt
365  functorName is ":" =>
366    [functorName,first argl,expandTypeArgs(second argl,template,domform)]
367  lazyt is ['local,x] =>
368    n := POSN1(x,$FormalMapVariableList)
369    domform.(1 + n)
370  [functorName,:[expandTypeArgs(a,template,domform) for a in argl]]
371 
372expandTypeArgs(u,template,domform) ==
373  u is '$ => u
374  integer? u => expandType(vectorRef(template,u),template,domform)
375  u is [.,y] and u.op in '(NRTEVAL QUOTE) => y
376  u isnt [.,:.] => u
377  expandType(u,template,domform)
378
379--% Subdomains
380
381++ We are defining a functor with head given by `form', as a subdomain
382++ of the domain designated by the domain form `super', and predicate
383++ `pred' (a VM instruction form).  Emit appropriate info into the
384++ databases.
385emitSubdomainInfo(form,super,pred) ==
386  pred := applySubst!(pairList(form.args,$AtVariables),pred)
387  super := applySubst!(pairList(form.args,$AtVariables),super)
388  evalAndRwriteLispForm("evalOnLoad2",["noteSubDomainInfo",
389     quoteForm form.op,quoteForm super, quoteForm pred])
390
391
392++ List of operations defined in a given capsule
393++ Each item on this list is of the form
394++    (op sig pred)
395++ where
396++   op:   name of the operation
397++   sig:  signature of the operation
398++   pred: scope predicate of the operation.
399$capsuleFunctions := nil
400
401++ record that the operation `op' with signature `sig' and predicate
402++ `pred' is defined in the current capsule of the current domain
403++ being compiled.
404noteCapsuleFunctionDefinition(op,sig,pred) ==
405  listMember?([op,sig,pred],$capsuleFunctions) =>
406    stackAndThrow('"redefinition of %1b: %2 %3",
407      [op,formatUnabbreviated ["Mapping",:sig],formatIf pred])
408  $capsuleFunctions := [[op,sig,pred],:$capsuleFunctions]
409
410++ Clear the list of functions defined in the last domain capsule.
411clearCapsuleFunctionTable() ==
412  $capsuleFunctions := nil
413
414
415++ List of exports (paireed with scope predicate) declared in
416++ the category of the currend domain or package.
417++ Note: for category packages, this list is nil.
418$exports := nil
419
420noteExport(form,pred) ==
421  -- don't recheck category package exports; we just check
422  -- them when defining the category.  Plus, we might actually
423  -- get indirect duplicates, which is OK.
424  $insideCategoryPackageIfTrue => nil
425  listMember?([form,pred],$exports) =>
426    stackAndThrow('"redeclaration of %1 %2",
427      [form,formatIf pred])
428  $exports := [[form,pred],:$exports]
429
430clearExportsTable() ==
431  $exports := nil
432
433makePredicate l ==
434  null l => true
435  MKPF(l,"and")
436
437--% FUNCTIONS WHICH MUNCH ON == STATEMENTS
438
439++ List of reserved identifiers for which the compiler has special
440++ meanings and that shall not be redefined.
441$reservedNames == '(per rep _$)
442
443++ Check that `var' (a variable of parameter name) is not a reversed name.
444checkVariableName var ==
445  symbolMember?(var,$reservedNames) =>
446    stackAndThrow('"You cannot use reserved name %1b as variable",[var])
447  var
448
449checkParameterNames parms ==
450  for p in parms repeat
451    checkVariableName p
452
453compDefine(form,m,e) ==
454  $macroIfTrue: local := false
455  compDefine1(form,m,e)
456
457++ We are about to process the body of a capsule.  Check the form of
458++ `Rep' definition, and whether it is appropriate to activate the
459++ implicitly generated morphisms
460++     per: Rep -> %
461++     rep: % -> Rep
462++ as local inline functions.
463checkRepresentation: (%Form,%List %Form,%Env) -> %Env
464checkRepresentation(addForm,body,env) ==
465  domainRep := nil
466  hasAssignRep := false        -- assume code does not assign to Rep.
467  viewFuns := nil
468
469  null body => env             -- Don't be too hard on nothing.
470 
471  -- Locate possible Rep definition
472  for [stmt,:.] in tails body repeat
473    stmt is ["%LET","Rep",val] =>
474      domainRep ~= nil =>
475        stackAndThrow('"You cannot assign to constant domain %1b",["Rep"])
476      if addForm = val then
477        stackWarning('"OpenAxiom suggests removing assignment to %1b",["Rep"])
478      else if addForm ~= nil then
479        stackWarning('"%1b differs from the base domain",["Rep"])
480      return hasAssignRep := true
481    stmt is ["MDEF",["Rep",:.],:.] =>
482      stackWarning('"Consider using == definition for %1b",["Rep"])
483      return hasAssignRep := true
484    stmt is ["IF",.,:l] or stmt is ["SEQ",:l] or stmt is ["exit",:l] =>
485      checkRepresentation(nil,l,env)
486    stmt isnt ["DEF",[op,:args],sig,.,val] => nil -- skip for now.
487    op in '(rep per) =>
488      domainRep ~= nil =>
489        stackAndThrow('"You cannot define implicitly generated %1b",[op])
490      viewFuns := [op,:viewFuns]
491    op ~= "Rep" => nil        -- we are only interested in Rep definition
492    domainRep := val
493    viewFuns ~= nil =>
494      stackAndThrow('"You cannot define both %1b and %2b",["Rep",:viewFuns])
495    -- A package has no "%".
496    $functorKind = "package" =>
497      stackAndThrow('"You cannot define %1b in a package",["Rep"])
498    -- It is a mistake to define Rep in category defaults
499    $insideCategoryPackageIfTrue =>
500      stackAndThrow('"You cannot define %1b in category defaults",["Rep"])
501    if args ~= nil then
502      stackAndThrow('"%1b does take arguments",["Rep"])
503    if sig.target ~= nil then
504      stackAndThrow('"You cannot specify type for %1b",["Rep"])
505    -- Now, trick the rest of the compiler into believing that
506    -- `Rep' was defined the Old Way, for lookup purpose.
507    stmt.op := "%LET"
508    stmt.rest := ["Rep",domainRep]
509    $useRepresentationHack := false          -- Don't confuse `Rep' and `%'.
510
511  -- Shall we perform the dirty tricks?
512  if hasAssignRep then
513    $useRepresentationHack := true
514  -- Domain extensions with no explicit Rep definition have the
515  -- the base domain as representation (at least operationally).
516  else if null domainRep and addForm ~= nil then
517    if $functorKind = "domain" and addForm isnt ["%Comma",:.] then
518      domainRep :=
519        addForm is ["SubDomain",dom,.] =>
520          $subdomain := true
521          dom
522        addForm
523      $useRepresentationHack := false
524      env := putMacro('Rep,domainRep,env)
525  env
526
527
528compDefine1: (%Form,%Mode,%Env) -> %Maybe %Triple
529compDefine1(form,m,e) ==
530  $insideExpressionIfTrue: local:= false
531  --1. decompose after macro-expanding form
532  ['DEF,lhs,signature,specialCases,rhs]:= form:= macroExpand(form,e)
533  $insideWhereIfTrue and isMacro(form,e) and (m=$EmptyMode or m=$NoValueMode)
534     => [lhs,m,putMacro(lhs.op,rhs,e)]
535  checkParameterNames lhs.args
536  null signature.target and symbol? KAR rhs and not builtinConstructor? KAR rhs and
537    (sig:= getSignatureFromMode(lhs,e)) =>
538  -- here signature of lhs is determined by a previous declaration
539      compDefine1(['DEF,lhs,[sig.target,:signature.source],specialCases,rhs],m,e)
540  if signature.target=$Category then $insideCategoryIfTrue:= true
541 
542-- RDJ (11/83): when argument and return types are all declared,
543--  or arguments have types declared in the environment,
544--  and there is no existing modemap for this signature, add
545--  the modemap by a declaration, then strip off declarations and recurse
546  e := compDefineAddSignature(lhs,signature,e)
547-- 2. if signature list for arguments is not empty, replace ('DEF,..) by
548--       ('where,('DEF,..),..) with an empty signature list;
549--     otherwise, fill in all NILs in the signature
550  or/[x ~= nil for x in signature.source] => compDefWhereClause(form,m,e)
551  signature.target=$Category =>
552    compDefineCategory(form,m,e,nil,$formalArgList)
553  isDomainForm(rhs,e) and not $insideFunctorIfTrue =>
554    if null signature.target then signature:=
555      [getTargetFromRhs(lhs,rhs,giveFormalParametersValues(lhs.args,e)),:
556          signature.source]
557    rhs:= addEmptyCapsuleIfNecessary(signature.target,rhs)
558    compDefineFunctor(['DEF,lhs,signature,specialCases,rhs],m,e,nil,
559      $formalArgList)
560  null $form => stackAndThrow ['"bad == form ",form]
561  newPrefix:=
562    $prefix => makeSymbol strconc(encodeItem $prefix,'",",encodeItem $op)
563    getConstructorAbbreviationFromDB $op
564  compDefineCapsuleFunction(form,m,e,newPrefix,$formalArgList)
565
566compDefineAddSignature([op,:argl],signature,e) ==
567  (sig:= hasFullSignature(argl,signature,e)) and
568   null assoc(['$,:sig],symbolLassoc('modemap,getProplist(op,e))) =>
569     declForm:=
570       [":",[op,:[[":",x,m] for x in argl for m in sig.source]],signature.target]
571     [.,.,e]:= comp(declForm,$EmptyMode,e)
572     e
573  e
574 
575hasFullSignature(argl,[target,:ml],e) ==
576  target =>
577    u := [m or get(x,"mode",e) or return 'failed for x in argl for m in ml]
578    u is 'failed => nil
579    [target,:u]
580  nil
581 
582addEmptyCapsuleIfNecessary: (%Form,%Form) -> %Form
583addEmptyCapsuleIfNecessary(target,rhs) ==
584  symbolMember?(KAR rhs,$SpecialDomainNames) => rhs
585  ['add,rhs,['CAPSULE]]
586
587getTargetFromRhs: (%Form, %Form, %Env) -> %Form
588getTargetFromRhs(lhs,rhs,e) ==
589  --undeclared target mode obtained from rhs expression
590  rhs is ['CAPSULE,:.] =>
591    stackSemanticError(['"target category of ",lhs,
592      '" cannot be determined from definition"],nil)
593  rhs is ['SubDomain,D,:.] => getTargetFromRhs(lhs,D,e)
594  rhs is ['add,D,['CAPSULE,:.]] => getTargetFromRhs(lhs,D,e)
595  rhs is ['Record,:l] => ['RecordCategory,:l]
596  rhs is ['Union,:l] => ['UnionCategory,:l]
597  (compOrCroak(rhs,$EmptyMode,e)).mode
598 
599giveFormalParametersValues(argl,e) ==
600  for x in argl | ident? x repeat
601    e := giveVariableSomeValue(x,get(x,'mode,e),e)
602  e
603
604
605macroExpandInPlace: (%Form,%Env) -> %Form
606macroExpandInPlace(x,e) ==
607  y:= macroExpand(x,e)
608  x isnt [.,:.] or y isnt [.,:.] => y
609  x.first := first y
610  x.rest := rest y
611  x
612
613macroExpand: (%Form,%Env) -> %Form
614macroExpand(x,e) ==   --not worked out yet
615  x isnt [.,:.] =>
616    not ident? x or (u := get(x,"macro",e)) = nil => x
617    -- Don't expand a functional macro name by itself.
618    u is ['%mlambda,:.] => x
619    macroExpand(u,e)
620  x is ['DEF,lhs,sig,spCases,rhs] =>
621    ['DEF,macroExpand(lhs,e),macroExpandList(sig,e),macroExpandList(spCases,e),
622      macroExpand(rhs,e)]
623  -- macros should override niladic props
624  [op,:args] := x
625  ident? op and args = nil and niladicConstructorFromDB op and
626    (u := get(op,"macro", e)) => macroExpand(u,e)
627  ident? op and (get(op,"macro",e) is ['%mlambda,parms,body]) =>
628    nargs := #args
629    nparms := #parms
630    msg :=
631      nargs < nparms => '"Too few arguments"
632      nargs > nparms => '"Too many arguments"
633      nil
634    msg => (stackMessage(strconc(msg,'" to macro %1bp"),[op]); x)
635    args' := macroExpandList(args,e)
636    applySubst(pairList(parms,args'),body)
637  macroExpandList(x,e)
638 
639macroExpandList(l,e) ==
640  [macroExpand(x,e) for x in l]
641
642--% constructor evaluation
643 
644mkEvalableCategoryForm c ==
645  c is [op,:argl] =>
646    op="Join" => ["Join",:[mkEvalableCategoryForm x for x in argl]]
647    op is "DomainSubstitutionMacro" => mkEvalableCategoryForm second argl
648    op is "mkCategory" => c
649    builtinCategoryName? op =>
650      ([x,m,$e]:= compOrCroak(c,$EmptyMode,$e); m=$Category => x)
651    --loadIfNecessary op
652    getConstructorKindFromDB op = 'category or
653      get(op,"isCategory",$CategoryFrame) =>
654        [op,:[MKQ x for x in argl]]
655    [x,m,$e]:= compOrCroak(c,$EmptyMode,$e)
656    m=$Category => x
657  MKQ c
658 
659++ Return true if we should skip compilation of category package.
660++ This situation happens either when there is no default, of we are in
661++ bootstrap mode, or we are compiling only for exports.
662skipCategoryPackage? capsule ==
663  null capsule or $bootStrapMode or $compileExportsOnly
664
665compDefineCategory1(df is ['DEF,form,sig,sc,body],m,e,prefix,fal) ==
666  categoryCapsule :=
667    body is ['add,cat,capsule] =>
668      body := cat
669      capsule
670    nil
671  [d,m,e]:= compDefineCategory2(form,sig,sc,body,m,e,prefix,fal)
672  if not skipCategoryPackage? categoryCapsule then [.,.,e] :=
673    $insideCategoryPackageIfTrue: local := true
674    $categoryPredicateList: local :=
675        makeCategoryPredicates(form,$lisplibCategory)
676    T := compDefine1(mkCategoryPackage(form,cat,categoryCapsule),$EmptyMode,e)
677           or return stackSemanticError(
678                        ['"cannot compile defaults of",:bright opOf form],nil)
679    if $compileDefaultsOnly then
680      [d,m,e] := T
681  [d,m,e]
682
683makeCategoryPredicates(form,u) ==
684      $tvl: local := TAKE(#rest form,$TriangleVariableList)
685      $mvl: local := TAKE(#rest form,rest $FormalMapVariableList)
686      fn(u,nil) where
687        fn(u,pl) ==
688          u is ['Join,:.,a] => fn(a,pl)
689          u is ["IF",p,:x] =>
690            fnl(x,insert(applySubst(pairList($tvl,$mvl),p),pl))
691          u is ["has",:.] =>
692            insert(applySubst(pairList($tvl,$mvl),u),pl)
693          u is [op,:.] and op in '(SIGNATURE ATTRIBUTE) => pl
694          u isnt [.,:.] => pl
695          fnl(u,pl)
696        fnl(u,pl) ==
697          for x in u repeat pl := fn(x,pl)
698          pl
699 
700mkCategoryPackage(form is [op,:argl],cat,def) ==
701  packageName:= makeDefaultPackageName symbolName op
702  packageAbb := makeSymbol(strconc(getConstructorAbbreviationFromDB op,'"-"))
703  $options:local := []
704  -- This stops the next line from becoming confused
705  abbreviationsSpad2Cmd ['domain,packageAbb,packageName]
706  -- This is a little odd, but the parser insists on calling
707  -- domains, rather than packages
708  nameForDollar := first SETDIFFERENCE('(S A B C D E F G H I),argl)
709  packageArgl := [nameForDollar,:argl]
710  capsuleDefAlist := fn(def,nil) where fn(x,oplist) ==
711    x isnt [.,:.] => oplist
712    x is ['DEF,y,:.] => [y,:oplist]
713    fn(x.args,fn(x.op,oplist))
714  catvec := eval mkEvalableCategoryForm form
715  fullCatOpList := categoryExports JoinInner([catvec],$e)
716  catOpList :=
717    [['SIGNATURE,op1,sig] for [[op1,sig],:.] in fullCatOpList
718        | assoc(op1,capsuleDefAlist)]
719  null catOpList => nil
720  packageCategory :=
721    ['CATEGORY,'domain,
722       :applySubst(pairList($FormalMapVariableList,argl),catOpList)]
723  nils:= [nil for x in argl]
724  packageSig := [packageCategory,form,:nils]
725  $categoryPredicateList := substitute(nameForDollar,'$,$categoryPredicateList)
726  substitute(nameForDollar,'$,
727      ['DEF,[packageName,:packageArgl],packageSig,[nil,:nils],def])
728 
729compDefineCategory2(form,signature,specialCases,body,m,e,
730  $prefix,$formalArgList) ==
731    --1. bind global variables
732    $insideCategoryIfTrue: local := true
733    $definition: local := form   --used by DomainSubstitutionFunction
734    $form: local := nil
735    $op: local := nil
736    $extraParms: local := nil
737    -- Remember the body for checking the current instantiation.
738    $currentCategoryBody : local := body
739         --Set in DomainSubstitutionFunction, used further down
740    -- 1.1  augment e to add declaration $: <form>
741    [$op,:argl] := $definition
742    e:= addBinding("$",[['mode,:$definition]],e)
743 
744    -- 2. obtain signature
745    signature':=
746      [signature.target,
747        :[getArgumentModeOrMoan(a,$definition,e) for a in argl]]
748    e:= giveFormalParametersValues(argl,e)
749 
750    -- 3. replace arguments by $1,..., substitute into body,
751    --    and introduce declarations into environment
752    sargl:= TAKE(# argl, $TriangleVariableList)
753    $functorForm:= $form:= [$op,:sargl]
754    $formalArgList:= [:sargl,:$formalArgList]
755    aList := pairList(argl,sargl)
756    formalBody:= applySubst(aList,body)
757    signature' := applySubst(aList,signature')
758    --Begin lines for category default definitions
759    $functionStats: local:= [0,0]
760    $functorStats: local:= [0,0]
761    $getDomainCode: local := nil
762    $addForm: local:= nil
763    for x in sargl for t in signature'.source repeat
764      [.,.,e]:= compMakeDeclaration(x,t,e)
765 
766    -- 4. compile body in environment of %type declarations for arguments
767    op':= $op
768    -- following line causes cats with no with or Join to be fresh copies
769    if opOf(formalBody)~='Join and opOf(formalBody)~='mkCategory then
770           formalBody := ['Join, formalBody]
771    body:= optFunctorBody compOrCroak(formalBody,signature'.target,e).expr
772    if $extraParms then
773      formals:=actuals:=nil
774      for u in $extraParms repeat
775        formals:=[first u,:formals]
776        actuals:=[MKQ rest u,:actuals]
777      body := ['sublisV,['pairList,['QUOTE,formals],['%list,:actuals]],body]
778    if argl then body:=  -- always subst for args after extraparms
779        ['sublisV,['pairList,['QUOTE,sargl],['%list,:
780          [['devaluate,u] for u in sargl]]],body]
781    body:=
782      ["%bind",[[g:= gensym(),body]],
783         ['%store,['%tref,g,0],mkConstructor $form],g]
784    fun:= compile [op',["LAM",sargl,body]]
785 
786    -- 5. give operator a 'modemap property
787    pairlis := pairList(argl,$FormalMapVariableList)
788    parSignature:= applySubst(pairlis,signature')
789    parForm:= applySubst(pairlis,form)
790    -- If we are only interested in the defaults, there is no point
791    -- in writing out compiler info and load-time stuff for
792    -- the category which is assumed to have already been translated.
793    if not $compileDefaultsOnly then
794      lisplibWrite('"compilerInfo",
795        removeZeroOne ['SETQ,'$CategoryFrame,
796         ['put,['QUOTE,op'],'
797          (QUOTE isCategory),true,['addModemap,MKQ op',MKQ parForm,
798            MKQ parSignature,true,MKQ fun,'$CategoryFrame]]],$libFile)
799      --Equivalent to the following two lines, we hope
800      if null sargl then
801        evalAndRwriteLispForm('NILADIC,
802              ['MAKEPROP,['QUOTE,op'],'(QUOTE NILADIC),true])
803 
804    -- 6. put modemaps into InteractiveModemapFrame
805    $domainShell := eval [op',:[MKQ f for f in sargl]]
806    $lisplibCategory:= formalBody
807    if $LISPLIB then
808      $lisplibForm:= form
809      $lisplibKind:= 'category
810      modemap:= [[parForm,:parSignature],[true,op']]
811      $lisplibModemap:= modemap
812      $lisplibParents  :=         
813        getParentsFor($op,$FormalMapVariableList,$lisplibCategory)
814      $lisplibAncestors := computeAncestorsOf($form,nil)
815      $lisplibAbbreviation := getConstructorAbbreviationFromDB $op
816      form':=[op',:sargl]
817      augLisplibModemapsFromCategory(form',formalBody,signature')
818    [fun,$Category,e]
819
820mkConstructor: %Form -> %Form
821mkConstructor form ==
822  form isnt [.,:.] => ['devaluate,form]
823  null form.args => ['QUOTE,[form.op]]
824  ['%list,MKQ form.op,:[mkConstructor x for x in form.args]]
825 
826compDefineCategory(df,m,e,prefix,fal) ==
827  $domainShell: local := nil -- holds the category of the object being compiled
828  $lisplibCategory: local := nil
829  -- since we have so many ways to say state the kind of a constructor,
830  -- make sure we do have some minimal internal coherence.
831  ctor := opOf second df
832  kind := getConstructorKindFromDB ctor
833  kind ~= "category" => throwKeyedMsg("S2IC0016",[ctor,"category",kind])
834  $insideFunctorIfTrue or not $LISPLIB or $compileDefaultsOnly =>
835    compDefineCategory1(df,m,e,prefix,fal)
836  compDefineLisplib(df,m,e,prefix,fal,'compDefineCategory1)
837
838
839%CatObjRes                   -- result of compiling a category
840  <=> [%Shell,:[%Mode,:[%Env,:null]]]
841 
842compMakeCategoryObject: (%Form,%Env) -> %Maybe %CatObjRes
843compMakeCategoryObject(c,$e) ==
844  not isCategoryForm(c,$e) => nil
845  u:= mkEvalableCategoryForm c => [eval u,$Category,$e]
846  nil
847
848predicatesFromAttributes: %List %Form -> %List %Form
849predicatesFromAttributes attrList ==
850  removeDuplicates [second x for x in attrList]
851
852++ Subroutine of inferConstructorImplicitParameters.
853typeDependencyPath(m,path,e) ==
854  ident? m and assoc(m,$whereDecls) =>
855    get(m,'value,e) => nil  -- parameter was given value
856    [[m,:reverse path],:typeDependencyPath(getmode(m,e),path,e)]
857  atomic? m => nil
858  [ctor,:args] := m
859  -- We don't expect implicit parameters in builtin constructors.
860  builtinConstructor? ctor => nil
861  -- FIXME: assume constructors cannot be parameters
862  not constructor? ctor => nil
863  [:typeDependencyPath(m',[i,:path],e) for m' in args for i in 0..]
864
865++ Given the list `parms' of explicit constructor parameters, compute
866++ a list of pairs `(p . path)' where `p' is a parameter implicitly
867++ introduced (either directly or indirectly) by a declaration of
868++ one of the explicit parameters.
869inferConstructorImplicitParameters(parms,e) ==
870  removeDuplicates
871    [:typeDependencyPath(getmode(p,e),[i],e) for p in parms for i in 0..]
872 
873compDefineFunctor(df,m,e,prefix,fal) ==
874  $domainShell: local := nil -- holds the category of the object being compiled
875  $profileCompiler: local := true
876  $profileAlist:    local := nil
877  $mutableDomain: local := false
878  $compileExportsOnly or not $LISPLIB =>
879    compDefineFunctor1(df,m,e,prefix,fal)
880  compDefineLisplib(df,m,e,prefix,fal,'compDefineFunctor1)
881 
882compDefineFunctor1(df is ['DEF,form,signature,nils,body],
883  m,$e,$prefix,$formalArgList) ==
884    --  1. bind global variables
885    $addForm: local := nil
886    $subdomain: local := false
887    $functionStats: local:= [0,0]
888    $functorStats: local:= [0,0]
889    $form: local := nil
890    $op: local := nil
891    $signature: local := nil
892    $functorTarget: local := nil
893    $Representation: local := nil
894         --Set in doIt, accessed in the compiler - compNoStacking
895    $functorForm: local := nil
896    $functorLocalParameters: local := nil
897    $CheckVectorList: local := nil
898    $getDomainCode: local := nil -- code for getting views
899    $insideFunctorIfTrue: local:= true
900    $genSDVar: local:= 0
901    originale:= $e
902    [$op,:argl]:= form
903    $formalArgList:= [:argl,:$formalArgList]
904    $pairlis: local := pairList(argl,$FormalMapVariableList)
905    $mutableDomain: local :=
906      -- all defaulting packages should have caching turned off
907       isCategoryPackageName $op or symbolMember?($op,$mutableDomains)
908                                    --true if domain has mutable state
909    signature':=
910      [signature.target,:[getArgumentModeOrMoan(a,form,$e) for a in argl]]
911    $functorForm := $form := [$op,:argl]
912    if null signature'.target then signature':=
913      modemap2Signature getModemap($form,$e)
914    $functorTarget := target := signature'.target
915    $functorKind: local :=
916      $functorTarget is ["CATEGORY",key,:.] => key
917      "domain"
918    $e := giveFormalParametersValues(argl,$e)
919    $implicitParameters: local := inferConstructorImplicitParameters(argl,$e)
920    [ds,.,$e]:= compMakeCategoryObject(target,$e) or return
921       stackAndThrow('"   cannot produce category object: %1pb",[target])
922    $compileExportsOnly =>
923      compDefineExports(form, categoryExports ds, signature',$e)
924    $domainShell: local := copyVector ds
925    attributeList := categoryAttributes ds --see below under "loadTimeAlist"
926    $condAlist: local := nil
927    $uncondAlist: local := nil
928    $NRTslot1PredicateList: local := predicatesFromAttributes attributeList
929    $NRTattributeAlist: local := NRTgenInitialAttributeAlist attributeList
930    $NRTslot1Info: local := nil  --set in NRTmakeSlot1Info
931       --this is used below to set $lisplibSlot1 global
932    $NRTaddForm: local := nil   -- see compAdd
933    $NRTdeltaList: local := nil --list of misc. elts used in compiled fncts
934    $NRTdeltaListComp: local := nil --list of compiled forms for $NRTdeltaList
935    $NRTdeltaLength: local := 0 -- =length of block of extra entries in vector
936    $template: local:= nil --stored in the lisplib
937    $functionLocations: local := nil --locations of defined functions in source
938    -- generate slots for arguments first, then for $NRTaddForm in compAdd
939    for x in argl repeat NRTgetLocalIndex x
940    [.,.,$e]:= compMakeDeclaration("$",target,$e)
941    if not $insideCategoryPackageIfTrue  then
942      $e:= augModemapsFromCategory('_$,'_$,'_$,target,$e)
943    $signature:= signature'
944    parSignature:= applySubst($pairlis,signature')
945    parForm:= applySubst($pairlis,form)
946 
947    --  (3.1) now make a list of the functor's local parameters; for
948    --  domain D in argl,check its signature: if domain, its type is Join(A1,..,An);
949    --  in this case, D is replaced by D1,..,Dn (gensyms) which are set
950    --  to the A1,..,An view of D
951    makeFunctorArgumentParameters(argl,signature'.source,signature'.target)
952    $functorLocalParameters := argl
953
954    --  4. compile body in environment of %type declarations for arguments
955    op':= $op
956    rettype:= signature'.target
957    -- If this functor is defined as instantiation of a functor
958    -- that is a subdomain of `D', then make this functor also a subdomain
959    -- of that super domain `D'.
960    if body is ["add",[rhsCtor,:rhsArgs],["CAPSULE"]]
961        and constructor? rhsCtor
962         and (u := getSuperDomainFromDB rhsCtor) then
963           u := sublisFormal(rhsArgs,u,$AtVariables)
964           emitSubdomainInfo($form,first u, second u)
965    T:= compFunctorBody(body,rettype,$e,parForm)
966    -- If only compiling certain items, then ignore the body shell.
967    $compileOnlyCertainItems =>
968       reportOnFunctorCompilation()
969       [nil, ['Mapping, :signature'], originale]
970 
971    body':= T.expr
972    lamOrSlam:= if $mutableDomain then 'LAM else 'SPADSLAM
973    fun:= compile applySubst($pairlis, [op',[lamOrSlam,argl,body']])
974    --The above statement stops substitutions gettting in one another's way
975    operationAlist := applySubst($pairlis,$lisplibOperationAlist)
976    if $LISPLIB then
977      augmentLisplibModemapsFromFunctor(parForm,operationAlist,parSignature)
978    reportOnFunctorCompilation()
979 
980    --  5. give operator a 'modemap property
981    if $LISPLIB then
982      modemap:= [[parForm,:parSignature],[true,op']]
983      $lisplibModemap:= modemap
984      $lisplibCategory := modemap.mmTarget
985      $lisplibParents  :=         
986        getParentsFor($op,$FormalMapVariableList,$lisplibCategory)
987      $lisplibAncestors := computeAncestorsOf($form,nil)
988      $lisplibAbbreviation := getConstructorAbbreviationFromDB $op
989    $insideFunctorIfTrue:= false
990    if $LISPLIB then
991      $lisplibKind:=
992        $functorTarget is ["CATEGORY",key,:.] and key~="domain" => 'package
993        'domain
994      $lisplibForm:= form
995      if not $bootStrapMode then
996        $NRTslot1Info := NRTmakeSlot1Info()
997        $isOpPackageName: local := isCategoryPackageName $op
998        if $isOpPackageName then lisplibWrite('"slot1DataBase",
999          ['updateSlot1DataBase,MKQ $NRTslot1Info],$libFile)
1000        $lisplibFunctionLocations := applySubst($pairlis,$functionLocations)
1001        libFn := getConstructorAbbreviationFromDB op'
1002        $lookupFunction: local :=
1003            NRTgetLookupFunction($functorForm,$lisplibModemap.mmTarget,$NRTaddForm,$e)
1004            --either lookupComplete (for forgetful guys) or lookupIncomplete
1005        $byteAddress :local := 0
1006        $byteVec :local := nil
1007        $NRTslot1PredicateList :=
1008          [simpBool x for x in $NRTslot1PredicateList]
1009        rwriteLispForm('loadTimeStuff,
1010          ['MAKEPROP,MKQ $op,''infovec,getInfovecCode()])
1011      $lisplibSlot1 := $NRTslot1Info
1012      $lisplibOperationAlist:= operationAlist
1013    lisplibWrite('"compilerInfo",
1014       removeZeroOne ['SETQ,'$CategoryFrame,
1015        ['put,['QUOTE,op'],'
1016         (QUOTE isFunctor),
1017          ['QUOTE,operationAlist],['addModemap,['QUOTE,op'],['
1018           QUOTE,parForm],['QUOTE,parSignature],true,['QUOTE,op'],
1019            ['put,['QUOTE,op' ],'(QUOTE mode),
1020             ['QUOTE,['Mapping,:parSignature]],'$CategoryFrame]]]],$libFile)
1021    if null argl then
1022      evalAndRwriteLispForm('NILADIC,
1023            ['MAKEPROP, ['QUOTE,op'], ['QUOTE,'NILADIC], true])
1024    -- Functors are incomplete during bootstrap
1025    if $bootStrapMode then
1026      evalAndRwriteLispForm('%incomplete,
1027            ['MAKEPROP, ['QUOTE,op'], ['QUOTE,'%incomplete], true])
1028    [fun,['Mapping,:signature'],originale]
1029
1030++ Subroutine of compDefineFunctor1.  Called to generate backend code
1031++ for a functor definition.
1032compFunctorBody(body,m,e,parForm) ==
1033  $bootStrapMode =>
1034    [bootStrapError($functorForm, _/EDITFILE),m,e]
1035  clearCapsuleDirectory()        -- start collecting capsule functions.
1036  T:= compOrCroak(body,m,e)
1037  $capsuleFunctionStack := reverse! $capsuleFunctionStack
1038  -- ??? Don't resolve default definitions, yet.
1039  if $insideCategoryPackageIfTrue then
1040    backendCompile $capsuleFunctionStack
1041  else
1042    backendCompile foldExportedFunctionReferences $capsuleFunctionStack
1043  clearCapsuleDirectory()        -- release storage.
1044  body is [op,:.] and op in '(add CAPSULE) => T
1045  $NRTaddForm :=
1046    body is ["SubDomain",domainForm,predicate] => domainForm
1047    body
1048  T
1049 
1050reportOnFunctorCompilation() ==
1051  displayMissingFunctions()
1052  if $semanticErrorStack then sayBrightly '" "
1053  displaySemanticErrors()
1054  if $warningStack then sayBrightly '" "
1055  displayWarnings()
1056  $functorStats:= addStats($functorStats,$functionStats)
1057  [byteCount,elapsedSeconds] := $functorStats
1058  sayBrightly ['%l,:bright '"  Cumulative Statistics for Constructor",$op]
1059  timeString := normalizeStatAndStringify elapsedSeconds
1060  sayBrightly ['"      Time:",:bright timeString,'"seconds"]
1061  sayBrightly '" "
1062  'done
1063 
1064displayMissingFunctions() ==
1065  null $CheckVectorList => nil
1066  loc := nil              -- list of local operation signatures
1067  exp := nil              -- list of exported operation signatures
1068  for [[op,sig,:.],:pred] in $CheckVectorList  | not pred repeat
1069    not symbolMember?(op,$formalArgList) and getmode(op,$e) is ['Mapping,:.] =>
1070      loc := [[op,sig],:loc]
1071    exp := [[op,sig],:exp]
1072  if loc then
1073    sayBrightly ['"%l",:bright '"  Missing Local Functions:"]
1074    for [op,sig] in loc for i in 1.. repeat
1075      sayBrightly ['"      [",i,'"]",:bright op,
1076        ": ",:formatUnabbreviatedSig sig]
1077  if exp then
1078    sayBrightly ['"%l",:bright '"  Missing Exported Functions:"]
1079    for [op,sig] in exp for i in 1.. repeat
1080      sayBrightly ['"      [",i,'"]",:bright op,
1081        ": ",:formatUnabbreviatedSig sig]
1082 
1083--% domain view code
1084 
1085makeFunctorArgumentParameters(argl,sigl,target) ==
1086  $forceAdd: local:= true
1087  $ConditionalOperators: local := nil
1088  ("append"/[fn(a,augmentSig(s,findExtras(a,target)))
1089              for a in argl for s in sigl]) where
1090    findExtras(a,target) ==
1091      --  see if conditional information implies anything else
1092      --  in the signature of a
1093      target is ['Join,:l] => "union"/[findExtras(a,x) for x in l]
1094      target is ['CATEGORY,.,:l] => "union"/[findExtras1(a,x) for x in l] where
1095        findExtras1(a,x) ==
1096          x is ['AND,:l] => "union"/[findExtras1(a,y) for y in l]
1097          x is ['OR,:l] => "union"/[findExtras1(a,y) for y in l]
1098          x is ['IF,c,p,q] =>
1099            union(findExtrasP(a,c),
1100                  union(findExtras1(a,p),findExtras1(a,q))) where
1101              findExtrasP(a,x) ==
1102                x is ['AND,:l] => "union"/[findExtrasP(a,y) for y in l]
1103                x is ['OR,:l] => "union"/[findExtrasP(a,y) for y in l]
1104                x is ["has",=a,y] and y is ['SIGNATURE,:.] => [y]
1105                nil
1106        nil
1107    augmentSig(s,ss) ==
1108       -- if we find something extra, add it to the signature
1109      null ss => s
1110      for u in ss repeat
1111        $ConditionalOperators:=[rest u,:$ConditionalOperators]
1112      s is ['Join,:sl] =>
1113        u:=ASSQ('CATEGORY,ss) =>
1114          MSUBST([:u,:ss],u,s)
1115        ['Join,:sl,['CATEGORY,'package,:ss]]
1116      ['Join,s,['CATEGORY,'package,:ss]]
1117    fn(a,s) ==
1118      isCategoryForm(s,$CategoryFrame) =>
1119        s is ["Join",:catlist] => genDomainViewList(a,s.args)
1120        [genDomainView(a,a,s,"getDomainView")]
1121      [a]
1122 
1123genDomainOps(viewName,dom,cat) ==
1124  oplist:= getOperationAlist(dom,dom,cat)
1125  siglist:= [sig for [sig,:.] in oplist]
1126  oplist:= substNames(dom,viewName,dom,oplist)
1127  cd:=
1128    ["%LET",viewName,['mkOpVec,dom,['%list,:
1129      [['%list,MKQ op,['%list,:[mkTypeForm mode for mode in sig]]]
1130        for [op,sig] in siglist]]]]
1131  $getDomainCode:= [cd,:$getDomainCode]
1132  for [opsig,cond,:.] in oplist for i in 0.. repeat
1133    if listMember?(opsig,$ConditionalOperators) then cond:=nil
1134    [op,sig]:=opsig
1135    $e:= addModemap(op,dom,sig,cond,['ELT,viewName,i],$e)
1136  viewName
1137 
1138genDomainView(viewName,originalName,c,viewSelector) ==
1139  c is ['CATEGORY,.,:l] => genDomainOps(viewName,originalName,c)
1140  code:=
1141    c is ['SubsetCategory,c',.] => c'
1142    c
1143  $e:= augModemapsFromCategory(originalName,viewName,nil,c,$e)
1144  cd:= ["%LET",viewName,[viewSelector,originalName,mkTypeForm code]]
1145  if not listMember?(cd,$getDomainCode) then
1146          $getDomainCode:= [cd,:$getDomainCode]
1147  viewName
1148
1149genDomainViewList: (%Symbol,%List %Form) -> %List %Code
1150genDomainViewList(id,catlist) ==
1151  [genDomainView(id,id,cat,"getDomainView")
1152     for cat in catlist | isCategoryForm(cat,$EmptyEnvironment)]
1153 
1154mkOpVec(dom,siglist) ==
1155  dom:= getPrincipalView dom
1156  substargs := [['$,:canonicalForm dom],
1157                  :pairList($FormalMapVariableList,instantiationArgs dom)]
1158  oplist:= getConstructorOperationsFromDB instantiationCtor dom
1159  --new form is (<op> <signature> <slotNumber> <condition> <kind>)
1160  ops := newVector #siglist
1161  for (opSig:= [op,sig]) in siglist for i in 0.. repeat
1162    u:= ASSQ(op,oplist)
1163    assoc(sig,u) is [.,n,.,'ELT] =>
1164      vectorRef(ops,i) := vectorRef(dom,n)
1165    noplist := applySubst(substargs,u)
1166  -- following variation on assoc needed for GENSYMS in Mutable domains
1167    AssocBarGensym(substitute(dom.0,'$,sig),noplist) is [.,n,.,'ELT] =>
1168      vectorRef(ops,i) := vectorRef(dom,n)
1169    vectorRef(ops,i) := [function Undef,[dom.0,i],:opSig]
1170  ops
1171 
1172
1173++ form is lhs (f a1 ... an) of definition; body is rhs;
1174++ signature is (t0 t1 ... tn) where t0= target type, ti=type of ai, i > 0;
1175++ specialCases is (NIL l1 ... ln) where li is list of special cases
1176++ which can be given for each ti
1177++ removes declarative and assignment information from form and
1178++ signature, placing it in list L, replacing form by ("where",form',:L),
1179++ signature by a list of NILs (signifying declarations are in e)
1180compDefWhereClause(['DEF,form,signature,specialCases,body],m,e) ==
1181  $sigAlist: local := nil
1182  $predAlist: local := nil
1183  -- 1. create sigList= list of all signatures which have embedded
1184  --    declarations moved into global variable $sigAlist
1185  sigList:=
1186    [transformType fetchType(a,x,e,form)
1187      for a in form.args for x in signature.source] where
1188        fetchType(a,x,e,form) ==
1189          x => x
1190          getmode(a,e) or userError concat(
1191            '"There is no mode for argument",a,'"of function",form.op)
1192        transformType x ==
1193          x isnt [.,:.] => x
1194          x is [":",R,Rtype] =>
1195            ($sigAlist:= [[R,:transformType Rtype],:$sigAlist]; x)
1196          x is ['Record,:.] => x --RDJ 8/83
1197          [x.op,:[transformType y for y in x.args]]
1198 
1199  -- 2. replace each argument of the form (|| x p) by x, recording
1200  --    the given predicate in global variable $predAlist
1201  argList:=
1202    [removeSuchthat a for a in form.args] where
1203      removeSuchthat x ==
1204        x is ["|",y,p] => ($predAlist:= [[y,:p],:$predAlist]; y)
1205        x
1206 
1207  -- 3. obtain a list of parameter identifiers (x1 .. xn) ordered so that
1208  --       the type of xi is independent of xj if i < j
1209  varList :=
1210    orderByDependency(ASSOCLEFT argDepAlist,ASSOCRIGHT argDepAlist) where
1211      argDepAlist :=
1212        [[x,:dependencies] for [x,:y] in argSigAlist] where
1213          dependencies() ==
1214            union(listOfIdentifiersIn y,
1215              remove(listOfIdentifiersIn LASSOC(x,$predAlist),x))
1216          argSigAlist := [:$sigAlist,:pairList(argList,sigList)]
1217 
1218  -- 4. construct a WhereList which declares and/or defines the xi's in
1219  --    the order constructed in step 3
1220  whereList := [addSuchthat(x,[":",x,LASSOC(x,argSigAlist)]) for x in varList]
1221     where addSuchthat(x,y) ==
1222             p := LASSOC(x,$predAlist) => ["|",y,p]
1223             y
1224 
1225  -- 5. compile new ('DEF,("where",form',:WhereList),:.) where
1226  --    all argument parameters of form' are bound/declared in WhereList
1227  comp(form',m,e) where
1228    form' := ["where",defform,:whereList] where
1229      defform := ['DEF,form'',signature',specialCases,body] where
1230        form'' := [form.op,:argList]
1231        signature' := [signature.target,:[nil for x in signature.source]]
1232 
1233orderByDependency(vl,dl) ==
1234  -- vl is list of variables, dl is list of dependency-lists
1235  selfDependents:= [v for v in vl for d in dl | symbolMember?(v,d)]
1236  for v in vl for d in dl | symbolMember?(v,d) repeat
1237    (SAY(v," depends on itself"); fatalError:= true)
1238  fatalError => userError '"Parameter specification error"
1239  until vl = nil repeat
1240    newl:=
1241      [v for v in vl for d in dl | null intersection(d,vl)] or return nil
1242    orderedVarList:= [:newl,:orderedVarList]
1243    vl' := setDifference(vl,newl)
1244    dl' := [setDifference(d,newl) for x in vl for d in dl
1245             | symbolMember?(x,vl')]
1246    vl := vl'
1247    dl := dl'
1248  removeDuplicates reverse! orderedVarList --ordered so ith is indep. of jth if i < j
1249 
1250compDefineCapsuleFunction(df is ['DEF,form,signature,specialCases,body],
1251  m,$e,$prefix,$formalArgList) ==
1252    [lineNumber,:specialCases] := specialCases
1253    e := $e
1254    --1. bind global variables
1255    $form: local := nil
1256    $op: local := nil
1257    $functionStats: local:= [0,0]
1258    $argumentConditionList: local := nil
1259    $finalEnv: local := nil
1260             --used by ReplaceExitEtc to get a common environment
1261    $initCapsuleErrorCount: local:= #$semanticErrorStack
1262    $insideCapsuleFunctionIfTrue: local:= true
1263    $CapsuleModemapFrame: local:= e
1264    $CapsuleDomainsInScope: local:= get("$DomainsInScope","special",e)
1265    $insideExpressionIfTrue: local:= true
1266    $returnMode:= m
1267    -- Change "^" to "**" in definitions.  All other places have
1268    -- been changed before we get here.
1269    if form.op = "^" then
1270      sayBrightly ['"Replacing", :bright '"^", '"with",:bright '"**"]
1271      form.op := "**"
1272    [$op,:argl]:= form
1273    $form:= [$op,:argl]
1274    argl:= stripOffArgumentConditions argl
1275    $formalArgList:= [:argl,:$formalArgList]
1276 
1277    --let target and local signatures help determine modes of arguments
1278    argModeList :=
1279      identSig := hasSigInTargetCategory(argl,form,signature.target,e) =>
1280        (e:= checkAndDeclare(argl,form,identSig,e); identSig.source)
1281      [getArgumentModeOrMoan(a,form,e) for a in argl]
1282    argModeList := stripOffSubdomainConditions(argModeList,argl)
1283    signature' := [signature.target,:argModeList]
1284    if null identSig then  --make $op a local function
1285      $e := put($op,'mode,['Mapping,:signature'],$e)
1286 
1287    --obtain target type if not given
1288    if null signature'.target then signature':=
1289      identSig => identSig
1290      getSignature($op,signature'.source,e) or return nil
1291    e:= giveFormalParametersValues(argl,e)
1292 
1293    $signatureOfForm:= signature' --this global is bound in compCapsuleItems
1294    $functionLocations := [[[$op,$signatureOfForm],:lineNumber],
1295      :$functionLocations]
1296    e:= addDomain(signature'.target,e)
1297    e:= compArgumentConditions e
1298 
1299    if $profileCompiler then
1300      for x in argl for t in signature'.source repeat
1301        profileRecord('arguments,x,t)
1302
1303    --4. introduce needed domains into extendedEnv
1304    for domain in signature' repeat e:= addDomain(domain,e)
1305 
1306    --6. compile body in environment with extended environment
1307    rettype:= resolve(signature'.target,$returnMode)
1308 
1309    localOrExported :=
1310      not symbolMember?($op,$formalArgList) and
1311        getmode($op,e) is ['Mapping,:.] => 'local
1312      'exported
1313 
1314    --6a skip if compiling only certain items but not this one
1315    -- could be moved closer to the top
1316    formattedSig := formatUnabbreviated ['Mapping,:signature']
1317    $compileOnlyCertainItems and _
1318      not symbolMember?($op, $compileOnlyCertainItems) =>
1319        sayBrightly ['"   skipping ", localOrExported,:bright $op]
1320        [nil,['Mapping,:signature'],$e]
1321    sayBrightly ['"   compiling ",localOrExported,
1322      :bright $op,'": ",:formattedSig]
1323 
1324    noteCapsuleFunctionDefinition($op,signature', makePredicate $predl)
1325    T := CATCH('compCapsuleBody, compOrCroak(body,rettype,e))
1326         or [$ClearBodyToken,rettype,e]
1327    NRTassignCapsuleFunctionSlot($op,signature')
1328    if $newCompCompare=true then
1329       SAY '"The old compiler generates:"
1330       prTriple T
1331    --  A THROW to the above CATCH occurs if too many semantic errors occur
1332    --  see stackSemanticError
1333    catchTag:= MKQ gensym()
1334    fun:=
1335      body':= replaceExitEtc(T.expr,catchTag,"TAGGEDreturn",$returnMode)
1336      body':= addArgumentConditions(body',$op)
1337      finalBody:= ["CATCH",catchTag,body']
1338      compile [$op,["LAM",[:argl,'_$],finalBody]]
1339    $functorStats:= addStats($functorStats,$functionStats)
1340 
1341    --7. give operator a 'value property
1342    val:= [fun,signature',e]
1343    [fun,['Mapping,:signature'],$e]
1344 
1345getSignatureFromMode(form,e) ==
1346  getmode(opOf form,e) is ['Mapping,:signature] =>
1347    #form~=#signature => stackAndThrow ["Wrong number of arguments: ",form]
1348    applySubst(pairList($FormalMapVariableList,form.args),signature)
1349
1350candidateSignatures(op,nmodes,slot1) ==
1351  [sig for [[=op,sig,:.],:.] in slot1 | #sig = nmodes]
1352
1353++ We are compiling a capsule function definition with head given by `form'.
1354++ Determine whether the function with possibly partial signature `opsig'
1355++ is exported.  Return the complete signature if yes; otherwise
1356++ return nil, with diagnostic in ambiguity case.
1357hasSigInTargetCategory(argl,form,opsig,e) ==
1358  sigs := candidateSignatures($op,#form,categoryExports $domainShell)
1359  cc := checkCallingConvention(sigs,#argl)
1360  mList:= [(cc.i > 0 => quasiquote x; getArgumentMode(x,e))
1361            for x in argl for i in 0..]
1362    --each element is a declared mode for the variable or nil if none exists
1363  potentialSigList:=
1364    removeDuplicates
1365      [sig for sig in sigs |
1366          fn(sig,opsig,mList)] where
1367            fn(sig,opsig,mList) ==
1368              (null opsig or opsig=sig.target) and
1369                (and/[compareMode2Arg(x,m) for x in mList for m in sig.source])
1370  c:= #potentialSigList
1371  1=c => first potentialSigList
1372    --accept only those signatures op right length which match declared modes
1373  0=c => (#(sig:= getSignatureFromMode(form,e))=#form => sig; nil)
1374  1<c =>
1375    ambiguousSignatureError($op,potentialSigList)
1376    first potentialSigList
1377  nil --this branch will force all arguments to be declared
1378 
1379compareMode2Arg(x,m) == null x or modeEqual(x,m)
1380 
1381getArgumentModeOrMoan: (%Form, %Form, %Env) -> %Mode
1382getArgumentModeOrMoan(x,form,e) ==
1383  getArgumentMode(x,e) or
1384    stackSemanticError(["argument ",x," of ",form," is not declared"],nil)
1385
1386getArgumentMode: (%Form,%Env) -> %Mode
1387getArgumentMode(x,e) ==
1388  string? x => x
1389  m:= get(x,'mode,e) => m
1390 
1391checkAndDeclare(argl,form,sig,e) ==
1392-- arguments with declared types must agree with those in sig;
1393-- those that don't get declarations put into e
1394  for a in argl for m in sig.source repeat
1395    isQuasiquote m => nil         -- we just built m from a.
1396    m1:= getArgumentMode(a,e) =>
1397      not modeEqual(m1,m) =>
1398        stack:= ["   ",:bright a,'"must have type ",m,
1399          '" not ",m1,'"%l",:stack]
1400    e:= put(a,'mode,m,e)
1401  if stack then
1402    sayBrightly ['"   Parameters of ",:bright form.op,
1403      '" are of wrong type:",'"%l",:stack]
1404  e
1405 
1406getSignature(op,argModeList,$e) ==
1407  1=#
1408    (sigl:=
1409      removeDuplicates
1410        [sig
1411          for [[dc,:sig],[pred,:.]] in (mmList:= get(op,'modemap,$e)) | dc='_$
1412            and sig.source = argModeList and knownInfo pred]) => first sigl
1413  null sigl =>
1414    (u:= getmode(op,$e)) is ['Mapping,:sig] => sig
1415    SAY '"************* USER ERROR **********"
1416    SAY("available signatures for ",op,": ")
1417    if null mmList
1418       then SAY "    NONE"
1419       else for [[dc,:sig],:.] in mmList repeat printSignature("     ",op,sig)
1420    printSignature("NEED ",op,["?",:argModeList])
1421    nil
1422  1=#sigl => first sigl
1423  stackSemanticError(["duplicate signatures for ",op,": ",argModeList],nil)
1424 
1425--% ARGUMENT CONDITION CODE
1426 
1427stripOffArgumentConditions argl ==
1428  [f for x in argl for i in 1..] where
1429    f() ==
1430      x is ["|",arg,condition] =>
1431        condition:= substitute('_#1,arg,condition)
1432        -- in case conditions are given in terms of argument names, replace
1433        $argumentConditionList:= [[i,arg,condition],:$argumentConditionList]
1434        arg
1435      x
1436 
1437stripOffSubdomainConditions(margl,argl) ==
1438  [f for x in margl for arg in argl for i in 1..] where
1439    f() ==
1440      x is ['SubDomain,marg,condition] =>
1441        pair:= assoc(i,$argumentConditionList) =>
1442          (pair.rest.first := MKPF([condition,second pair],'AND); marg)
1443        $argumentConditionList:= [[i,arg,condition],:$argumentConditionList]
1444        marg
1445      x
1446 
1447compArgumentConditions: %Env -> %Env
1448compArgumentConditions e ==
1449  $argumentConditionList:=
1450    [f for [n,a,x] in $argumentConditionList] where
1451      f() ==
1452        y:= substitute(a,'_#1,x)
1453        T := [.,.,e]:= compOrCroak(y,$Boolean,e)
1454        [n,x,T.expr]
1455  e
1456
1457addArgumentConditions($body,$functionName) ==
1458  $argumentConditionList =>
1459               --$body is only used in this function
1460    fn $argumentConditionList where
1461      fn clist ==
1462        clist is [[n,untypedCondition,typedCondition],:.] =>
1463          ['%when,[typedCondition,fn rest clist],
1464            ['%otherwise,["argumentDataError",n,
1465              MKQ untypedCondition,MKQ $functionName]]]
1466        null clist => $body
1467        systemErrorHere ["addArgumentConditions",clist]
1468  $body
1469 
1470putInLocalDomainReferences (def := [opName,[lam,varl,body]]) ==
1471  NRTputInTail CDDADR def
1472  def
1473 
1474 
1475$savableItems := nil
1476 
1477compile u ==
1478  [op,lamExpr] := u
1479  if $suffix then
1480    $suffix:= $suffix+1
1481    op':=
1482      opexport:=nil
1483      opmodes:=
1484        [sel
1485          for [[DC,:sig],[.,sel]] in get(op,'modemap,$e) |
1486            DC='_$ and (opexport:=true) and
1487             (and/[modeEqual(x,y) for x in sig for y in $signatureOfForm])]
1488      isLocalFunction op =>
1489        if opexport then userError ['"%b",op,'"%d",'" is local and exported"]
1490        makeSymbol strconc(encodeItem $prefix,'";",encodeItem op)
1491      encodeFunctionName(op,$functorForm,$signatureOfForm,";",$suffix)
1492     where
1493       isLocalFunction op ==
1494         null symbolMember?(op,$formalArgList) and
1495           getmode(op,$e) is ['Mapping,:.]
1496    u:= [op',lamExpr]
1497  -- If just updating certain functions, check for previous existence.
1498  -- Deduce old sequence number and use it (items have been skipped).
1499  if $LISPLIB and $compileOnlyCertainItems then
1500    parts := splitEncodedFunctionName(u.op, ";")
1501  --  Next line JHD/SMWATT 7/17/86 to deal with inner functions
1502    parts='inner => $savableItems:=[u.op,:$savableItems]
1503    unew  := nil
1504    for [s,t] in $splitUpItemsAlreadyThere repeat
1505       if parts.0=s.0 and parts.1=s.1 and parts.2=s.2 then unew := t
1506    null unew =>
1507      sayBrightly ['"   Error: Item did not previously exist"]
1508      sayBrightly ['"   Item not saved: ", :bright u.op]
1509      sayBrightly ['"   What's there is: ", $lisplibItemsAlreadyThere]
1510      nil
1511    sayBrightly ['"   Renaming ", u.op, '" as ", unew]
1512    u := [unew, :rest u]
1513    $savableItems := [unew, :$saveableItems] -- tested by embedded RWRITE
1514  optimizedBody:= optimizeFunctionDef u
1515  stuffToCompile:=
1516    if not $insideCapsuleFunctionIfTrue
1517       then optimizedBody
1518       else putInLocalDomainReferences optimizedBody
1519  $doNotCompileJustPrint => (PRETTYPRINT stuffToCompile; op')
1520  $macroIfTrue => constructMacro stuffToCompile
1521
1522  -- Let the backend know about this function's type
1523  if $insideCapsuleFunctionIfTrue and $optProclaim then
1524    proclaimCapsuleFunction(op',$signatureOfForm)
1525
1526  result:= spadCompileOrSetq stuffToCompile
1527  functionStats:=[0,elapsedTime()]
1528  $functionStats:= addStats($functionStats,functionStats)
1529  printStats functionStats
1530  result
1531
1532++ Subroutine of compile.  Called to generate backend code for
1533++ items defined directly or indirectly at capsule level.   This is
1534++ also used to compile functors.
1535spadCompileOrSetq (form is [nam,[lam,vl,body]]) ==
1536        --bizarre hack to take account of the existence of "known" functions
1537        --good for performance (LISPLLIB size, BPI size, NILSEC)
1538  CONTAINED($ClearBodyToken,body) => sayBrightly ['"  ",:bright nam,'" not compiled"]
1539
1540  -- flag parameters needs to be made atomic, otherwise Lisp is confused.
1541  -- We try our best to preserve
1542  -- Note that we don't need substitution in the body because flag
1543  -- parameters are never used in the body.
1544  vl := [ renameParameter for v in vl] where
1545    renameParameter() ==
1546      integer? v or ident? v or string? v => v
1547      gensym '"flag"
1548  clearReplacement nam   -- Make sure we have fresh info
1549  if $optReplaceSimpleFunctions then
1550    body := replaceSimpleFunctions body
1551
1552  if nam' := forwardingCall?(vl,body) then
1553      registerFunctionReplacement(nam,nam')
1554      sayBrightly ['"     ",:bright nam,'"is replaced by",:bright nam']
1555  else if macform := expandableDefinition?(vl,body) then
1556           registerFunctionReplacement(nam,macform)
1557           sayBrightly ['"     ",:bright nam,'"is replaced by",:bright body]
1558
1559  form :=
1560    getFunctionReplacement nam =>
1561      [nam,[lam,vl,["DECLARE",["IGNORE",last vl]],body]]
1562    [nam,[lam,vl,body]]
1563
1564  $insideCapsuleFunctionIfTrue =>
1565    $optExportedFunctionReference =>
1566      $capsuleFunctionStack := [form,:$capsuleFunctionStack]
1567      first form
1568    first backendCompile [form]
1569  compileConstructor form
1570 
1571compileConstructor form ==
1572  u:= compileConstructor1 form
1573  clearClams()                  --clear all CLAMmed functions
1574  u
1575 
1576compileConstructor1 (form:=[fn,[key,vl,:bodyl]]) ==
1577-- fn is the name of some category/domain/package constructor;
1578-- we will cache all of its values on $ConstructorCache with reference
1579-- counts
1580  $clamList: local := nil
1581  lambdaOrSlam :=
1582    getConstructorKindFromDB fn = "category" => 'SPADSLAM
1583    $mutableDomain => 'LAMBDA
1584    $clamList:=
1585      [[fn,"$ConstructorCache",'domainEqualList,'count],:$clamList]
1586    'LAMBDA
1587  compForm:= [[fn,[lambdaOrSlam,vl,:bodyl]]]
1588  if getConstructorKindFromDB fn = "category"
1589      then u:= compAndDefine compForm
1590      else u:= backendCompile compForm
1591  clearConstructorCache fn      --clear cache for constructor
1592  first u
1593 
1594constructMacro: %Form -> %Form
1595constructMacro (form is [nam,[lam,vl,body]]) ==
1596  not (and/[x isnt [.,:.] for x in vl]) =>
1597    stackSemanticError(["illegal parameters for macro: ",vl],nil)
1598  ["XLAM",vl':= [x for x in vl | ident? x],body]
1599 
1600listInitialSegment(u,v) ==
1601  null u => true
1602  null v => nil
1603  first u=first v and listInitialSegment(rest u,rest v)
1604  --returns true iff u.i=v.i for i in 1..(#u)-1
1605 
1606modemap2Signature [[.,:sig],:.] == sig
1607
1608uncons: %Form -> %Form
1609uncons x ==
1610  x isnt [.,:.] => x
1611  x is ["CONS",a,b] => [a,:uncons b]
1612 
1613--% CAPSULE
1614 
1615bootStrapError(functorForm,sourceFile) ==
1616  ['%when, _
1617    ['$bootStrapMode, _
1618        ['%vector,mkTypeForm functorForm,nil,nil,nil,nil,nil]],
1619    ['%otherwise, ['systemError,['%list,'"%b",MKQ functorForm.op,'"%d",'"from", _
1620      '"%b",MKQ namestring sourceFile,'"%d",'"needs to be compiled"]]]]
1621
1622registerInlinableDomain(x,e) ==
1623  x := macroExpand(x,e)
1624  x is [ctor,:.] =>
1625    constructor? ctor => nominateForInlining ctor
1626    ctor is ":" => registerInlinableDomain(third x,e)
1627    builtinFunctorName? ctor =>
1628      for t in x.args repeat
1629        registerInlinableDomain(t,e)
1630    nil
1631  nil
1632
1633compAdd(['add,$addForm,capsule],m,e) ==
1634  $bootStrapMode =>
1635    if $addForm is ["%Comma",:.] then code := nil
1636       else [code,m,e]:= comp($addForm,m,e)
1637    [['%when, _
1638       ['$bootStrapMode, _
1639           code],_
1640       ['%otherwise, ['systemError,['%list,'"%b",MKQ $functorForm.op,'"%d",'"from", _
1641         '"%b",MKQ namestring _/EDITFILE,'"%d",'"needs to be compiled"]]]],m,e]
1642  $addFormLhs: local:= $addForm
1643  if $addForm is ["SubDomain",domainForm,predicate] then
1644    $NRTaddForm := domainForm
1645    NRTgetLocalIndex domainForm
1646    registerInlinableDomain(domainForm,e)
1647    --need to generate slot for add form since all $ go-get
1648    --  slots will need to access it
1649    [$addForm,.,e]:= compSubDomain1(domainForm,predicate,m,e)
1650  else
1651    $NRTaddForm := $addForm
1652    [$addForm,.,e]:=
1653      $addForm is ["%Comma",:.] =>
1654        $NRTaddForm := ["%Comma",:[NRTgetLocalIndex x for x in $addForm.args]]
1655        for x in $addForm.args repeat registerInlinableDomain(x,e)
1656        compOrCroak(compTuple2Record $addForm,$EmptyMode,e)
1657      registerInlinableDomain($addForm,e)
1658      compOrCroak($addForm,$EmptyMode,e)
1659  compCapsule(capsule,m,e)
1660 
1661compTuple2Record u ==
1662  ['Record,:[[":",i,x] for i in 1.. for x in u.args]]
1663
1664compCapsule(['CAPSULE,:itemList],m,e) ==
1665  $bootStrapMode =>
1666    [bootStrapError($functorForm, _/EDITFILE),m,e]
1667  $insideExpressionIfTrue: local:= false
1668  $useRepresentationHack := true
1669  clearCapsuleFunctionTable()
1670  e := checkRepresentation($addFormLhs,itemList,e)
1671  compCapsuleInner(itemList,m,addDomain('_$,e))
1672 
1673compSubDomain(["SubDomain",domainForm,predicate],m,e) ==
1674  $addFormLhs: local:= domainForm
1675  $addForm: local := nil
1676  $NRTaddForm := domainForm
1677  [$addForm,.,e]:= compSubDomain1(domainForm,predicate,m,e)
1678  compCapsule(['CAPSULE],m,e)
1679 
1680compSubDomain1(domainForm,predicate,m,e) ==
1681  [.,.,e]:=
1682    compMakeDeclaration("#1",domainForm,addDomain(domainForm,e))
1683  u:=
1684    compCompilerPredicate(predicate,e) or
1685      stackSemanticError(["predicate: ",predicate,
1686        " cannot be interpreted with #1: ",domainForm],nil)
1687  pred := simplifyVMForm u.expr
1688  -- For now, reject predicates that directly reference domains
1689  CONTAINED("$",pred) =>
1690    stackAndThrow('"predicate %1pb is not simple enough",[predicate])
1691  emitSubdomainInfo($form,domainForm,pred)
1692  $lisplibSuperDomain := [domainForm,predicate]
1693  [domainForm,m,e]
1694
1695compCapsuleInner(itemList,m,e) ==
1696  e:= addInformation(m,e)
1697           --puts a new 'special' property of $Information
1698  data:= ["PROGN",:itemList]
1699      --RPLACd by compCapsuleItems and Friends
1700  e:= compCapsuleItems(itemList,nil,e)
1701  localParList:= $functorLocalParameters
1702  if $addForm then data:= ['add,$addForm,data]
1703  code:=
1704    $insideCategoryIfTrue and not $insideCategoryPackageIfTrue => data
1705    processFunctor($form,$signature,data,localParList,e)
1706  [MKPF([:$getDomainCode,code],"PROGN"),m,e]
1707 
1708--% PROCESS FUNCTOR CODE
1709 
1710processFunctor(form,signature,data,localParList,e) ==
1711  form is ["CategoryDefaults"] =>
1712    error "CategoryDefaults is a reserved name"
1713  buildFunctor(form,signature,data,localParList,e)
1714 
1715compCapsuleItems(itemlist,$predl,$e) ==
1716  $signatureOfForm: local := nil
1717  $suffix: local:= 0
1718  for item in itemlist repeat
1719    $e:= compSingleCapsuleItem(item,$predl,$e)
1720  $e
1721 
1722compSingleCapsuleItem(item,$predl,$e) ==
1723  doIt(macroExpandInPlace(item,$e),$predl)
1724  $e
1725 
1726
1727++ subroutine of doIt.  Called to generate runtime noop insn.
1728mutateToNothing item ==
1729  item.op := 'PROGN
1730  item.rest := nil
1731
1732doIt(item,$predl) ==
1733  $GENNO: local:= 0
1734  item is ['SEQ,:l,['exit,1,x]] =>
1735    item.op := "PROGN"
1736    lastNode(item).first := x
1737    for it1 in rest item repeat $e:= compSingleCapsuleItem(it1,$predl,$e)
1738        --This will RPLAC as appropriate
1739  isDomainForm(item,$e) =>
1740    -- convert naked top level domains to import.
1741    -- Note: The apparent useless destructing of `item' below is necessary
1742    -- because it is subject to RPLACA/RPLACD, which would create
1743    -- a cycle otherwise.
1744    u:= ["import", [first item,:rest item]]
1745    stackWarning('"Use: import %1p",[[first item,:rest item]])
1746    item.op := u.op
1747    item.rest := rest u
1748    doIt(item,$predl)
1749  item is ["%LET",lhs,rhs,:.] =>
1750    compOrCroak(item,$EmptyMode,$e) isnt [code,.,$e] =>
1751      stackSemanticError(["cannot compile assigned value to",:bright lhs],nil)
1752    not (code is ["%LET",lhs',rhs',:.] and lhs' isnt [.,:.]) =>
1753      code is ["PROGN",:.] =>
1754         stackSemanticError(["multiple assignment ",item," not allowed"],nil)
1755      item.first := first code
1756      item.rest := rest code
1757    lhs:= lhs'
1758    if not symbolMember?(KAR rhs,$NonMentionableDomainNames) and
1759      not symbolMember?(lhs, $functorLocalParameters) then
1760         $functorLocalParameters:= [:$functorLocalParameters,lhs]
1761    if code is ["%LET",.,rhs',:.] and isDomainForm(rhs',$e) then
1762      if lhs="Rep" then
1763        --$Representation bound by compDefineFunctor, used in compNoStacking
1764        $Representation := getRepresentation $e
1765        if $optimizeRep then
1766          registerInlinableDomain($Representation,$e)
1767    code is ["%LET",:.] =>
1768      item.op := '%store
1769      rhsCode := rhs'
1770      item.args := [['%tref,'$,NRTgetLocalIndex lhs],rhsCode]
1771    item.op := code.op
1772    item.rest := rest code
1773  item is [":",a,t] => [.,.,$e]:= compOrCroak(item,$EmptyMode,$e)
1774  item is ["import",:doms] =>
1775     for dom in doms repeat
1776       sayBrightly ['"   importing ",:formatUnabbreviated dom]
1777     [.,.,$e] := compOrCroak(item,$EmptyMode,$e)
1778     mutateToNothing item
1779  item is ["%Inline",type] =>
1780    processInlineRequest(type,$e)
1781    mutateToNothing item
1782  item is ["%SignatureImport",:.] =>
1783    [.,.,$e] := compSignatureImport(item,$EmptyMode,$e)
1784    mutateToNothing item
1785  item is ["IF",p,x,y] => doItConditionally(item,$predl)
1786  item is ["where",b,:l] => compOrCroak(item,$EmptyMode,$e)
1787  item is ["MDEF",:.] => [.,.,$e]:= compOrCroak(item,$EmptyMode,$e)
1788  item is ['DEF,[op,:.],:.] =>
1789    body := isMacro(item,$e) => $e := putMacro(op,body,$e)
1790    [.,.,$e]:= t:= compOrCroak(item,$EmptyMode,$e)
1791    item.op := "CodeDefine"
1792        --Note that DescendCode, in CodeDefine, is looking for this
1793    second(item).rest := [$signatureOfForm]
1794      --This is how the signature is updated for buildFunctor to recognise
1795    functionPart:= ['dispatchFunction,t.expr]
1796    item.rest.rest.first := functionPart
1797    item.rest.rest.rest := nil
1798  u:= compOrCroak(item,$EmptyMode,$e) =>
1799    ([code,.,$e]:= u; item.first := first code; item.rest := rest code)
1800  systemErrorHere ["doIt", item]
1801 
1802isMacro(x,e) ==
1803  x is ['DEF,[op,:args],signature,specialCases,body] and
1804    null get(op,'modemap,e) and null args and null get(op,'mode,e)
1805      and signature is [nil] => body
1806
1807++ Compile capsule-level `item' which is a conditional expression.
1808++ OpenAxiom's take on prepositional logical is a constructive
1809++ interpretation of logical connectives, in terms of IF-expresions.
1810++ In particular, a negation is positively interpretated by swapping
1811++ branches, and- and or-expressions are decomposed into nested
1812++ IF-expressions.  -- gdr, 2009-06-15.
1813doItConditionally(item,predl) ==
1814  item isnt ["IF",p,x,y] => systemErrorHere ["doItConditionally",item]
1815  p is ["not",p'] =>
1816    -- swap branches and recurse for positive interpretation.
1817    item.rest.first := p'
1818    item.rest.rest.first := y
1819    item.rest.rest.rest.first := x
1820    doItConditionally(item,predl)
1821  p is ["and",p',p''] =>
1822    item.rest.first := p'
1823    item.rest.rest.first := ["IF",p'',x,COPY y]
1824    doItConditionally(item,predl)
1825  p is ["or",p',p''] =>
1826    item.rest.first := p'
1827    item.rest.rest.rest.first := ["IF",p'',COPY x,y]
1828    doItConditionally(item,predl)
1829  doItIf(item,predl,$e)
1830   
1831 
1832doItIf(item is [.,p,x,y],$predl,$e) ==
1833  olde:= $e
1834  [p',.,$e]:= compCompilerPredicate(p,$e) or userError ['"not a Boolean:",p]
1835  oldFLP:=$functorLocalParameters
1836  if x~="%noBranch" then
1837    compSingleCapsuleItem(x,[p,:$predl],getSuccessEnvironment(p,$e))
1838    x':=localExtras(oldFLP)
1839  oldFLP:=$functorLocalParameters
1840  if y~="%noBranch" then
1841    compSingleCapsuleItem(y,[["not",p],:$predl],getInverseEnvironment(p,olde))
1842    y':=localExtras(oldFLP)
1843  item.op := '%when
1844  item.args := [[p',x,:x'],['%otherwise,y,:y']]
1845 where localExtras(oldFLP) ==
1846   sameObject?(oldFLP,$functorLocalParameters) => nil
1847   flp1:=$functorLocalParameters
1848   oldFLP':=oldFLP
1849   n:=0
1850   while oldFLP' repeat
1851     oldFLP':=rest oldFLP'
1852     flp1:=rest flp1
1853     n:=n+1
1854   -- Now we have to add code to compile all the elements
1855   -- of functorLocalParameters that were added during the
1856   -- conditional compilation
1857   nils:=ans:=[]
1858   for u in flp1 repeat -- is =u form always an atom?
1859     if u isnt [.,:.] or (or/[v is [.,=u,:.] for v in $getDomainCode])
1860       then
1861         nils:=[u,:nils]
1862       else
1863         gv := gensym()
1864         ans:=[["%LET",gv,u],:ans]
1865         nils:=[gv,:nils]
1866     n:=n+1
1867   $functorLocalParameters:=[:oldFLP,:reverse! nils]
1868   reverse! ans
1869 
1870--% CATEGORY AND DOMAIN FUNCTIONS
1871
1872compContained: (%Form, %Mode, %Env) -> %Maybe %Triple
1873compContained(["CONTAINED",a,b],m,e) ==
1874  [a,ma,e]:= comp(a,$EmptyMode,e) or return nil
1875  [b,mb,e]:= comp(b,$EmptyMode,e) or return nil
1876  isCategoryForm(ma,e) and isCategoryForm(mb,e) =>
1877    (T:= [["CONTAINED",a,b],$Boolean,e]; convert(T,m))
1878  nil
1879
1880compJoin(["Join",:argl],m,e) ==
1881  catList:= [(compForMode(x,$Category,e) or return 'failed).expr for x in argl]
1882  catList='failed => stackSemanticError(["cannot form Join of: ",argl],nil)
1883  catList':=
1884    [extract for x in catList] where
1885      extract() ==
1886        isCategoryForm(x,e) =>
1887          parameters:=
1888            union("append"/[getParms(y,e) for y in rest x],parameters)
1889              where getParms(y,e) ==
1890                y isnt [.,:.] =>
1891                  isDomainForm(y,e) => [y]
1892                  nil
1893                y is [op,y'] and op in '(LENGTH %llength) => [y,y']
1894                [y]
1895          x
1896        x is ["DomainSubstitutionMacro",pl,body] =>
1897          (parameters:= union(pl,parameters); body)
1898        x is ["mkCategory",:.] => x
1899        x isnt [.,:.] and getmode(x,e) = $Category => x
1900        stackSemanticError(["invalid argument to Join: ",x],nil)
1901        x
1902  T:= [wrapDomainSub(parameters,["Join",:catList']),$Category,e]
1903  convert(T,m)
1904
1905compForMode: (%Form,%Mode,%Env) -> %Maybe %Triple
1906compForMode(x,m,e) ==
1907  $compForModeIfTrue: local:= true
1908  comp(x,m,e)
1909
1910makeCategoryForm(c,e) ==
1911  not isCategoryForm(c,e) => nil
1912  [x,m,e]:= compOrCroak(c,$EmptyMode,e)
1913  [x,e]
1914
1915mustInstantiate: %Form -> %Thing
1916mustInstantiate D ==
1917  D is [fn,:.] and
1918    not (symbolMember?(fn,$DummyFunctorNames) or GET(fn,"makeFunctionList"))
1919
1920wrapDomainSub: (%List %Form, %Form) -> %Form
1921wrapDomainSub(parameters,x) ==
1922   ["DomainSubstitutionMacro",parameters,x]
1923 
1924mkExplicitCategoryFunction(domainOrPackage,sigList,atList) ==
1925  body:=
1926    ["mkCategory",MKQ domainOrPackage,['%list,:reverse sigList],
1927      ['%list,:reverse atList],MKQ domList,nil] where
1928        domList() ==
1929          ("union"/[fn sig for ["QUOTE",[[.,sig,:.],:.]] in sigList]) where
1930            fn sig == [D for D in sig | mustInstantiate D]
1931  parameters:=
1932    removeDuplicates
1933      ("append"/
1934        [[x for x in sig | ident? x and x~='_$]
1935          for ["QUOTE",[[.,sig,:.],:.]] in sigList])
1936  wrapDomainSub(parameters,body)
1937
1938DomainSubstitutionFunction(parameters,body) ==
1939  --see definition of DomainSubstitutionMacro in SPAD LISP
1940  if parameters then
1941    (body := Subst(parameters,body)) where
1942      Subst(parameters,body) ==
1943        body isnt [.,:.] =>
1944          symbolMember?(body,parameters) => MKQ body
1945          body
1946        listMember?(body,parameters) =>
1947          g := gensym()
1948          $extraParms := PUSH([g,:body],$extraParms)
1949           --Used in SetVector12 to generate a substitution list
1950           --bound in buildFunctor
1951           --For categories, bound and used in compDefineCategory
1952          MKQ g
1953        body.op = "QUOTE" => body
1954        cons? $definition and
1955            isFunctor body.op and
1956              body.op ~= $definition.op
1957          =>  ['QUOTE,simplifyVMForm body]
1958        [Subst(parameters,u) for u in body]
1959  body isnt ["Join",:.] => body
1960  $definition isnt [.,:.] => body
1961  null $definition.args => body
1962           --should not bother if it will only be called once
1963  name := makeSymbol strconc(KAR $definition,";CAT")
1964  SETANDFILE(name,nil)
1965  body := ['%when,[name],['%otherwise,['%store,name,body]]]
1966  body
1967
1968
1969++ Subroutine of compCategoryItem.
1970++ Compile exported signature `opsig' under predicate `pred' in
1971++ environment `env'.
1972compSignature(opsig,pred,env) ==
1973  [op,:sig] := opsig
1974  cons? op =>
1975    for y in op repeat
1976      compSignature([y,:sig],pred,env)
1977  op in '(per rep) =>
1978    stackSemanticError(['"cannot export signature for", :bright op],nil)
1979    nil
1980  noteExport(opsig,pred)
1981  PUSH(MKQ [opsig,pred],$sigList)
1982 
1983compCategoryItem(x,predl,env) ==
1984  x is nil => nil
1985  --1. if x is a conditional expression, recurse; otherwise, form the predicate
1986  x is ['%when,[p,e]] =>
1987    predl':= [p,:predl]
1988    e is ["PROGN",:l] =>
1989      for y in l repeat compCategoryItem(y,predl',env)
1990    compCategoryItem(e,predl',env)
1991  x is ["IF",a,b,c] =>
1992    a is ["not",p] => compCategoryItem(["IF",p,c,b],predl,env)
1993    a is ["and",p,q] =>
1994      compCategoryItem(["IF",p,["IF",q,b,c],COPY c],predl,env)
1995    a is ["or",p,q] =>
1996      compCategoryItem(["IF",p,b,["IF",q,COPY b,c]],predl,env)
1997    predl':= [a,:predl]
1998    if b~="%noBranch" then
1999      b is ["PROGN",:l] =>
2000        for y in l repeat compCategoryItem(y,predl',env)
2001      compCategoryItem(b,predl',env)
2002    c="%noBranch" => nil
2003    predl':= [["not",a],:predl]
2004    c is ["PROGN",:l] =>
2005      for y in l repeat compCategoryItem(y,predl',env)
2006    compCategoryItem(c,predl',env)
2007  pred := (predl => MKPF(predl,"AND"); true)
2008 
2009  --2. if attribute, push it and return
2010  x is ["ATTRIBUTE",y] =>
2011    -- Attribute 'nil' carries no semantics.
2012    y = "nil" => nil
2013    noteExport(y,pred)
2014    PUSH(MKQ [y,pred],$atList)
2015 
2016  --3. it may be a list, with PROGN as the first, and some information as the rest
2017  x is ["PROGN",:l] =>
2018    for u in l repeat
2019      compCategoryItem(u,predl,env)
2020 
2021  -- 4. otherwise, x gives a signature for a
2022  --    single operator name or a list of names; if a list of names,
2023  --    recurse
2024  x is ["SIGNATURE",:opsig] => compSignature(opsig,pred,env)
2025  systemErrorHere ["compCategoryItem",x]
2026
2027compCategory: (%Form,%Mode,%Env) -> %Maybe %Triple
2028compCategory(x,m,e) ==
2029  clearExportsTable()
2030  (m:= resolve(m,$Category))=$Category and x is ['CATEGORY,
2031    domainOrPackage,:l] =>
2032      $sigList: local := nil
2033      $atList: local := nil
2034      for x in l repeat compCategoryItem(x,nil,e)
2035      rep:= mkExplicitCategoryFunction(domainOrPackage,$sigList,$atList)
2036    --if inside compDefineCategory, provide for category argument substitution
2037      [rep,m,e]
2038  systemErrorHere ["compCategory",x]
2039
2040--%
Note: See TracBrowser for help on using the browser.