<> <> DIRECTORY Atom USING [ MakeAtom ], BasicTime USING [ Now, nullGMT ], IO, Log, Nice, Rope USING [ Cat, Substr ], SafeStorage USING [ GetCanonicalReferentType, NarrowRefFault, Type, unspecType ], Thrush USING [ Epoch, H, nullHandle, ROPE, ServerProblem, ThHandle], ThNet, ThParty USING [ DescribeParty ], ThPartyPrivate USING [ PartyData, SmartsData ], ThSmartsPrivate USING [ SmartsInfo ], Triples USING [ Any, Erase, Foreach, ForeachProc, Item, Make, Select, SelectCandidate ], TU, Commander USING [ CommandProc, Register ], CommandToolExtras USING [ ArgN ] ; TUImpl: CEDAR MONITOR IMPORTS Atom, BasicTime, IO, Nice, Log, Rope, ThParty, SafeStorage, Thrush, Triples, Commander, CommandToolExtras EXPORTS Thrush, ThNet, TU = { <> epoch: PUBLIC Thrush.Epoch; ePoch: Thrush.Epoch; ServerError: PUBLIC ERROR[code: Thrush.ServerProblem] = CODE; pERROR: PUBLIC ERROR = CODE; pd: PUBLIC REF ThNet.PD _ NEW[ThNet.PD_[ debug: FALSE, encryptionRequested: TRUE, encryptVoice: TRUE ]]; <> ThHandle: TYPE = Thrush.ThHandle; nullHandle: ThHandle = Thrush.nullHandle; ROPE: TYPE = Thrush.ROPE; <> HandleRef: TYPE = REF HandleValue; HandleValue: TYPE = RECORD [ epoch: Thrush.Epoch, type: SafeStorage.Type -- concrete type -- ]; Enhandle: PUBLIC ENTRY PROC[r: REF] RETURNS [Thrush.ThHandle] = TRUSTED { ENABLE UNWIND=>NULL; h: HandleRef; IF r=NIL THEN RETURN[Thrush.nullHandle]; h _ NARROW[Triples.Select[$Handle, r, Triples.Any! SafeStorage.NarrowRefFault=>ERROR HandleFault[LOOPHOLE[h]]]]; IF h=NIL THEN { h _ NEW[HandleValue _ [epoch: ePoch, type: SafeStorage.GetCanonicalReferentType[ref: r]]]; Triples.Make[$Handle, r, h]; }; RETURN[LOOPHOLE[r]]; }; <> <<{ RETURN[LOOPHOLE[r]]; };>> <> <<>> <> <> <> <> Dehandle: PUBLIC ENTRY PROC[h: ThHandle, type: SafeStorage.Type, insist: BOOLEAN] RETURNS [LONG UNSPECIFIED] = { ENABLE UNWIND=>NULL; RETURN[DoDehandle[h, type, insist]]; }; DoDehandle: INTERNAL PROC[h: ThHandle, type: SafeStorage.Type, insist: BOOLEAN] RETURNS [REF] = TRUSTED { r, hrc: REF; hr: HandleRef; NoGood: PROC RETURNS[REF]=TRUSTED{ IF insist THEN ERROR HandleFault[h]; RETURN[NIL]; }; IF h=nullHandle THEN RETURN[NIL]; [r, hrc] _ Triples.SelectCandidate[$Handle, h]; IF hrc=NIL THEN RETURN[NoGood[]]; hr_NARROW[hrc!SafeStorage.NarrowRefFault=>CONTINUE]; IF hr=NIL OR ePoch # hr.epoch OR type#hr.type AND type#SafeStorage.unspecType THEN RETURN[NoGood[]]; RETURN[r]; }; <> KillHandle: PUBLIC ENTRY PROC[h: ThHandle, type: SafeStorage.Type] = TRUSTED { OPEN Triples; ENABLE UNWIND=>NULL; r: REF; hr: HandleRef; IF h=nullHandle THEN RETURN; r _ DoDehandle[h, type, TRUE]; -- blows up if not of correct type. hr _ NARROW[Select[$Handle, r, -- hr--]]; hr.epoch_BasicTime.nullGMT; -- no longer a valid-looking handle. Erase[$Handle, r, hr]; }; HandleFault: PUBLIC ERROR[h: ThHandle] = CODE; <> <<>> MakeUnique: PUBLIC PROC [att, obj, val: Triples.Item] = TRUSTED { Triples.Erase[att, obj, Triples.Any]; Triples.Make[att, obj, val]; }; <> DH: PUBLIC PROC[h: ThHandle] RETURNS [REF] = TRUSTED { RETURN[Dehandle[h, SafeStorage.unspecType, FALSE]]; }; -- for debugging Any: Triples.Item = Triples.Any; gsI: INT_0; World: PUBLIC PROC [o: IO.STREAM] = TRUSTED { OPEN IO; Country: Triples.ForeachProc= TRUSTED { IF trip.att#$iD THEN o.PutF["%g[ %g ] = %g\n", RefAddr[trip.att], RefAddr[trip.obj], RefAddr[trip.val]]; }; gsI_0; Triples.Erase[$iD, Any, Any]; -- from last time! o.PutF["------- World as of %g -------\n", time[]]; Triples.Foreach[Any, Any, Any, Country]; o.PutRope["--------------\n\n"]; }; Show: PUBLIC PROC[o: IO.STREAM, iD: ATOM] = TRUSTED { OPEN IO; obj: REF_Triples.Select[$iD, --obj--, iD]; IF obj=NIL THEN obj_iD; -- assume we want to talk about the id itself. o.PutF["%g (%d):\n %g\n", refAny[iD], card[LOOPHOLE[obj]], refAny[obj]!ANY=>{o.PutRope["...failed...\n"];CONTINUE}]; }; Ref: PUBLIC PROC[iD: ATOM] RETURNS [r: REF] = { OPEN IO; r_Triples.Select[$iD, --obj--, iD]; IF r=NIL THEN r_iD; -- assume we want to talk about the id itself. }; RefFromRope: PUBLIC PROC[iD: ROPE] RETURNS [REF] = { RETURN[Ref[Atom.MakeAtom[iD]]]; }; RefAddr: PUBLIC PROC[r: REF] RETURNS [IO.Value] = TRUSTED { id: ATOM_NIL; IF r=NIL THEN RETURN[IO.refAny[NIL]]; id_NARROW[r!ANY=>CONTINUE]; -- not an atom, get its id. IF id=NIL THEN id_NARROW[Triples.Select[$iD, r, --id--]]; IF id=NIL THEN { id_Gensym[r, 'R]; Triples.Make[$iD, r, id]; }; RETURN [IO.atom[id]]; }; Gensym: PROC[r: REF, c: CHAR] RETURNS [ATOM] = TRUSTED { OPEN IO; symName: ROPE_WITH r SELECT FROM party: ThPartyPrivate.PartyData => Party[party], smarts: ThPartyPrivate.SmartsData => Smarts[smarts], info: ThSmartsPrivate.SmartsInfo => Smarts[info.smarts, "si"], ENDCASE=>NIL; IF symName=NIL THEN symName_IO.PutFR["%c%02d", char[c], int[gsI_gsI+1]]; RETURN[Atom.MakeAtom[symName]]; }; Smarts: PROC[smarts:ThPartyPrivate.SmartsData,qual: ROPE_"sm"]RETURNS[name:ROPE_NIL]= TRUSTED { party: ThPartyPrivate.PartyData _ NARROW[Triples.Select[$VoiceTerminal, Any, smarts]]; IF party#NIL THEN name_Party[party, qual]; RETURN[name]; }; Party: PROC[party: ThPartyPrivate.PartyData, qual: ROPE_"pt"] RETURNS[name: ROPE_NIL] = TRUSTED { OPEN IO; moreQual: ROPE_"."; SELECT party.type FROM trunk => { party _ NARROW[Triples.Select[$TrunkParty, --owner--, party]]; moreQual_".k"; }; recording => name _ IO.PutFR["Rec%02d", int[gsI_gsI+1]]; ENDCASE; IF name=NIL THEN { name_ThParty.DescribeParty[partyID: Thrush.H[party]]; name_name.Substr[len: 3]; }; IF name=NIL THEN RETURN; name_name.Cat[moreQual, qual]; }; <> <<>> WorldCmd: Commander.CommandProc = TRUSTED { World[Log.FindWhere[$Cmd, NIL]]; }; ShowCmd: Commander.CommandProc = TRUSTED { Show[Log.FindWhere[$Cmd, NIL], Atom.MakeAtom[CommandToolExtras.ArgN[cmd,1]]]; }; epoch_BasicTime.Now[]; ePoch _ epoch; Commander.Register["world", WorldCmd, "Print Thrush World"]; Commander.Register["show", ShowCmd, "Describe Item"]; <> Nice.View[pd, "Thrush-wide PD"]; Nice.View[Log.pd, "Log PD"]; }.