DIRECTORY AMBridge USING [FHFromTV, GetWorld, Loophole, RemoteFHFromTV, TVToLC], AMMiniModel USING [GetInterfaceRecordFromType], AMTypes USING [Argument, Class, Domain, EnclosingBody, Error, GlobalParent, Globals, IndexToDefaultInitialValue, IndexToName, IndexToTV, IndexToType, IsComputed, IsInterface, IsOverlaid, Locals, NameToIndex, NComponents, New, NValues, Procedure, Range, Referent, Result, Signal, Tag, TV, TVSize, TVToType, TVType, TypeClass, UnderClass, UnderType, Variant], InterpreterPrivate USING [], Rope USING [Equal, ROPE, Size], SafeStorage USING [nullType, Type], WorldVM USING [LocalWorld, World]; RecordSearchImpl: CEDAR PROGRAM IMPORTS AMBridge, AMMiniModel, AMTypes, Rope, WorldVM EXPORTS InterpreterPrivate = BEGIN OPEN AMTypes, Rope, SafeStorage; World: TYPE = WorldVM.World; RecordSearch: PUBLIC PROC [record: TV, name: ROPE] RETURNS [tv: TV _ NIL] = TRUSTED { lastFrame: TV _ NIL; -- indicate that we have not encountered any frames DO type: Type; IF record = NIL THEN RETURN[NIL]; type _ AMTypes.UnderType[AMTypes.TVType[record]]; SELECT AMTypes.TypeClass[type] FROM ref, list, pointer, longPointer => {record _ AMTypes.Referent[record]; LOOP}; type => { ENABLE AMTypes.Error => EXIT; typeValue: Type _ AMTypes.TVToType[record]; index: NAT _ AMTypes.NameToIndex[typeValue, name]; IF index = 0 THEN RETURN[NIL] -- no such component ELSE { --There is a component of this name, so try to get its value... world: WorldVM.World = AMBridge.GetWorld[record]; instance: TV _ NIL; IF AMTypes.IsInterface[typeValue] THEN instance _ AMMiniModel.GetInterfaceRecordFromType[typeValue, world ! AMTypes.Error => CONTINUE]; IF instance # NIL THEN tv _ AMTypes.IndexToTV[instance, index] -- use the instance ELSE tv _ AMTypes.IndexToDefaultInitialValue[typeValue, index]; IF tv = NIL THEN { record _ AMTypes.New[type: typeValue, world: world]; tv _ AMTypes.IndexToTV[record, index]; }; IF AMTypes.TVSize[tv] <= 2 AND AMBridge.TVToLC[tv] = 0 THEN { elemType: Type _ AMTypes.IndexToType[typeValue, index]; SELECT AMTypes.UnderClass[elemType] FROM procedure, error, signal, program, port => RETURN[NIL]; ENDCASE; }; RETURN[tv]; }; -- end IF index # 0 THEN }; -- end case type record, structure => { n: NAT _ AMTypes.NComponents[type]; lastType, domain: Type _ nullType; lastClass: Class _ nil; overlaid: BOOL _ FALSE; index: NAT _ 0; IF n = 0 THEN EXIT; {ENABLE AMTypes.Error => GOTO dontWorry; lastType _ AMTypes.IndexToType[type, n]; lastType _ AMTypes.UnderType[lastType]; lastClass _ AMTypes.TypeClass[lastType]; EXITS dontWorry => {} }; IF n = 1 AND AMTypes.IndexToName[type, 1].Size[] = 0 AND lastClass # union THEN {record _ AMTypes.IndexToTV[record, 1]; LOOP}; index _ AMTypes.NameToIndex[type, name ! AMTypes.Error => CONTINUE]; IF index # 0 THEN RETURN[AMTypes.IndexToTV[record, index]]; SELECT lastClass FROM union => { domain _ AMTypes.UnderType[AMTypes.Domain[lastType]]; IF AMTypes.TypeClass[domain] # enumerated THEN RETURN[NIL]; overlaid _ AMTypes.IsOverlaid[lastType] OR AMTypes.IsComputed[lastType]; }; sequence => IF AMTypes.IsComputed[lastType] THEN RETURN[NIL]; ENDCASE => RETURN[NIL]; IF NOT overlaid AND name.Equal[AMTypes.IndexToName[lastType, 0]] THEN RETURN[AMTypes.Tag[AMTypes.IndexToTV[record, n]]]; IF lastClass = sequence THEN RETURN[NIL]; IF overlaid THEN { found: BOOL _ FALSE; FOR armIndex: INT IN [1..AMTypes.NValues[domain]] DO armType: Type _ AMTypes.UnderType[AMTypes.IndexToType[lastType, armIndex ! AMTypes.Error => LOOP]]; tag: TV _ NIL; index: NAT _ 0; index _ AMTypes.NameToIndex[armType, name ! AMTypes.Error => CONTINUE]; IF index # 0 THEN { record _ AMBridge.Loophole[record, armType]; found _ TRUE; EXIT; }; ENDLOOP; IF found THEN LOOP ELSE RETURN[NIL]; } ELSE { record _ AMTypes.Variant[AMTypes.IndexToTV[record, n]]; -- get last element LOOP; }; }; -- end case record, structure globalFrame => {record _ AMTypes.Globals[lastFrame _ record]; LOOP}; localFrame => RETURN[LocalFrameSearch[record, name]]; ENDCASE => RETURN[NIL]; ENDLOOP; RETURN[NIL]; }; -- end RecordSearch SearchArgsAndRtns: PROC [lf: TV, name: ROPE] RETURNS [tv: TV _ NIL] = TRUSTED { procType, recType: Type; class: Class; procTV: TV _ NIL; n: CARDINAL _ 0; index: CARDINAL _ 0; IF AMTypes.UnderClass[AMTypes.TVType[lf]] # localFrame THEN ERROR; procTV _ AMTypes.Procedure[lf ! AMTypes.Error => IF reason = typeFault THEN CONTINUE]; IF procTV = NIL THEN procTV _ AMTypes.Signal[lf]; procType _ AMTypes.UnderType[TVType[procTV]]; class _ AMTypes.TypeClass[procType]; SELECT class FROM procedure, signal, error, program, port => { recType _ AMTypes.UnderType[AMTypes.Domain[procType]]; IF recType # nullType AND (n _ AMTypes.NComponents[recType]) # 0 THEN { index _ AMTypes.NameToIndex[recType, name ! AMTypes.Error => IF reason = badName THEN CONTINUE]; IF index # 0 THEN {tv _ AMTypes.Argument[lf, index]; RETURN}; }; SELECT class FROM procedure, signal => { recType _ AMTypes.UnderType[AMTypes.Range[procType]]; IF recType # nullType AND (n _ AMTypes.NComponents[recType]) # 0 THEN { index _ AMTypes.NameToIndex[recType, name ! AMTypes.Error => IF reason = badName THEN CONTINUE]; IF index # 0 THEN {tv _ AMTypes.Result[lf, index]; RETURN}; }; }; ENDCASE; }; ENDCASE; }; -- end SearchArgsAndRtns LocalFrameSearch: PROC [lf: TV, name: ROPE] RETURNS [tv: TV _ NIL] = TRUSTED { lastFH: TV _ NIL; WHILE lf # NIL DO rec: TV _ NIL; tv _ RecordSearch[AMTypes.Locals[lf], name]; IF tv # NIL THEN RETURN[tv]; rec _ AMTypes.EnclosingBody[lf]; IF rec = NIL THEN { rec _ AMTypes.GlobalParent[lf]; IF rec = NIL THEN EXIT; tv _ RecordSearch[rec, name]; IF tv = NIL THEN EXIT; RETURN[tv]; } ELSE IF NOT EqualLocalFrames[lf, rec] THEN { lastFH _ lf; tv _ SearchArgsAndRtns[lf, name]; IF tv # NIL THEN RETURN[tv]; }; lf _ rec; ENDLOOP; IF NOT EqualLocalFrames[lf, lastFH] THEN RETURN[SearchArgsAndRtns[lf, name]]; }; EqualLocalFrames: PROC [lf1,lf2: TV] RETURNS [BOOL] = TRUSTED { IF lf1 = lf2 THEN RETURN [TRUE]; IF lf1 # NIL AND lf2 # NIL THEN { w1: WorldVM.World _ AMBridge.GetWorld[lf1]; IF w1 # AMBridge.GetWorld[lf2] THEN RETURN [FALSE]; IF w1 = WorldVM.LocalWorld[] THEN RETURN [AMBridge.FHFromTV[lf1] = AMBridge.FHFromTV[lf2]] ELSE RETURN [AMBridge.RemoteFHFromTV[lf1] = AMBridge.RemoteFHFromTV[lf2]]; }; RETURN [FALSE]; }; END. ÀRecordSearchImpl.mesa Russ Atkinson, July 6, 1983 8:56 pm Paul Rovner, October 31, 1983 5:12 pm record represents a tv from which (somehow) one can get to a record type or instance. automatic dereferencing of refs to records If this thing is a type, then we try to get the value associated with its named component. Of course, this only works for record and structure types, but that is good enough. Other classes of type will get an AMTypes.Error somewhere, and we will exit, behaving as though there were no such component. First, try to get an IR using the Runtime Model... There is no instance, so use the default value for the component Last chance: try to instantiate the type and pull out the value this way... This could be an unbound procedure. If so, then we return NIL, which should result in it being undefined. I wish that we could do something else here. This case usually results from not having the implementing module loaded or from not having the interface exported to the top level. We now have a valid TV in hand, so return it... an unnamed record component gets auto-selected IF it is not a union if name does not match this could be a variant record that needs the variant bound maybe want named tag oh, we want the tag! we have to treat overlaid variant records as somewhat funny beasts we found it! force AMTypes to assume the "right" type this routine searches args and rtns for the given frame ... searches the given local frame for the given name. The search will include all levels of variables, including those in statically enclosing local frames and the global frame. ... search all of the enclosing bodies level change! need to search args & rtns ... search arguments and results Ê☚œ™Jšœ#™#Jšœ%™%—J˜šÏk ˜ šœ ˜Jšœ7˜7—Jšœ œ˜/šœ˜ JšœŽœG˜×—Jšœœ˜Jšœœ œ˜Jšœ œ˜#Jšœœ˜"—J˜šÏbœœ˜Jšœ.˜5Jšœ˜Jšœœœ˜(—˜Jšœœ˜˜JšœV™V—šÏn œœœ œœœœœœ˜UJšœ œœÏc3˜Hš˜J˜ Jš œ œœœœ˜!J˜1šœ˜#šœGœ˜MJšœ*™*—˜ Jšœ®™®Jšœœ˜J˜+Jšœœ(˜2š œ œœœ ˜3šœ ?˜GJ˜1Jšœ œœ˜Jšœ2™2Jšœ˜!šœC˜GJšœœ˜—šœ ˜Jšœ* ˜Ašœ;˜?Jšœ@™@——šœœœ˜JšœK™KJšœ4˜4Jšœ&˜&J˜—šœœœ˜=Jšœž™žJšœ7˜7šœ˜(Jšœ+œœ˜7Jšœ˜—J˜—Jšœ/™/Jšœ˜ Jšœ ˜——Jšœ ˜—šœ˜Jšœœ˜#J˜"J˜Jšœ œ˜Jšœœ˜Jšœœœ˜šœœœ ˜(J˜(J˜'J˜(Jšœ˜—Jšœ˜šœœ)œ˜JJšœ)œ˜3JšœC™C—Jšœ:œ˜DJšœ œœ#˜;J™JšœR™Ršœ ˜˜ J˜5Jšœ(œœœ˜;Jšœ(œ˜HJ˜—š œ œœœœ˜=Jšœ™—Jšœœœ˜—šœœ œ-˜@Jšœ™Jšœœ,˜7—Jšœœœœ˜)šœ ˜ šœ˜JšœB™BJšœœœ˜šœ œœ˜4šœ ˜ šœ:˜:Jšœœ˜#——Jšœœœ˜Jšœœ˜šœ)˜)Jšœœ˜—šœ œ˜Jšœ6™6J˜,Jšœœ˜ Jšœ˜J˜—Jšœ˜—Jš œœœœœœ˜$J˜—šœ˜Jšœ8 ˜KJšœ˜J˜——Jšœ ˜!—Jšœ>œ˜DJšœœ!˜5Jšœœœ˜—Jšœ˜—Jšœœ˜ Jšœ ˜—J˜šŸœœœœœœœœ˜OJšœ7™7J˜J˜ Jšœœœ˜Jšœœ˜Jšœœ˜J˜Jšœ5œœ˜BJšœ1œœœ˜VJšœ œœ˜1J˜-J˜$šœ˜˜,J˜6šœœ'˜@šœ˜šœ)˜)Jšœœœœ˜6—Jšœ œ$œ˜=Jšœ˜——šœ˜˜Jšœ5˜5šœœ'˜@šœ˜šœ)˜)Jšœœœœ˜6—Jšœ œ"œ˜;Jšœ˜——J˜—Jšœ˜—J˜—Jšœ˜—Jšœ ˜J˜—šŸœœœœ˜+Jšœœœœ˜"Jšœ´™´Jšœœœ˜Jšœ&™&šœœ˜Jšœœœ˜Jšœ,˜,Jšœœœœ˜Jšœ ˜ šœœœ˜Jšœ˜Jšœœœœ˜Jšœ˜Jšœœœœ˜Jšœ˜ Jšœ˜—šœœœ˜,Jšœ(™(Jšœ ˜ Jšœ!˜!Jš œœœœ˜Jšœ˜—Jšœ ˜ Jšœ˜J˜—Jšœ ™ Jšœœœœ˜MJ˜J˜—š Ÿœœ œœœœ˜?Jšœ œœœ˜ š œœœœœ˜!Jšœ+˜+Jšœœœœ˜3šœ˜Jšœœ2˜=Jšœœ?˜J—J˜—Jšœœ˜J˜J˜—Jšœ˜—˜J˜——…—„(&