aboutsummaryrefslogtreecommitdiff
path: root/src/interp/i-intern.boot.pamphlet
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp/i-intern.boot.pamphlet')
-rw-r--r--src/interp/i-intern.boot.pamphlet818
1 files changed, 818 insertions, 0 deletions
diff --git a/src/interp/i-intern.boot.pamphlet b/src/interp/i-intern.boot.pamphlet
new file mode 100644
index 00000000..144aa0e5
--- /dev/null
+++ b/src/interp/i-intern.boot.pamphlet
@@ -0,0 +1,818 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/interp i-intern.boot}
+\author{The Axiom Team}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\begin{verbatim}
+Internal Interpreter Facilities
+
+Vectorized Attributed Trees
+
+The interpreter translates parse forms into vats for analysis.
+These contain a number of slots in each node for information.
+The leaves are now all vectors, though the leaves for basic types
+such as integers and strings used to just be the objects themselves.
+The vectors for the leaves with such constants now have the value
+of $immediateDataSymbol as their name. Their are undoubtably still
+some functions that still check whether a leaf is a constant. Note
+that if it is not a vector it is a subtree.
+
+attributed tree nodes have the following form:
+slot description
+---- -----------------------------------------------------
+ 0 operation name or literal
+ 1 declared mode of variable
+ 2 computed value of subtree from this node
+ 3 modeset: list of single computed mode of subtree
+ 4 prop list for extra things
+
+\end{verbatim}
+\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>>
+
+SETANDFILEQ($useParserSrcPos, NIL)
+SETANDFILEQ($transferParserSrcPos, NIL)
+
+-- Making Trees
+
+mkAtreeNode x ==
+ -- maker of attrib tree node
+ v := MAKE_-VEC 5
+ v.0 := x
+ v
+
+mkAtree x ==
+ -- maker of attrib tree from parser form
+ mkAtree1 mkAtreeExpandMacros x
+
+mkAtreeWithSrcPos(form, posnForm) ==
+ posnForm and $useParserSrcPos => pf2Atree(posnForm)
+ transferSrcPosInfo(posnForm, mkAtree form)
+
+mkAtree1WithSrcPos(form, posnForm) ==
+ transferSrcPosInfo(posnForm, mkAtree1 form)
+
+mkAtreeNodeWithSrcPos(form, posnForm) ==
+ transferSrcPosInfo(posnForm, mkAtreeNode form)
+
+transferSrcPosInfo(pf, atree) ==
+ not (pf and $transferParserSrcPos) => atree
+ pos := pfPosOrNopos(pf)
+ pfNoPosition?(pos) => atree
+
+ -- following is a hack because parser code for getting filename
+ -- seems wrong.
+ fn := lnPlaceOfOrigin poGetLineObject(pos)
+ if NULL fn or fn = '"strings" then fn := '"console"
+
+ putSrcPos(atree, fn, pfSourceText(pf), pfLinePosn(pos), pfCharPosn(pos))
+ atree
+
+mkAtreeExpandMacros x ==
+ -- handle macro expansion. if the macros have args we require that
+ -- we match the correct number of args
+ if x isnt ['MDEF,:.] and x isnt ['DEF,['macro,:.],:.] then
+ atom x and (m := isInterpMacro x) =>
+ [args,:body] := m
+ args => 'doNothing
+ x := body
+ x is [op,:argl] =>
+ op = 'QUOTE => 'doNothing
+ op = 'where and argl is [before,after] =>
+ -- in a where clause, what follows "where" (the "after" parm
+ -- above) might be a local macro, so do not expand the "before"
+ -- part yet
+ x := [op,before,mkAtreeExpandMacros after]
+ argl := [mkAtreeExpandMacros a for a in argl]
+ (m := isInterpMacro op) =>
+ [args,:body] := m
+ #args = #argl =>
+ sl := [[a,:s] for a in args for s in argl]
+ x := SUBLISNQ(sl,body)
+ null args => x := [body,:argl]
+ x := [op,:argl]
+ x := [mkAtreeExpandMacros op,:argl]
+ x
+
+mkAtree1 x ==
+ -- first special handler for making attrib tree
+ null x => throwKeyedMsg("S2IP0005",['"NIL"])
+ VECP x => x
+ atom x =>
+ x in '(noBranch noMapVal) => x
+ x in '(nil true false) => mkAtree2([x],x,NIL)
+ x = '_/throwAway =>
+ -- don't want to actually compute this
+ tree := mkAtree1 '(void)
+ putValue(tree,objNewWrap(voidValue(),$Void))
+ putModeSet(tree,[$Void])
+ tree
+ getBasicMode x =>
+ v := mkAtreeNode $immediateDataSymbol
+ putValue(v,getBasicObject x)
+ v
+ IDENTP x => mkAtreeNode x
+ keyedSystemError("S2II0002",[x])
+ x is [op,:argl] => mkAtree2(x,op,argl)
+ systemErrorHere '"mkAtree1"
+
+-- mkAtree2 and mkAtree3 were created because mkAtree1 got so big
+
+mkAtree2(x,op,argl) ==
+ nargl := #argl
+ (op= '_-) and (nargl = 1) and (INTEGERP CAR argl) =>
+ mkAtree1(MINUS CAR argl)
+ op='_: and argl is [y,z] => [mkAtreeNode 'Declare,:argl]
+ op='COLLECT => [mkAtreeNode op,:transformCollect argl]
+ op= 'break =>
+ argl is [.,val] =>
+ if val = '$NoValue then val := '(void)
+ [mkAtreeNode op,mkAtree1 val]
+ [mkAtreeNode op,mkAtree1 '(void)]
+ op= 'return =>
+ argl is [val] =>
+ if val = '$NoValue then val := '(void)
+ [mkAtreeNode op,mkAtree1 val]
+ [mkAtreeNode op,mkAtree1 '(void)]
+ op='exit => mkAtree1 CADR argl
+ op = 'QUOTE => [mkAtreeNode op,:argl]
+ op='SEGMENT =>
+ argl is [a] => [mkAtreeNode op, mkAtree1 a]
+ z :=
+ null argl.1 => nil
+ mkAtree1 argl.1
+ [mkAtreeNode op, mkAtree1 argl.0,z]
+ op in '(pretend is isnt) =>
+ [mkAtreeNode op,mkAtree1 first argl,:rest argl]
+ op = '_:_: =>
+ [mkAtreeNode 'COERCE,mkAtree1 first argl,CADR argl]
+ x is ['_@, expr, type] =>
+ t := evaluateType unabbrev type
+ t = '(DoubleFloat) and expr is [['_$elt, '(Float), 'float], :args] =>
+ mkAtree1 [['_$elt, '(DoubleFloat), 'float], :args]
+ t = '(DoubleFloat) and INTEGERP expr =>
+ v := mkAtreeNode $immediateDataSymbol
+ putValue(v,getBasicObject float expr)
+ v
+ t = '(Float) and INTEGERP expr =>
+ mkAtree1 ["::", expr, t]
+ typeIsASmallInteger(t) and INTEGERP expr =>
+ mkAtree1 ["::", expr, t]
+ [mkAtreeNode 'TARGET,mkAtree1 expr, type]
+ (op='case) and (nargl = 2) =>
+ [mkAtreeNode 'case,mkAtree1 first argl,unabbrev CADR argl]
+ op='REPEAT => [mkAtreeNode op,:transformREPEAT argl]
+ op='LET and argl is [['construct,:.],rhs] =>
+ [mkAtreeNode 'LET,first argl,mkAtree1 rhs]
+ op='LET and argl is [['_:,a,.],rhs] =>
+ mkAtree1 ['SEQ,first argl,['LET,a,rhs]]
+ op is ['_$elt,D,op1] =>
+ op1 is '_= =>
+ a' := [mkAtreeNode '_=,:[mkAtree1 arg for arg in argl]]
+ [mkAtreeNode 'Dollar,D,a']
+ [mkAtreeNode 'Dollar,D,mkAtree1 [op1,:argl]]
+ op='_$elt =>
+ argl is [D,a] =>
+ INTEGERP a =>
+ a = 0 => mkAtree1 [['_$elt,D,'Zero]]
+ a = 1 => mkAtree1 [['_$elt,D,'One]]
+ t := evaluateType unabbrev [D]
+ typeIsASmallInteger(t) and SINTP a =>
+ v := mkAtreeNode $immediateDataSymbol
+ putValue(v,mkObjWrap(a, t))
+ v
+ mkAtree1 ["*",a,[['_$elt,D,'One]]]
+ [mkAtreeNode 'Dollar,D,mkAtree1 a]
+ keyedSystemError("S2II0003",['"$",argl,
+ '"not qualifying an operator"])
+ mkAtree3(x,op,argl)
+
+mkAtree3(x,op,argl) ==
+ op='REDUCE and argl is [op1,axis,body] =>
+ [mkAtreeNode op,axis,mkAtree1 op1,mkAtree1 body]
+ op='has => [mkAtreeNode op, :argl]
+ op='_| => [mkAtreeNode 'AlgExtension,:[mkAtree1 arg for arg in argl]]
+ op='_= => [mkAtreeNode 'equation,:[mkAtree1 arg for arg in argl]]
+ op='not and argl is [["=",lhs,rhs]] =>
+ [mkAtreeNode 'not,[mkAtreeNode "=",mkAtree1 lhs,mkAtree1 rhs]]
+ op='in and argl is [var ,['SEGMENT,lb,ul]] =>
+ upTest:=
+ null ul => NIL
+ mkLessOrEqual(var,ul)
+ lowTest:=mkLessOrEqual(lb,var)
+ z :=
+ ul => ['and,lowTest,upTest]
+ lowTest
+ mkAtree1 z
+ x is ['IF,p,'noBranch,a] => mkAtree1 ['IF,['not,p],a,'noBranch]
+ x is ['RULEDEF,:.] => [mkAtreeNode 'RULEDEF,:CDR x]
+ x is ['MDEF,sym,junk1,junk2,val] =>
+ -- new macros look like macro f == or macro f(x) ===
+ -- so transform into that format
+ mkAtree1 ['DEF,['macro,sym],junk1,junk2,val]
+ x is ["~=",a,b] => mkAtree1 ['not,["=",a,b]]
+ x is ["+->",funargs,funbody] =>
+ if funbody is [":",body,type] then
+ types := [type]
+ funbody := body
+ else types := [NIL]
+ v := collectDefTypesAndPreds funargs
+ types := [:types,:v.1]
+ [mkAtreeNode 'ADEF,[v.0,types,[NIL for a in types],funbody],
+ if v.2 then v.2 else true, false]
+ x is ['ADEF,arg,:r] =>
+ r := mkAtreeValueOf r
+ v :=
+ null arg => VECTOR(NIL,NIL,NIL)
+ PAIRP arg and rest arg and first arg^= "|" =>
+ collectDefTypesAndPreds ['Tuple,:arg]
+ null rest arg => collectDefTypesAndPreds first arg
+ collectDefTypesAndPreds arg
+ [types,:r'] := r
+ at := [fn(x,y) for x in rest types for y in v.1] where
+ fn(a,b) ==
+ a and b =>
+ if a = b then a
+ else throwMessage '" double declaration of parameter"
+ a or b
+ r := [[first types,:at],:r']
+ [mkAtreeNode 'ADEF,[v.0,:r],if v.2 then v.2 else true,false]
+ x is ['where,before,after] =>
+ [mkAtreeNode 'where,before,mkAtree1 after]
+ x is ['DEF,['macro,form],.,.,body] =>
+ [mkAtreeNode 'MDEF,form,body]
+ x is ['DEF,a,:r] =>
+ r := mkAtreeValueOf r
+ a is [op,:arg] =>
+ v :=
+ null arg => VECTOR(NIL,NIL,NIL)
+ PAIRP arg and rest arg and first arg^= "|" =>
+ collectDefTypesAndPreds ['Tuple,:arg]
+ null rest arg => collectDefTypesAndPreds first arg
+ collectDefTypesAndPreds arg
+ [types,:r'] := r
+ -- see case for ADEF above for defn of fn
+ at := [fn(x,y) for x in rest types for y in v.1]
+ r := [[first types,:at],:r']
+ [mkAtreeNode 'DEF,[[op,:v.0],:r],if v.2 then v.2 else true,false]
+ [mkAtreeNode 'DEF,[a,:r],true,false]
+--x is ['when,y,pred] =>
+-- y isnt ['DEF,a,:r] =>
+-- keyedSystemError("S2II0003",['"when",y,'"improper argument form"])
+-- a is [op,p1,:pr] =>
+-- null pr => mkAtree1 ['DEF,[op,["|",p1,pred]],:r]
+-- mkAtree1 ['DEF,[op,["|",['Tuple,p1,:pr],pred]],:r]
+-- [mkAtreeNode 'DEF, CDR y,pred,false]
+--x is ['otherwise,u] =>
+-- throwMessage '" otherwise is no longer supported."
+ z :=
+ getBasicMode op =>
+ v := mkAtreeNode $immediateDataSymbol
+ putValue(v,getBasicObject op)
+ v
+ atom op => mkAtreeNode op
+ mkAtree1 op
+ [z,:[mkAtree1 y for y in argl]]
+
+collectDefTypesAndPreds args ==
+ -- given an arglist to a DEF-like form, this function returns
+ -- a vector of three things:
+ -- slot 0: just the variables
+ -- slot 1: the type declarations on the variables
+ -- slot 2: a predicate for all arguments
+ pred := types := vars := NIL
+ junk :=
+ IDENTP args =>
+ types := [NIL]
+ vars := [args]
+ args is [":",var,type] =>
+ types := [type]
+ var is ["|",var',p] =>
+ vars := [var']
+ pred := addPred(pred,p) where
+ addPred(old,new) ==
+ null new => old
+ null old => new
+ ['and,old,new]
+ vars := [var]
+ args is ["|",var,p] =>
+ pred := addPred(pred,p)
+ var is [":",var',type] =>
+ types := [type]
+ vars := [var']
+ var is ['Tuple,:.] or var is ["|",:.] =>
+ v := collectDefTypesAndPreds var
+ vars := [:vars,:v.0]
+ types := [:types,:v.1]
+ pred := addPred(pred,v.2)
+ vars := [var]
+ types := [NIL]
+ args is ['Tuple,:args'] =>
+ for a in args' repeat
+ v := collectDefTypesAndPreds a
+ vars := [:vars,first v.0]
+ types := [:types,first v.1]
+ pred := addPred(pred,v.2)
+ types := [NIL]
+ vars := [args]
+ VECTOR(vars,types,pred)
+
+mkAtreeValueOf l ==
+ -- scans for ['valueOf,atom]
+ not CONTAINED('valueOf,l) => l
+ mkAtreeValueOf1 l
+
+mkAtreeValueOf1 l ==
+ null l or atom l or null rest l => l
+ l is ['valueOf,u] and IDENTP u =>
+ v := mkAtreeNode $immediateDataSymbol
+ putValue(v,get(u,'value,$InteractiveFrame) or
+ objNewWrap(u,['Variable,u]))
+ v
+ [mkAtreeValueOf1 x for x in l]
+
+mkLessOrEqual(lhs,rhs) == ['not,['_<,rhs,lhs]]
+
+emptyAtree expr ==
+ -- remove mode, value, and misc. info from attrib tree
+ VECP expr =>
+ $immediateDataSymbol = expr.0 => nil
+ expr.1:= NIL
+ expr.2:= NIL
+ expr.3:= NIL
+ -- kill proplist too?
+ atom expr => nil
+ for e in expr repeat emptyAtree e
+
+unVectorize body ==
+ -- transforms from an atree back into a tree
+ VECP body =>
+ name := getUnname body
+ name ^= $immediateDataSymbol => name
+ objValUnwrap getValue body
+ atom body => body
+ body is [op,:argl] =>
+ newOp:=unVectorize op
+ if newOp = 'SUCHTHAT then newOp := '_|
+ if newOp = 'COERCE then newOp := '_:_:
+ if newOp = 'Dollar then newOp := "$elt"
+ [newOp,:unVectorize argl]
+ systemErrorHere '"unVectorize"
+
+
+-- Stuffing and Getting Info
+
+putAtree(x,prop,val) ==
+ x is [op,:.] =>
+ -- only willing to add property if op is a vector
+ -- otherwise will be pushing to deeply into calling structure
+ if VECP op then putAtree(op,prop,val)
+ x
+ null VECP x => x -- just ignore it
+ n := QLASSQ(prop,'((mode . 1) (value . 2) (modeSet . 3)))
+ => x.n := val
+ x.4 := insertShortAlist(prop,val,x.4)
+ x
+
+getAtree(x,prop) ==
+ x is [op,:.] =>
+ -- only willing to get property if op is a vector
+ -- otherwise will be pushing to deeply into calling structure
+ VECP op => getAtree(op,prop)
+ NIL
+ null VECP x => NIL -- just ignore it
+ n:= QLASSQ(prop,'((mode . 1) (value . 2) (modeSet . 3)))
+ => x.n
+ QLASSQ(prop,x.4)
+
+putTarget(x, targ) ==
+ -- want to put nil modes perhaps to clear old target
+ if targ = $EmptyMode then targ := nil
+ putAtree(x,'target,targ)
+
+getTarget(x) == getAtree(x,'target)
+
+insertShortAlist(prop,val,al) ==
+ pair := QASSQ(prop,al) =>
+ RPLACD(pair,val)
+ al
+ [[prop,:val],:al]
+
+transferPropsToNode(x,t) ==
+ propList := getProplist(x,$env)
+ QLASSQ('Led,propList) or QLASSQ('Nud,propList) => nil
+ node :=
+ VECP t => t
+ first t
+ for prop in '(mode localModemap value name generatedCode)
+ repeat transfer(x,node,prop)
+ where
+ transfer(x,node,prop) ==
+ u := get(x,prop,$env) => putAtree(node,prop,u)
+ (not (x in $localVars)) and (u := get(x,prop,$e)) =>
+ putAtree(node,prop,u)
+ if not getMode(t) and (am := get(x,'automode,$env)) then
+ putModeSet(t,[am])
+ putMode(t,am)
+ t
+
+isLeaf x == atom x --may be a number or a vector
+
+getMode x ==
+ x is [op,:.] => getMode op
+ VECP x => x.1
+ m := getBasicMode x => m
+ keyedSystemError("S2II0001",[x])
+
+putMode(x,y) ==
+ x is [op,:.] => putMode(op,y)
+ null VECP x => keyedSystemError("S2II0001",[x])
+ x.1 := y
+
+getValue x ==
+ VECP x => x.2
+ atom x =>
+ t := getBasicObject x => t
+ keyedSystemError("S2II0001",[x])
+ getValue first x
+
+putValue(x,y) ==
+ x is [op,:.] => putValue(op,y)
+ null VECP x => keyedSystemError("S2II0001",[x])
+ x.2 := y
+
+putValueValue(vec,val) ==
+ putValue(vec,val)
+ vec
+
+getUnnameIfCan x ==
+ VECP x => x.0
+ x is [op,:.] => getUnnameIfCan op
+ atom x => x
+ nil
+
+getUnname x ==
+ x is [op,:.] => getUnname op
+ getUnname1 x
+
+getUnname1 x ==
+ VECP x => x.0
+ null atom x => keyedSystemError("S2II0001",[x])
+ x
+
+computedMode t ==
+ getModeSet t is [m] => m
+ keyedSystemError("S2GE0016",['"computedMode",'"non-singleton modeset"])
+
+putModeSet(x,y) ==
+ x is [op,:.] => putModeSet(op,y)
+ not VECP x => keyedSystemError("S2II0001",[x])
+ x.3 := y
+ y
+
+getModeOrFirstModeSetIfThere x ==
+ x is [op,:.] => getModeOrFirstModeSetIfThere op
+ VECP x =>
+ m := x.1 => m
+ val := x.2 => objMode val
+ y := x.aModeSet =>
+ (y = [$EmptyMode]) and ((m := getMode x) is ['Mapping,:.]) => m
+ first y
+ NIL
+ m := getBasicMode x => m
+ NIL
+
+getModeSet x ==
+ x and PAIRP x => getModeSet first x
+ VECP x =>
+ y:= x.aModeSet =>
+ (y = [$EmptyMode]) and ((m := getMode x) is ['Mapping,:.]) =>
+ [m]
+ y
+ keyedSystemError("S2GE0016",['"getModeSet",'"no mode set"])
+ m:= getBasicMode x => [m]
+ null atom x => getModeSet first x
+ keyedSystemError("S2GE0016",['"getModeSet",
+ '"not an attributed tree"])
+
+getModeSetUseSubdomain x ==
+ x and PAIRP x => getModeSetUseSubdomain first x
+ VECP(x) =>
+ -- don't play subdomain games with retracted args
+ getAtree(x,'retracted) => getModeSet x
+ y := x.aModeSet =>
+ (y = [$EmptyMode]) and ((m := getMode x) is ['Mapping,:.]) =>
+ [m]
+ val := getValue x
+ (x.0 = $immediateDataSymbol) and (y = [$Integer]) =>
+ val := objValUnwrap val
+ m := getBasicMode0(val,true)
+ x.2 := objNewWrap(val,m)
+ x.aModeSet := [m]
+ [m]
+ null val => y
+ isEqualOrSubDomain(objMode(val),$Integer) and
+ INTEGERP(f := objValUnwrap val) =>
+ [getBasicMode0(f,true)]
+ y
+ keyedSystemError("S2GE0016",
+ ['"getModeSetUseSubomain",'"no mode set"])
+ m := getBasicMode0(x,true) => [m]
+ null atom x => getModeSetUseSubdomain first x
+ keyedSystemError("S2GE0016",
+ ['"getModeSetUseSubomain",'"not an attributed tree"])
+
+atree2EvaluatedTree x == atree2Tree1(x,true)
+
+atree2Tree1(x,evalIfTrue) ==
+ (triple := getValue x) and objMode(triple) ^= $EmptyMode =>
+ coerceOrCroak(triple,$OutputForm,$mapName)
+ isLeaf x =>
+ VECP x => x.0
+ x
+ [atree2Tree1(y,evalIfTrue) for y in x]
+
+--% Environment Utilities
+
+-- getValueFromEnvironment(x,mode) ==
+-- $failure ^= (v := getValueFromSpecificEnvironment(x,mode,$env)) => v
+-- $failure ^= (v := getValueFromSpecificEnvironment(x,mode,$e)) => v
+-- throwKeyedMsg("S2IE0001",[x])
+getValueFromEnvironment(x,mode) ==
+ $failure ^= (v := getValueFromSpecificEnvironment(x,mode,$env)) => v
+ $failure ^= (v := getValueFromSpecificEnvironment(x,mode,$e)) => v
+ null(v := coerceInt(objNew(x, ['Variable, x]), mode)) =>
+ throwKeyedMsg("S2IE0001",[x])
+ objValUnwrap v
+
+getValueFromSpecificEnvironment(id,mode,e) ==
+ PAIRP e =>
+ u := get(id,'value,e) =>
+ objMode(u) = $EmptyMode =>
+ systemErrorHere '"getValueFromSpecificEnvironment"
+ v := objValUnwrap u
+ mode isnt ['Mapping,:mapSig] => v
+ v isnt ['MAP,:.] => v
+ v' := coerceInt(u,mode)
+ null v' => throwKeyedMsg("S2IC0002",[objMode u,mode])
+ objValUnwrap v'
+
+ m := get(id,'mode,e) =>
+ -- See if we can make it into declared mode from symbolic form
+ -- For example, (x : P[x] I; x + 1)
+ if isPartialMode(m) then m' := resolveTM(['Variable,id],m)
+ else m' := m
+ m' and
+ (u := coerceInteractive(objNewWrap(id,['Variable,id]),m')) =>
+ objValUnwrap u
+
+ throwKeyedMsg("S2IE0002",[id,m])
+ $failure
+ $failure
+
+addBindingInteractive(var,proplist,e is [[curContour,:.],:.]) ==
+ -- change proplist of var in e destructively
+ u := ASSQ(var,curContour) =>
+ RPLACD(u,proplist)
+ e
+ RPLAC(CAAR e,[[var,:proplist],:curContour])
+ e
+
+augProplistInteractive(proplist,prop,val) ==
+ u := ASSQ(prop,proplist) =>
+ RPLACD(u,val)
+ proplist
+ [[prop,:val],:proplist]
+
+getFlag x == get("--flags--",x,$e)
+
+putFlag(flag,value) ==
+ $e := put ("--flags--", flag, value, $e)
+
+get(x,prop,e) ==
+ $InteractiveMode => get0(x,prop,e)
+ get1(x,prop,e)
+
+get0(x,prop,e) ==
+ null atom x => get(QCAR x,prop,e)
+ u:= QLASSQ(x,CAR QCAR e) => QLASSQ(prop,u)
+ (tail:= CDR QCAR e) and (u:= fastSearchCurrentEnv(x,tail)) =>
+ QLASSQ(prop,u)
+ nil
+
+get1(x,prop,e) ==
+ --this is the old get
+ null atom x => get(QCAR x,prop,e)
+ prop="modemap" and $insideCapsuleFunctionIfTrue=true =>
+ LASSOC("modemap",getProplist(x,$CapsuleModemapFrame))
+ or get2(x,prop,e)
+ LASSOC(prop,getProplist(x,e)) or get2(x,prop,e)
+
+get2(x,prop,e) ==
+ prop="modemap" and constructor? x =>
+ (u := getConstructorModemap(x)) => [u]
+ nil
+ nil
+
+getI(x,prop) == get(x,prop,$InteractiveFrame)
+
+putI(x,prop,val) == ($InteractiveFrame := put(x,prop,val,$InteractiveFrame))
+
+getIProplist x == getProplist(x,$InteractiveFrame)
+
+removeBindingI x ==
+ RPLAC(CAAR $InteractiveFrame,deleteAssocWOC(x,CAAR $InteractiveFrame))
+
+rempropI(x,prop) ==
+ id:=
+ atom x => x
+ first x
+ getI(id,prop) =>
+ recordNewValue(id,prop,NIL)
+ recordOldValue(id,prop,getI(id,prop))
+ $InteractiveFrame:= remprop(id,prop,$InteractiveFrame)
+
+remprop(x,prop,e) ==
+ u:= ASSOC(prop,pl:= getProplist(x,e)) =>
+ e:= addBinding(x,DELASC(first u,pl),e)
+ e
+ e
+
+fastSearchCurrentEnv(x,currentEnv) ==
+ u:= QLASSQ(x,CAR currentEnv) => u
+ while (currentEnv:= QCDR currentEnv) repeat
+ u:= QLASSQ(x,CAR currentEnv) => u
+
+put(x,prop,val,e) ==
+ $InteractiveMode and not EQ(e,$CategoryFrame) =>
+ putIntSymTab(x,prop,val,e)
+ --e must never be $CapsuleModemapFrame
+ null atom x => put(first x,prop,val,e)
+ newProplist:= augProplistOf(x,prop,val,e)
+ prop="modemap" and $insideCapsuleFunctionIfTrue=true =>
+ SAY ["**** modemap PUT on CapsuleModemapFrame: ",val]
+ $CapsuleModemapFrame:=
+ addBinding(x,augProplistOf(x,"modemap",val,$CapsuleModemapFrame),
+ $CapsuleModemapFrame)
+ e
+ addBinding(x,newProplist,e)
+
+putIntSymTab(x,prop,val,e) ==
+ null atom x => putIntSymTab(first x,prop,val,e)
+ pl0 := pl := search(x,e)
+ pl :=
+ null pl => [[prop,:val]]
+ u := ASSQ(prop,pl) =>
+ RPLACD(u,val)
+ pl
+ lp := LASTPAIR pl
+ u := [[prop,:val]]
+ RPLACD(lp,u)
+ pl
+ EQ(pl0,pl) => e
+ addIntSymTabBinding(x,pl,e)
+
+addIntSymTabBinding(var,proplist,e is [[curContour,:.],:.]) ==
+ -- change proplist of var in e destructively
+ u := ASSQ(var,curContour) =>
+ RPLACD(u,proplist)
+ e
+ RPLAC(CAAR e,[[var,:proplist],:curContour])
+ e
+
+
+--% Source and position information
+
+-- In the following, src is a string containing an original input line,
+-- line is the line number of the string within the source file,
+-- and col is the index within src of the start of the form represented
+-- by x. x is a VAT.
+
+putSrcPos(x, file, src, line, col) ==
+ putAtree(x, 'srcAndPos, srcPos_New(file, src, line, col))
+
+getSrcPos(x) == getAtree(x, 'srcAndPos)
+
+srcPosNew(file, src, line, col) == LIST2VEC [file, src, line, col]
+
+srcPosFile(sp) ==
+ if sp then sp.0 else nil
+
+srcPosSource(sp) ==
+ if sp then sp.1 else nil
+
+srcPosLine(sp) ==
+ if sp then sp.2 else nil
+
+srcPosColumn(sp) ==
+ if sp then sp.3 else nil
+
+srcPosDisplay(sp) ==
+ null sp => nil
+ s := STRCONC('"_"", srcPosFile sp, '"_", line ",
+ STRINGIMAGE srcPosLine sp, '": ")
+ sayBrightly [s, srcPosSource sp]
+ col := srcPosColumn sp
+ dots :=
+ col = 0 => '""
+ fillerSpaces(col, '".")
+ sayBrightly [fillerSpaces(#s, '" "), dots, '"^"]
+ true
+
+--% Functions on interpreter objects
+
+-- Interpreter objects used to be called triples because they had the
+-- structure [value, type, environment]. For many years, the environment
+-- was not used, so finally in January, 1990, the structure of objects
+-- was changed to be (type . value). This was chosen because it was the
+-- structure of objects of type Any. Sometimes the values are wrapped
+-- (see the function isWrapped to see what this means physically).
+-- Wrapped values are not actual values belonging to their types. An
+-- unwrapped value must be evaluated to get an actual value. A wrapped
+-- value must be unwrapped before being passed to a library function.
+-- Typically, an unwrapped value in the interpreter consists of LISP
+-- code, e.g., parts of a function that is being constructed.
+-- RSS 1/14/90
+
+-- These are the new structure functions.
+
+mkObj(val, mode) == CONS(mode,val) -- old names
+mkObjWrap(val, mode) == CONS(mode,wrap val)
+mkObjCode(val, mode) == ['CONS, MKQ mode,val ]
+
+objNew(val, mode) == CONS(mode,val) -- new names as of 10/14/93
+objNewWrap(val, mode) == CONS(mode,wrap val)
+objNewCode(val, mode) == ['CONS, MKQ mode,val ]
+objSetVal(obj,val) == RPLACD(obj,val)
+objSetMode(obj,mode) == RPLACA(obj,mode)
+
+objVal obj == CDR obj
+objValUnwrap obj == unwrap CDR obj
+objMode obj == CAR obj
+objEnv obj == $NE
+
+objCodeVal obj == CADDR obj
+objCodeMode obj == CADR obj
+
+
+
+
+--% Library compiler structures needed by the interpreter
+
+-- Tuples and Crosses
+
+asTupleNew(size, listOfElts) == CONS(size, LIST2VEC listOfElts)
+asTupleNew0(listOfElts) == CONS(#listOfElts, LIST2VEC listOfElts)
+
+asTupleNewCode(size, listOfElts) == ["asTupleNew", size, ['LIST, :listOfElts]]
+asTupleNewCode0(listForm) == ["asTupleNew0", listForm]
+
+asTupleSize(at) == CAR at
+asTupleAsVector(at) == CDR at
+asTupleAsList(at) == VEC2LIST asTupleAsVector at
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}