-- Copyright (c) 1991-2002, The Numerical Algorithms Group Ltd. -- All rights reserved. -- Copyright (C) 2007-2008, 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. -- This file contains the constructors for the domains that cannot -- be written in ScratchpadII yet. They are not cached because they -- are very cheap to instantiate. -- SMW and SCM July 86 import '"sys-macros" )package "BOOT" $noCategoryDomains == '(Mode SubDomain) $nonLisplibDomains == APPEND($Primitives,$noCategoryDomains) ++ Category ancestors for Record, Union, Mapping, and Enumeration domains. $commonCategoryAncestors == ['(SetCategory), '(BasicType), '(CoercibleTo (OutputForm))] ++ Default category packages for Record, Union, Mapping and ++ Enumeration domains. $commonCategoryDefaults == ['(SetCategory_&), '(BasicType_&), NIL] --% Record -- Want to eventually have the elts and setelts. -- Record is a macro in BUILDOM LISP. It takes out the colons. isRecord type == type is ["Record",:.] RecordInner args == -- this is old and should be removed wherever it occurs if $evalDomain then sayBrightly '"-->> Whoops! RecordInner called from this code." Record0 VEC2LIST args Record0 args == dom := newShell 10 -- JHD added an extra slot to cache EQUAL methods dom.0 := ["Record", :[["_:", CAR a, devaluate CDR a] for a in args]] dom.1 := [function lookupInTable,dom, [["_=",[[["Boolean"],"_$","_$"],:12]], ["coerce",[[$OutputForm,"_$"],:14]]]] dom.2 := NIL dom.3 := ["RecordCategory",:QCDR dom.0] dom.4 := [$commonCategoryDefaults, $commonCategoryAncestors] dom.5 := [CDR a for a in args] dom.6 := [function RecordEqual, :dom] dom.7 := [function RecordPrint, :dom] dom.8 := [function Undef, :dom] -- following is cache for equality functions dom.9 := if (n:= LENGTH args) <= 2 then [NIL,:NIL] else newShell n dom RecordEqual(x,y,dom) == PAIRP x => b:= SPADCALL(CAR x, CAR y, CAR(dom.9) or CAR RPLACA(dom.9,findEqualFun(dom.5.0))) NULL rest(dom.5) => b b and SPADCALL(CDR x, CDR y, CDR (dom.9) or CDR RPLACD(dom.9,findEqualFun(dom.5.1))) VECP x => equalfuns := dom.9 and/[SPADCALL(x.i,y.i,equalfuns.i or (equalfuns.i:=findEqualFun(fdom))) for i in 0.. for fdom in dom.5] error '"Bug: Silly record representation" RecordPrint(x,dom) == coerceRe2E(x,dom.3) coerceVal2E(x,m) == objValUnwrap coerceByFunction(objNewWrap(x,m),$OutputForm) findEqualFun(dom) == compiledLookup("_=",[$Boolean,"$","$"],dom) coerceRe2E(x,source) == n := # CDR source n = 1 => ["construct", ["_=", source.1.1, coerceVal2E(CAR x,source.1.2)] ] n = 2 => ["construct", ["_=", source.1.1, coerceVal2E(CAR x,source.1.2)], _ ["_=", source.2.1, coerceVal2E(CDR x,source.2.2)] ] VECP x => ['construct, :[["_=",tag,coerceVal2E(x.i, fdom)] for i in 0.. for [.,tag,fdom] in rest source]] error '"Bug: ridiculous record representation" --% Union -- Want to eventually have the coerce to and from branch types. Union(:args) == dom := newShell 9 dom.0 := ["Union", :[(if a is ["_:",tag,domval] then ["_:",tag,devaluate domval] else devaluate a) for a in args]] dom.1 := [function lookupInTable,dom, [["_=",[[["Boolean"],"_$","_$"],:12]], ["coerce",[[$OutputForm,"_$"],:14]]]] dom.2 := NIL dom.3 := ["UnionCategory",:QCDR dom.0] dom.4 := [$commonCategoryDefaults, $commonCategoryAncestors] dom.5 := args dom.6 := [function UnionEqual, :dom] dom.7 := [function UnionPrint, :dom] dom.8 := [function Undef, :dom] dom UnionEqual(x, y, dom) == ["Union",:branches] := dom.0 branches := orderUnionEntries branches predlist := mkPredList branches same := false for b in stripUnionTags branches for p in predlist while not same repeat typeFun := eval ["LAMBDA", '(_#1), p] FUNCALL(typeFun,x) and FUNCALL(typeFun,y) => STRINGP b => same := (x = y) if p is ["EQCAR", :.] then (x := rest x; y := rest y) same := SPADCALL(x, y, findEqualFun(evalDomain b)) same UnionPrint(x, dom) == coerceUn2E(x, dom.0) coerceUn2E(x,source) == ["Union",:branches] := source branches := orderUnionEntries branches predlist := mkPredList branches byGeorge := byJane := GENSYM() for b in stripUnionTags branches for p in predlist repeat typeFun := eval ["LAMBDA", '(_#1), p] if FUNCALL(typeFun,x) then return if p is ["EQCAR", :.] then x := rest x -- STRINGP b => return x -- to catch "failed" etc. STRINGP b => byGeorge := x -- to catch "failed" etc. byGeorge := coerceVal2E(x,b) byGeorge = byJane => error '"Union bug: Cannot find appropriate branch for coerce to E" byGeorge --% Mapping -- Want to eventually have elt: ($, args) -> target Mapping(:args) == dom := newShell 9 dom.0 := ["Mapping", :[devaluate a for a in args]] dom.1 := [function lookupInTable,dom, [["_=",[[["Boolean"],"_$","_$"],:12]], ["coerce",[[$OutputForm,"_$"],:14]]]] dom.2 := NIL dom.3 := '(SetCategory) dom.4 := [$commonCategoryDefaults, $commonCategoryAncestors] dom.5 := args dom.6 := [function MappingEqual, :dom] dom.7 := [function MappingPrint, :dom] dom.8 := [function Undef, :dom] dom MappingEqual(x, y, dom) == EQ(x,y) MappingPrint(x, dom) == coerceMap2E(x) coerceMap2E(x) == -- nrlib domain ARRAYP CDR x => ["theMap", BPINAME CAR x, if $testingSystem then 0 else REMAINDER(HASHEQ CDR x, 1000)] -- aldor ["theMap", BPINAME CAR x ] --% Enumeration Enumeration(:"args") == dom := newShell 9 -- JHD added an extra slot to cache EQUAL methods dom.0 := ["Enumeration", :args] dom.1 := [function lookupInTable,dom, [["_=",[[["Boolean"],"_$","_$"],:12]], ["coerce",[[$OutputForm,"_$"],:14], [["_$", $Symbol], :16]] ]] dom.2 := NIL dom.3 := ["EnumerationCategory",:QCDR dom.0] dom.4 := [$commonCategoryDefaults, $commonCategoryAncestors] dom.5 := args dom.6 := [function EnumEqual, :dom] dom.7 := [function EnumPrint, :dom] dom.8 := [function createEnum, :dom] dom EnumEqual(e1,e2,dom) == e1=e2 EnumPrint(enum, dom) == dom.5.enum createEnum(sym, dom) == args := dom.5 val := -1 for v in args for i in 0.. repeat sym=v => return(val:=i) val<0 => error ["Cannot coerce",sym,"to",["Enumeration",:args]] val --% INSTANTIATORS RecordCategory(:"x") == constructorCategory ["Record",:x] EnumerationCategory(:"x") == constructorCategory ["Enumeration",:x] UnionCategory(:"x") == constructorCategory ["Union",:x] constructorCategory (title is [op,:.]) == constructorFunction:= GETL(op,"makeFunctionList") or systemErrorHere '"constructorCategory" [funlist,.]:= FUNCALL(constructorFunction,"$",title,$CategoryFrame) oplist:= [[[a,b],true,c] for [a,b,c] in funlist] cat:= JoinInner([eval ["SetCategory"],mkCategory("domain",oplist,nil,nil,nil)], $EmptyEnvironment) cat.(0):= title cat --mkMappingFunList(nam,mapForm,e) == [[],e] mkMappingFunList(nam,mapForm,e) == dc := GENSYM() sigFunAlist:= [["_=",[["Boolean"],nam ,nam],["ELT",dc,6]], ["coerce",[$OutputForm,nam],["ELT",dc,7]]] [substitute(nam,dc,substituteDollarIfRepHack sigFunAlist),e] mkRecordFunList(nam,["Record",:Alist],e) == len:= #Alist -- for (.,a,.) in Alist do -- if getmode(a,e) then MOAN("Symbol: ",a, -- " must not be both a variable and literal") -- e:= put(a,"isLiteral","true",e) dc := GENSYM() sigFunAlist:= --:((a,(A,nam),("XLAM",("$1","$2"),("RECORDELT","$1",i,len))) -- for i in 0..,(.,a,A) in Alist), [["construct",[nam,:[A for [.,a,A] in Alist]],"mkRecord"], ["_=",[["Boolean"],nam ,nam],["ELT",dc,6]], ["coerce",[$OutputForm,nam],["ELT",dc,7]],: [["elt",[A,nam,PNAME a],["XLAM",["$1","$2"],["RECORDELT","$1",i,len]]] for i in 0.. for [.,a,A] in Alist],: [["setelt",[A,nam,PNAME a,A],["XLAM",["$1","$2","$3"], ["SETRECORDELT","$1",i, len,"$3"]]] for i in 0.. for [.,a,A] in Alist],: [["copy",[nam,nam],["XLAM",["$1"],["RECORDCOPY", "$1",len]]]]] [substitute(nam,dc,substituteDollarIfRepHack sigFunAlist),e] mkNewUnionFunList(name,form is ["Union",:listOfEntries],e) == dc := name m := dollarIfRepHack name --2. create coercions from subtypes to subUnion cList:= [["_=",[["Boolean"],name ,name],["ELT",dc,6]], ["coerce",[$OutputForm,name],["ELT",dc,7]],: ("append"/ [[["construct",[name,type],["XLAM",["#1"],["CONS",i,"#1"]]], ["elt",[type,name,tag],cdownFun], ["case",['(Boolean),name,tag], ["XLAM",["#1"],["QEQCAR","#1",i]]]] for [.,tag,type] in listOfEntries for i in 0..])] where cdownFun() == gg:=GENSYM() $InteractiveMode => ["XLAM",["#1"],["PROG1",["QCDR","#1"], ["check_-union",["QEQCAR","#1",i],type,"#1"]]] ["XLAM",["#1"],["PROG2",["LET",gg,"#1"],["QCDR",gg], ["check_-union",["QEQCAR",gg,i],type,gg]]] [cList,e] mkEnumerationFunList(nam,["Enumeration",:SL],e) == len:= #SL dc := nam cList := [nil, ["_=",[["Boolean"],nam ,nam],["ELT",dc,6]], ["_^_=",[["Boolean"],nam ,nam],["ELT",dc,7]], ["coerce",[nam, ["Symbol"]], ["ELT", dc, 8]], ["coerce",[["OutputForm"],nam],["ELT",dc, 9]]] [substitute(nam, dc, cList),e] mkUnionFunList(op,form is ["Union",:listOfEntries],e) == first listOfEntries is [":",.,.] => mkNewUnionFunList(op,form,e) -- following call to order is a bug, but needs massive recomp to fix listOfEntries:= orderUnionEntries listOfEntries --1. create representations of subtypes predList:= mkPredList listOfEntries g:=GENSYM() --2. create coercions from subtypes to subUnion cList:= [["_=",[["Boolean"],g ,g],["ELT",op,6]], ["coerce",[$OutputForm,g],["ELT",op,7]],: ("append"/ [[["autoCoerce",[g,t],upFun], ["coerce",[t,g],cdownFun], ["autoCoerce",[t,g],downFun], --this should be removed eventually ["case",['(Boolean),g,t],typeFun]] for p in predList for t in listOfEntries])] where upFun() == p is ["EQCAR",x,n] => ["XLAM",["#1"],["CONS",n,"#1"]] ["XLAM",["#1"],"#1"] cdownFun() == gg:=GENSYM() if p is ["EQCAR",x,n] then ref:=["QCDR",gg] q:= ["QEQCAR", gg, n] else ref:=gg q:= substitute(gg,"#1",p) ["XLAM",["#1"],["PROG2",["LET",gg,"#1"],ref, ["check_-union",q,t,gg]]] downFun() == p is ["EQCAR",x,.] => ["XLAM",["#1"],["QCDR","#1"]] ["XLAM",["#1"],"#1"] typeFun() == p is ["EQCAR",x,n] => ["XLAM",["#1"],["QEQCAR",x,n]] ["XLAM",["#1"],p] cList:= substitute(dollarIfRepHack op,g,cList) [cList,e]