aboutsummaryrefslogtreecommitdiff
path: root/src/interp/define.boot
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp/define.boot')
-rw-r--r--src/interp/define.boot1507
1 files changed, 1507 insertions, 0 deletions
diff --git a/src/interp/define.boot b/src/interp/define.boot
new file mode 100644
index 00000000..20238790
--- /dev/null
+++ b/src/interp/define.boot
@@ -0,0 +1,1507 @@
+-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+-- All rights reserved.
+-- Copyright (C) 2007, Gabriel Dos Reis.
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are
+-- met:
+--
+-- - Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+--
+-- - Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in
+-- the documentation and/or other materials provided with the
+-- distribution.
+--
+-- - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+-- names of its contributors may be used to endorse or promote products
+-- derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+import '"c-util"
+import '"cattable"
+import '"category"
+)package "BOOT"
+
+NRTPARSE := false
+
+--% FUNCTIONS WHICH MUNCH ON == STATEMENTS
+
+compDefine(form,m,e) ==
+ $tripleHits: local:= 0
+ $macroIfTrue: local
+ $packagesUsed: local
+ result:= compDefine1(form,m,e)
+ result
+
+compDefine1(form,m,e) ==
+ $insideExpressionIfTrue: local:= false
+ --1. decompose after macro-expanding form
+ ['DEF,lhs,signature,specialCases,rhs]:= form:= macroExpand(form,e)
+ $insideWhereIfTrue and isMacro(form,e) and (m=$EmptyMode or m=$NoValueMode)
+ => [lhs,m,put(first lhs,'macro,rhs,e)]
+ null signature.target and not MEMQ(KAR rhs,$ConstructorNames) and
+ (sig:= getSignatureFromMode(lhs,e)) =>
+ -- here signature of lhs is determined by a previous declaration
+ compDefine1(['DEF,lhs,[first sig,:rest signature],specialCases,rhs],m,e)
+ if signature.target=$Category then $insideCategoryIfTrue:= true
+--?? following 3 lines seem bogus, BMT 6/23/93
+--? if signature.target is ['Mapping,:map] then
+--? signature:= map
+--? form:= ['DEF,lhs,signature,specialCases,rhs]
+
+-- RDJ (11/83): when argument and return types are all declared,
+-- or arguments have types declared in the environment,
+-- and there is no existing modemap for this signature, add
+-- the modemap by a declaration, then strip off declarations and recurse
+ e := compDefineAddSignature(lhs,signature,e)
+-- 2. if signature list for arguments is not empty, replace ('DEF,..) by
+-- ('where,('DEF,..),..) with an empty signature list;
+-- otherwise, fill in all NILs in the signature
+ not (and/[null x for x in rest signature]) => compDefWhereClause(form,m,e)
+ signature.target=$Category =>
+ compDefineCategory(form,m,e,nil,$formalArgList)
+ isDomainForm(rhs,e) and not $insideFunctorIfTrue =>
+ if null signature.target then signature:=
+ [getTargetFromRhs(lhs,rhs,giveFormalParametersValues(rest lhs,e)),:
+ rest signature]
+ rhs:= addEmptyCapsuleIfNecessary(signature.target,rhs)
+ compDefineFunctor(['DEF,lhs,signature,specialCases,rhs],m,e,nil,
+ $formalArgList)
+ null $form => stackAndThrow ['"bad == form ",form]
+ newPrefix:=
+ $prefix => INTERN STRCONC(encodeItem $prefix,'",",encodeItem $op)
+ getAbbreviation($op,#rest $form)
+ compDefineCapsuleFunction(form,m,e,newPrefix,$formalArgList)
+
+compDefineAddSignature([op,:argl],signature,e) ==
+ (sig:= hasFullSignature(argl,signature,e)) and
+ not assoc(['$,:sig],LASSOC('modemap,getProplist(op,e))) =>
+ declForm:=
+ [":",[op,:[[":",x,m] for x in argl for m in rest sig]],first signature]
+ [.,.,e]:= comp(declForm,$EmptyMode,e)
+ e
+ e
+
+hasFullSignature(argl,[target,:ml],e) ==
+ target =>
+ u:= [m or get(x,"mode",e) or return 'failed for x in argl for m in ml]
+ u^='failed => [target,:u]
+
+addEmptyCapsuleIfNecessary(target,rhs) ==
+ MEMQ(KAR rhs,$SpecialDomainNames) => rhs
+ ['add,rhs,['CAPSULE]]
+
+getTargetFromRhs(lhs,rhs,e) ==
+ --undeclared target mode obtained from rhs expression
+ rhs is ['CAPSULE,:.] =>
+ stackSemanticError(['"target category of ",lhs,
+ '" cannot be determined from definition"],nil)
+ rhs is ['SubDomain,D,:.] => getTargetFromRhs(lhs,D,e)
+ rhs is ['add,D,['CAPSULE,:.]] => getTargetFromRhs(lhs,D,e)
+ rhs is ['Record,:l] => ['RecordCategory,:l]
+ rhs is ['Union,:l] => ['UnionCategory,:l]
+ rhs is ['List,:l] => ['ListCategory,:l]
+ rhs is ['Vector,:l] => ['VectorCategory,:l]
+ [.,target,.]:= compOrCroak(rhs,$EmptyMode,e)
+ target
+
+giveFormalParametersValues(argl,e) ==
+ for x in argl repeat
+ e:= put(x,'value,[genSomeVariable(),get(x,'mode,e),nil],e)
+ e
+
+macroExpandInPlace(x,e) ==
+ y:= macroExpand(x,e)
+ atom x or atom y => y
+ RPLACA(x,first y)
+ RPLACD(x,rest y)
+ x
+
+macroExpand(x,e) == --not worked out yet
+ atom x => (u:= get(x,'macro,e) => macroExpand(u,e); x)
+ x is ['DEF,lhs,sig,spCases,rhs] =>
+ ['DEF,macroExpand(lhs,e),macroExpandList(sig,e),macroExpandList(spCases,e),
+ macroExpand(rhs,e)]
+ macroExpandList(x,e)
+
+macroExpandList(l,e) ==
+ -- macros should override niladic props
+ (l is [name]) and IDENTP name and GETDATABASE(name, 'NILADIC) and
+ (u := get(name, 'macro, e)) => macroExpand(u,e)
+ [macroExpand(x,e) for x in l]
+
+compDefineCategory1(df is ['DEF,form,sig,sc,body],m,e,prefix,fal) ==
+ categoryCapsule :=
+--+
+ body is ['add,cat,capsule] =>
+ body := cat
+ capsule
+ nil
+ [d,m,e]:= compDefineCategory2(form,sig,sc,body,m,e,prefix,fal)
+--+ next two lines
+ if categoryCapsule and not $bootStrapMode then [.,.,e] :=
+ $insideCategoryPackageIfTrue: local := true --see NRTmakeSlot1
+-->
+ $categoryPredicateList: local :=
+ makeCategoryPredicates(form,$lisplibCategory)
+ compDefine1(mkCategoryPackage(form,cat,categoryCapsule),$EmptyMode,e)
+ [d,m,e]
+
+makeCategoryPredicates(form,u) ==
+ $tvl := TAKE(#rest form,$TriangleVariableList)
+ $mvl := TAKE(#rest form,rest $FormalMapVariableList)
+ fn(u,nil) where
+ fn(u,pl) ==
+ u is ['Join,:.,a] => fn(a,pl)
+ u is ['has,:.] => insert(EQSUBSTLIST($mvl,$tvl,u),pl)
+ u is [op,:.] and MEMQ(op,'(SIGNATURE ATTRIBUTE)) => pl
+ atom u => pl
+ fnl(u,pl)
+ fnl(u,pl) ==
+ for x in u repeat pl := fn(x,pl)
+ pl
+
+--+ the following function
+mkCategoryPackage(form is [op,:argl],cat,def) ==
+ packageName:= INTERN(STRCONC(PNAME op,'"&"))
+ packageAbb := INTERN(STRCONC(GETDATABASE(op,'ABBREVIATION),'"-"))
+ $options:local := []
+ -- This stops the next line from becoming confused
+ abbreviationsSpad2Cmd ['domain,packageAbb,packageName]
+ -- This is a little odd, but the parser insists on calling
+ -- domains, rather than packages
+ nameForDollar := first SETDIFFERENCE('(S A B C D E F G H I),argl)
+ packageArgl := [nameForDollar,:argl]
+ capsuleDefAlist := fn(def,nil) where fn(x,oplist) ==
+ atom x => oplist
+ x is ['DEF,y,:.] => [y,:oplist]
+ fn(rest x,fn(first x,oplist))
+ explicitCatPart := gn cat where gn cat ==
+ cat is ['CATEGORY,:.] => rest rest cat
+ cat is ['Join,:u] => gn last u
+ nil
+ catvec := eval mkEvalableCategoryForm form
+ fullCatOpList:=(JoinInner([catvec],$e)).1
+ catOpList :=
+ --note: this gets too many modemaps in general
+ -- this is cut down in NRTmakeSlot1
+ [['SIGNATURE,op1,sig] for [[op1,sig],:.] in fullCatOpList
+ --above line calls the category constructor just compiled
+ | assoc(op1,capsuleDefAlist)]
+ null catOpList => nil
+ packageCategory := ['CATEGORY,'domain,
+ :SUBLISLIS(argl,$FormalMapVariableList,catOpList)]
+ nils:= [nil for x in argl]
+ packageSig := [packageCategory,form,:nils]
+ $categoryPredicateList := SUBST(nameForDollar,'$,$categoryPredicateList)
+ SUBST(nameForDollar,'$,
+ ['DEF,[packageName,:packageArgl],packageSig,[nil,:nils],def])
+
+compDefineCategory2(form,signature,specialCases,body,m,e,
+ $prefix,$formalArgList) ==
+ --1. bind global variables
+ $insideCategoryIfTrue: local:= true
+ $TOP__LEVEL: local
+ $definition: local
+ --used by DomainSubstitutionFunction
+ $form: local
+ $op: local
+ $extraParms: local
+ --Set in DomainSubstitutionFunction, used further down
+-- 1.1 augment e to add declaration $: <form>
+ [$op,:argl]:= $definition:= form
+ e:= addBinding("$",[['mode,:$definition]],e)
+
+-- 2. obtain signature
+ signature':=
+ [first signature,:[getArgumentModeOrMoan(a,$definition,e) for a in argl]]
+ e:= giveFormalParametersValues(argl,e)
+
+-- 3. replace arguments by $1,..., substitute into body,
+-- and introduce declarations into environment
+ sargl:= TAKE(# argl, $TriangleVariableList)
+ $functorForm:= $form:= [$op,:sargl]
+ $formalArgList:= [:sargl,:$formalArgList]
+ aList:= [[a,:sa] for a in argl for sa in sargl]
+ formalBody:= SUBLIS(aList,body)
+ signature' := SUBLIS(aList,signature')
+--Begin lines for category default definitions
+ $functionStats: local:= [0,0]
+ $functorStats: local:= [0,0]
+ $frontier: local := 0
+ $getDomainCode: local := nil
+ $addForm: local:= nil
+ for x in sargl for t in rest signature' repeat
+ [.,.,e]:= compMakeDeclaration([":",x,t],m,e)
+
+-- 4. compile body in environment of %type declarations for arguments
+ op':= $op
+ -- following line causes cats with no with or Join to be fresh copies
+ if opOf(formalBody)^='Join and opOf(formalBody)^='mkCategory then
+ formalBody := ['Join, formalBody]
+ body:= optFunctorBody (compOrCroak(formalBody,signature'.target,e)).expr
+ if $extraParms then
+ formals:=actuals:=nil
+ for u in $extraParms repeat
+ formals:=[CAR u,:formals]
+ actuals:=[MKQ CDR u,:actuals]
+ body := ['sublisV,['PAIR,['QUOTE,formals],['LIST,:actuals]],body]
+ if argl then body:= -- always subst for args after extraparms
+ ['sublisV,['PAIR,['QUOTE,sargl],['LIST,:
+ [['devaluate,u] for u in sargl]]],body]
+ body:=
+ ['PROG1,['LET,g:= GENSYM(),body],['SETELT,g,0,mkConstructor $form]]
+ fun:= compile [op',['LAM,sargl,body]]
+
+-- 5. give operator a 'modemap property
+ pairlis:= [[a,:v] for a in argl for v in $FormalMapVariableList]
+ parSignature:= SUBLIS(pairlis,signature')
+ parForm:= SUBLIS(pairlis,form)
+ lisplibWrite('"compilerInfo",
+ removeZeroOne ['SETQ,'$CategoryFrame,
+ ['put,['QUOTE,op'],'
+ (QUOTE isCategory),true,['addModemap,MKQ op',MKQ parForm,
+ MKQ parSignature,true,MKQ fun,'$CategoryFrame]]],$libFile)
+ --Equivalent to the following two lines, we hope
+ if null sargl then
+ evalAndRwriteLispForm('NILADIC,
+ ['MAKEPROP,['QUOTE,op'],'(QUOTE NILADIC),true])
+
+-- 6. put modemaps into InteractiveModemapFrame
+ $domainShell := eval [op',:MAPCAR('MKQ,sargl)]
+ $lisplibCategory:= formalBody
+ if $LISPLIB then
+ $lisplibForm:= form
+ $lisplibKind:= 'category
+ modemap:= [[parForm,:parSignature],[true,op']]
+ $lisplibModemap:= modemap
+ $lisplibParents :=
+ getParentsFor($op,$FormalMapVariableList,$lisplibCategory)
+ $lisplibAncestors := computeAncestorsOf($form,nil)
+ $lisplibAbbreviation := constructor? $op
+ form':=[op',:sargl]
+ augLisplibModemapsFromCategory(form',formalBody,signature')
+ [fun,'(Category),e]
+
+mkConstructor form ==
+ atom form => ['devaluate,form]
+ null rest form => ['QUOTE,[first form]]
+ ['LIST,MKQ first form,:[mkConstructor x for x in rest form]]
+
+compDefineCategory(df,m,e,prefix,fal) ==
+ $domainShell: local -- holds the category of the object being compiled
+ $lisplibCategory: local
+ not $insideFunctorIfTrue and $LISPLIB =>
+ compDefineLisplib(df,m,e,prefix,fal,'compDefineCategory1)
+ compDefineCategory1(df,m,e,prefix,fal)
+
+compDefineFunctor(df,m,e,prefix,fal) ==
+ $domainShell: local -- holds the category of the object being compiled
+ $profileCompiler: local := true
+ $profileAlist: local := nil
+ $LISPLIB => compDefineLisplib(df,m,e,prefix,fal,'compDefineFunctor1)
+ compDefineFunctor1(df,m,e,prefix,fal)
+
+compDefineFunctor1(df is ['DEF,form,signature,$functorSpecialCases,body],
+ m,$e,$prefix,$formalArgList) ==
+ if NRTPARSE = true then
+ [lineNumber,:$functorSpecialCases] := $functorSpecialCases
+-- 1. bind global variables
+ $addForm: local
+ $viewNames: local:= nil
+
+ --This list is only used in genDomainViewName, for generating names
+ --for alternate views, if they do not already exist.
+ --format: Alist: (domain name . sublist)
+ --sublist is alist: category . name of view
+ $functionStats: local:= [0,0]
+ $functorStats: local:= [0,0]
+ $form: local
+ $op: local
+ $signature: local
+ $functorTarget: local
+ $Representation: local
+ --Set in doIt, accessed in the compiler - compNoStacking
+ $LocalDomainAlist: local --set in doIt, accessed in genDeltaEntry
+ $LocalDomainAlist:= nil
+ $functorForm: local
+ $functorLocalParameters: local
+ SETQ($myFunctorBody, body)
+ $CheckVectorList: local
+ --prevents CheckVector from printing out same message twice
+ $getDomainCode: local -- code for getting views
+ $insideFunctorIfTrue: local:= true
+ $functorsUsed: local --not currently used, finds dependent functors
+ $setelt: local :=
+ $QuickCode = true => 'QSETREFV
+ 'SETELT
+ $TOP__LEVEL: local
+ $genSDVar: local:= 0
+ originale:= $e
+ [$op,:argl]:= form
+ $formalArgList:= [:argl,:$formalArgList]
+ $pairlis := [[a,:v] for a in argl for v in $FormalMapVariableList]
+ $mutableDomain: local :=
+ -- all defaulting packages should have caching turned off
+ isCategoryPackageName $op or
+ (if BOUNDP '$mutableDomains then MEMQ($op,$mutableDomains)
+ else false ) --true if domain has mutable state
+ signature':=
+ [first signature,:[getArgumentModeOrMoan(a,form,$e) for a in argl]]
+ $functorForm:= $form:= [$op,:argl]
+ if null first signature' then signature':=
+ modemap2Signature getModemap($form,$e)
+ target:= first signature'
+ $functorTarget:= target
+ $e:= giveFormalParametersValues(argl,$e)
+ [ds,.,$e]:= compMakeCategoryObject(target,$e) or
+--+ copy needed since slot1 is reset; compMake.. can return a cached vector
+ sayBrightly '" cannot produce category object:"
+ pp target
+ return nil
+ $domainShell:= COPY_-SEQ ds
+ $attributesName:local := INTERN STRCONC(PNAME $op,'";attributes")
+ attributeList := disallowNilAttribute ds.2 --see below under "loadTimeAlist"
+--+ 7 lines for $NRT follow
+ $goGetList: local := nil
+-->--these globals used by NRTmakeCategoryAlist, set by NRTsetVector4Part1
+ $condAlist: local := nil
+ $uncondAlist: local := nil
+-->>-- next global initialized here, reset by NRTbuildFunctor
+ $NRTslot1PredicateList: local :=
+ REMDUP [CADR x for x in attributeList]
+-->>-- next global initialized here, used by NRTgenAttributeAlist (NRUNOPT)
+ $NRTattributeAlist: local := NRTgenInitialAttributeAlist attributeList
+ $NRTslot1Info: local --set in NRTmakeSlot1 called by NRTbuildFunctor
+ --this is used below to set $lisplibSlot1 global
+ $NRTbase: local := 6 -- equals length of $domainShell
+ $NRTaddForm: local := nil -- see compAdd; NRTmakeSlot1
+ $NRTdeltaList: local := nil --list of misc. elts used in compiled fncts
+ $NRTdeltaListComp: local := nil --list of COMP-ed forms for $NRTdeltaList
+ $NRTaddList: local := nil --list of fncts not defined in capsule (added)
+ $NRTdeltaLength: local := 0 -- =length of block of extra entries in vector
+ $NRTloadTimeAlist: local := nil --used for things in slot4 (NRTsetVector4)
+ $NRTdomainFormList: local := nil -- of form ((gensym . (Repe...)) ...
+ -- the above optimizes the calls to local domains
+ $template: local:= nil --stored in the lisplib (if $NRTvec = true)
+ $functionLocations: local := nil --locations of defined functions in source
+ -- generate slots for arguments first, then for $NRTaddForm in compAdd
+ for x in argl repeat NRTgetLocalIndex x
+ [.,.,$e]:= compMakeDeclaration([":",'_$,target],m,$e)
+ --The following loop sees if we can economise on ADDed operations
+ --by using those of Rep, if that is the same. Example: DIRPROD
+ if $insideCategoryPackageIfTrue^= true then
+ if body is ['add,ab:=[fn,:.],['CAPSULE,:cb]] and MEMQ(fn,'(List Vector))
+ and FindRep(cb) = ab
+ where FindRep cb ==
+ u:=
+ while cb repeat
+ ATOM cb => return nil
+ cb is [['LET,'Rep,v,:.],:.] => return (u:=v)
+ cb:=CDR cb
+ u
+ then $e:= augModemapsFromCategoryRep('_$,ab,cb,target,$e)
+ else $e:= augModemapsFromCategory('_$,'_$,'_$,target,$e)
+ $signature:= signature'
+ operationAlist:= SUBLIS($pairlis,$domainShell.(1))
+ parSignature:= SUBLIS($pairlis,signature')
+ parForm:= SUBLIS($pairlis,form)
+
+-- (3.1) now make a list of the functor's local parameters; for
+-- domain D in argl,check its signature: if domain, its type is Join(A1,..,An);
+-- in this case, D is replaced by D1,..,Dn (gensyms) which are set
+-- to the A1,..,An view of D
+ if isPackageFunction() then $functorLocalParameters:=
+ [nil,:
+ [nil
+ for i in 6..MAXINDEX $domainShell |
+ $domainShell.i is [.,.,['ELT,'_$,.]]]]
+ --leave space for vector ops and package name to be stored
+--+
+ $functorLocalParameters:=
+ argPars :=
+ makeFunctorArgumentParameters(argl,rest signature',first signature')
+ -- must do above to bring categories into scope --see line 5 of genDomainView
+ argl
+-- 4. compile body in environment of %type declarations for arguments
+ op':= $op
+ rettype:= signature'.target
+ T:= compFunctorBody(body,rettype,$e,parForm)
+ -- If only compiling certain items, then ignore the body shell.
+ $compileOnlyCertainItems =>
+ reportOnFunctorCompilation()
+ [nil, ['Mapping, :signature'], originale]
+
+ body':= T.expr
+ lamOrSlam:= if $mutableDomain then 'LAM else 'SPADSLAM
+ fun:= compile SUBLIS($pairlis, [op',[lamOrSlam,argl,body']])
+ --The above statement stops substitutions gettting in one another's way
+--+
+ operationAlist := SUBLIS($pairlis,$lisplibOperationAlist)
+ if $LISPLIB then
+ augmentLisplibModemapsFromFunctor(parForm,operationAlist,parSignature)
+ reportOnFunctorCompilation()
+
+-- 5. give operator a 'modemap property
+-- if $functorsUsed then MAKEPROP(op',"NEEDS",$functorsUsed)
+ if $LISPLIB then
+ modemap:= [[parForm,:parSignature],[true,op']]
+ $lisplibModemap:= modemap
+ $lisplibCategory := modemap.mmTarget
+ $lisplibParents :=
+ getParentsFor($op,$FormalMapVariableList,$lisplibCategory)
+ $lisplibAncestors := computeAncestorsOf($form,nil)
+ $lisplibAbbreviation := constructor? $op
+ $insideFunctorIfTrue:= false
+ if $LISPLIB then
+ $lisplibKind:=
+------->This next line prohibits changing the KIND once given
+--------kk:=GETDATABASE($op,'CONSTRUCTORKIND) => kk
+ $functorTarget is ["CATEGORY",key,:.] and key^="domain" => 'package
+ 'domain
+ $lisplibForm:= form
+ if null $bootStrapMode then
+ $NRTslot1Info := NRTmakeSlot1Info()
+ $isOpPackageName: local := isCategoryPackageName $op
+ if $isOpPackageName then lisplibWrite('"slot1DataBase",
+ ['updateSlot1DataBase,MKQ $NRTslot1Info],$libFile)
+ $lisplibFunctionLocations := SUBLIS($pairlis,$functionLocations)
+ $lisplibCategoriesExtended := SUBLIS($pairlis,$lisplibCategoriesExtended)
+ -- see NRTsetVector4 for initial setting of $lisplibCategoriesExtended
+ libFn := GETDATABASE(op','ABBREVIATION)
+ $lookupFunction: local :=
+ NRTgetLookupFunction($functorForm,CADAR $lisplibModemap,$NRTaddForm)
+ --either lookupComplete (for forgetful guys) or lookupIncomplete
+ $byteAddress :local := 0
+ $byteVec :local := nil
+ $NRTslot1PredicateList :=
+ [simpBool x for x in $NRTslot1PredicateList]
+ rwriteLispForm('loadTimeStuff,
+ ['MAKEPROP,MKQ $op,''infovec,getInfovecCode()])
+ $lisplibSlot1 := $NRTslot1Info --NIL or set by $NRTmakeSlot1
+ $lisplibOperationAlist:= operationAlist
+ $lisplibMissingFunctions:= $CheckVectorList
+ lisplibWrite('"compilerInfo",
+ removeZeroOne ['SETQ,'$CategoryFrame,
+ ['put,['QUOTE,op'],'
+ (QUOTE isFunctor),
+ ['QUOTE,operationAlist],['addModemap,['QUOTE,op'],['
+ QUOTE,parForm],['QUOTE,parSignature],true,['QUOTE,op'],
+ ['put,['QUOTE,op' ],'(QUOTE mode),
+ ['QUOTE,['Mapping,:parSignature]],'$CategoryFrame]]]], $libFile)
+ if null argl then
+ evalAndRwriteLispForm('NILADIC,
+ ['MAKEPROP, ['QUOTE,op'], ['QUOTE,'NILADIC], true])
+ [fun,['Mapping,:signature'],originale]
+
+disallowNilAttribute x ==
+ res := [y for y in x | car y and car y ^= "nil"]
+--HACK to get rid of nil attibutes ---NOTE: nil is RENAMED to NIL
+
+compFunctorBody(body,m,e,parForm) ==
+ $bootStrapMode = true =>
+ [bootStrapError($functorForm, _/EDITFILE),m,e]
+ T:= compOrCroak(body,m,e)
+ body is [op,:.] and MEMQ(op,'(add CAPSULE)) => T
+ $NRTaddForm :=
+ body is ["SubDomain",domainForm,predicate] => domainForm
+ body
+ T
+
+reportOnFunctorCompilation() ==
+ displayMissingFunctions()
+ if $semanticErrorStack then sayBrightly '" "
+ displaySemanticErrors()
+ if $warningStack then sayBrightly '" "
+ displayWarnings()
+ $functorStats:= addStats($functorStats,$functionStats)
+ [byteCount,elapsedSeconds] := $functorStats
+ sayBrightly ['%l,:bright '" Cumulative Statistics for Constructor",
+ $op]
+ timeString := normalizeStatAndStringify elapsedSeconds
+ sayBrightly ['" Time:",:bright timeString,'"seconds"]
+ sayBrightly '" "
+ 'done
+
+displayMissingFunctions() ==
+ null $CheckVectorList => nil
+ loc := nil
+ exp := nil
+ for [[op,sig,:.],:pred] in $CheckVectorList | null pred repeat
+ null member(op,$formalArgList) and
+ getmode(op,$env) is ['Mapping,:.] =>
+ loc := [[op,sig],:loc]
+ exp := [[op,sig],:exp]
+ if loc then
+ sayBrightly ['%l,:bright '" Missing Local Functions:"]
+ for [op,sig] in loc for i in 1.. repeat
+ sayBrightly ['" [",i,'"]",:bright op,
+ ": ",:formatUnabbreviatedSig sig]
+ if exp then
+ sayBrightly ['%l,:bright '" Missing Exported Functions:"]
+ for [op,sig] in exp for i in 1.. repeat
+ sayBrightly ['" [",i,'"]",:bright op,
+ ": ",:formatUnabbreviatedSig sig]
+
+--% domain view code
+
+makeFunctorArgumentParameters(argl,sigl,target) ==
+ $alternateViewList: local:= nil
+ $forceAdd: local:= true
+ $ConditionalOperators: local
+ ("append"/[fn(a,augmentSig(s,findExtras(a,target)))
+ for a in argl for s in sigl]) where
+ findExtras(a,target) ==
+ -- see if conditional information implies anything else
+ -- in the signature of a
+ target is ['Join,:l] => "union"/[findExtras(a,x) for x in l]
+ target is ['CATEGORY,.,:l] => "union"/[findExtras1(a,x) for x in l] where
+ findExtras1(a,x) ==
+ x is ['AND,:l] => "union"/[findExtras1(a,y) for y in l]
+ x is ['OR,:l] => "union"/[findExtras1(a,y) for y in l]
+ x is ['IF,c,p,q] =>
+ union(findExtrasP(a,c),
+ union(findExtras1(a,p),findExtras1(a,q))) where
+ findExtrasP(a,x) ==
+ x is ['AND,:l] => "union"/[findExtrasP(a,y) for y in l]
+ x is ['OR,:l] => "union"/[findExtrasP(a,y) for y in l]
+ x is ['has,=a,y] and y is ['SIGNATURE,:.] => [y]
+ nil
+ nil
+ augmentSig(s,ss) ==
+ -- if we find something extra, add it to the signature
+ null ss => s
+ for u in ss repeat
+ $ConditionalOperators:=[CDR u,:$ConditionalOperators]
+ s is ['Join,:sl] =>
+ u:=ASSQ('CATEGORY,ss) =>
+ SUBST([:u,:ss],u,s)
+ ['Join,:sl,['CATEGORY,'package,:ss]]
+ ['Join,s,['CATEGORY,'package,:ss]]
+ fn(a,s) ==
+ isCategoryForm(s,$CategoryFrame) =>
+ s is ["Join",:catlist] => genDomainViewList0(a,rest s)
+ [genDomainView(a,a,s,"getDomainView")]
+ [a]
+
+genDomainViewList0(id,catlist) ==
+ l:= genDomainViewList(id,catlist,true)
+ l
+
+genDomainViewList(id,catlist,firsttime) ==
+ null catlist => nil
+ catlist is [y] and not isCategoryForm(y,$EmptyEnvironment) => nil
+ [genDomainView(if firsttime then id else genDomainViewName(id,first catlist),
+ id,first catlist,"getDomainView"),:genDomainViewList(id,rest catlist,nil)]
+
+genDomainView(viewName,originalName,c,viewSelector) ==
+ c is ['CATEGORY,.,:l] => genDomainOps(viewName,originalName,c)
+ code:=
+ c is ['SubsetCategory,c',.] => c'
+ c
+ $e:= augModemapsFromCategory(originalName,viewName,nil,c,$e)
+ --$alternateViewList:= ((viewName,:code),:$alternateViewList)
+ cd:= ['LET,viewName,[viewSelector,originalName,mkDomainConstructor code]]
+ if null member(cd,$getDomainCode) then
+ $getDomainCode:= [cd,:$getDomainCode]
+ viewName
+
+genDomainOps(viewName,dom,cat) ==
+ oplist:= getOperationAlist(dom,dom,cat)
+ siglist:= [sig for [sig,:.] in oplist]
+ oplist:= substNames(dom,viewName,dom,oplist)
+ cd:=
+ ['LET,viewName,['mkOpVec,dom,['LIST,:
+ [['LIST,MKQ op,['LIST,:[mkDomainConstructor mode for mode in sig]]]
+ for [op,sig] in siglist]]]]
+ $getDomainCode:= [cd,:$getDomainCode]
+ for [opsig,cond,:.] in oplist for i in 0.. repeat
+ if opsig in $ConditionalOperators then cond:=nil
+ [op,sig]:=opsig
+ $e:= addModemap(op,dom,sig,cond,['ELT,viewName,i],$e)
+ viewName
+
+mkOpVec(dom,siglist) ==
+ dom:= getPrincipalView dom
+ substargs:= [['$,:dom.0],:
+ [[a,:x] for a in $FormalMapVariableList for x in rest dom.0]]
+ oplist:= getOperationAlistFromLisplib opOf dom.0
+ --new form is (<op> <signature> <slotNumber> <condition> <kind>)
+ ops:= MAKE_-VEC (#siglist)
+ for (opSig:= [op,sig]) in siglist for i in 0.. repeat
+ u:= ASSQ(op,oplist)
+ assoc(sig,u) is [.,n,.,'ELT] => ops.i := dom.n
+ noplist:= SUBLIS(substargs,u)
+ -- following variation on assoc needed for GENSYMS in Mutable domains
+ AssocBarGensym(SUBST(dom.0,'$,sig),noplist) is [.,n,.,'ELT] =>
+ ops.i := dom.n
+ ops.i := [function Undef,[dom.0,i],:opSig]
+ ops
+
+genDomainViewName(a,category) ==
+--+
+ a
+
+compDefWhereClause(['DEF,form,signature,specialCases,body],m,e) ==
+-- form is lhs (f a1 ... an) of definition; body is rhs;
+-- signature is (t0 t1 ... tn) where t0= target type, ti=type of ai, i > 0;
+-- specialCases is (NIL l1 ... ln) where li is list of special cases
+-- which can be given for each ti
+
+-- removes declarative and assignment information from form and
+-- signature, placing it in list L, replacing form by ("where",form',:L),
+-- signature by a list of NILs (signifying declarations are in e)
+ $sigAlist: local
+ $predAlist: local
+
+-- 1. create sigList= list of all signatures which have embedded
+-- declarations moved into global variable $sigAlist
+ sigList:=
+ [transformType fetchType(a,x,e,form) for a in rest form for x in rest signature]
+ where
+ fetchType(a,x,e,form) ==
+ x => x
+ getmode(a,e) or userError concat(
+ '"There is no mode for argument",a,'"of function",first form)
+ transformType x ==
+ atom x => x
+ x is [":",R,Rtype] =>
+ ($sigAlist:= [[R,:transformType Rtype],:$sigAlist]; x)
+ x is ['Record,:.] => x --RDJ 8/83
+ [first x,:[transformType y for y in rest x]]
+
+-- 2. replace each argument of the form (|| x p) by x, recording
+-- the given predicate in global variable $predAlist
+ argList:=
+ [removeSuchthat a for a in rest form] where
+ removeSuchthat x ==
+ x is ["|",y,p] => ($predAlist:= [[y,:p],:$predAlist]; y)
+ x
+
+-- 3. obtain a list of parameter identifiers (x1 .. xn) ordered so that
+-- the type of xi is independent of xj if i < j
+ varList:=
+ orderByDependency(ASSOCLEFT argDepAlist,ASSOCRIGHT argDepAlist) where
+ argDepAlist:=
+ [[x,:dependencies] for [x,:y] in argSigAlist] where
+ dependencies() ==
+ union(listOfIdentifiersIn y,
+ delete(x,listOfIdentifiersIn LASSOC(x,$predAlist)))
+ argSigAlist:= [:$sigAlist,:pairList(argList,sigList)]
+
+-- 4. construct a WhereList which declares and/or defines the xi's in
+-- the order constructed in step 3
+ (whereList:= [addSuchthat(x,[":",x,LASSOC(x,argSigAlist)]) for x in varList])
+ where addSuchthat(x,y) == (p:= LASSOC(x,$predAlist) => ["|",y,p]; y)
+
+-- 5. compile new ('DEF,("where",form',:WhereList),:.) where
+-- all argument parameters of form' are bound/declared in WhereList
+ comp(form',m,e) where
+ form':=
+ ["where",defform,:whereList] where
+ defform:=
+ ['DEF,form'',signature',specialCases,body] where
+ form'':= [first form,:argList]
+ signature':= [first signature,:[nil for x in rest signature]]
+
+orderByDependency(vl,dl) ==
+ -- vl is list of variables, dl is list of dependency-lists
+ selfDependents:= [v for v in vl for d in dl | MEMQ(v,d)]
+ for v in vl for d in dl | MEMQ(v,d) repeat
+ (SAY(v," depends on itself"); fatalError:= true)
+ fatalError => userError '"Parameter specification error"
+ until (null vl) repeat
+ newl:=
+ [v for v in vl for d in dl | null intersection(d,vl)] or return nil
+ orderedVarList:= [:newl,:orderedVarList]
+ vl':= setDifference(vl,newl)
+ dl':= [setDifference(d,newl) for x in vl for d in dl | member(x,vl')]
+ vl:= vl'
+ dl:= dl'
+ REMDUP NREVERSE orderedVarList --ordered so ith is indep. of jth if i < j
+
+compDefineCapsuleFunction(df is ['DEF,form,signature,specialCases,body],
+ m,oldE,$prefix,$formalArgList) ==
+ [lineNumber,:specialCases] := specialCases
+ e := oldE
+ --1. bind global variables
+ $form: local
+ $op: local
+ $functionStats: local:= [0,0]
+ $argumentConditionList: local
+ $finalEnv: local
+ --used by ReplaceExitEtc to get a common environment
+ $initCapsuleErrorCount: local:= #$semanticErrorStack
+ $insideCapsuleFunctionIfTrue: local:= true
+ $CapsuleModemapFrame: local:= e
+ $CapsuleDomainsInScope: local:= get("$DomainsInScope","special",e)
+ $insideExpressionIfTrue: local:= true
+ $returnMode:= m
+ [$op,:argl]:= form
+ $form:= [$op,:argl]
+ argl:= stripOffArgumentConditions argl
+ $formalArgList:= [:argl,:$formalArgList]
+
+ --let target and local signatures help determine modes of arguments
+ argModeList:=
+ identSig:= hasSigInTargetCategory(argl,form,first signature,e) =>
+ (e:= checkAndDeclare(argl,form,identSig,e); rest identSig)
+ [getArgumentModeOrMoan(a,form,e) for a in argl]
+ argModeList:= stripOffSubdomainConditions(argModeList,argl)
+ signature':= [first signature,:argModeList]
+ if null identSig then --make $op a local function
+ oldE := put($op,'mode,['Mapping,:signature'],oldE)
+
+ --obtain target type if not given
+ if null first signature' then signature':=
+ identSig => identSig
+ getSignature($op,rest signature',e) or return nil
+ e:= giveFormalParametersValues(argl,e)
+
+ $signatureOfForm:= signature' --this global is bound in compCapsuleItems
+ $functionLocations := [[[$op,$signatureOfForm],:lineNumber],
+ :$functionLocations]
+ e:= addDomain(first signature',e)
+ e:= compArgumentConditions e
+
+ if $profileCompiler then
+ for x in argl for t in rest signature' repeat profileRecord('arguments,x,t)
+
+
+ --4. introduce needed domains into extendedEnv
+ for domain in signature' repeat e:= addDomain(domain,e)
+
+ --6. compile body in environment with extended environment
+ rettype:= resolve(signature'.target,$returnMode)
+
+ localOrExported :=
+ null member($op,$formalArgList) and
+ getmode($op,e) is ['Mapping,:.] => 'local
+ 'exported
+
+ --6a skip if compiling only certain items but not this one
+ -- could be moved closer to the top
+ formattedSig := formatUnabbreviated ['Mapping,:signature']
+ $compileOnlyCertainItems and _
+ not member($op, $compileOnlyCertainItems) =>
+ sayBrightly ['" skipping ", localOrExported,:bright $op]
+ [nil,['Mapping,:signature'],oldE]
+ sayBrightly ['" compiling ",localOrExported,
+ :bright $op,'": ",:formattedSig]
+
+ if $newComp = true then
+ wholeBody := ['DEF, form, signature', specialCases, body]
+ T := CATCH('compCapsuleBody, newComp(wholeBody,$NoValueMode,e))
+ or [" ",rettype,e]
+ T := [T.expr.2.2, rettype, T.env]
+ if $newCompCompare=true then
+ oldT := CATCH('compCapsuleBody, compOrCroak(body,rettype,e))
+ or [" ",rettype,e]
+ SAY '"The old compiler generates:"
+ prTriple oldT
+ SAY '"The new compiler generates:"
+ prTriple T
+ else
+ T := CATCH('compCapsuleBody, compOrCroak(body,rettype,e))
+ or [" ",rettype,e]
+--+
+ NRTassignCapsuleFunctionSlot($op,signature')
+ if $newCompCompare=true then
+ SAY '"The old compiler generates:"
+ prTriple T
+-- A THROW to the above CATCH occurs if too many semantic errors occur
+-- see stackSemanticError
+ catchTag:= MKQ GENSYM()
+ fun:=
+ body':= replaceExitEtc(T.expr,catchTag,"TAGGEDreturn",$returnMode)
+ body':= addArgumentConditions(body',$op)
+ finalBody:= ["CATCH",catchTag,body']
+ compileCases([$op,["LAM",[:argl,'_$],finalBody]],oldE)
+ $functorStats:= addStats($functorStats,$functionStats)
+
+
+-- 7. give operator a 'value property
+ val:= [fun,signature',e]
+ [fun,['Mapping,:signature'],oldE] -- oldE:= put($op,'value,removeEnv val,e)
+
+getSignatureFromMode(form,e) ==
+ getmode(opOf form,e) is ['Mapping,:signature] =>
+ #form^=#signature => stackAndThrow ["Wrong number of arguments: ",form]
+ EQSUBSTLIST(rest form,take(#rest form,$FormalMapVariableList),signature)
+
+hasSigInTargetCategory(argl,form,opsig,e) ==
+ mList:= [getArgumentMode(x,e) for x in argl]
+ --each element is a declared mode for the variable or nil if none exists
+ potentialSigList:=
+ REMDUP
+ [sig
+ for [[opName,sig,:.],:.] in $domainShell.(1) |
+ fn(opName,sig,opsig,mList,form)] where
+ fn(opName,sig,opsig,mList,form) ==
+ opName=$op and #sig=#form and (null opsig or opsig=first sig) and
+ (and/[compareMode2Arg(x,m) for x in mList for m in rest sig])
+ c:= #potentialSigList
+ 1=c => first potentialSigList
+ --accept only those signatures op right length which match declared modes
+ 0=c => (#(sig:= getSignatureFromMode(form,e))=#form => sig; nil)
+ 1<c =>
+ sig:= first potentialSigList
+ stackWarning ["signature of lhs not unique:",
+ :bright formatSignature sig, "chosen"]
+ sig
+ nil --this branch will force all arguments to be declared
+
+compareMode2Arg(x,m) == null x or modeEqual(x,m)
+
+getArgumentModeOrMoan(x,form,e) ==
+ getArgumentMode(x,e) or
+ stackSemanticError(["argument ",x," of ",form," is not declared"],nil)
+
+getArgumentMode(x,e) ==
+ STRINGP x => x
+ m:= get(x,'mode,e) => m
+
+checkAndDeclare(argl,form,sig,e) ==
+
+-- arguments with declared types must agree with those in sig;
+-- those that don't get declarations put into e
+ for a in argl for m in rest sig repeat
+ m1:= getArgumentMode(a,e) =>
+ ^modeEqual(m1,m) =>
+ stack:= [" ",:bright a,'"must have type ",m,
+ '" not ",m1,'%l,:stack]
+ e:= put(a,'mode,m,e)
+ if stack then
+ sayBrightly ['" Parameters of ",:bright first form,
+ '" are of wrong type:",'%l,:stack]
+ e
+
+getSignature(op,argModeList,$e) ==
+ 1=#
+ (sigl:=
+ REMDUP
+ [sig
+ for [[dc,:sig],[pred,:.]] in (mmList:= get(op,'modemap,$e)) | dc='_$
+ and rest sig=argModeList and knownInfo pred]) => first sigl
+ null sigl =>
+ (u:= getmode(op,$e)) is ['Mapping,:sig] => sig
+ SAY '"************* USER ERROR **********"
+ SAY("available signatures for ",op,": ")
+ if null mmList
+ then SAY " NONE"
+ else for [[dc,:sig],:.] in mmList repeat printSignature(" ",op,sig)
+ printSignature("NEED ",op,["?",:argModeList])
+ nil
+ for u in sigl repeat
+ for v in sigl | not (u=v) repeat
+ if SourceLevelSubsume(u,v) then sigl:= delete(v,sigl)
+ --before we complain about duplicate signatures, we should
+ --check that we do not have for example, a partial - as
+ --well as a total one. SourceLevelSubsume (from CATEGORY BOOT)
+ --should do this
+ 1=#sigl => first sigl
+ stackSemanticError(["duplicate signatures for ",op,": ",argModeList],nil)
+
+--% ARGUMENT CONDITION CODE
+
+stripOffArgumentConditions argl ==
+ [f for x in argl for i in 1..] where
+ f() ==
+ x is ["|",arg,condition] =>
+ condition:= SUBST('_#1,arg,condition)
+ -- in case conditions are given in terms of argument names, replace
+ $argumentConditionList:= [[i,arg,condition],:$argumentConditionList]
+ arg
+ x
+
+stripOffSubdomainConditions(margl,argl) ==
+ [f for x in margl for arg in argl for i in 1..] where
+ f() ==
+ x is ['SubDomain,marg,condition] =>
+ pair:= assoc(i,$argumentConditionList) =>
+ (RPLAC(CADR pair,MKPF([condition,CADR pair],'AND)); marg)
+ $argumentConditionList:= [[i,arg,condition],:$argumentConditionList]
+ marg
+ x
+
+compArgumentConditions e ==
+ $argumentConditionList:=
+ [f for [n,a,x] in $argumentConditionList] where
+ f() ==
+ y:= SUBST(a,'_#1,x)
+ T := [.,.,e]:= compOrCroak(y,$Boolean,e)
+ [n,x,T.expr]
+ e
+
+addArgumentConditions($body,$functionName) ==
+ $argumentConditionList =>
+ --$body is only used in this function
+ fn $argumentConditionList where
+ fn clist ==
+ clist is [[n,untypedCondition,typedCondition],:.] =>
+ ['COND,[typedCondition,fn rest clist],
+ [$true,["argumentDataError",n,
+ MKQ untypedCondition,MKQ $functionName]]]
+ null clist => $body
+ systemErrorHere '"addArgumentConditions"
+ $body
+
+putInLocalDomainReferences (def := [opName,[lam,varl,body]]) ==
+ $elt: local := ($QuickCode => 'QREFELT; 'ELT)
+--+
+ NRTputInTail CDDADR def
+ def
+
+
+canCacheLocalDomain(dom,elt)==
+ dom is [op,'_$,n] and MEMQ(op,'(ELT QREFELT)) => nil
+ domargsglobal(dom) =>
+ $functorLocalParameters:= [:$functorLocalParameters,dom]
+ PUSH([dom,GENVAR(),[elt,$selector,$funcLocLen]],$usedDomList)
+ $selcount:= $selcount+1
+ $funcLocLen:= $funcLocLen+1
+ nil
+ where
+ domargsglobal(dom) ==
+ dom='_$ => true
+ IDENTP dom => MEMQ(dom,$functorLocalParameters)
+ ATOM dom => true
+ and/[domargsglobal(arg) for arg in rest dom]
+
+
+compileCases(x,$e) == -- $e is referenced in compile
+ $specialCaseKeyList: local
+ not ($insideFunctorIfTrue=true) => compile x
+ specialCaseAssoc:=
+ [y for y in getSpecialCaseAssoc() | not get(first y,"specialCase",$e) and
+ ([R,R']:= y) and isEltArgumentIn(FindNamesFor(R,R'),x)] where
+ FindNamesFor(R,R') ==
+ [R,:
+ [v
+ for ['LET,v,u,:.] in $getDomainCode | CADR u=R and
+ eval substitute(R',R,u)]]
+ isEltArgumentIn(Rlist,x) ==
+ atom x => nil
+ x is ['ELT,R,.] => MEMQ(R,Rlist) or isEltArgumentIn(Rlist,rest x)
+ x is ["QREFELT",R,.] => MEMQ(R,Rlist) or isEltArgumentIn(Rlist,rest x)
+ isEltArgumentIn(Rlist,first x) or isEltArgumentIn(Rlist,rest x)
+ null specialCaseAssoc => compile x
+ listOfDomains:= ASSOCLEFT specialCaseAssoc
+ listOfAllCases:= outerProduct ASSOCRIGHT specialCaseAssoc
+ cl:=
+ [u for l in listOfAllCases] where
+ u() ==
+ $specialCaseKeyList:= [[D,:C] for D in listOfDomains for C in l]
+ [MKPF([["EQUAL",D,C] for D in listOfDomains for C in l],"AND"),
+ compile COPY x]
+ $specialCaseKeyList:= nil
+ ["COND",:cl,[$true,compile x]]
+
+getSpecialCaseAssoc() ==
+ [[R,:l] for R in rest $functorForm
+ for l in rest $functorSpecialCases | l]
+
+compile u ==
+ [op,lamExpr] := u
+ if $suffix then
+ $suffix:= $suffix+1
+ op':=
+ opexport:=nil
+ opmodes:=
+ [sel
+ for [[DC,:sig],[.,sel]] in get(op,'modemap,$e) |
+ DC='_$ and (opexport:=true) and
+ (and/[modeEqual(x,y) for x in sig for y in $signatureOfForm])]
+ isLocalFunction op =>
+ if opexport then userError ['%b,op,'%d,'" is local and exported"]
+ INTERN STRCONC(encodeItem $prefix,'";",encodeItem op)
+ isPackageFunction() and KAR $functorForm^="CategoryDefaults" =>
+ if null opmodes then userError ['"no modemap for ",op]
+ opmodes is [['PAC,.,name]] => name
+ encodeFunctionName(op,$functorForm,$signatureOfForm,";",$suffix)
+ encodeFunctionName(op,$functorForm,$signatureOfForm,";",$suffix)
+ where
+ isLocalFunction op ==
+ null member(op,$formalArgList) and
+ getmode(op,$e) is ['Mapping,:.]
+ u:= [op',lamExpr]
+ -- If just updating certain functions, check for previous existence.
+ -- Deduce old sequence number and use it (items have been skipped).
+ if $LISPLIB and $compileOnlyCertainItems then
+ parts := splitEncodedFunctionName(u.0, ";")
+-- Next line JHD/SMWATT 7/17/86 to deal with inner functions
+ parts='inner => $savableItems:=[u.0,:$savableItems]
+ unew := nil
+ for [s,t] in $splitUpItemsAlreadyThere repeat
+ if parts.0=s.0 and parts.1=s.1 and parts.2=s.2 then unew := t
+ null unew =>
+ sayBrightly ['" Error: Item did not previously exist"]
+ sayBrightly ['" Item not saved: ", :bright u.0]
+ sayBrightly ['" What's there is: ", $lisplibItemsAlreadyThere]
+ nil
+ sayBrightly ['" Renaming ", u.0, '" as ", unew]
+ u := [unew, :rest u]
+ $savableItems := [unew, :$saveableItems] -- tested by embedded RWRITE
+ optimizedBody:= optimizeFunctionDef u
+ stuffToCompile:=
+ if null $insideCapsuleFunctionIfTrue
+ then optimizedBody
+ else putInLocalDomainReferences optimizedBody
+ $doNotCompileJustPrint=true => (PRETTYPRINT stuffToCompile; op')
+ $macroIfTrue => constructMacro stuffToCompile
+ result:= spadCompileOrSetq stuffToCompile
+ functionStats:=[0,elapsedTime()]
+ $functionStats:= addStats($functionStats,functionStats)
+ printStats functionStats
+ result
+
+spadCompileOrSetq (form is [nam,[lam,vl,body]]) ==
+ --bizarre hack to take account of the existence of "known" functions
+ --good for performance (LISPLLIB size, BPI size, NILSEC)
+ CONTAINED(" ",body) => sayBrightly ['" ",:bright nam,'" not compiled"]
+ if vl is [:vl',E] and body is [nam',: =vl'] then
+ LAM_,EVALANDFILEACTQ ['PUT,MKQ nam,MKQ 'SPADreplace,MKQ nam']
+ sayBrightly ['" ",:bright nam,'"is replaced by",:bright nam']
+ else if (ATOM body or and/[ATOM x for x in body])
+ and vl is [:vl',E] and not CONTAINED(E,body) then
+ macform := ['XLAM,vl',body]
+ LAM_,EVALANDFILEACTQ ['PUT,MKQ nam,MKQ 'SPADreplace,MKQ macform]
+ sayBrightly ['" ",:bright nam,'"is replaced by",:bright body]
+ $insideCapsuleFunctionIfTrue => first COMP LIST form
+ compileConstructor form
+
+compileConstructor form ==
+ u:= compileConstructor1 form
+ clearClams() --clear all CLAMmed functions
+ u
+
+compileConstructor1 (form:=[fn,[key,vl,:bodyl]]) ==
+-- fn is the name of some category/domain/package constructor;
+-- we will cache all of its values on $ConstructorCache with reference
+-- counts
+ $clamList: local
+ lambdaOrSlam :=
+ GETDATABASE(fn,'CONSTRUCTORKIND) = 'category => 'SPADSLAM
+ $mutableDomain => 'LAMBDA
+ $clamList:=
+ [[fn,"$ConstructorCache",'domainEqualList,'count],:$clamList]
+ 'LAMBDA
+ compForm:= LIST [fn,[lambdaOrSlam,vl,:bodyl]]
+ if GETDATABASE(fn,'CONSTRUCTORKIND) = 'category
+ then u:= compAndDefine compForm
+ else u:=COMP compForm
+ clearConstructorCache fn --clear cache for constructor
+ first u
+
+constructMacro (form is [nam,[lam,vl,body]]) ==
+ ^(and/[atom x for x in vl]) =>
+ stackSemanticError(["illegal parameters for macro: ",vl],nil)
+ ["XLAM",vl':= [x for x in vl | IDENTP x],body]
+
+listInitialSegment(u,v) ==
+ null u => true
+ null v => nil
+ first u=first v and listInitialSegment(rest u,rest v)
+ --returns true iff u.i=v.i for i in 1..(#u)-1
+
+modemap2Signature [[.,:sig],:.] == sig
+
+uncons x ==
+ atom x => x
+ x is ["CONS",a,b] => [a,:uncons b]
+
+--% CAPSULE
+
+bootStrapError(functorForm,sourceFile) ==
+ ['COND, _
+ ['$bootStrapMode, _
+ ['VECTOR,mkDomainConstructor functorForm,nil,nil,nil,nil,nil]],
+ [''T, ['systemError,['LIST,''%b,MKQ CAR functorForm,''%d,'"from", _
+ ''%b,MKQ namestring sourceFile,''%d,'"needs to be compiled"]]]]
+
+compAdd(['add,$addForm,capsule],m,e) ==
+ $bootStrapMode = true =>
+ if $addForm is ['Tuple,:.] then code := nil
+ else [code,m,e]:= comp($addForm,m,e)
+ [['COND, _
+ ['$bootStrapMode, _
+ code],_
+ [''T, ['systemError,['LIST,''%b,MKQ CAR $functorForm,''%d,'"from", _
+ ''%b,MKQ namestring _/EDITFILE,''%d,'"needs to be compiled"]]]],m,e]
+ $addFormLhs: local:= $addForm
+ if $addForm is ["SubDomain",domainForm,predicate] then
+ $packagesUsed := [domainForm,:$packagesUsed]
+--+
+ $NRTaddForm := domainForm
+ NRTgetLocalIndex domainForm
+ --need to generate slot for add form since all $ go-get
+ -- slots will need to access it
+ [$addForm,.,e]:= compSubDomain1(domainForm,predicate,m,e)
+ else
+ $packagesUsed :=
+ $addForm is ['Tuple,:u] => [:u,:$packagesUsed]
+ [$addForm,:$packagesUsed]
+--+
+ $NRTaddForm := $addForm
+ [$addForm,.,e]:=
+ $addForm is ['Tuple,:.] =>
+ $NRTaddForm := ['Tuple,:[NRTgetLocalIndex x for x in rest $addForm]]
+ compOrCroak(compTuple2Record $addForm,$EmptyMode,e)
+ compOrCroak($addForm,$EmptyMode,e)
+ compCapsule(capsule,m,e)
+
+compTuple2Record u == ['Record,:[[":",i,x] for i in 1.. for x in rest u]]
+
+compCapsule(['CAPSULE,:itemList],m,e) ==
+ $bootStrapMode = true =>
+ [bootStrapError($functorForm, _/EDITFILE),m,e]
+ $insideExpressionIfTrue: local:= false
+ compCapsuleInner(itemList,m,addDomain('_$,e))
+
+compSubDomain(["SubDomain",domainForm,predicate],m,e) ==
+ $addFormLhs: local:= domainForm
+ $addForm: local
+ $NRTaddForm := domainForm
+ [$addForm,.,e]:= compSubDomain1(domainForm,predicate,m,e)
+--+
+ compCapsule(['CAPSULE],m,e)
+
+compSubDomain1(domainForm,predicate,m,e) ==
+ [.,.,e]:=
+ compMakeDeclaration([":","#1",domainForm],$EmptyMode,addDomain(domainForm,e))
+ u:=
+ compOrCroak(predicate,$Boolean,e) or
+ stackSemanticError(["predicate: ",predicate,
+ " cannot be interpreted with #1: ",domainForm],nil)
+ prefixPredicate:= lispize u.expr
+ $lisplibSuperDomain:=
+ [domainForm,predicate]
+ evalAndRwriteLispForm('evalOnLoad2,
+ ['SETQ,'$CategoryFrame,['put,op':= ['QUOTE,$op],'
+ (QUOTE SuperDomain),dF':= ['QUOTE,domainForm],['put,dF','(QUOTE SubDomain),[
+ 'CONS,['QUOTE,[$op,:prefixPredicate]],['DELASC,op',['get,dF','
+ (QUOTE SubDomain),'$CategoryFrame]]],'$CategoryFrame]]])
+ [domainForm,m,e]
+
+compCapsuleInner(itemList,m,e) ==
+ e:= addInformation(m,e)
+ --puts a new 'special' property of $Information
+ data:= ["PROGN",:itemList]
+ --RPLACd by compCapsuleItems and Friends
+ e:= compCapsuleItems(itemList,nil,e)
+ localParList:= $functorLocalParameters
+ if $addForm then data:= ['add,$addForm,data]
+ code:=
+ $insideCategoryIfTrue and not $insideCategoryPackageIfTrue => data
+ processFunctorOrPackage($form,$signature,data,localParList,m,e)
+ [MKPF([:$getDomainCode,code],"PROGN"),m,e]
+
+--% PROCESS FUNCTOR CODE
+
+processFunctor(form,signature,data,localParList,e) ==
+ form is ["CategoryDefaults"] =>
+ error "CategoryDefaults is a reserved name"
+ buildFunctor(form,signature,data,localParList,e)
+
+compCapsuleItems(itemlist,$predl,$e) ==
+ $TOP__LEVEL: local
+ $myFunctorBody :local -- := data ---needed for translator
+ -- ??? the following line needs more investigation. Why is data
+ -- ??? expected to be a dynamic variable? Looks more like a bug.
+ if (BOUNDP 'data) then
+ $myFunctorBody:= SYMBOL_-VALUE 'data -- unbound at runtime?
+ $signatureOfForm: local
+ $suffix: local:= 0
+ for item in itemlist repeat $e:= compSingleCapsuleItem(item,$predl,$e)
+ $e
+
+compSingleCapsuleItem(item,$predl,$e) ==
+ doIt(macroExpandInPlace(item,$e),$predl)
+ $e
+
+doIt(item,$predl) ==
+ $GENNO: local:= 0
+ item is ['SEQ,:l,['exit,1,x]] =>
+ RPLACA(item,"PROGN")
+ RPLACA(LASTNODE item,x)
+ for it1 in rest item repeat $e:= compSingleCapsuleItem(it1,$predl,$e)
+ --This will RPLAC as appropriate
+ isDomainForm(item,$e) =>
+ -- convert naked top level domains to import
+ u:= ["import", [first item,:rest item]]
+ stackWarning ["Use: import ", [first item,:rest item]]
+ RPLACA(item,first u)
+ RPLACD(item,rest u)
+ doIt(item,$predl)
+ item is ['LET,lhs,rhs,:.] =>
+ not (compOrCroak(item,$EmptyMode,$e) is [code,.,$e]) =>
+ stackSemanticError(["cannot compile assigned value to",:bright lhs],nil)
+ not (code is ['LET,lhs',rhs',:.] and atom lhs') =>
+ code is ["PROGN",:.] =>
+ stackSemanticError(["multiple assignment ",item," not allowed"],nil)
+ RPLACA(item,first code)
+ RPLACD(item,rest code)
+ lhs:= lhs'
+ if not member(KAR rhs,$NonMentionableDomainNames) and
+ not MEMQ(lhs, $functorLocalParameters) then
+ $functorLocalParameters:= [:$functorLocalParameters,lhs]
+ if code is ['LET,.,rhs',:.] and isDomainForm(rhs',$e) then
+ if isFunctor rhs' then
+ $functorsUsed:= insert(opOf rhs',$functorsUsed)
+ $packagesUsed:= insert([opOf rhs'],$packagesUsed)
+ if lhs="Rep" then
+ $Representation:= (get("Rep",'value,$e)).(0)
+ --$Representation bound by compDefineFunctor, used in compNoStacking
+--+
+ if $NRTopt = true
+ then NRTgetLocalIndex $Representation
+--+
+ $LocalDomainAlist:= --see genDeltaEntry
+ [[lhs,:SUBLIS($LocalDomainAlist,(get(lhs,'value,$e)).0)],:$LocalDomainAlist]
+--+
+ code is ['LET,:.] =>
+ RPLACA(item,($QuickCode => 'QSETREFV;'SETELT))
+ rhsCode:=
+ rhs'
+ RPLACD(item,['$,NRTgetLocalIndexClear lhs,rhsCode])
+ RPLACA(item,first code)
+ RPLACD(item,rest code)
+ item is [":",a,t] => [.,.,$e]:= compOrCroak(item,$EmptyMode,$e)
+ item is ["import",:doms] =>
+ for dom in doms repeat
+ sayBrightly ['" importing ",:formatUnabbreviated dom]
+ [.,.,$e] := compOrCroak(item,$EmptyMode,$e)
+ RPLACA(item,'PROGN)
+ RPLACD(item,NIL) -- creates a no-op
+ item is ["IF",:.] => doItIf(item,$predl,$e)
+ item is ["where",b,:l] => compOrCroak(item,$EmptyMode,$e)
+ item is ["MDEF",:.] => [.,.,$e]:= compOrCroak(item,$EmptyMode,$e)
+ item is ['DEF,[op,:.],:.] =>
+ body:= isMacro(item,$e) => $e:= put(op,'macro,body,$e)
+ [.,.,$e]:= t:= compOrCroak(item,$EmptyMode,$e)
+ RPLACA(item,"CodeDefine")
+ --Note that DescendCode, in CodeDefine, is looking for this
+ RPLACD(CADR item,[$signatureOfForm])
+ --This is how the signature is updated for buildFunctor to recognise
+--+
+ functionPart:= ['dispatchFunction,t.expr]
+ RPLACA(CDDR item,functionPart)
+ RPLACD(CDDR item,nil)
+ u:= compOrCroak(item,$EmptyMode,$e) =>
+ ([code,.,$e]:= u; RPLACA(item,first code); RPLACD(item,rest code))
+ true => cannotDo()
+
+isMacro(x,e) ==
+ x is ['DEF,[op,:args],signature,specialCases,body] and
+ null get(op,'modemap,e) and null args and null get(op,'mode,e)
+ and signature is [nil] => body
+
+doItIf(item is [.,p,x,y],$predl,$e) ==
+ olde:= $e
+ [p',.,$e]:= comp(p,$Boolean,$e) or userError ['"not a Boolean:",p]
+ oldFLP:=$functorLocalParameters
+ if x^="noBranch" then
+ compSingleCapsuleItem(x,$predl,getSuccessEnvironment(p,$e))
+ x':=localExtras(oldFLP)
+ oldFLP:=$functorLocalParameters
+ if y^="noBranch" then
+ compSingleCapsuleItem(y,$predl,getInverseEnvironment(p,olde))
+ y':=localExtras(oldFLP)
+ RPLACA(item,"COND")
+ RPLACD(item,[[p',x,:x'],['(QUOTE T),y,:y']])
+ where localExtras(oldFLP) ==
+ EQ(oldFLP,$functorLocalParameters) => NIL
+ flp1:=$functorLocalParameters
+ oldFLP':=oldFLP
+ n:=0
+ while oldFLP' repeat
+ oldFLP':=CDR oldFLP'
+ flp1:=CDR flp1
+ n:=n+1
+ -- Now we have to add code to compile all the elements
+ -- of functorLocalParameters that were added during the
+ -- conditional compilation
+ nils:=ans:=[]
+ for u in flp1 repeat -- is =u form always an ATOM?
+ if ATOM u or (or/[v is [.,=u,:.] for v in $getDomainCode])
+ then
+ nils:=[u,:nils]
+ else
+ gv := GENSYM()
+ ans:=[['LET,gv,u],:ans]
+ nils:=[gv,:nils]
+ n:=n+1
+ $functorLocalParameters:=[:oldFLP,:NREVERSE nils]
+ NREVERSE ans
+
+--compSingleCapsuleIf(x,predl,e,$functorLocalParameters) ==
+-- compSingleCapsuleItem(x,predl,e)
+
+--% CATEGORY AND DOMAIN FUNCTIONS
+compContained(["CONTAINED",a,b],m,e) ==
+ [a,ma,e]:= comp(a,$EmptyMode,e) or return nil
+ [b,mb,e]:= comp(b,$EmptyMode,e) or return nil
+ isCategoryForm(ma,e) and isCategoryForm(mb,e) =>
+ (T:= [["CONTAINED",a,b],$Boolean,e]; convert(T,m))
+ nil
+
+compJoin(["Join",:argl],m,e) ==
+ catList:= [(compForMode(x,$Category,e) or return 'failed).expr for x in argl]
+ catList='failed => stackSemanticError(["cannot form Join of: ",argl],nil)
+ catList':=
+ [extract for x in catList] where
+ extract() ==
+ isCategoryForm(x,e) =>
+ parameters:=
+ union("append"/[getParms(y,e) for y in rest x],parameters)
+ where getParms(y,e) ==
+ atom y =>
+ isDomainForm(y,e) => LIST y
+ nil
+ y is ['LENGTH,y'] => [y,y']
+ LIST y
+ x
+ x is ["DomainSubstitutionMacro",pl,body] =>
+ (parameters:= union(pl,parameters); body)
+ x is ["mkCategory",:.] => x
+ atom x and getmode(x,e)=$Category => x
+ stackSemanticError(["invalid argument to Join: ",x],nil)
+ x
+ T:= [wrapDomainSub(parameters,["Join",:catList']),$Category,e]
+ convert(T,m)
+
+compForMode(x,m,e) ==
+ $compForModeIfTrue: local:= true
+ comp(x,m,e)
+
+compMakeCategoryObject(c,$e) ==
+ not isCategoryForm(c,$e) => nil
+ u:= mkEvalableCategoryForm c => [eval u,$Category,$e]
+ nil
+
+quotifyCategoryArgument x == MKQ x
+
+makeCategoryForm(c,e) ==
+ not isCategoryForm(c,e) => nil
+ [x,m,e]:= compOrCroak(c,$EmptyMode,e)
+ [x,e]
+
+compCategory(x,m,e) ==
+ $TOP__LEVEL: local:= true
+ (m:= resolve(m,["Category"]))=["Category"] and x is ['CATEGORY,
+ domainOrPackage,:l] =>
+ $sigList: local
+ $atList: local
+ $sigList:= $atList:= nil
+ for x in l repeat compCategoryItem(x,nil)
+ rep:= mkExplicitCategoryFunction(domainOrPackage,$sigList,$atList)
+ --if inside compDefineCategory, provide for category argument substitution
+ [rep,m,e]
+ systemErrorHere '"compCategory"
+
+mkExplicitCategoryFunction(domainOrPackage,sigList,atList) ==
+ body:=
+ ["mkCategory",MKQ domainOrPackage,['LIST,:REVERSE sigList],['LIST,:
+ REVERSE atList],MKQ domList,nil] where
+ domList() ==
+ ("union"/[fn sig for ["QUOTE",[[.,sig,:.],:.]] in sigList]) where
+ fn sig == [D for D in sig | mustInstantiate D]
+ parameters:=
+ REMDUP
+ ("append"/
+ [[x for x in sig | IDENTP x and x^='_$]
+ for ["QUOTE",[[.,sig,:.],:.]] in sigList])
+ wrapDomainSub(parameters,body)
+
+wrapDomainSub(parameters,x) ==
+ ["DomainSubstitutionMacro",parameters,x]
+
+mustInstantiate D ==
+ D is [fn,:.] and ^(MEMQ(fn,$DummyFunctorNames) or GETL(fn,"makeFunctionList"))
+
+DomainSubstitutionFunction(parameters,body) ==
+ --see definition of DomainSubstitutionMacro in SPAD LISP
+ if parameters then
+ (body:= Subst(parameters,body)) where
+ Subst(parameters,body) ==
+ ATOM body =>
+ MEMQ(body,parameters) => MKQ body
+ body
+ member(body,parameters) =>
+ g:=GENSYM()
+ $extraParms:=PUSH([g,:body],$extraParms)
+ --Used in SetVector12 to generate a substitution list
+ --bound in buildFunctor
+ --For categories, bound and used in compDefineCategory
+ MKQ g
+ first body="QUOTE" => body
+ PAIRP $definition and
+ isFunctor first body and
+ first body ^= first $definition
+ => ['QUOTE,optimize body]
+ [Subst(parameters,u) for u in body]
+ not (body is ["Join",:.]) => body
+ atom $definition => body
+ null rest $definition => body
+ --should not bother if it will only be called once
+ name:= INTERN STRCONC(KAR $definition,";CAT")
+ SETANDFILE(name,nil)
+ body:= ["COND",[name],['(QUOTE T),['SETQ,name,body]]]
+ body
+
+compCategoryItem(x,predl) ==
+ x is nil => nil
+ --1. if x is a conditional expression, recurse; otherwise, form the predicate
+ x is ["COND",[p,e]] =>
+ predl':= [p,:predl]
+ e is ["PROGN",:l] => for y in l repeat compCategoryItem(y,predl')
+ compCategoryItem(e,predl')
+ x is ["IF",a,b,c] =>
+ predl':= [a,:predl]
+ if b^="noBranch" then
+ b is ["PROGN",:l] => for y in l repeat compCategoryItem(y,predl')
+ compCategoryItem(b,predl')
+ c="noBranch" => nil
+ predl':= [["not",a],:predl]
+ c is ["PROGN",:l] => for y in l repeat compCategoryItem(y,predl')
+ compCategoryItem(c,predl')
+ pred:= (predl => MKPF(predl,"AND"); true)
+
+ --2. if attribute, push it and return
+ x is ["ATTRIBUTE",y] => PUSH(MKQ [y,pred],$atList)
+
+ --3. it may be a list, with PROGN as the CAR, and some information as the CDR
+ x is ["PROGN",:l] => for u in l repeat compCategoryItem(u,predl)
+
+-- 4. otherwise, x gives a signature for a
+-- single operator name or a list of names; if a list of names,
+-- recurse
+ ["SIGNATURE",op,:sig]:= x
+ null atom op =>
+ for y in op repeat compCategoryItem(["SIGNATURE",y,:sig],predl)
+
+ --4. branch on a single type or a signature %with source and target
+ PUSH(MKQ [rest x,pred],$sigList)
+
+
+
+
+
+
+
+