-- JaMArray.mesa -- Written by: John Warnock, March 2, 1979 -- Last changed by Doug Wyatt, December 8, 1980 4:38 PM DIRECTORY JaMArrayDefs, JaMMasterDefs USING [Frame, Object, Stack], JaMControlDefs USING [GetCurrentFrame, NotifyCommand, NotifyStringObject, RegisterIntCommand], JaMExecDefs USING [JaMError], JaMFnsDefs USING [PopInteger, PopObject, PushObject], JaMStackDefs USING [CountStk, MoveStkOps, Pop, Push, Top], JaMTypeChkDefs USING [DescArrayType], JaMVMDefs USING [AllocateWordsVM, GetWordsVM, PutWordsVM]; JaMArray: PROGRAM IMPORTS JaMControlDefs,JaMExecDefs,JaMFnsDefs, JaMStackDefs,JaMTypeChkDefs,JaMVMDefs EXPORTS JaMArrayDefs = BEGIN OPEN JaMArrayDefs,JaMMasterDefs,JaMFnsDefs,JaMVMDefs; Array: PUBLIC PROCEDURE = BEGIN null:Object _ [lit,NullType[]]; i:INTEGER _ PopInteger[]; j:INTEGER _ 0; array:ArrayType Object _ [lit,ArrayType[i,AllocateWordsVM[i*SIZE[Object]]]]; IF i < 0 THEN RangeErr[]; FOR j IN [0..i-1] DO PutWordsVM[array.ArrayPtr + SIZE[Object]*j,@null,SIZE[Object]]; ENDLOOP; PushObject[array]; END; ArrayCopy: PUBLIC PROCEDURE = BEGIN obj: Object; arrayd: ArrayType Object; arrays: ArrayType Object; j,l: INTEGER; arrays _ JaMTypeChkDefs.DescArrayType[PopObject[]]; l_arrays.Length; arrayd_ [arrays.litflag,ArrayType[l,AllocateWordsVM[l*SIZE[Object]]]]; FOR j IN [0..l) DO GetWordsVM[arrays.ArrayPtr+SIZE[Object]*j,@obj,SIZE[Object]]; PutWordsVM[arrayd.ArrayPtr+SIZE[Object]*j,@obj,SIZE[Object]]; ENDLOOP; PushObject[arrayd]; END; ArrayPut: PUBLIC PROCEDURE = BEGIN val:Object _ PopObject[]; i:INTEGER _ PopInteger[]; array:ArrayType Object _ JaMTypeChkDefs.DescArrayType[PopObject[]]; IF i < 0 OR ABS[i] > array.Length - 1 THEN RangeErr[]; PutWordsVM[array.ArrayPtr + SIZE[Object]*i,@val,SIZE[Object]]; END; ArrayGet: PUBLIC PROCEDURE = BEGIN val:Object; i:INTEGER _ PopInteger[]; array:ArrayType Object _ JaMTypeChkDefs.DescArrayType[PopObject[]]; IF i < 0 OR ABS[i] > array.Length - 1 THEN RangeErr[]; GetWordsVM[array.ArrayPtr + SIZE[Object]*i,@val,SIZE[Object]]; PushObject[val]; END; ArrayPart: PUBLIC PROCEDURE = BEGIN i:INTEGER _ PopInteger[]; j:INTEGER _ PopInteger[]; array:ArrayType Object _ JaMTypeChkDefs.DescArrayType[PopObject[]]; IF i < 0 OR j < 0 THEN RangeErr[]; IF ABS[i+j] >= array.Length THEN RangeErr[]; array.ArrayPtr _ array.ArrayPtr + j*SIZE[Object]; array.Length_ i; PushObject[array]; END; ArrayAtom: PUBLIC PROCEDURE [aob:ArrayType Object,stk:JaMMasterDefs.Stack] RETURNS [BOOLEAN] = BEGIN ob:Object; IF aob.Length <= 0 THEN RETURN [FALSE]; GetWordsVM[aob.ArrayPtr,@ob,SIZE[Object]]; aob.ArrayPtr _ aob.ArrayPtr + SIZE[Object]; aob.Length_ aob.Length - 1; JaMStackDefs.Push[aob,stk]; JaMStackDefs.Push[ob,stk]; RETURN [TRUE]; END; ArrayStore: PUBLIC PROCEDURE = -- expects opstk: (ob0, ob1, ... , obn-1, array) array of length n -- returns opstk: (array) BEGIN array: ArrayType Object _ JaMTypeChkDefs.DescArrayType[PopObject[]]; frame: Frame _ JaMControlDefs.GetCurrentFrame[]; val: Object; i: CARDINAL _ array.Length*SIZE[Object]; IF array.Length > JaMStackDefs.CountStk[frame.opstk] THEN JaMExecDefs.JaMError[StkUndFlw,TRUE]; THROUGH [0..array.Length) DO i _ i - SIZE[Object]; val _ PopObject[]; PutWordsVM[array.ArrayPtr + i, @val,SIZE[Object]]; ENDLOOP; JaMStackDefs.Push[array, frame.opstk]; END; ArrayLoad: PUBLIC PROCEDURE = -- expects opstk: (array) array of length n -- returns opstk: (array[0], array[1], ... , array[n-1], array) BEGIN array: ArrayType Object _ JaMTypeChkDefs.DescArrayType[PopObject[]]; frame: Frame _ JaMControlDefs.GetCurrentFrame[]; val: Object; i: CARDINAL; FOR i _ 0, i+SIZE[Object] UNTIL i = array.Length*SIZE[Object] DO GetWordsVM[array.ArrayPtr + i, @val,SIZE[Object]]; PushObject[val]; ENDLOOP; JaMStackDefs.Push[array, frame.opstk]; END; --"ArrayForall" is the "do for each array element" instruction. Two operands are required: -- an Object. The Object is executed for each member of the -- given array. ArrayForall: PUBLIC PROCEDURE = BEGIN OPEN JaMStackDefs; frame:Frame _ JaMControlDefs.GetCurrentFrame[]; ob:Object _ Pop[frame.opstk]; array:ArrayType Object _ JaMTypeChkDefs.DescArrayType[Pop[frame.opstk]]; m:MarkType Object_[nolit,MarkType[]]; Push[m,frame.execstk]; Push[ob,frame.execstk]; Push[array,frame.execstk]; Push[arrayc,frame.execstk]; END; CArrayForall: PUBLIC PROCEDURE = BEGIN OPEN JaMStackDefs; frame:Frame _ JaMControlDefs.GetCurrentFrame[]; array:ArrayType Object _ JaMTypeChkDefs.DescArrayType[Pop[frame.execstk]]; ob:Object _ Top[frame.execstk]; IF ArrayAtom[array,frame.execstk] THEN BEGIN MoveStkOps[frame.execstk,frame.opstk,1]; Push[arrayc,frame.execstk]; Push[ob,frame.execstk]; END ELSE BEGIN []_Pop[frame.execstk]; []_Pop[frame.execstk]; END; END; RangeErr: PROCEDURE = BEGIN JaMExecDefs.JaMError[rangechk,TRUE]; END; arrayc: CommandType Object; StkUndFlw: StringType Object; rangechk:StringType Object; StartArray: PROCEDURE = BEGIN OPEN JaMControlDefs; arrayc _ RegisterIntCommand[CArrayForall]; NotifyStringObject[@StkUndFlw, ".stkundflw"L]; NotifyStringObject[@rangechk, ".rangechk"L]; NotifyCommand[".array"L,Array]; NotifyCommand[".aget"L,ArrayGet]; NotifyCommand[".aput"L,ArrayPut]; NotifyCommand[".subarray"L,ArrayPart]; NotifyCommand[".arrayforall"L,ArrayForall]; NotifyCommand[".astore"L,ArrayStore]; NotifyCommand[".aload"L,ArrayLoad]; NotifyCommand[".acopy"L,ArrayCopy]; END; -- Initialization StartArray; END. DKW March 28, 1980 4:56 PM added StartArray DKW April 1, 1980 2:56 PM now uses NotifyCommand, NotifyStringObject DKW December 8, 1980 12:41 PM cleaned up CArrayForall to reduce stack shuffling (600)\735b5B337b10B442b8B279b8B284b9B330b9B347b10B579b10B648b11B354b13B439b8B66b6B22b9B21b8B21b10B