-- JaMArrayImpl.mesa -- Last edit by Doug Wyatt, 7-Oct-81 16:57:40 DIRECTORY JaMBasic USING [Object], JaMInternal USING [Frame, Stack], JaMOps USING [CountStack, Equal, Error, Install, InstallReason, MarkLoop, nullOb, Pop, PopArray, PopCardinal, PopDict, Push, PushBoolean, PushInteger, rangechk, RegisterExplicit, RegisterInternal, Top, TryToGet, Underflow, UnmarkLoop], JaMVM USING [AllocArray, CopyArray, GetElem, PutElem], Inline USING [LongMult]; JaMArrayImpl: PROGRAM IMPORTS JaMOps, JaMVM, Inline EXPORTS JaMOps = { OPEN VM:JaMVM, JaMOps, JaMInternal, JaMBasic; -- Constants lengthLimit: CARDINAL = LAST[CARDINAL]; -- maximum length for an array -- GLOBALS arraycmd: command Object; -- Primitives Head: PROC[a: array Object, n: CARDINAL] RETURNS[array Object] = INLINE { IF n<a.length THEN a.length ← n; RETURN[a] }; Tail: PROC[a: array Object, n: CARDINAL] RETURNS[array Object] = INLINE { IF n>a.length THEN n ← a.length; a.length ← a.length - n; a.base ← a.base + Inline.LongMult[n,SIZE[Object]]; RETURN[a] }; -- Array Operations Array: PUBLIC PROC[length: CARDINAL] RETURNS[array Object] = { array: array Object ← VM.AllocArray[length]; RETURN[array]; }; ACopy: PUBLIC PROC[array: array Object, expand: CARDINAL ← 0] RETURNS[array Object] = { oldlen: CARDINAL = array.length; newlen: CARDINAL = oldlen + MIN[expand,lengthLimit-oldlen]; new: array Object ← VM.AllocArray[newlen]; VM.CopyArray[src: array, dst: new]; RETURN[new]; }; SubArray: PUBLIC PROC[array: array Object, beg,len: CARDINAL] RETURNS[array Object] = { IF beg>array.length OR len>(array.length-beg) THEN ERROR Error[rangechk]; RETURN[Head[Tail[array,beg],len]]; }; PutArray: PUBLIC PROC[from: array Object, beg: CARDINAL, into: array Object] = { IF beg>into.length OR from.length>(into.length-beg) THEN ERROR Error[rangechk]; VM.CopyArray[from,Tail[into,beg]]; }; APut: PUBLIC PROC[array: array Object, i: CARDINAL, ob: Object] = { IF i<array.length THEN VM.PutElem[array,i,ob] ELSE ERROR Error[rangechk]; }; AGet: PUBLIC PROC[array: array Object, i: CARDINAL] RETURNS[Object] = { IF i<array.length THEN RETURN[VM.GetElem[array,i]] ELSE ERROR Error[rangechk]; }; AFind: PUBLIC PROC[array: array Object, ob: Object] RETURNS[found: BOOLEAN, i: CARDINAL] = { FOR i: CARDINAL IN[0..array.length) DO elem: Object ← VM.GetElem[array,i]; IF Equal[elem,ob] THEN RETURN[TRUE,i]; ENDLOOP; RETURN[FALSE,0]; }; -- find object in array AAtom: PUBLIC PROC[array: array Object] RETURNS[found: BOOLEAN, atom: Object, rem: array Object] = { IF array.length>0 THEN RETURN[TRUE,VM.GetElem[array,0],Tail[array,1]] ELSE RETURN[FALSE,nullOb,array]; }; -- return first element and remainder of array AStore: PUBLIC PROC[stack: Stack, array: array Object] = { IF CountStack[stack, array.length]<array.length THEN Underflow[stack]; FOR i: CARDINAL DECREASING IN[0..array.length) DO ob: Object ← Pop[stack]; VM.PutElem[array,i,ob]; ENDLOOP; }; -- store all elements into array from stack ALoad: PUBLIC PROC[stack: Stack, array: array Object] = { FOR i: CARDINAL IN[0..array.length) DO ob: Object ← VM.GetElem[array,i]; Push[stack,ob]; ENDLOOP; }; -- push all elements from array onto stack ABind: PUBLIC PROC[array: array Object, dict: dict Object] = { FOR i: CARDINAL IN[0..array.length) DO ob: Object ← VM.GetElem[array,i]; WITH ob:ob SELECT FROM array => ABind[ob,dict]; name => IF ob.tag=X THEN { value: Object; known: BOOLEAN; [known,value] ← TryToGet[dict,ob]; IF known THEN VM.PutElem[array,i,value] }; ENDCASE; ENDLOOP; }; -- bind names in array to values in dict -- Array Intrinsics JArray: PUBLIC PROC[frame: Frame] = { n: CARDINAL ← PopCardinal[frame.opstk,lengthLimit]; array: array Object ← Array[n]; Push[frame.opstk,array]; }; JACopy: PUBLIC PROC[frame: Frame] = { array: array Object ← PopArray[frame.opstk]; acopy: array Object ← ACopy[array]; Push[frame.opstk,acopy]; }; JAPut: PUBLIC PROC[frame: Frame] = { ob: Object ← Pop[frame.opstk]; i: CARDINAL ← PopCardinal[frame.opstk]; array: array Object ← PopArray[frame.opstk]; APut[array,i,ob]; }; JAGet: PUBLIC PROC[frame: Frame] = { i: CARDINAL ← PopCardinal[frame.opstk]; array: array Object ← PopArray[frame.opstk]; ob: Object ← AGet[array,i]; Push[frame.opstk,ob]; }; JSubArray: PUBLIC PROC[frame: Frame] = { len: CARDINAL ← PopCardinal[frame.opstk]; beg: CARDINAL ← PopCardinal[frame.opstk]; array: array Object ← PopArray[frame.opstk]; t: array Object ← SubArray[array,beg,len]; Push[frame.opstk,t]; }; JPutArray: PUBLIC PROC[frame: Frame] = { from: array Object ← PopArray[frame.opstk]; beg: CARDINAL ← PopCardinal[frame.opstk]; into: array Object ← PopArray[frame.opstk]; PutArray[from,beg,into]; Push[frame.opstk,into]; }; JAFind: PUBLIC PROC[frame: Frame] = { ob: Object ← Pop[frame.opstk]; array: array Object ← PopArray[frame.opstk]; known: BOOLEAN; i: CARDINAL; [known,i] ← AFind[array,ob]; IF known THEN PushInteger[frame.opstk,i]; PushBoolean[frame.opstk,known]; }; JAAtom: PUBLIC PROC[frame: Frame] = { array: array Object ← PopArray[frame.opstk]; found: BOOLEAN; atom,rest: Object; [found,atom,rest] ← AAtom[array]; IF found THEN { Push[frame.opstk,rest]; Push[frame.opstk,atom] }; PushBoolean[frame.opstk,found]; }; JAStore: PUBLIC PROC[frame: Frame] = { array: array Object ← PopArray[frame.opstk]; AStore[frame.opstk,array]; Push[frame.opstk,array]; }; JALoad: PUBLIC PROC[frame: Frame] = { array: array Object ← PopArray[frame.opstk]; ALoad[frame.opstk,array]; Push[frame.opstk,array]; }; JABind: PUBLIC PROC[frame: Frame] = { dict: dict Object ← PopDict[frame.opstk]; array: array Object ← PopArray[frame.opstk]; ABind[array,dict]; }; CArrayForall: PROC[frame: Frame] = { array: array Object ← PopArray[frame.execstk]; ob: Object ← Top[frame.execstk]; IF array.length>0 THEN { elem: Object ← VM.GetElem[array,0]; rest: array Object ← Tail[array,1]; Push[frame.execstk,rest]; -- rest of array Push[frame.execstk,arraycmd]; -- this procedure Push[frame.opstk,elem]; -- current array element Push[frame.execstk,ob]; -- object to be executed } ELSE { [] ← Pop[frame.execstk]; -- remove object UnmarkLoop[frame]; -- remove mark }; }; JArrayForAll: PUBLIC PROC[frame: Frame] = { ob: Object ← Pop[frame.opstk]; array: array Object ← PopArray[frame.opstk]; MarkLoop[frame]; -- mark scope of loop Push[frame.execstk,ob]; -- object to be executed for each element Push[frame.execstk,array]; -- array to be enumerated Push[frame.execstk,arraycmd]; -- internal command that does the work }; -- Initialization InstallArray: PROC[why: InstallReason, frame: Frame] = { SELECT why FROM register => { arraycmd ← RegisterInternal["@arrayforall"L, CArrayForall]; RegisterExplicit[frame, ".array"L, JArray]; RegisterExplicit[frame, ".aget"L, JAGet]; RegisterExplicit[frame, ".aput"L, JAPut]; RegisterExplicit[frame, ".subarray"L, JSubArray]; RegisterExplicit[frame, ".putarray"L, JPutArray]; RegisterExplicit[frame, ".arrayforall"L, JArrayForAll]; RegisterExplicit[frame, ".astore"L, JAStore]; RegisterExplicit[frame, ".aload"L, JALoad]; RegisterExplicit[frame, ".acopy"L, JACopy]; RegisterExplicit[frame, ".abind"L, JABind]; RegisterExplicit[frame, ".afind"L, JAFind]; }; ENDCASE; }; Install[InstallArray]; }. Paxton January 7, 1981 5:03 PM added ArraySpread, ArryCopy, Arry, ArryGet, ArryPut Paxton January 23, 1981 2:47 PM added ArrayBind, ArryBind, ArrayFind, ArryFind Wyatt 16-Apr-81 12:46:09 Pilot conversion Wyatt 28-Aug-81 14:45:50 rewrite Wyatt 22-Sep-81 14:46:44 add .putarray