VersionMap2Variable.mesa
Last tweaked by Mike Spreitzer on March 27, 1992 9:04 pm PST
DIRECTORY Card2Tab, Card4Tab, PFSNames, RefTab, Rope, RopeHash, SymTab, VersionMap2, VersionMap2Implr;
VersionMap2Variable: CEDAR PROGRAM
IMPORTS Card2Tab, Card4Tab, PFSNames, RefTab, Rope, RopeHash, SymTab, VersionMap2, VersionMap2Implr
EXPORTS VersionMap2
=
BEGIN OPEN VM2i:VersionMap2Implr, VersionMap2;
VarMap: TYPE ~ REF VarMapPrivate;
VarMapPrivate: TYPE ~ RECORD [
size: INT ← 0,
byName: RefTab.Ref--Name->TupleList--,
byShort: SymTab.Ref-->TupleList--,
byCreated: Card4Tab.Ref-->TupleList--,
byStamp: Card2Tab.Ref-->TupleList--
];
TupleList: TYPE ~ REF TupleCons;
TupleCons: TYPE ~ RECORD [
first: VersionTuple,
rest: ARRAY ListId OF TupleList ← ALL[NIL]];
ListId: TYPE ~ {short, created, stamp};
vapMapClass: MapClass ~ VM2i.FillinDefaults[TRUE, writable, [
Has: VarMapHas,
Scan: VarMapScan,
Size: VarMapSize,
AddTuple: VarMapAddTuple,
AddMap: VM2i.AddMapByTuples,
RemTuple: VarMapRemTuple,
RemMap: VM2i.RemMapByTuples,
data: NIL]];
CreateVariableMap: PUBLIC PROC RETURNS [Map] ~ {
varm: VarMap ~ NEW [VarMapPrivate ← [
size: 0,
byName: RefTab.Create[equal: EqualName, hash: HashName],
byShort: SymTab.Create[case: FALSE],
byCreated: Card4Tab.Create[],
byStamp: Card2Tab.Create[]
]];
RETURN [[class: vapMapClass, data: varm]]};
VarMapHas: PROC [map: Map, elt: VersionTuple] RETURNS [BOOL] ~ {
varm: VarMap ~ NARROW[map.data];
tl: TupleList ~ NARROW[varm.byName.Fetch[elt.name].val];
RETURN [tl#NIL AND elt.created=tl.first.created AND elt.stamp=tl.first.stamp]};
VarMapScan: PROC [map: Map, Consume: TupleConsumer, inOrder: BOOL, pfml: PatternFactoredMapList] RETURNS [MaybeTuple] ~ {
IF inOrder THEN RETURN VM2i.SortScan[map, map.class.Scan, Consume, pfml];
{varm: VarMap ~ NARROW[map.data];
lp: ListAndPattern ~ PickListAndPattern[varm, pfml.pattern];
IF TEqual[lp.p, pfml.pattern] THEN pfml.pattern ← nullTuple;
IF lp.l = alluvem
THEN {
mt: MaybeTuple ← noMaybe;
ScanPerStamp: PROC [key: VersionStamp, val: REF ANY] RETURNS [quit: BOOLFALSE] --Card2Tab.EachPairAction-- ~ {
FOR tl: TupleList ← NARROW[val], tl.rest[stamp] WHILE tl#NIL DO
IF PfmlHas[pfml, tl.first] AND Consume[tl.first]
THEN {mt.it ← tl.first; RETURN [TRUE]};
ENDLOOP;
RETURN [FALSE]};
mt.found ← varm.byStamp.Pairs[ScanPerStamp];
RETURN [mt]}
ELSE {
FOR tl: TupleList ← lp.l, tl.rest[lp.lid] WHILE tl#NIL DO
IF PfmlHas[pfml, tl.first] AND Consume[tl.first] THEN RETURN [[TRUE, tl.first]];
ENDLOOP;
RETURN [noMaybe]};
}};
ListAndPattern: TYPE ~ RECORD [l: TupleList, lid: ListId, p: VersionTuple];
alluvem: TupleList ~ NEW [TupleCons ← [nullTuple]];
allrest: ARRAY ListId OF TupleList ~ alluvem.rest ← ALL[alluvem];
Nobody should ever cdr down alluvem!
PickListAndPattern: PROC [varm: VarMap, pat: VersionTuple] RETURNS [ListAndPattern] ~ {
short: ROPE ~ IF pat.name # nullName THEN ShortName[pat.name] ELSE NIL;
shortL: TupleList ~ IF short # NIL AND short.Find["*"] < 0 THEN NARROW[varm.byShort.Fetch[short].val] ELSE alluvem;
createdL: TupleList ~ IF pat.created # nullCreated THEN NARROW[varm.byCreated.Fetch[CreatedTo4[pat.created]].val] ELSE alluvem;
stampL: TupleList ~ IF pat.stamp # nullStamp THEN NARROW[varm.byStamp.Fetch[pat.stamp].val] ELSE alluvem;
ans12: ListAndPattern ~ SELECT TRUE FROM
shortL=NIL => [shortL, short, ShortNameToPattern[short]],
createdL=NIL => [createdL, created, [created: pat.created]],
shortL=alluvem => [createdL, created, [created: pat.created]],
createdL=alluvem => [shortL, short, ShortNameToPattern[short]],
createdL.rest[created]=NIL => [createdL, created, [created: pat.created]],
shortL.rest[short]=NIL => [shortL, short, ShortNameToPattern[short]],
ENDCASE => [createdL, created, [created: pat.created]];
ans123: ListAndPattern ~ SELECT TRUE FROM
stampL=NIL => [stampL, stamp, [stamp: pat.stamp]],
ans12.l=NIL => ans12,
ans12.l=alluvem => [stampL, stamp, [stamp: pat.stamp]],
stampL=alluvem => ans12,
ans12.l.rest[ans12.lid]=NIL => ans12,
stampL.rest[stamp]=NIL => [stampL, stamp, [stamp: pat.stamp]],
ENDCASE => ans12;
RETURN [ans123]};
VarMapSize: PROC [map: Map, limit: INT] RETURNS [INT] ~ {
varm: VarMap ~ NARROW[map.data];
RETURN [varm.size]};
VarMapAddTuple: PROC [map: Map, t: VersionTuple, if: IfHads] RETURNS [had: Hads] ~ {
varm: VarMap ~ NARROW[map.data];
nl: TupleList ~ NARROW[varm.byName.Fetch[t.name].val];
IF nl=NIL THEN had ← ALL[none]
ELSE had ← [IF t.created=nl.first.created THEN same ELSE different, IF t.stamp=nl.first.stamp THEN same ELSE different];
IF had=ALL[same] THEN RETURN;
IF if[VM2i.OcFromHad[had]] THEN {
short: ROPE ~ ShortName[t.name];
it: TupleList ← nl;
IF nl#NIL THEN {
had2: Hads ~ VarMapRemTuple[map, [t.name, nl.first.created, nl.first.stamp]];
IF had2 # [same, same] THEN ERROR;
it.first ← t}
ELSE it ← NEW [TupleCons ← [t]];
IF NOT varm.byName.Insert[t.name, it] THEN ERROR;
it.rest[short] ← NARROW[varm.byShort.Fetch[short].val];
it.rest[created] ← NARROW[varm.byCreated.Fetch[CreatedTo4[t.created]].val];
it.rest[stamp] ← NARROW[varm.byStamp.Fetch[t.stamp].val];
[] ← varm.byShort.Store[short, it];
[] ← varm.byCreated.Store[CreatedTo4[t.created], it];
[] ← varm.byStamp.Store[t.stamp, it];
varm.size ← varm.size+1};
RETURN};
ListDel: PROC [list, elt: TupleList, lid: ListId] RETURNS [TupleList] ~ {
IF list=elt THEN RETURN [list.rest[lid]];
{cur: TupleList ← list.rest[lid];
prev: TupleList ← list;
DO
IF cur = elt THEN {prev.rest[lid] ← cur.rest[lid]; RETURN [list]};
prev ← cur; cur ← cur.rest[lid];
ENDLOOP}};
VarMapRemTuple: PROC [map: Map, t: VersionTuple] RETURNS [had: Hads] ~ {
varm: VarMap ~ NARROW[map.data];
nl: TupleList ~ NARROW[varm.byName.Fetch[t.name].val];
IF nl=NIL THEN had ← ALL[none]
ELSE had ← [IF t.created=nl.first.created THEN same ELSE different, IF t.stamp=nl.first.stamp THEN same ELSE different];
IF had # ALL[same] THEN RETURN;
IF NOT varm.byName.Delete[t.name] THEN ERROR;
{short: ROPE ~ ShortName[t.name];
[] ← varm.byShort.Store[short, ListDel[NARROW[varm.byShort.Fetch[short].val], nl, short]];
[] ← varm.byCreated.Store[CreatedTo4[t.created], ListDel[NARROW[varm.byCreated.Fetch[CreatedTo4[t.created]].val], nl, created]];
[] ← varm.byStamp.Store[t.stamp, ListDel[NARROW[varm.byStamp.Fetch[t.stamp].val], nl, stamp]];
varm.size ← varm.size - 1;
RETURN}};
EqualName: PROC [key1, key2: REF ANY] RETURNS [BOOL] ~ {
n1: Name ~ NARROW[key1];
n2: Name ~ NARROW[key2];
RETURN n1.Equal[n2]};
HashName: PROC [key: REF ANY] RETURNS [hash: CARDINAL ← 0] ~ {
name: Name ~ NARROW[key];
FOR i: NAT IN [0 .. name.ComponentCount[]) DO
c: PFSNames.Component ~ name.Fetch[i];
cr: ROPE ~ c.ComponentRope[--don't care whether version is included--];
hash ← hash + RopeHash.FromRope[cr, FALSE];
ENDLOOP;
RETURN};
ShortName: PROC [n: Name] RETURNS [ROPE] ~ {
RETURN n.ShortName[].ComponentRope[--must not and does not include version--]};
CreatedTo4: PROC [c: Created] RETURNS [Card4Tab.Key]
~ TRUSTED INLINE {RETURN [LOOPHOLE[c]]};
END.