TU.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last modified by D. Swinehart, May 17, 1986 5:18:21 pm PDT
DIRECTORY
BasicTime USING [ Now, nullGMT ],
Commander USING [ CommandProc, Handle, Register ],
CommandTool USING [ DoCommand, NextArgument ],
IO,
Nice,
RefID USING [ Reseal ],
RefTab USING [ Create, Fetch, Ref, Store ],
Rope USING [ Cat, ROPE ],
SafeStorage USING [ GetCanonicalReferentType, NarrowRefFault, Type, unspecType ],
Thrush USING [ Epoch, nullHandle, ThHandle ],
ThNet,
ThParty USING [ DescribeParty ],
ThPartyPrivate USING [ PartyData, SmartsData ],
ThSmartsPrivate USING [ SmartsInfo ],
Triples
USING [
Any, Erase, Foreach, ForeachProc, Item, Make, Select, SelectCandidate ],
TU,
VoiceUtils USING [ MakeAtom, pd ]
;
TUImpl:
CEDAR
MONITOR
IMPORTS
BasicTime,
Commander,
CommandTool,
IO,
Nice,
RefID,
RefTab,
Rope,
SafeStorage,
ThParty,
Triples,
VoiceUtils
EXPORTS Thrush, ThNet, TU = {
Obligatory concrete
epoch: PUBLIC Thrush.Epoch;
ePoch: Thrush.Epoch;
pERROR: PUBLIC ERROR = CODE;
gsI: INT𡤀
nameToValueTab: RefTab.Ref;
valueToNameTab: RefTab.Ref;
pd:
PUBLIC
REF ThNet.
PD ←
NEW[ThNet.
PD←[
debug: FALSE,
encryptionRequested: TRUE,
encryptVoice: TRUE
]];
Copies
ThHandle: TYPE = Thrush.ThHandle;
nullHandle: ThHandle = Thrush.nullHandle;
ROPE: TYPE = Rope.ROPE;
ThHandle types and procedures
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]]; };
Rehandle, H: PUBLIC PROC[r: REF] RETURNS [ThHandle] = INLINE
{ RETURN[LOOPHOLE[r]]; };
Can be used if one obtained r from Dehandle, or knows it was obtained that way. The next Dehandle will check the handle's validity again.
Validates type if not RTTypesBasic.unspecType, then returns REF as unspecified.
Virtually any Handle value may be supplied to this procedure without breaking the
RTTypes system!! Handles that are or were once valid are preferred!
Fails with ERROR if insist is TRUE, else by returning NIL.
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 makes the handle invalid, but does not eliminate it. PurgeHandle does that.
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.epochsicTime.nullGMT; -- no longer a valid-looking handle.
Erase[$Handle, r, hr]; };
HandleFault: PUBLIC ERROR[h: ThHandle] = CODE;
Miscellaneous routines
MakeUnique:
PUBLIC
PROC [att, obj, val: Triples.Item] = {
Triples.Erase[att, obj, Triples.Any];
Triples.Make[att, obj, val]; };
Procedures for debugging only
Any: Triples.Item = Triples.Any;
AllAbout:
PROC [cmd: Commander.Handle, subject:
ROPE] = {
OPEN IO;
o: IO.STREAM = cmd.out;
iD: REF ← RefFromRope[subject];
Country: Triples.ForeachProc= {
o.PutF["%g[ %g ] = %g\n", RefAddr[trip.att], RefAddr[trip.obj], RefAddr[trip.val]];
Triples.Foreach[Any, trip.val, Any, Country];
};
Triples.Foreach[iD, Any, Any, Country];
Triples.Foreach[Any, iD, Any, Country];
Triples.Foreach[Any, Any, iD, Country];
o.PutRope["--------------\n\n"]; };
Show:
PROC[cmd: Commander.Handle, iD:
ROPE, name:
ROPE←
NIL] =
TRUSTED {
OPEN IO;
[]𡤌ommandTool.DoCommand[
IO.PutFR["← &%g ← TU.RefFromRope[""%g""]",
rope[IF name#NIL THEN name ELSE "v"], rope[iD]], cmd];
Ref:
PUBLIC PROC[iD:
ATOM]
RETURNS [r:
REF] = {
OPEN IO;
r←nameToValueTab.Fetch[iD].val;
IF r=NIL THEN r←iD; -- assume we want to talk about the id itself.
RefFromRope:
PUBLIC
PROC[iD:
ROPE]
RETURNS [
REF] = {
RETURN[Ref[VoiceUtils.MakeAtom[iD, TRUE]]];
};
RefAddr:
PUBLIC
PROC[r:
REF]
RETURNS [
IO.Value] = {
id: ATOM←NIL;
IF r=NIL THEN RETURN[IO.refAny[NIL]];
id ← NARROW[r!SafeStorage.NarrowRefFault => CONTINUE];
IF id=NIL THEN id←NARROW[valueToNameTab.Fetch[r].val];
IF id=
NIL
THEN {
id←Gensym[r, 'R];
[]←nameToValueTab.Store[id, r];
[]←valueToNameTab.Store[r, id];
};
RETURN [IO.atom[id]]; };
NewNames:
PROC = {
gsI𡤀
nameToValueTab ← RefTab.Create[113];
valueToNameTab ← RefTab.Create[113];
};
Gensym:
PROC[r:
REF, c:
CHAR]
RETURNS [
ATOM] = {
OPEN IO;
symName:
ROPE←
WITH r
SELECT
FROM
ref: RefTab.Ref => "abcde",
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[VoiceUtils.MakeAtom[symName]];
};
Smarts:
PROC[smarts:ThPartyPrivate.SmartsData,qual:
ROPE←"sm"]
RETURNS[name:
ROPE←
NIL]=
{
party: ThPartyPrivate.PartyData ← NARROW[Triples.Select[$Smarts, Any, smarts]];
IF party#NIL THEN name←Party[party, qual];
RETURN[name];
};
Party:
PROC[party: ThPartyPrivate.PartyData, qual:
ROPE←"pt"]
RETURNS[name:
ROPE←
NIL] = {
OPEN IO;
moreQual: ROPE←".";
SELECT party.type
FROM
$trunk => {
name ←
ThParty.DescribeParty[partyID: RefID.Reseal[party]].description;
moreQual←".k";
};
$service => name ← IO.PutFR["Srv%02d(%g)", int[gsI←gsI+1], rope[party.serviceName]];
ENDCASE => {
name←ThParty.DescribeParty[
partyID: RefID.Reseal[party]].description;
IF party.type=$individual THEN qual ← Rope.Cat["i", qual];
};
IF name=NIL THEN RETURN;
name←name.Cat[moreQual, qual];
};
Initialization
AllAboutCmd: Commander.CommandProc = {
AllAbout[cmd, CommandTool.NextArgument[cmd]];
};
WorldClear: Commander.CommandProc = {
NewNames[];
};
ShowCmd: Commander.CommandProc = {
Show[cmd, CommandTool.NextArgument[cmd], CommandTool.NextArgument[cmd]];
};
Debugging nonsense
ViewCmd: Commander.CommandProc = {
Nice.View[pd, "Thrush-wide PD"];
Nice.View[VoiceUtils.pd, "Log PD"];
};
epochsicTime.Now[];
ePoch ← epoch;
NewNames[];
Commander.Register["AllAbout", AllAboutCmd, "Print Thrush World relating to atom or invented name"];
Commander.Register["Show", ShowCmd, "Show <spec> [<name>] sets &v or &<name> to the value of <spec>, which is an atom or an invented name"];
Commander.Register["WorldClear", WorldClear, "Forget invented names"];
Commander.Register["VuThrush", ViewCmd, "Program Management variables for Thrush and VoiceUtils"];
}.
Swinehart, May 16, 1985 9:14:29 am PDT
Cedar 6.0
changes to: DIRECTORY (CommandToolExtras => ...Tool), TUImpl, ShowCmd