<> <> <> DIRECTORY CD, PW, PWDescr, Rope; PWDescrImpl: CEDAR PROGRAM IMPORTS PW, Rope EXPORTS PWDescr = BEGIN OPEN PWDescr; <<>> <<--User-level procs for manipulating descriptors>> <<--Turn a list of ropes in a vanilla descriptor of the appropriate size>> RopesToDescr: PUBLIC PROC [names: LIST OF ROPE, genRef: REF _ NIL] RETURNS [descr: Descriptor] = BEGIN n: INT _ 0; <<-- Size of the list?>> FOR l: LIST OF ROPE _ names, l.rest WHILE l#NIL DO n _ n+1; ENDLOOP; -- Now create the descriptor. . . descr _ NEW[DescriptorRec[n]]; descr.genRef _ genRef; <<-- . . . and precise only the names>> n _ -1; -- just reusing the variable FOR l: LIST OF ROPE _ names, l.rest WHILE l#NIL DO descr[n _ n+1] _ NEW[ItemRec _ [l.first]]; ENDLOOP; END; <<>> <<-- Set the type of an item>> SetTypeBit: PUBLIC PROC [descr: Descriptor, name: ROPE, initVal: BOOL _ FALSE, data: REF _ NIL] = -- data useless??? BEGIN i: INT _ IndexInDescr[descr, name]; descr[i].specificRef _ NEW[BitRec _ [initVal]]; descr[i].data _ data; -- ??? END; SetTypeBool: PUBLIC PROC [descr: Descriptor, name: ROPE, initVal: BOOL _ FALSE, complement: BOOL _ FALSE, data: REF _ NIL] = BEGIN i: INT _ IndexInDescr[descr, name]; descr[i].specificRef _ NEW[BoolRec _ [initVal, IF complement THEN ~initVal ELSE initVal]]; descr[i].data _ data; -- ??? END; SetTypeInt: PUBLIC PROC [descr: Descriptor, name: ROPE, nbBits: INT, initVal: INT _ 0, complement: INT _ 0, data: REF _ NIL] = BEGIN index: INT _ IndexInDescr[descr, name]; intRef: IntRef _ NEW[IntRec[nbBits]]; intRef.val _ initVal MOD PW.TwoToThe[nbBits]; intRef.mask _ complement MOD PW.TwoToThe[nbBits]; <<-- Decompose the integer in a sequence of booleans>> FOR i: INT DECREASING IN [0..nbBits) DO intRef[i] _ NEW[BoolRec _ [ PW.ODD[initVal], IF PW.ODD[complement] THEN ~PW.ODD[initVal] ELSE PW.ODD[initVal]]]; initVal _ initVal/2; -- shift complement _ complement/2; ENDLOOP; descr[index].specificRef _ intRef; descr[index].data _ data; -- ??? END; SetTypePad: PUBLIC PROC [descr: Descriptor, name: ROPE, padRef: PadRef, data: REF _ NIL] = BEGIN i: INT _ IndexInDescr[descr, name]; descr[i].specificRef _ padRef; descr[i].data _ data; END; <<-- Set the value of an item>> SetBit: PUBLIC PROC [descr: Descriptor, name: ROPE, val: BOOL] = BEGIN item: Item _ NameToItem[descr, name]; r: BitRef _ NARROW[item.specificRef]; r.val _ val; END; SetBool: PUBLIC PROC [descr: Descriptor, name: ROPE, val: BOOL, complement: BOOL _ TRUE] = BEGIN item: Item _ NameToItem[descr, name]; r: BoolRef _ NARROW[item.specificRef]; r.val0 _ val; r.val1 _ IF complement THEN ~val ELSE val; END; SetInt: PUBLIC PROC [descr: Descriptor, name: ROPE, val: INT, complement: INT _ allOnes] = BEGIN item: Item _ NameToItem[descr, name]; intRef: IntRef _ NARROW[item.specificRef]; nbBits: INT _ intRef.nbBits; intRef.val _ val MOD PW.TwoToThe[nbBits]; intRef.mask _ complement MOD PW.TwoToThe[nbBits]; FOR i: INT DECREASING IN [0..nbBits) DO -- get low-order intRef[i].val0 _ PW.ODD[val]; intRef[i].val1 _ IF PW.ODD[complement] THEN ~PW.ODD[val] ELSE PW.ODD[val]; val _ val/2; -- shift complement _ complement/2; ENDLOOP; END; <> <> <> <> < boolRef.mask _ PW.ODD[mask];>> < {>> <> <> <> <> <> <> <<};>> < ERROR;>> <> SetData: PUBLIC PROC [descr: Descriptor, name: ROPE, data: REF] = {NameToItem[descr, name].data _ data}; NameToItem: PUBLIC PROC [descr: Descriptor, name: ROPE] RETURNS [item: Item] = {item _ descr[IndexInDescr[descr, name]]}; IsInDescr: PUBLIC PROC [descr: Descriptor, name: ROPE] RETURNS [yes: BOOL] = {yes _ IndexInDescr[descr, name, FALSE]>=0}; <<>> <<-- Enumeration procs (the order matters)>> EnumerateItems: PUBLIC PROC [descr: Descriptor, forEachItemDo: ForEachItemProc] = {FOR i: INT IN [0..descr.size) DO forEachItemDo[descr[i]]; ENDLOOP;}; <<>> <<>> <<-- Internal utilities>> IndexInDescr: PROC [descr: Descriptor, name: ROPE, boundCheck: BOOL _ TRUE] RETURNS [index: INT] = BEGIN index _ -1; FOR i: INT IN [0..descr.size) DO IF Rope.Equal[name, descr[i].name] THEN {index _ i; EXIT}; ENDLOOP; IF index<0 AND boundCheck THEN ERROR; END; END. <<>>