<> <> <> DIRECTORY PrincOpsUtils USING[LongCOPY], RCMap USING[Base, Index], RCMapOps USING[GetBase], Rope USING[ROPE], RTCommon USING[FetchField], RTTypesBasicPrivate USING [MapTiRcmx], SafeStorage USING[GetReferentType, Type]; RCMapWalkerImpl: PROGRAM IMPORTS RCMapOps, RTCommon, SafeStorage, RTTypesBasicPrivate, PrincOpsUtils EXPORTS RTTypesBasicPrivate = BEGIN OPEN SafeStorage, RTTypesBasicPrivate, RTCommon; NotImplemented: PUBLIC ERROR[msg: Rope.ROPE] = CODE; checking: BOOLEAN = FALSE; rcmb: RCMap.Base = RCMapOps.GetBase[].base; AssignComposite: PUBLIC PROC[rhs, lhs: LONG POINTER, type: Type, nwords: CARDINAL] = {DoAssignComposite[rhs, lhs, type, nwords]}; DoAssignComposite: PROC[rhs, lhs: LONG POINTER, type: Type, nwords: CARDINAL] = INLINE { rcmx: RCMap.Index = MapTiRcmx[type]; IF checking THEN WITH rcmr: rcmb[rcmx] SELECT FROM -- in case there are mutable variants variant => { v1: CARDINAL = FetchField[lhs + rcmr.fdTag.wordOffset, [bitFirst: rcmr.fdTag.bitFirst, bitCount: rcmr.fdTag.bitCount]]; v2: CARDINAL = FetchField[rhs + rcmr.fdTag.wordOffset, [bitFirst: rcmr.fdTag.bitFirst, bitCount: rcmr.fdTag.bitCount]]; IF v1 # v2 THEN ERROR NotImplemented["mutable variant records"]}; sequence => { v1: CARDINAL = FetchField[lhs + rcmr.fdLength.wordOffset, [bitFirst: rcmr.fdLength.bitFirst, bitCount: rcmr.fdLength.bitCount]]; v2: CARDINAL = FetchField[rhs + rcmr.fdLength.wordOffset, [bitFirst: rcmr.fdLength.bitFirst, bitCount: rcmr.fdLength.bitCount]]; IF v1 # v2 THEN ERROR NotImplemented["mutable sequences"]}; ENDCASE; ASSIGNify[rhs, rcmx, LOOPHOLE[lhs, LONG CARDINAL] - LOOPHOLE[rhs, LONG CARDINAL]]; PrincOpsUtils.LongCOPY[from: rhs, to: lhs, nwords: nwords]}; AssignCompositeNew: PUBLIC PROC[rhs, lhs: LONG POINTER, type: Type, nwords: CARDINAL] = { d: LONG CARDINAL = LOOPHOLE[lhs, LONG CARDINAL] - LOOPHOLE[rhs, LONG CARDINAL]; ASSIGNNEWify[rhs, MapTiRcmx[type], d]; PrincOpsUtils.LongCOPY[from: rhs, to: lhs, nwords: nwords]}; FreeCollectibleObject: PUBLIC PROC[refObj: REF ANY] = {NILify[LOOPHOLE[refObj], MapTiRcmx[GetReferentType[refObj]]]}; MapRefs: PUBLIC PROC[ptr: LONG POINTER, rcmx: RCMap.Index, procLeaf: PROC[p: REF ANY]] = {MapComponents[ptr, rcmx, procLeaf]}; DoFREEify: PUBLIC PROC[ptr: LONG POINTER, rcmx: RCMap.Index, procLeaf: PROC[p: REF ANY]] = {INLDoMapComponents[ptr, rcmx, procLeaf]}; MapRefOffsets: PUBLIC PROC[ref: REF ANY, procLeaf: PROC[offset: LONG CARDINAL]] = {DoMapRefOffsets[LOOPHOLE[ref], MapTiRcmx[GetReferentType[ref]], procLeaf]}; DoMapRefOffsets: PROC[ptr: LONG POINTER, rcmx: RCMap.Index, procLeaf: PROC[offset: LONG CARDINAL]] = { WITH rcmr: rcmb[rcmx] SELECT FROM simple => {FOR i: CARDINAL IN [0..rcmr.length) DO IF rcmr.refs[i] THEN procLeaf[i] ENDLOOP}; oneRef => procLeaf[rcmr.offset]; ref => procLeaf[0]; null => NULL; nonVariant => FOR i: CARDINAL IN [0..rcmr.nComponents) DO DoMapRefOffsets[ptr + rcmr.components[i].wordOffset, rcmr.components[i].rcmi, procLeaf]; ENDLOOP; variant => {v: CARDINAL = FetchField[ptr + rcmr.fdTag.wordOffset, [bitFirst: rcmr.fdTag.bitFirst, bitCount: rcmr.fdTag.bitCount]]; IF checking THEN IF v > rcmr.nVariants THEN ERROR; DoMapRefOffsets[ptr, rcmr.variants[v], procLeaf]}; array => FOR i: CARDINAL IN [0..rcmr.nElements) DO DoMapRefOffsets[ptr + i * rcmr.wordsPerElement, rcmr.rcmi, procLeaf]; ENDLOOP; sequence => {length: CARDINAL = FetchField[ptr+rcmr.fdLength.wordOffset, [bitFirst: rcmr.fdLength.bitFirst, bitCount: rcmr.fdLength.bitCount]]; DoMapRefOffsets[ptr, rcmr.commonPart, procLeaf]; FOR i: CARDINAL IN [0..length) DO DoMapRefOffsets[ptr + rcmr.dataOffset + i * rcmr.wordsPerElement, rcmr.rcmi, procLeaf]; ENDLOOP}; ENDCASE => ERROR }; ASSIGNNEWify: PROC[ptr: LONG POINTER, rcmx: RCMap.Index, d: LONG CARDINAL] = INLINE {WITH rcmr: rcmb[rcmx] SELECT FROM simple => { FOR i: CARDINAL IN [0..rcmr.length) DO IF rcmr.refs[i] THEN { LOOPHOLE[ptr+i+d, REF LONG CARDINAL]^ _ 0; LOOPHOLE[ptr+i+d, REF REF ANY]^ _ LOOPHOLE[ptr+i, LONG POINTER TO REF ANY]^}; ENDLOOP}; oneRef => { f: CARDINAL = rcmr.offset; LOOPHOLE[ptr+d+f, REF LONG CARDINAL]^ _ 0; LOOPHOLE[ptr+d+f, REF REF ANY]^ _ LOOPHOLE[ptr+f, LONG POINTER TO REF ANY]^}; ref => { LOOPHOLE[ptr+d, REF LONG CARDINAL]^ _ 0; LOOPHOLE[ptr+d, REF REF ANY]^ _ LOOPHOLE[ptr, LONG POINTER TO REF ANY]^}; null => NULL; ENDCASE => DoASSIGNNEWify[ptr, rcmx, d]}; DoASSIGNNEWify: PROC[ptr: LONG POINTER, rcmx: RCMap.Index, d: LONG CARDINAL] = { WITH rcmr: rcmb[rcmx] SELECT FROM nonVariant => FOR i: CARDINAL IN [0..rcmr.nComponents) DO ASSIGNNEWify[ptr + rcmr.components[i].wordOffset, rcmr.components[i].rcmi, d]; ENDLOOP; variant => {v: CARDINAL = FetchField[ptr + rcmr.fdTag.wordOffset, [bitFirst: rcmr.fdTag.bitFirst, bitCount: rcmr.fdTag.bitCount]]; IF checking THEN IF v > rcmr.nVariants THEN ERROR; ASSIGNNEWify[ptr, rcmr.variants[v], d]}; array => FOR i: CARDINAL IN [0..rcmr.nElements) DO ASSIGNNEWify[ptr + i * rcmr.wordsPerElement, rcmr.rcmi, d]; ENDLOOP; sequence => {length: CARDINAL = FetchField[ptr+rcmr.fdLength.wordOffset, [bitFirst: rcmr.fdLength.bitFirst, bitCount: rcmr.fdLength.bitCount]]; ASSIGNNEWify[ptr, rcmr.commonPart, d]; FOR i: CARDINAL IN [0..length) DO ASSIGNNEWify[ptr + rcmr.dataOffset + i * rcmr.wordsPerElement, rcmr.rcmi, d]; ENDLOOP; }; ENDCASE => ERROR }; ASSIGNify: PROC[ptr: LONG POINTER, rcmx: RCMap.Index, d: LONG CARDINAL] = INLINE { WITH rcmr: rcmb[rcmx] SELECT FROM simple => FOR i: CARDINAL IN [0..rcmr.length) DO IF rcmr.refs[i] THEN LOOPHOLE[ptr+i+d, REF REF ANY]^ _ LOOPHOLE[ptr+i, LONG POINTER TO REF ANY]^; ENDLOOP; oneRef => { f: CARDINAL = rcmr.offset; LOOPHOLE[ptr+d+f, REF REF ANY]^ _ LOOPHOLE[ptr+f, LONG POINTER TO REF ANY]^}; ref => LOOPHOLE[ptr+d, REF REF ANY]^ _ LOOPHOLE[ptr, LONG POINTER TO REF ANY]^; null => NULL; ENDCASE => DoASSIGNify[ptr, rcmx, d]}; DoASSIGNify: PROC[ptr: LONG POINTER, rcmx: RCMap.Index, d: LONG CARDINAL] = { WITH rcmr: rcmb[rcmx] SELECT FROM nonVariant => FOR i: CARDINAL IN [0..rcmr.nComponents) DO ASSIGNify[ptr + rcmr.components[i].wordOffset, rcmr.components[i].rcmi, d]; ENDLOOP; variant => {v: CARDINAL = FetchField[ptr + rcmr.fdTag.wordOffset, [bitFirst: rcmr.fdTag.bitFirst, bitCount: rcmr.fdTag.bitCount]]; IF checking THEN IF v > rcmr.nVariants THEN ERROR; ASSIGNify[ptr, rcmr.variants[v], d]}; array => FOR i: CARDINAL IN [0..rcmr.nElements) DO ASSIGNify[ptr + i * rcmr.wordsPerElement, rcmr.rcmi, d]; ENDLOOP; sequence => {length: CARDINAL = FetchField[ptr+rcmr.fdLength.wordOffset, [bitFirst: rcmr.fdLength.bitFirst, bitCount: rcmr.fdLength.bitCount]]; ASSIGNify[ptr, rcmr.commonPart, d]; FOR i: CARDINAL IN [0..length) DO ASSIGNify[ptr + rcmr.dataOffset + i * rcmr.wordsPerElement, rcmr.rcmi, d]; ENDLOOP}; ENDCASE => ERROR}; NILify: PROC[ptr: LONG POINTER, rcmx: RCMap.Index] = INLINE { WITH rcmr: rcmb[rcmx] SELECT FROM simple => FOR i: CARDINAL IN [0..rcmr.length) DO IF rcmr.refs[i] THEN LOOPHOLE[ptr+i, REF REF ANY]^ _ NIL; ENDLOOP; oneRef => LOOPHOLE[ptr+rcmr.offset, REF REF ANY]^ _ NIL; ref => LOOPHOLE[ptr, REF REF ANY]^ _ NIL; null => NULL; ENDCASE => DoNILify[ptr, rcmx]}; DoNILify: PROC[ptr: LONG POINTER, rcmx: RCMap.Index] = { WITH rcmr: rcmb[rcmx] SELECT FROM nonVariant => FOR i: CARDINAL IN [0..rcmr.nComponents) DO NILify[ptr + rcmr.components[i].wordOffset, rcmr.components[i].rcmi]; ENDLOOP; variant => {v: CARDINAL = FetchField[ptr + rcmr.fdTag.wordOffset, [bitFirst: rcmr.fdTag.bitFirst, bitCount: rcmr.fdTag.bitCount]]; IF checking THEN IF v > rcmr.nVariants THEN ERROR; NILify[ptr, rcmr.variants[v]]}; array => FOR i: CARDINAL IN [0..rcmr.nElements) DO NILify[ptr + i * rcmr.wordsPerElement, rcmr.rcmi]; ENDLOOP; sequence => {length: CARDINAL = FetchField[ptr+rcmr.fdLength.wordOffset, [bitFirst: rcmr.fdLength.bitFirst, bitCount: rcmr.fdLength.bitCount]]; NILify[ptr, rcmr.commonPart]; FOR i: CARDINAL IN [0..length) DO NILify[ptr + rcmr.dataOffset + i * rcmr.wordsPerElement, rcmr.rcmi]; ENDLOOP}; ENDCASE => ERROR}; MapComponents: PROC[ptr: LONG POINTER, rcmx: RCMap.Index, procLeaf: PROC[p: REF ANY]] = INLINE { WITH rcmr: rcmb[rcmx] SELECT FROM simple => FOR i: CARDINAL IN [0..rcmr.length) DO IF rcmr.refs[i] THEN {ref: REF ANY = LOOPHOLE[ptr+i, REF REF ANY]^; IF ref # NIL THEN procLeaf[ref]}; ENDLOOP; oneRef => {ref: REF ANY = LOOPHOLE[ptr+rcmr.offset, REF REF ANY]^; IF ref # NIL THEN procLeaf[ref]}; ref => {ref: REF ANY = LOOPHOLE[ptr, REF REF ANY]^; IF ref # NIL THEN procLeaf[ref]}; null => NULL; ENDCASE => DoMapComponents[ptr, rcmx, procLeaf]}; DoMapComponents: PROC[ptr: LONG POINTER, rcmx: RCMap.Index, procLeaf: PROC[p: REF ANY]] = {INLDoMapComponents[ptr, rcmx, procLeaf]}; INLDoMapComponents: PROC[ptr: LONG POINTER, rcmx: RCMap.Index, procLeaf: PROC[p: REF ANY]] = INLINE {WITH rcmr: rcmb[rcmx] SELECT FROM nonVariant => FOR i: CARDINAL IN [0..rcmr.nComponents) DO MapComponents[ptr + rcmr.components[i].wordOffset, rcmr.components[i].rcmi, procLeaf]; ENDLOOP; variant => {v: CARDINAL = FetchField[ptr + rcmr.fdTag.wordOffset, [bitFirst: rcmr.fdTag.bitFirst, bitCount: rcmr.fdTag.bitCount]]; IF checking THEN IF v > rcmr.nVariants THEN ERROR; MapComponents[ptr, rcmr.variants[v], procLeaf]}; array => FOR i: CARDINAL IN [0..rcmr.nElements) DO MapComponents[ptr + i * rcmr.wordsPerElement, rcmr.rcmi, procLeaf]; ENDLOOP; sequence => {length: CARDINAL = FetchField[ptr+rcmr.fdLength.wordOffset, [bitFirst: rcmr.fdLength.bitFirst, bitCount: rcmr.fdLength.bitCount]]; MapComponents[ptr, rcmr.commonPart, procLeaf]; FOR i: CARDINAL IN [0..length) DO MapComponents[ptr + rcmr.dataOffset + i * rcmr.wordsPerElement, rcmr.rcmi, procLeaf]; ENDLOOP}; ENDCASE => ERROR}; END.