diff options
author | dos-reis <gdr@axiomatics.org> | 2007-11-07 20:54:59 +0000 |
---|---|---|
committer | dos-reis <gdr@axiomatics.org> | 2007-11-07 20:54:59 +0000 |
commit | 4edaea6cff2d604009b8f2723a9436b0fc97895d (patch) | |
tree | eb5d3765b2e4f131610571cf5f15eef53419fca0 /src/interp/i-funsel.boot.pamphlet | |
parent | 45ce0071c30e84b72e4c603660285fa6a462e7f7 (diff) | |
download | open-axiom-4edaea6cff2d604009b8f2723a9436b0fc97895d.tar.gz |
remove more pamphlets
Diffstat (limited to 'src/interp/i-funsel.boot.pamphlet')
-rw-r--r-- | src/interp/i-funsel.boot.pamphlet | 1822 |
1 files changed, 0 insertions, 1822 deletions
diff --git a/src/interp/i-funsel.boot.pamphlet b/src/interp/i-funsel.boot.pamphlet deleted file mode 100644 index 5f5d4278..00000000 --- a/src/interp/i-funsel.boot.pamphlet +++ /dev/null @@ -1,1822 +0,0 @@ -\documentclass{article} -\usepackage{axiom} - -\title{\File{src/interp/i-funsel.boot} Pamphlet} -\author{The Axiom Team} - -\begin{document} -\maketitle -\begin{abstract} -\end{abstract} -\eject -\tableofcontents -\eject - -\begin{verbatim} -New Selection of Modemaps - -selection of applicable modemaps is done in two steps: - first it tries to find a modemap inside an argument domain, and if - this fails, by evaluation of pattern modemaps -the result is a list of functions with signatures, which have the - following form: - [sig,elt,cond] where - sig is the signature gained by evaluating the modemap condition - elt is the slot number to get the implementation - cond are runtime checks which are the results of evaluating the - modemap condition - -the following flags are used: - $Coerce is NIL, if function selection is done which requires exact - matches (e.g. for coercion functions) - if $SubDom is true, then runtime checks have to be compiled -\end{verbatim} -\section{Functions} -\subsection{isPartialMode} -[[isPartialMode]] tests whether m contains [[$EmptyMode]]. The -constant [[$EmptyMode]] (defined in bootfuns.lisp) evaluates to -[[|$EmptyMode|]]. This constants is inserted in a modemap during -compile time if the modemap is not yet complete. -<<isPartialMode>>= -isPartialMode m == - CONTAINED($EmptyMode,m) - -@ -\section{License} -<<license>>= --- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd. --- 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. - -@ -<<*>>= -<<license>> - -import '"i-coerfn" -)package "BOOT" - -$constructorExposureList := '(Boolean Integer String) - -sayFunctionSelection(op,args,target,dc,func) == - $abbreviateTypes : local := true - startTimingProcess 'debug - fsig := formatSignatureArgs args - if not LISTP fsig then fsig := LIST fsig - if func then func := bright ['"by ",func] - sayMSG concat ['%l,:bright '"Function Selection for",op,:func,'%l, - '" Arguments:",:bright fsig] - if target then sayMSG concat ['" Target type:", - :bright prefix2String target] - if dc then sayMSG concat ['" From: ", - :bright prefix2String dc] - stopTimingProcess 'debug - -sayFunctionSelectionResult(op,args,mmS) == - $abbreviateTypes : local := true - startTimingProcess 'debug - if mmS then printMms mmS - else sayMSG concat ['" -> no function",:bright op, - '"found for arguments",:bright formatSignatureArgs args] - stopTimingProcess 'debug - -selectMms(op,args,$declaredMode) == - -- selects applicable modemaps for node op and arguments args - -- if there is no local modemap, and it is not a package call, then - -- the cached function selectMms1 is called - startTimingProcess 'modemaps - n:= getUnname op - val := getValue op - opMode := objMode val - - -- see if we have a functional parameter - ((isSharpVarWithNum(n) and opMode) or (val and opMode)) and - opMode is ['Mapping,:ta] => - imp := - val => wrapped2Quote objVal val - n - [[['local,:ta], imp , NIL]] - - ((isSharpVarWithNum(n) and opMode) or (val and opMode)) and - opMode is ['Variable,f] => - emptyAtree op - op.0 := f - selectMms(op,args,$declaredMode) - - isSharpVarWithNum(n) and opMode is ['FunctionCalled,f] => - op.0 := f - selectMms(op,args,$declaredMode) - - types1 := getOpArgTypes(n,args) - numArgs := #args - member('(SubDomain (Domain)),types1) => NIL - member('(Domain),types1) => NIL - member($EmptyMode,types1) => NIL - - tar := getTarget op - dc := getAtree(op,'dollar) - - null dc and val and objMode(val) = $AnonymousFunction => - tree := mkAtree objValUnwrap getValue op - putTarget(tree,['Mapping,tar,:types1]) - bottomUp tree - val := getValue tree - [[['local,:rest objMode val], wrapped2Quote objVal val, NIL]] - - if (n = 'map) and (first types1 = $AnonymousFunction) - then - tree := mkAtree objValUnwrap getValue first args - ut := - tar => underDomainOf tar - NIL - ua := [underDomainOf x for x in rest types1] - member(NIL,ua) => NIL - putTarget(tree,['Mapping,ut,:ua]) - bottomUp tree - val := getValue tree - types1 := [objMode val,:rest types1] - RPLACA(args,tree) - - if numArgs = 1 and (n = "numer" or n = "denom") and - isEqualOrSubDomain(first types1,$Integer) and null dc then - dc := ['Fraction, $Integer] - putAtree(op, 'dollar, dc) - - - if $reportBottomUpFlag then sayFunctionSelection(n,types1,tar,dc,NIL) - - identType := 'Variable - for x in types1 while not $declaredMode repeat - not EQCAR(x,identType) => $declaredMode:= x - types2 := [altTypeOf(x,y,$declaredMode) for x in types1 for y in args] - - mmS:= - dc => selectDollarMms(dc,n,types1,types2) - - if n = "/" and tar = $Integer then - tar := $RationalNumber - putTarget(op,tar) - - -- now to speed up some standard selections - if not tar then - tar := defaultTarget(op,n,#types1,types1) - if tar and $reportBottomUpFlag then - sayMSG concat ['" Default target type:", - :bright prefix2String tar] - - selectLocalMms(op,n,types1,tar) or - (VECTORP op and selectMms1(n,tar,types1,types2,'T)) - if $reportBottomUpFlag then sayFunctionSelectionResult(n,types1,mmS) - stopTimingProcess 'modemaps - mmS - --- selectMms1 is in clammed.boot - -selectMms2(op,tar,args1,args2,$Coerce) == - -- decides whether to find functions from a domain or package - -- or by general modemap evaluation - or/[STRINGP arg for arg in args1] => NIL - if tar = $EmptyMode then tar := NIL - nargs := #args1 - mmS := NIL - mmS := - -- special case map for the time being - $Coerce and (op = 'map) and (2 = nargs) and - (first(args1) is ['Variable,fun]) => - null (ud := underDomainOf CADR args1) => NIL - if tar then ut := underDomainOf(tar) - else ut := nil - null (mapMms := selectMms1(fun,ut,[ud],[NIL],true)) => NIL - mapMm := CDAAR mapMms - selectMms1(op,tar,[['Mapping,:mapMm],CADR args1], - [NIL,CADR args2],$Coerce) - - $Coerce and (op = 'map) and (2 = nargs) and - (first(args1) is ['FunctionCalled,fun]) => - null (ud := underDomainOf CADR args1) => NIL - if tar then ut := underDomainOf(tar) - else ut := nil - funNode := mkAtreeNode fun - transferPropsToNode(fun,funNode) - null (mapMms := selectLocalMms(funNode,fun,[ud],NIL)) => NIL - mapMm := CDAAR mapMms - selectMms1(op,tar,[['Mapping,:mapMm],CADR args1], - [NIL,CADR args2],$Coerce) - - -- get the argument domains and the target - a := nil - for x in args1 repeat if x then a := cons(x,a) - for x in args2 repeat if x then a := cons(x,a) - if tar and not isPartialMode tar then a := cons(tar,a) - - -- for typically homogeneous functions, throw in resolve too - if op in '(_= _+ _* _- ) then - r := resolveTypeList a - if r ^= nil then a := cons(r,a) - - if tar and not isPartialMode tar then - if xx := underDomainOf(tar) then a := cons(xx,a) - for x in args1 repeat - PAIRP(x) and CAR(x) in '(List Vector Stream FiniteSet Array) => - xx := underDomainOf(x) => a := cons(xx,a) - - -- now extend this list with those from the arguments to - -- any Unions, Mapping or Records - - a' := nil - a := nreverse REMDUP a - for x in a repeat - null x => 'iterate - x = '(RationalRadicals) => a' := cons($RationalNumber,a') - x is ['Union,:l] => - -- check if we have a tagged union - l and first l is [":",:.] => - for [.,.,t] in l repeat - a' := cons(t,a') - a' := append(reverse l,a') - x is ['Mapping,:l] => a' := append(reverse l,a') - x is ['Record,:l] => - a' := append(reverse [CADDR s for s in l],a') - x is ['FunctionCalled,name] => - (xm := get(name,'mode,$e)) and not isPartialMode xm => - a' := cons(xm,a') - a := append(a,REMDUP a') - a := [x for x in a | PAIRP(x)] - - -- step 1. see if we have one without coercing - a' := a - while a repeat - x:= CAR a - a:= CDR a - ATOM x => 'iterate - mmS := append(mmS, findFunctionInDomain(op,x,tar,args1,args2,NIL,NIL)) - - -- step 2. if we didn't get one, trying coercing (if we are - -- suppose to) - - if null(mmS) and $Coerce then - a := a' - while a repeat - x:= CAR a - a:= CDR a - ATOM x => 'iterate - mmS := append(mmS, - findFunctionInDomain(op,x,tar,args1,args2,$Coerce,NIL)) - - mmS or selectMmsGen(op,tar,args1,args2) - mmS and orderMms(op, mmS,args1,args2,tar) - -isAVariableType t == - t is ['Variable,.] or t = $Symbol or t is ['OrderedVariableList,.] - -defaultTarget(opNode,op,nargs,args) == - -- this is for efficiency. Chooses standard targets for operations - -- when no target exists. - - target := nil - - nargs = 0 => - op = 'nil => - putTarget(opNode, target := '(List (None))) - target - op = 'true or op = 'false => - putTarget(opNode, target := $Boolean) - target - op = 'pi => - putTarget(opNode, target := ['Pi]) - target - op = 'infinity => - putTarget(opNode, target := ['OnePointCompletion, $Integer]) - target - member(op, '(plusInfinity minusInfinity)) => - putTarget(opNode, target := ['OrderedCompletion, $Integer]) - target - target - - a1 := CAR args - ATOM a1 => target - a1f := QCAR a1 - - nargs = 1 => - op = 'kernel => - putTarget(opNode, target := ['Kernel, ['Expression, $Integer]]) - target - op = 'list => - putTarget(opNode, target := ['List, a1]) - target - target - - a2 := CADR args - - nargs >= 2 and op = "draw" and a1 is ['FunctionCalled,sym] and a2 is ['Segment,.] => - - -- this clears up some confusion over 2D and 3D graphics - - symNode := mkAtreeNode sym - transferPropsToNode(sym,symNode) - - nargs >= 3 and CADDR args is ['Segment,.] => - selectLocalMms(symNode,sym,[$DoubleFloat, $DoubleFloat],NIL) - putTarget(opNode, target := '(ThreeDimensionalViewport)) - target - - (mms := selectLocalMms(symNode,sym,[$DoubleFloat],NIL)) => - [.,targ,:.] := CAAR mms - targ = $DoubleFloat => - putTarget(opNode, target := '(TwoDimensionalViewport)) - target - targ = ['Point, $DoubleFloat] => - putTarget(opNode, target := '(ThreeDimensionalViewport)) - target - target - - target - - nargs >= 2 and op = "makeObject" and a1 is ['FunctionCalled,sym] and a2 is ['Segment,.] => - -- we won't actually bother to put a target on makeObject - -- this is just to figure out what the first arg is - symNode := mkAtreeNode sym - transferPropsToNode(sym,symNode) - - nargs >= 3 and CADDR args is ['Segment,.] => - selectLocalMms(symNode,sym,[$DoubleFloat, $DoubleFloat],NIL) - target - - selectLocalMms(symNode,sym,[$DoubleFloat],NIL) - target - - nargs = 2 => - op = "elt" => - a1 = '(BasicOperator) and a2 is ['List, ['OrderedVariableList, .]] => - ['Expression, $Integer] - target - - op = "eval" => - a1 is ['Expression,b1] and a2 is ['Equation, ['Polynomial,b2]] => - target := - canCoerce(b2, a1) => a1 - t := resolveTT(b1, b2) - (not t) or (t = $Any) => nil - resolveTT(a1, t) - if target then putTarget(opNode, target) - target - a1 is ['Equation, .] and a2 is ['Equation, .] => - target := resolveTT(a1, a2) - if target and not (target = $Any) then putTarget(opNode,target) - else target := nil - target - a1 is ['Equation, .] and a2 is ['List, a2e] and a2e is ['Equation, .] => - target := resolveTT(a1, a2e) - if target and not (target = $Any) then putTarget(opNode,target) - else target := nil - target - a2 is ['Equation, a2e] or a2 is ['List, ['Equation, a2e]] => - target := resolveTT(a1, a2e) - if target and not (target = $Any) then putTarget(opNode,target) - else target := nil - target - - op = "**" or op = "^" => - a2 = $Integer => - if (target := resolveTCat(a1,'(Field))) then - putTarget(opNode,target) - target - a1 = '(AlgebraicNumber) and (a2 = $Float or a2 = $DoubleFloat) => - target := ['Expression, a2] - putTarget(opNode,target) - target - a1 = '(AlgebraicNumber) and a2 is ['Complex, a3] and (a3 = $Float or a3 = $DoubleFloat) => - target := ['Expression, a3] - putTarget(opNode,target) - target - ((a2 = $RationalNumber) and - (typeIsASmallInteger(a1) or isEqualOrSubDomain(a1,$Integer))) => - putTarget(opNode, target := '(AlgebraicNumber)) - target - ((a2 = $RationalNumber) and (isAVariableType(a1) - or a1 is ['Polynomial,.] or a1 is ['RationalFunction,.])) => - putTarget(opNode, target := defaultTargetFE a1) - target - isAVariableType(a1) and (a2 = $PositiveInteger or a2 = $NonNegativeInteger) => - putTarget(opNode, target := '(Polynomial (Integer))) - target - isAVariableType(a2) => - putTarget(opNode, target := defaultTargetFE a1) - target - a2 is ['Polynomial, D] => - (a1 = a2) or isAVariableType(a1) - or ((a1 is ['RationalFunction, D1]) and (D1 = D)) or (a1 = D) - or ((a1 is [=$QuotientField, D1]) and (D1 = a1)) => - putTarget(opNode, target := defaultTargetFE a2) - target - target - a2 is ['RationalFunction, D] => - (a1 = a2) or isAVariableType(a1) - or ((a1 is ['RationalFunction, D1]) and (D1 = D)) or (a1 = D) - or ((a1 is [=$QuotientField, D1]) and (D1 = a1)) => - putTarget(opNode, target := defaultTargetFE a2) - target - target - target - - op = "/" => - isEqualOrSubDomain(a1, $Integer) and isEqualOrSubDomain(a2, $Integer) => - putTarget(opNode, target := $RationalNumber) - target - a1 = a2 => - if (target := resolveTCat(CAR args,'(Field))) then - putTarget(opNode,target) - target - a1 is ['Variable,.] and a2 is ['Variable,.] => - putTarget(opNode,target := mkRationalFunction '(Integer)) - target - isEqualOrSubDomain(a1,$Integer) and a2 is ['Variable,.] => - putTarget(opNode,target := mkRationalFunction '(Integer)) - target - a1 is ['Variable,.] and - a2 is ['Polynomial,D] => - putTarget(opNode,target := mkRationalFunction D) - target - target - a2 is ['Variable,.] and - a1 is ['Polynomial,D] => - putTarget(opNode,target := mkRationalFunction D) - target - target - a2 is ['Polynomial,D] and (a1 = D) => - putTarget(opNode,target := mkRationalFunction D) - target - target - - a3 := CADDR args - nargs = 3 => - op = "eval" => - a3 is ['List, a3e] => - target := resolveTT(a1, a3e) - if not (target = $Any) then putTarget(opNode,target) - else target := nil - target - - target := resolveTT(a1, a3) - if not (target = $Any) then putTarget(opNode,target) - else target := nil - target - target - -mkRationalFunction D == ['Fraction, ['Polynomial, D]] - -defaultTargetFE(a,:options) == - a is ['Variable,.] or a = $RationalNumber or MEMQ(QCAR a, - [QCAR $Symbol, 'RationalRadicals, - 'Pi]) or typeIsASmallInteger(a) or isEqualOrSubDomain(a, $Integer) or - a = '(AlgebraicNumber) => - IFCAR options => [$FunctionalExpression, ['Complex, $Integer]] - [$FunctionalExpression, $Integer] - a is ['Complex,uD] => defaultTargetFE(uD, true) - a is [D,uD] and MEMQ(D, '(Polynomial RationalFunction Fraction)) => - defaultTargetFE(uD, IFCAR options) - a is [=$FunctionalExpression,.] => a - IFCAR options => [$FunctionalExpression, ['Complex, a]] - [$FunctionalExpression, a] - -altTypeOf(type,val,$declaredMode) == - (EQCAR(type,'Symbol) or EQCAR(type,'Variable)) and - (a := getMinimalVarMode(objValUnwrap getValue(val),$declaredMode)) => - a - type is ['OrderedVariableList,vl] and - INTEGERP(val1 := objValUnwrap getValue(val)) and - (a := getMinimalVarMode(vl.(val1 - 1),$declaredMode)) => - a - type = $PositiveInteger => $Integer - type = $NonNegativeInteger => $Integer - type = '(List (PositiveInteger)) => '(List (Integer)) - NIL - -getOpArgTypes(opname, args) == - l := getOpArgTypes1(opname, args) - [f(a,opname) for a in l] where - f(x,op) == - x is ['FunctionCalled,g] and op ^= 'name => - m := get(g,'mode,$e) => - m is ['Mapping,:.] => m - x - x - x - -getOpArgTypes1(opname, args) == - null args => NIL - -- special cases first - opname = 'coef and args is [b,n] => - [CAR getModeSet b, CAR getModeSetUseSubdomain n] - opname = 'monom and args is [d,c] => - [CAR getModeSetUseSubdomain d,CAR getModeSet c] - opname = 'monom and args is [v,d,c] => - [CAR getModeSet v,CAR getModeSetUseSubdomain d,CAR getModeSet c] - (opname = 'cons) and (2 = #args) and (CADR(args) = 'nil) => - ms := [CAR getModeSet x for x in args] - if CADR(ms) = '(List (None)) then - ms := [first ms,['List,first ms]] - ms - nargs := #args - v := argCouldBelongToSubdomain(opname,nargs) - mss := NIL - for i in 0..(nargs-1) for x in args repeat - ms := - v.i = 0 => CAR getModeSet x - CAR getModeSetUseSubdomain x - mss := [ms,:mss] - nreverse mss - -argCouldBelongToSubdomain(op, nargs) == - -- this returns a vector containing 0 or ^0 for each argument. - -- if ^0, this indicates that there exists a modemap for the - -- op that needs a subdomain in that position - nargs = 0 => NIL - v := GETZEROVEC nargs - isMap(op) => v - mms := getModemapsFromDatabase(op,nargs) - null mms => v - nargs:=nargs-1 - -- each signature has form - -- [domain of implementation, target, arg1, arg2, ...] - for [sig,cond,:.] in mms repeat - for t in CDDR sig for i in 0..(nargs) repeat - CONTAINEDisDomain(t,cond) => - v.i := 1 + v.i - v - -CONTAINEDisDomain(symbol,cond) == --- looks for [isSubDomain,symbol,[domain]] in cond: returning T or NIL --- with domain being one of PositiveInteger and NonNegativeInteger - ATOM cond => false - MEMQ(QCAR cond,'(AND OR and or)) => - or/[CONTAINEDisDomain(symbol, u) for u in QCDR cond] - EQ(QCAR cond,'isDomain) => - EQ(symbol,CADR cond) and PAIRP(dom:=CADDR cond) and - MEMQ(dom,'(PositiveInteger NonNegativeInteger)) - false - -selectDollarMms(dc,name,types1,types2) == - -- finds functions for name in domain dc - isPartialMode dc => throwKeyedMsg("S2IF0001",NIL) - mmS := findFunctionInDomain(name,dc,NIL,types1,types2,'T,'T) => - orderMms(name, mmS,types1,types2,NIL) - if $reportBottomUpFlag then sayMSG - ["%b",'" function not found in ",prefix2String dc,"%d","%l"] - NIL - -selectLocalMms(op,name,types,tar) == - -- partial rewrite, looks now for exact local modemap - mmS:= getLocalMms(name,types,tar) => mmS - obj := getValue op - obj and (objVal obj is ['MAP,:mapDef]) and - analyzeMap(op,types,mapDef,tar) and getLocalMms(name,types,tar) - --- next defn may be better, test when more time. RSS 3/11/94 --- selectLocalMms(op,name,types,tar) == --- mmS := getLocalMms(name,types,tar) --- -- if no target, just return what we got --- mmS and null tar => mmS --- matchingMms := nil --- for mm in mmS repeat --- [., targ, :.] := mm --- if tar = targ then matchingMms := cons(mm, matchingMms) --- -- if we got some exact matchs on the target, return them --- matchingMms => nreverse matchingMms --- --- obj := getValue op --- obj and (objVal obj is ['MAP,:mapDef]) and --- analyzeMap(op,types,mapDef,tar) and getLocalMms(name,types,tar) - -getLocalMms(name,types,tar) == - -- looks for exact or subsumed local modemap in $e - mmS := NIL - for (mm:=[dcSig,:.]) in get(name,'localModemap,$e) repeat - -- check format and destructure - dcSig isnt [dc,result,:args] => NIL - -- make number of args is correct - #types ^= #args => NIL - -- check for equal or subsumed arguments - subsume := (not $useIntegerSubdomain) or (tar = result) or - get(name,'recursive,$e) - acceptableArgs := - and/[f(b,a,subsume) for a in args for b in types] where - f(x,y,subsume) == - if subsume - then isEqualOrSubDomain(x,y) - else x = y - not acceptableArgs => - -- interpreted maps are ok - dc = 'interpOnly and not($Coerce)=> mmS := [mm,:mmS] - NIL - mmS := [mm,:mmS] - nreverse mmS - -mmCost(name, sig,cond,tar,args1,args2) == - cost := mmCost0(name, sig,cond,tar,args1,args2) - res := CADR sig - res = $PositiveInteger => cost - 2 - res = $NonNegativeInteger => cost - 1 - res = $DoubleFloat => cost + 1 - cost - -mmCost0(name, sig,cond,tar,args1,args2) == - sigArgs := CDDR sig - n:= - null cond => 1 - not (or/cond) => 1 - 0 - - -- try to favor homogeneous multiplication - ---if name = "*" and 2 = #sigArgs and first sigArgs ^= first rest sigArgs then n := n + 1 - - -- because of obscure problem in evalMm, sometimes we will have extra - -- modemaps with the wrong number of arguments if we want to the one - -- with no arguments and the name is overloaded. Thus check for this. - - if args1 then - for x1 in args1 for x2 in args2 for x3 in sigArgs repeat - n := n + - isEqualOrSubDomain(x1,x3) => 0 - topcon := first deconstructT x1 - topcon2 := first deconstructT x3 - topcon = topcon2 => 3 - CAR topcon2 = 'Mapping => 2 - 4 - else if sigArgs then n := n + 100000000000 - - res := CADR sig - res=tar => 10000*n - 10000*n + 1000*domainDepth(res) + hitListOfTarget(res) - -orderMms(name, mmS,args1,args2,tar) == - -- it counts the number of necessary coercions of the argument types - -- if this isn't enough, it compares the target types - mmS and null rest mmS => mmS - mS:= NIL - N:= NIL - for mm in MSORT mmS repeat - [sig,.,cond]:= mm - b:= 'T - p:= CONS(m := mmCost(name, sig,cond,tar,args1,args2),mm) - mS:= - null mS => list p - m < CAAR mS => CONS(p,mS) - S:= mS - until b repeat - b:= null CDR S or m < CAADR S => - RPLACD(S,CONS(p,CDR S)) - S:= CDR S - mS - mmS and [CDR p for p in mS] - -domainDepth(d) == - -- computes the depth of lisp structure d - atom d => 0 - MAX(domainDepth(CAR d)+1,domainDepth(CDR d)) - -hitListOfTarget(t) == - -- assigns a number between 1 and 998 to a type t - - -- want to make it hard to go to Polynomial Pi - - t = '(Polynomial (Pi)) => 90000 - - EQ(CAR t, 'Polynomial) => 300 - EQ(CAR t, 'List) => 400 - EQ(CAR t,'Matrix) => 910 - EQ(CAR t,'UniversalSegment) => 501 - EQ(CAR t,'RationalFunction) => 900 - EQ(CAR t,'Union) => 999 - EQ(CAR t,'Expression) => 1600 - 500 - -getFunctionFromDomain(op,dc,args) == - -- finds the function op with argument types args in dc - -- complains, if no function or ambiguous - $reportBottomUpFlag:local:= NIL - member(CAR dc,$nonLisplibDomains) => - throwKeyedMsg("S2IF0002",[CAR dc]) - not constructor? CAR dc => - throwKeyedMsg("S2IF0003",[CAR dc]) - p:= findFunctionInDomain(op,dc,NIL,args,args,NIL,NIL) => ---+ - --sig := [NIL,:args] - domain := evalDomain dc - for mm in nreverse p until b repeat - [[.,:osig],nsig,:.] := mm - b := compiledLookup(op,nsig,domain) - b or throwKeyedMsg("S2IS0023",[op,dc]) - throwKeyedMsg("S2IF0004",[op,dc]) - -isOpInDomain(opName,dom,nargs) == - -- returns true only if there is an op in the given domain with - -- the given number of arguments - mmList := ASSQ(opName,getOperationAlistFromLisplib CAR dom) - mmList := subCopy(mmList,constructSubst dom) - null mmList => NIL - gotOne := NIL - nargs := nargs + 1 - for mm in CDR mmList while not gotOne repeat - nargs = #CAR mm => gotOne := [mm, :gotOne] - gotOne - -findCommonSigInDomain(opName,dom,nargs) == - -- this looks at all signatures in dom with given opName and nargs - -- number of arguments. If no matches, returns NIL. Otherwise returns - -- a "signature" where a type position is non-NIL only if all - -- signatures shares that type . - CAR(dom) in '(Union Record Mapping) => NIL - mmList := ASSQ(opName,getOperationAlistFromLisplib CAR dom) - mmList := subCopy(mmList,constructSubst dom) - null mmList => NIL - gotOne := NIL - nargs := nargs + 1 - vec := NIL - for mm in CDR mmList repeat - nargs = #CAR mm => - null vec => vec := LIST2VEC CAR mm - for i in 0.. for x in CAR mm repeat - if vec.i and vec.i ^= x then vec.i := NIL - VEC2LIST vec - -findUniqueOpInDomain(op,opName,dom) == - -- return function named op in domain dom if unique, choose one if not - mmList := ASSQ(opName,getOperationAlistFromLisplib CAR dom) - mmList := subCopy(mmList,constructSubst dom) - null mmList => - throwKeyedMsg("S2IS0021",[opName,dom]) - if #CDR mmList > 1 then - mm := selectMostGeneralMm CDR mmList - sayKeyedMsg("S2IS0022",[opName,dom,['Mapping,:CAR mm]]) - else mm := CADR mmList - [sig,slot,:.] := mm - fun := ---+ - $genValue => - compiledLookupCheck(opName,sig,evalDomain dom) - NRTcompileEvalForm(opName, sig, evalDomain dom) - NULL(fun) or NULL(PAIRP(fun)) => NIL - CAR fun = function(Undef) => throwKeyedMsg("S2IS0023",[opName,dom]) - binVal := - $genValue => wrap fun - fun - putValue(op,objNew(binVal,m:=['Mapping,:sig])) - putModeSet(op,[m]) - -selectMostGeneralMm mmList == - -- selects the modemap in mmList with arguments all the other - -- argument types can be coerced to - -- also selects function with #args closest to 2 - min := 100 - mml := mmList - while mml repeat - [mm,:mml] := mml - sz := #CAR mm - if (met := ABS(sz - 3)) < min then - min := met - fsz := sz - mmList := [mm for mm in mmList | (#CAR mm) = fsz] - mml := CDR mmList - genMm := CAR mmList - while mml repeat - [mm,:mml] := mml - and/[canCoerceFrom(genMmArg,mmArg) for mmArg in CDAR mm - for genMmArg in CDAR genMm] => genMm := mm - genMm - -findFunctionInDomain(op,dc,tar,args1,args2,$Coerce,$SubDom) == - -- looks for a modemap for op with signature args1 -> tar - -- in the domain of computation dc - -- tar may be NIL (= unknown) - null isLegitimateMode(tar, nil, nil) => nil - dcName:= CAR dc - member(dcName,'(Union Record Mapping Enumeration)) => - -- First cut code that ignores args2, $Coerce and $SubDom - -- When domains no longer have to have Set, the hard coded 6 and 7 - -- should go. - op = '_= => - #args1 ^= 2 or args1.0 ^= dc or args1.1 ^= dc => NIL - tar and tar ^= '(Boolean) => NIL - [[[dc, '(Boolean), dc, dc], ['(Boolean),'$,'$], [NIL, NIL]]] - op = 'coerce => - #args1 ^= 1 - dcName='Enumeration and (args1.0=$Symbol or tar=dc)=> - [[[dc, dc, $Symbol], ['$,$Symbol], [NIL, NIL]]] - args1.0 ^= dc => NIL - tar and tar ^= $Expression => NIL - [[[dc, $Expression, dc], [$Expression,'$], [NIL, NIL]]] - member(dcName,'(Record Union)) => - findFunctionInCategory(op,dc,tar,args1,args2,$Coerce,$SubDom) - NIL - fun:= NIL - ( p := ASSQ(op,getOperationAlistFromLisplib dcName) ) and - SL := constructSubst dc - -- if the arglist is homogeneous, first look for homogeneous - -- functions. If we don't find any, look at remaining ones - if isHomogeneousList args1 then - q := NIL - r := NIL - for mm in CDR p repeat - -- CDAR of mm is the signature argument list - if isHomogeneousList CDAR mm then q := [mm,:q] - else r := [mm,:r] - q := allOrMatchingMms(q,args1,tar,dc) - for mm in q repeat - fun:= nconc(fun,findFunctionInDomain1(mm,op,tar,args1,args2,SL)) - r := reverse r - else r := CDR p - r := allOrMatchingMms(r,args1,tar,dc) - if not fun then -- consider remaining modemaps - for mm in r repeat - fun:= nconc(fun,findFunctionInDomain1(mm,op,tar,args1,args2,SL)) - if not fun and $reportBottomUpFlag then - sayMSG concat - ['" -> no appropriate",:bright op,'"found in", - :bright prefix2String dc] - fun - -allOrMatchingMms(mms,args1,tar,dc) == - -- if there are exact matches on the arg types, return them - -- otherwise return the original list - null mms or null rest mms => mms - x := NIL - for mm in mms repeat - [sig,:.] := mm - [res,:args] := MSUBSTQ(dc,"$",sig) - args ^= args1 => nil - x := CONS(mm,x) - if x then x - else mms - -isHomogeneousList y == - y is [x] => true - y and rest y => - z := CAR y - "and"/[x = z for x in CDR y] - NIL - -findFunctionInDomain1(omm,op,tar,args1,args2,SL) == - dc:= CDR (dollarPair := ASSQ('$,SL)) - -- need to drop '$ from SL - mm:= subCopy(omm, SL) - -- tests whether modemap mm is appropriate for the function - -- defined by op, target type tar and argument types args - $RTC:local:= NIL - -- $RTC is a list of run-time checks to be performed - - [sig,slot,cond,y] := mm - [osig,:.] := omm - osig := subCopy(osig, SUBSTQ(CONS('$,'$), dollarPair, SL)) - if CONTAINED('_#, sig) or CONTAINED('construct,sig) then - sig := [replaceSharpCalls t for t in sig] - matchMmCond cond and matchMmSig(mm,tar,args1,args2) and - EQ(y,'Subsumed) and - -- hmmmm: do Union check in following because (as in DP) - -- Unions are subsumed by total modemaps which are in the - -- mm list in findFunctionInDomain. - y := 'ELT -- if subsumed fails try it again - not $SubDom and CAR sig isnt ['Union,:.] and slot is [tar,:args] and - (f := findFunctionInDomain(op,dc,tar,args,args,NIL,NIL)) => f - EQ(y,'ELT) => [[CONS(dc,sig),osig,nreverse $RTC]] - EQ(y,'CONST) => [[CONS(dc,sig),osig,nreverse $RTC]] - EQ(y,'ASCONST) => [[CONS(dc,sig),osig,nreverse $RTC]] - y is ['XLAM,:.] => [[CONS(dc,sig),y,nreverse $RTC]] - sayKeyedMsg("S2IF0006",[y]) - NIL - -findFunctionInCategory(op,dc,tar,args1,args2,$Coerce,$SubDom) == - -- looks for a modemap for op with signature args1 -> tar - -- in the domain of computation dc - -- tar may be NIL (= unknown) - dcName:= CAR dc - not MEMQ(dcName,'(Record Union Enumeration)) => NIL - fun:= NIL - -- cat := constructorCategory dc - makeFunc := GETL(dcName,"makeFunctionList") or - systemErrorHere '"findFunctionInCategory" - [funlist,.] := FUNCALL(makeFunc,"$",dc,$CategoryFrame) - -- get list of implementations and remove sharps - maxargs := -1 - impls := nil - for [a,b,d] in funlist repeat - not EQ(a,op) => nil - d is ['XLAM,xargs,:.] => - if PAIRP(xargs) then maxargs := MAX(maxargs,#xargs) - else maxargs := MAX(maxargs,1) - impls := cons([b,nil,true,d],impls) - impls := cons([b,d,true,d],impls) - impls := NREVERSE impls - if maxargs ^= -1 then - SL:= NIL - for i in 1..maxargs repeat - impls := SUBSTQ(GENSYM(),INTERNL('"#",STRINGIMAGE i),impls) - impls and - SL:= constructSubst dc - for mm in impls repeat - fun:= nconc(fun,findFunctionInDomain1(mm,op,tar,args1,args2,SL)) - if not fun and $reportBottomUpFlag then - sayMSG concat - ['" -> no appropriate",:bright op,'"found in", - :bright prefix2String dc] - fun - -matchMmCond(cond) == - -- tests the condition, which comes with a modemap - -- cond is 'T or a list, but I hate to test for 'T (ALBI) - $domPvar: local := nil - atom cond or - cond is ['AND,:conds] or cond is ['and,:conds] => - and/[matchMmCond c for c in conds] - cond is ['OR,:conds] or cond is ['or,:conds] => - or/[matchMmCond c for c in conds] - cond is ['has,dom,x] => - hasCaty(dom,x,NIL) ^= 'failed - cond is ['not,cond1] => not matchMmCond cond1 - keyedSystemError("S2GE0016", - ['"matchMmCond",'"unknown form of condition"]) - -matchMmSig(mm,tar,args1,args2) == - -- matches the modemap signature against args1 -> tar - -- if necessary, runtime checks are created for subdomains - -- then the modemap condition is evaluated - [sig,:.]:= mm - if CONTAINED('_#, sig) then - sig := [replaceSharpCalls COPY t for t in sig] - null args1 => matchMmSigTar(tar,CAR sig) - a:= CDR sig - arg:= NIL - for i in 1.. while args1 and args2 and a until not b repeat - x1:= CAR args1 - args1:= CDR args1 - x2:= CAR args2 - args2:= CDR args2 - x:= CAR a - a:= CDR a - rtc:= NIL - if x is ['SubDomain,y,:.] then x:= y - b := isEqualOrSubDomain(x1,x) or - (STRINGP(x) and (x1 is ['Variable,v]) and (x = PNAME v)) or - $SubDom and isSubDomain(x,x1) => rtc:= 'T - $Coerce => x2=x or canCoerceFrom(x1,x) - x1 is ['Variable,:.] and x = '(Symbol) - $RTC:= CONS(rtc,$RTC) - null args1 and null a and b and matchMmSigTar(tar,CAR sig) - -matchMmSigTar(t1,t2) == - -- t1 is a target type specified by :: or by a declared variable - -- t2 is the target of a modemap signature - null t1 or - isEqualOrSubDomain(t2,t1) => true - if t2 is ['Union,a,b] then - if a='"failed" then return matchMmSigTar(t1, b) - if b='"failed" then return matchMmSigTar(t1, a) - $Coerce and - isPartialMode t1 => resolveTM(t2,t1) --- I think this should be true -SCM --- true - canCoerceFrom(t2,t1) - -constructSubst(d) == - -- constructs a substitution which substitutes d for $ - -- and the arguments of d for #1, #2 .. - SL:= list CONS('$,d) - for x in CDR d for i in 1.. repeat - SL:= CONS(CONS(INTERNL('"#",STRINGIMAGE i),x),SL) - SL - -filterModemapsFromPackages(mms, names, op) == - -- mms is a list of modemaps - -- names is a list of domain constructors - -- this returns a 2-list containing those modemaps that have one - -- of the names in the package source of the modemap and all the - -- rest of the modemaps in the second element. - good := NIL - bad := NIL - -- hack to speed up factorization choices for mpolys and to overcome - -- some poor naming of packages - mpolys := '("Polynomial" "MultivariatePolynomial" - "DistributedMultivariatePolynomial" - "HomogeneousDistributedMultivariatePolynomial") - mpacks := '("MFactorize" "MRationalFactorize") - for mm in mms repeat - isFreeFunctionFromMm(mm) => bad := cons(mm, bad) - type := getDomainFromMm mm - null type => bad := cons(mm,bad) - if PAIRP type then type := first type - GETDATABASE(type,'CONSTRUCTORKIND) = 'category => bad := cons(mm,bad) - name := object2String type - found := nil - for n in names while not found repeat - STRPOS(n,name,0,NIL) => found := true - -- hack, hack - (op = 'factor) and member(n,mpolys) and member(name,mpacks) => - found := true - if found - then good := cons(mm, good) - else bad := cons(mm,bad) - [good,bad] - - -isTowerWithSubdomain(towerType,elem) == - not PAIRP towerType => NIL - dt := deconstructT towerType - 2 ^= #dt => NIL - s := underDomainOf(towerType) - isEqualOrSubDomain(s,elem) and constructM(first dt,[elem]) - -selectMmsGen(op,tar,args1,args2) == - -- general modemap evaluation of op with argument types args1 - -- evaluates the condition and looks for the slot number - -- returns all functions which are applicable - -- args2 is a list of polynomial types for symbols - $Subst: local := NIL - $SymbolType: local := NIL - - null (S := getModemapsFromDatabase(op,QLENGTH args1)) => NIL - - if (op = 'map) and (2 = #args1) and - (CAR(args1) is ['Mapping,., elem]) and - (a := isTowerWithSubdomain(CADR args1,elem)) - then args1 := [CAR args1,a] - - -- we first split the modemaps into two groups: - -- haves: these are from packages that have one of the top level - -- constructor names in the package name - -- havenots: everything else - - -- get top level constructor names for constructors with parameters - conNames := nil - if op = 'reshape then args := APPEND(rest args1, rest args2) - else args := APPEND(args1,args2) - if tar then args := [tar,:args] - -- for common aggregates, use under domain also - for a in REMDUP args repeat - a => - atom a => nil - fa := QCAR a - fa in '(Record Union) => NIL - conNames := insert(STRINGIMAGE fa, conNames) - - if conNames - then [haves,havenots] := filterModemapsFromPackages(S,conNames,op) - else - haves := NIL - havenots := S - - mmS := NIL - - if $reportBottomUpFlag then - sayMSG ['%l,:bright '"Modemaps from Associated Packages"] - - if haves then - [havesExact,havesInexact] := exact?(haves,tar,args1) - if $reportBottomUpFlag then - for mm in APPEND(havesExact,havesInexact) for i in 1.. repeat - sayModemapWithNumber(mm,i) - if havesExact then - mmS := matchMms(havesExact,op,tar,args1,args2) - if mmS then - if $reportBottomUpFlag then - sayMSG '" found an exact match!" - return mmS - mmS := matchMms(havesInexact,op,tar,args1,args2) - else if $reportBottomUpFlag then sayMSG '" no modemaps" - mmS => mmS - - if $reportBottomUpFlag then - sayMSG ['%l,:bright '"Remaining General Modemaps"] - -- for mm in havenots for i in 1.. repeat sayModemapWithNumber(mm,i) - - if havenots then - [havesNExact,havesNInexact] := exact?(havenots,tar,args1) - if $reportBottomUpFlag then - for mm in APPEND(havesNExact,havesNInexact) for i in 1.. repeat - sayModemapWithNumber(mm,i) - if havesNExact then - mmS := matchMms(havesNExact,op,tar,args1,args2) - if mmS then - if $reportBottomUpFlag then - sayMSG '" found an exact match!" - return mmS - mmS := matchMms(havesNInexact,op,tar,args1,args2) - else if $reportBottomUpFlag then sayMSG '" no modemaps" - mmS - where - exact?(mmS,tar,args) == - ex := inex := NIL - for (mm := [sig,[mmC,:.],:.]) in mmS repeat - [c,t,:a] := sig - ok := true - for pat in a for arg in args while ok repeat - not CONTAINED(['isDomain,pat,arg],mmC) => ok := NIL - ok => ex := CONS(mm,ex) - inex := CONS(mm,inex) - [ex,inex] - matchMms(mmaps,op,tar,args1,args2) == - mmS := NIL - for [sig,mmC] in mmaps repeat - -- sig is [dc,result,:args] - $Subst := - tar and not isPartialMode tar => - -- throw in the target if it is not the same as one - -- of the arguments - res := CADR sig - member(res,CDDR sig) => NIL - [[res,:tar]] - NIL - [c,t,:a] := sig - if a then matchTypes(a,args1,args2) - not EQ($Subst,'failed) => - mmS := nconc(evalMm(op,tar,sig,mmC),mmS) - mmS - -matchTypes(pm,args1,args2) == - -- pm is a list of pattern variables, args1 a list of argument types, - -- args2 a list of polynomial types for symbols - -- the result is a match from pm to args, if one exists - for v in pm for t1 in args1 for t2 in args2 until $Subst='failed repeat - p:= ASSQ(v,$Subst) => - t:= CDR p - t=t1 => $Coerce and EQCAR(t1,'Symbol) and - (q := ASSQ(v,$SymbolType)) and t2 and - (t3 := resolveTT(CDR q, t2)) and - RPLACD(q, t3) - $Coerce => - if EQCAR(t,'Symbol) and (q := ASSQ(v,$SymbolType)) then - t := CDR q - if EQCAR(t1,'Symbol) and t2 then t1:= t2 - t0 := resolveTT(t,t1) => RPLACD(p,t0) - $Subst:= 'failed - $Subst:= 'failed - $Subst:= CONS(CONS(v,t1),$Subst) - if EQCAR(t1,'Symbol) and t2 then $SymbolType:= CONS(CONS(v,t2),$SymbolType) - -evalMm(op,tar,sig,mmC) == - -- evaluates a modemap with signature sig and condition mmC - -- the result is a list of lists [sig,slot,cond] or NIL - --if $Coerce is NIL, tar has to be the same as the computed target type ---if CONTAINED('LinearlyExplicitRingOver,mmC) then hohoho() - mS:= NIL - for st in evalMmStack mmC repeat - SL:= evalMmCond(op,sig,st) - not EQ(SL,'failed) => - SL := fixUpTypeArgs SL - sig:= [subCopy(deepSubCopy(x,SL),$Subst) for x in sig] - not containsVars sig => - isFreeFunctionFromMmCond mmC and (m := evalMmFreeFunction(op,tar,sig,mmC)) => - mS:= nconc(m,mS) - "or"/[^isValidType(arg) for arg in sig] => nil - [dc,t,:args]:= sig - $Coerce or null tar or tar=t => - mS:= nconc(findFunctionInDomain(op,dc,t,args,args,NIL,'T),mS) - mS - -evalMmFreeFunction(op,tar,sig,mmC) == - [dc,t,:args]:= sig - $Coerce or null tar or tar=t => - nilArgs := nil - for a in args repeat nilArgs := [NIL,:nilArgs] - [[[["__FreeFunction__",:dc],t,:args], [t, :args], nilArgs]] - nil - -evalMmStack(mmC) == - -- translates the modemap condition mmC into a list of stacks - mmC is ['AND,:a] => - ["NCONC"/[evalMmStackInner cond for cond in a]] - mmC is ['OR,:args] => [:evalMmStack a for a in args] - mmC is ['partial,:mmD] => evalMmStack mmD - mmC is ['ofCategory,pvar,cat] and cat is ['Join,:args] => - evalMmStack CONS('AND,[['ofCategory,pvar,c] for c in args]) - mmC is ['ofType,:.] => [NIL] - mmC is ['has,pat,x] => - MEMQ(x,'(ATTRIBUTE SIGNATURE)) => - [[['ofCategory,pat,['CATEGORY,'unknown,x]]]] - [['ofCategory,pat,x]] - [[mmC]] - -evalMmStackInner(mmC) == - mmC is ['OR,:args] => - keyedSystemError("S2GE0016", - ['"evalMmStackInner",'"OR condition nested inside an AND"]) - mmC is ['partial,:mmD] => evalMmStackInner mmD - mmC is ['ofCategory,pvar,cat] and cat is ['Join,:args] => - [['ofCategory, pvar, c] for c in args] - mmC is ['ofType,:.] => NIL - mmC is ['isAsConstant] => NIL - mmC is ['has,pat,x] => - MEMQ(x,'(ATTRIBUTE SIGNATURE)) => - [['ofCategory,pat,['CATEGORY,'unknown,x]]] - [['ofCategory,pat,x]] - [mmC] - -evalMmCond(op,sig,st) == - $insideEvalMmCondIfTrue : local := true - evalMmCond0(op,sig,st) - -evalMmCond0(op,sig,st) == - -- evaluates the nonempty list of modemap conditions st - -- the result is either 'failed or a substitution list - SL:= evalMmDom st - SL='failed => 'failed - for p in SL until p1 and not b repeat b:= - p1:= ASSQ(CAR p,$Subst) - p1 and - t1:= CDR p1 - t:= CDR p - t=t1 or - containsVars t => - if $Coerce and EQCAR(t1,'Symbol) then t1:= getSymbolType CAR p - resolveTM1(t1,t) - $Coerce and - -- if we are looking at the result of a function, the coerce - -- goes the opposite direction - (t1 = $AnonymousFunction and t is ['Mapping, :.]) => t - CAR p = CADR sig and not member(CAR p, CDDR sig) => - canCoerceFrom(t,t1) => 'T - NIL - canCoerceFrom(t1,t) => 'T - isSubDomain(t,t1) => RPLACD(p,t1) - EQCAR(t1,'Symbol) and canCoerceFrom(getSymbolType CAR p,t) - ( SL and p1 and not b and 'failed ) or evalMmCat(op,sig,st,SL) - -fixUpTypeArgs SL == - for (p := [v, :t2]) in SL repeat - t1 := LASSOC(v, $Subst) - null t1 => RPLACD(p,replaceSharpCalls t2) - RPLACD(p, coerceTypeArgs(t1, t2, SL)) - SL - -replaceSharpCalls t == - noSharpCallsHere t => t - doReplaceSharpCalls t - -doReplaceSharpCalls t == - ATOM t => t - t is ['_#, l] => #l - t is ['construct,: l] => EVAL ['LIST,:l] - [CAR t,:[ doReplaceSharpCalls u for u in CDR t]] - -noSharpCallsHere t == - t isnt [con, :args] => true - MEMQ(con,'(construct _#)) => NIL - and/[noSharpCallsHere u for u in args] - -coerceTypeArgs(t1, t2, SL) == - -- if the type t has type-valued arguments, coerce them to the new types, - -- if needed. - t1 isnt [con1, :args1] or t2 isnt [con2, :args2] => t2 - con1 ^= con2 => t2 - coSig := CDR GETDATABASE(CAR t1, 'COSIG) - and/coSig => t2 - csub1 := constructSubst t1 - csub2 := constructSubst t2 - cs1 := CDR getConstructorSignature con1 - cs2 := CDR getConstructorSignature con2 - [con1, : - [makeConstrArg(arg1, arg2, constrArg(c1,csub1,SL), - constrArg(c2,csub2,SL), cs) - for arg1 in args1 for arg2 in args2 for c1 in cs1 for c2 in cs2 - for cs in coSig]] - -constrArg(v,sl,SL) == - x := LASSOC(v,sl) => - y := LASSOC(x,SL) => y - y := LASSOC(x, $Subst) => y - x - y := LASSOC(x, $Subst) => y - v - -makeConstrArg(arg1, arg2, t1, t2, cs) == - if arg1 is ['_#, l] then arg1 := # l - if arg2 is ['_#, l] then arg2 := # l - cs => arg2 - t1 = t2 => arg2 - obj1 := objNewWrap(arg1, t1) - obj2 := coerceInt(obj1, t2) - null obj2 => throwKeyedMsgCannotCoerceWithValue(wrap arg1,t1,t2) - objValUnwrap obj2 - -evalMmDom(st) == - -- evals all isDomain(v,d) of st - SL:= NIL - for mmC in st until SL='failed repeat - mmC is ['isDomain,v,d] => - STRINGP d => SL:= 'failed - p:= ASSQ(v,SL) and not (d=CDR p) => SL:= 'failed - d1:= subCopy(d,SL) - CONSP(d1) and MEMQ(v,d1) => SL:= 'failed - SL:= augmentSub(v,d1,SL) - mmC is ['isFreeFunction,v,fun] => - SL:= augmentSub(v,subCopy(fun,SL),SL) - SL - -orderMmCatStack st == - -- tries to reorder stack so that free pattern variables appear - -- as parameters first - null(st) or null rest(st) => st - vars := DELETE_-DUPLICATES [CADR(s) for s in st | isPatternVar(CADR(s))] - null vars => st - havevars := nil - haventvars := nil - for s in st repeat - cat := CADDR s - mem := nil - for v in vars while not mem repeat - if MEMQ(v,cat) then - mem := true - havevars := cons(s,havevars) - if not mem then haventvars := cons(s,haventvars) - null havevars => st - st := nreverse nconc(haventvars,havevars) - SORT(st, function mmCatComp) - -mmCatComp(c1, c2) == - b1 := ASSQ(CADR c1, $Subst) - b2 := ASSQ(CADR c2, $Subst) - b1 and null(b2) => true - false - -evalMmCat(op,sig,stack,SL) == - -- evaluates all ofCategory's of stack as soon as possible - $hope:local:= NIL - numConds:= #stack - stack:= orderMmCatStack [mmC for mmC in stack | EQCAR(mmC,'ofCategory)] - while stack until not makingProgress repeat - st := stack - stack := NIL - makingProgress := NIL - for mmC in st repeat - S:= evalMmCat1(mmC,op, SL) - S='failed and $hope => - stack:= CONS(mmC,stack) - S = 'failed => return S - not atom S => - makingProgress:= 'T - SL:= mergeSubs(S,SL) - if stack or S='failed then 'failed else SL - -evalMmCat1(mmC is ['ofCategory,d,c],op, SL) == - -- evaluates mmC using information from the lisplib - -- d may contain variables, and the substitution list $Subst is used - -- the result is a substitution or failed - $domPvar: local := NIL - $hope:= NIL - NSL:= hasCate(d,c,SL) - NSL='failed and isPatternVar d and $Coerce and ( p:= ASSQ(d,$Subst) ) - and (EQCAR(CDR p,'Variable) or EQCAR(CDR p,'Symbol)) => - RPLACD(p,getSymbolType d) - hasCate(d,c,SL) - NSL='failed and isPatternVar d => - -- following is hack to take care of the case where we have a - -- free substitution variable with a category condition on it. - -- This would arise, for example, where a package has an argument - -- that is not in a needed modemap. After making the following - -- dummy substitutions, the package can be instantiated and the - -- modemap used. RSS 12-22-85 - -- If c is not Set, Ring or Field then the more general mechanism - dom := defaultTypeForCategory(c, SL) - null dom => - op ^= 'coerce => 'failed -- evalMmCatLastChance(d,c,SL) - null (p := ASSQ(d,$Subst)) => - dom => - NSL := [CONS(d,dom)] - op ^= 'coerce => 'failed -- evalMmCatLastChance(d,c,SL) - if containsVars dom then dom := resolveTM(CDR p, dom) - $Coerce and canCoerce(CDR p, dom) => - NSL := [CONS(d,dom)] - op ^= 'coerce => 'failed -- evalMmCatLastChance(d,c,SL) - NSL - -hasCate(dom,cat,SL) == - -- asks whether dom has cat under SL - -- augments substitution SL or returns 'failed - dom = $EmptyMode => NIL - isPatternVar dom => - (p:= ASSQ(dom,SL)) and ((NSL := hasCate(CDR p,cat,SL)) ^= 'failed) => - NSL - (p:= ASSQ(dom,$Subst)) or (p := ASSQ(dom, SL)) => --- S:= hasCate(CDR p,cat,augmentSub(CAR p,CDR p,copy SL)) - S:= hasCate1(CDR p,cat,SL, dom) - not (S='failed) => S - hasCateSpecial(dom,CDR p,cat,SL) - if SL ^= 'failed then $hope:= 'T - 'failed - SL1 := [[v,:d] for [v,:d] in SL | not containsVariables d] - if SL1 then cat := subCopy(cat, SL1) - hasCaty(dom,cat,SL) - -hasCate1(dom, cat, SL, domPvar) == - $domPvar:local := domPvar - hasCate(dom, cat, SL) - -hasCateSpecial(v,dom,cat,SL) == - -- v is a pattern variable, dom it's binding under $Subst - -- tries to change dom, so that it has category cat under SL - -- the result is a substitution list or 'failed - dom is ['FactoredForm,arg] => - if isSubDomain(arg,$Integer) then arg := $Integer - d := ['FactoredRing,arg] - SL:= hasCate(arg,'(Ring),augmentSub(v,d,SL)) - SL = 'failed => 'failed - hasCaty(d,cat,SL) - EQCAR(cat,'Field) or EQCAR(cat, 'DivisionRing) => - if isSubDomain(dom,$Integer) then dom := $Integer - d:= eqType [$QuotientField, dom] - hasCaty(dom,'(IntegralDomain),augmentSub(v,d,SL)) - cat is ['PolynomialCategory, d, :.] => - dom' := ['Polynomial, d] - (containsVars d or canCoerceFrom(dom, dom')) - and hasCaty(dom', cat, augmentSub(v,dom',SL)) - isSubDomain(dom,$Integer) => - NSL:= hasCate($Integer,cat,augmentSub(v,$Integer,SL)) - NSL = 'failed => - hasCateSpecialNew(v, dom, cat, SL) - hasCaty($Integer,cat,NSL) - hasCateSpecialNew(v, dom, cat, SL) - --- to be used in $newSystem only -hasCateSpecialNew(v,dom,cat,SL) == - fe := member(QCAR cat, '(ElementaryFunctionCategory - TrigonometricFunctionCategory ArcTrigonometricFunctionCategory - HyperbolicFunctionCategory ArcHyperbolicFunctionCategory - PrimitiveFunctionCategory SpecialFunctionCategory Evalable - CombinatorialOpsCategory TranscendentalFunctionCategory - AlgebraicallyClosedFunctionSpace ExpressionSpace - LiouvillianFunctionCategory FunctionSpace)) - alg := member(QCAR cat, '(RadicalCategory AlgebraicallyClosedField)) - fefull := fe or alg or EQCAR(cat, 'CombinatorialFunctionCategory) - partialResult := - EQCAR(dom, 'Variable) or EQCAR(dom, 'Symbol) => - CAR(cat) in - '(SemiGroup AbelianSemiGroup Monoid AbelianGroup AbelianMonoid - PartialDifferentialRing Ring InputForm) => - d := ['Polynomial, $Integer] - augmentSub(v, d, SL) - EQCAR(cat, 'Group) => - d := ['Fraction, ['Polynomial, $Integer]] - augmentSub(v, d, SL) - fefull => - d := defaultTargetFE dom - augmentSub(v, d, SL) - 'failed - isEqualOrSubDomain(dom, $Integer) => - fe => - d := defaultTargetFE $Integer - augmentSub(v, d, SL) - alg => - d := '(AlgebraicNumber) - --d := defaultTargetFE $Integer - augmentSub(v, d, SL) - 'failed - underDomainOf dom = $ComplexInteger => - d := defaultTargetFE $ComplexInteger - hasCaty(d,cat,augmentSub(v, d, SL)) - (dom = $RationalNumber) and alg => - d := '(AlgebraicNumber) - --d := defaultTargetFE $Integer - augmentSub(v, d, SL) - fefull => - d := defaultTargetFE dom - augmentSub(v, d, SL) - 'failed - partialResult = 'failed => 'failed - hasCaty(d, cat, partialResult) - -hasCaty(d,cat,SL) == - -- calls hasCat, which looks up a hashtable and returns: - -- 1. T, NIL or a (has x1 x2) condition, if cat is not parameterized - -- 2. a list of pairs (argument to cat,condition) otherwise - -- then the substitution SL is augmented, or the result is 'failed - cat is ['CATEGORY,.,:y] => hasAttSig(d,subCopy(y,constructSubst d),SL) - cat is ['SIGNATURE,foo,sig] => - hasSig(d,foo,subCopy(sig,constructSubst d),SL) - cat is ['ATTRIBUTE,a] => hasAtt(d,subCopy(a,constructSubst d),SL) - x:= hasCat(opOf d,opOf cat) => - y:= KDR cat => - S := constructSubst d - for [z,:cond] in x until not (S1='failed) repeat - S' := [[p, :mkDomPvar(p, d, z, y)] for [p,:d] in S] - if $domPvar then - dom := [CAR d, :[domArg(arg, i, z, y) for i in 0.. - for arg in CDR d]] - SL := augmentSub($domPvar, dom, copy SL) - z' := [domArg2(a, S, S') for a in z] - S1:= unifyStruct(y,z',copy SL) - if not (S1='failed) then S1:= - atom cond => S1 - ncond := subCopy(cond, S) - ncond is ['has, =d, =cat] => 'failed - hasCaty1(ncond,S1) - S1 - atom x => SL - ncond := subCopy(x, constructSubst d) - ncond is ['has, =d, =cat] => 'failed - hasCaty1(ncond, SL) - 'failed - -mkDomPvar(p, d, subs, y) == - l := MEMQ(p, $FormalMapVariableList) => - domArg(d, #$FormalMapVariableList - #l, subs, y) - d - -domArg(type, i, subs, y) == - p := MEMQ($FormalMapVariableList.i, subs) => - y.(#subs - #p) - type - -domArg2(arg, SL1, SL2) == - isSharpVar arg => subCopy(arg, SL1) - arg = '_$ and $domPvar => $domPvar - subCopy(arg, SL2) - -hasCaty1(cond,SL) == - -- cond is either a (has a b) or an OR clause of such conditions - -- SL is augmented, if cond is true, otherwise the result is 'failed - $domPvar: local := NIL - cond is ['has,a,b] => hasCate(a,b,SL) - cond is ['AND,:args] => - for x in args while not (S='failed) repeat S:= - x is ['has,a,b] => hasCate(a,b, SL) - -- next line is for an obscure bug in the table - x is [['has,a,b]] => hasCate(a,b, SL) - --'failed - hasCaty1(x, SL) - S - cond is ['OR,:args] => - for x in args until not (S='failed) repeat S:= - x is ['has,a,b] => hasCate(a,b,copy SL) - -- next line is for an obscure bug in the table - x is [['has,a,b]] => hasCate(a,b,copy SL) - --'failed - hasCaty1(x, copy SL) - S - keyedSystemError("S2GE0016", - ['"hasCaty1",'"unexpected condition from category table"]) - -hasAttSig(d,x,SL) == - -- d is domain, x a list of attributes and signatures - -- the result is an augmented SL, if d has x, 'failed otherwise - for y in x until SL='failed repeat SL:= - y is ['ATTRIBUTE,a] => hasAtt(d,a,SL) - y is ['SIGNATURE,foo,s] => hasSig(d,foo,s,SL) - keyedSystemError("S2GE0016", - ['"hasAttSig",'"unexpected form of unnamed category"]) - SL - -hasSigAnd(andCls, S0, SL) == - dead := NIL - SA := 'failed - for cls in andCls while not dead repeat - SA := - atom cls => copy SL - cls is ['has,a,b] => - hasCate(subCopy(a,S0),subCopy(b,S0),copy SL) - keyedSystemError("S2GE0016", - ['"hasSigAnd",'"unexpected condition for signature"]) - if SA = 'failed then dead := true - SA - -hasSigOr(orCls, S0, SL) == - found := NIL - SA := 'failed - for cls in orCls until found repeat - SA := - atom cls => copy SL - cls is ['has,a,b] => - hasCate(subCopy(a,S0),subCopy(b,S0),copy SL) - cls is ['AND,:andCls] or cls is ['and,:andCls] => - hasSigAnd(andCls, S0, SL) - keyedSystemError("S2GE0016", - ['"hasSigOr",'"unexpected condition for signature"]) - if SA ^= 'failed then found := true - SA - -hasSig(dom,foo,sig,SL) == - -- tests whether domain dom has function foo with signature sig - -- under substitution SL - $domPvar: local := nil - fun:= constructor? CAR dom => - S0:= constructSubst dom - p := ASSQ(foo,getOperationAlistFromLisplib CAR dom) => - for [x,.,cond,.] in CDR p until not (S='failed) repeat - S:= - atom cond => copy SL - cond is ['has,a,b] => - hasCate(subCopy(a,S0),subCopy(b,S0),copy SL) - cond is ['AND,:andCls] or cond is ['and,:andCls] => - hasSigAnd(andCls, S0, SL) - cond is ['OR,:orCls] or cond is ['or,:orCls] => - hasSigOr(orCls, S0, SL) - keyedSystemError("S2GE0016", - ['"hasSig",'"unexpected condition for signature"]) - not (S='failed) => S:= unifyStruct(subCopy(x,S0),sig,S) - S - 'failed - 'failed - -hasAtt(dom,att,SL) == - -- tests whether dom has attribute att under SL - -- needs S0 similar to hasSig above ?? - $domPvar: local := nil - fun:= CAR dom => - atts:= subCopy(GETDATABASE(fun,'ATTRIBUTES),constructSubst dom) => - PAIRP (u := getInfovec CAR dom) => - --UGH! New world has attributes stored as pairs not as lists!! - for [x,:cond] in atts until not (S='failed) repeat - S:= unifyStruct(x,att,copy SL) - not atom cond and not (S='failed) => S := hasCatExpression(cond,S) - S - for [x,cond] in atts until not (S='failed) repeat - S:= unifyStruct(x,att,copy SL) - not atom cond and not (S='failed) => S := hasCatExpression(cond,S) - S - 'failed - 'failed - -hasCatExpression(cond,SL) == - cond is ["OR",:l] => - or/[(y:=hasCatExpression(x,SL)) ^= 'failed for x in l] => y - cond is ["AND",:l] => - and/[(SL:= hasCatExpression(x,SL)) ^= 'failed for x in l] => SL - cond is ["has",a,b] => hasCate(a,b,SL) - keyedSystemError("S2GE0016", - ['"hasSig",'"unexpected condition for attribute"]) - -unifyStruct(s1,s2,SL) == - -- tests for equality of s1 and s2 under substitutions SL and $Subst - -- the result is a substitution list or 'failed - s1=s2 => SL - if s1 is [":",x,.] then s1:= x - if s2 is [":",x,.] then s2:= x - if ^atom s1 and CAR s1 = '_# then s1:= LENGTH CADR s1 - if ^atom s2 and CAR s2 = '_# then s2:= LENGTH CADR s2 - s1=s2 => SL - isPatternVar s1 => unifyStructVar(s1,s2,SL) - isPatternVar s2 => unifyStructVar(s2,s1,SL) - atom s1 or atom s2 => 'failed - until null s1 or null s2 or SL='failed repeat - SL:= unifyStruct(CAR s1,CAR s2,SL) - s1:= CDR s1 - s2:= CDR s2 - s1 or s2 => 'failed - SL - -unifyStructVar(v,s,SL) == - -- the first argument is a pattern variable, which is not substituted - -- by SL - CONTAINED(v,s) => 'failed - ps := LASSOC(s, SL) - s1 := (ps => ps; s) - (s0 := LASSOC(v, SL)) or (s0 := LASSOC(v,$Subst)) => - S:= unifyStruct(s0,s1,copy SL) - S='failed => - $Coerce and not atom s0 and constructor? CAR s0 => - containsVars s0 or containsVars s1 => - ns0 := subCopy(s0, SL) - ns1 := subCopy(s1, SL) - containsVars ns0 or containsVars ns1 => - $hope:= 'T - 'failed - if canCoerce(ns0, ns1) then s3 := s1 - else if canCoerce(ns1, ns0) then s3 := s0 - else s3 := nil - s3 => - if (s3 ^= s0) then SL := augmentSub(v,s3,SL) - if (s3 ^= s1) and isPatternVar(s) then SL := augmentSub(s,s3,SL) - SL - 'failed - $domPvar => - s3 := resolveTT(s0,s1) - s3 => - if (s3 ^= s0) then SL := augmentSub(v,s3,SL) - if (s3 ^= s1) and isPatternVar(s) then SL := augmentSub(s,s3,SL) - SL - 'failed --- isSubDomain(s,s0) => augmentSub(v,s0,SL) - 'failed - 'failed - augmentSub(v,s,S) - augmentSub(v,s,SL) - -ofCategory(dom,cat) == - -- entry point to category evaluation from other points than type - -- analysis - -- the result is true or NIL - $Subst:local:= NIL - $hope:local := NIL - IDENTP dom => NIL - cat is ['Join,:cats] => and/[ofCategory(dom,c) for c in cats] - (hasCaty(dom,cat,NIL) ^= 'failed) - -printMms(mmS) == - -- mmS a list of modemap signatures - sayMSG '" " - for [sig,imp,.] in mmS for i in 1.. repeat - istr := STRCONC('"[",STRINGIMAGE i,'"]") - if QCSIZE(istr) = 3 then istr := STRCONC(istr,'" ") - sayMSG [:bright istr,'"signature: ",:formatSignature CDR sig] - CAR sig='local => - sayMSG ['" implemented: local function ",imp] - imp is ['XLAM,:.] => - sayMSG concat('" implemented: XLAM from ", - prefix2String CAR sig) - sayMSG concat('" implemented: slot ",imp, - '" from ",prefix2String CAR sig) - sayMSG '" " - -containsVars(t) == - -- tests whether term t contains a * variable - atom t => isPatternVar t - containsVars1(t) - -containsVars1(t) == - -- recursive version, which works on a list - [t1,:t2]:= t - atom t1 => - isPatternVar t1 or - atom t2 => isPatternVar t2 - containsVars1(t2) - containsVars1(t1) or - atom t2 => isPatternVar t2 - containsVars1(t2) - -<<isPartialMode>> - -getSymbolType var == --- var is a pattern variable - p:= ASSQ(var,$SymbolType) => CDR p - t:= '(Polynomial (Integer)) - $SymbolType:= CONS(CONS(var,t),$SymbolType) - t - -isEqualOrSubDomain(d1,d2) == - -- last 2 parts are for tagged unions (hack for now, RSS) - (d1=d2) or isSubDomain(d1,d2) or - (atom(d1) and ((d2 is ['Variable,=d1]) or (d2 is [=d1]))) - or (atom(d2) and ((d1 is ['Variable,=d2]) or (d1 is [=d2]))) - -defaultTypeForCategory(cat, SL) == - -- this function returns a domain belonging to cat - -- note that it is important to note that in some contexts one - -- might not want to use this result. For example, evalMmCat1 - -- calls this and should possibly fail in some cases. - cat := subCopy(cat, SL) - c := CAR cat - d := GETDATABASE(c, 'DEFAULTDOMAIN) - d => [d, :CDR cat] - cat is [c] => - c = 'Field => $RationalNumber - c in '(Ring IntegralDomain EuclideanDomain GcdDomain - OrderedRing DifferentialRing) => '(Integer) - c = 'OrderedSet => $Symbol - c = 'FloatingPointSystem => '(Float) - NIL - cat is [c,p1] => - c = 'FiniteLinearAggregate => ['Vector, p1] - c = 'VectorCategory => ['Vector, p1] - c = 'SetAggregate => ['Set, p1] - c = 'SegmentCategory => ['Segment, p1] - NIL - cat is [c,p1,p2] => - NIL - cat is [c,p1,p2,p3] => - cat is ['MatrixCategory, d, ['Vector, =d], ['Vector, =d]] => - ['Matrix, d] - NIL - NIL - - -@ -\eject -\begin{thebibliography}{99} -\bibitem{1} nothing -\end{thebibliography} -\end{document} |