oblist.red 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. %
  2. % OBLIST.RED - Intern, RemOb and friends
  3. %
  4. % Author: Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 27 August 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % <PSL.INTERP>OBLIST.RED.9, 15-Sep-82 09:35:25, Edit by BENSON
  12. % InternP accepts a string as well as a symbol
  13. % CopyString and CopyStringToFrom are found in COPIERS.RED
  14. CompileTime flag('(AddToObList LookupOrAddToObList InObList
  15. InitNewID GenSym1),
  16. 'InternalFunction);
  17. on SysLisp;
  18. internal WConst DeletedSlotValue = -1,
  19. EmptySlotValue = 0;
  20. CompileTime <<
  21. syslsp smacro procedure DeletedSlot U;
  22. ObArray U eq DeletedSlotValue;
  23. syslsp smacro procedure EmptySlot U;
  24. ObArray U eq EmptySlotValue;
  25. syslsp smacro procedure NextSlot H;
  26. if H eq MaxObArray then 0 else H + 1;
  27. % StringEqual found in EQUAL.RED
  28. syslsp smacro procedure EqualObArrayEntry(ObArrayIndex, S);
  29. StringEqual(SymNam ObArray ObArrayIndex, S);
  30. >>;
  31. syslsp procedure AddToObList U;
  32. %
  33. % U is an ID, which is added to the oblist if an ID with the same
  34. % print name is not already there. The interned ID is returned.
  35. %
  36. begin scalar V, W, X, Y;
  37. W := IDInf U;
  38. U := StrInf SymNam W;
  39. Y := StrLen U;
  40. if Y < 0 then return StdError '"The null string cannot be interned";
  41. if Y eq 0 then return MkID StrByt(U, 0);
  42. return if OccupiedSlot(V := InObList U) then MkID ObArray V
  43. else
  44. << ObArray V := W;
  45. X := GtConstSTR Y;
  46. CopyStringToFrom(X, U);
  47. SymNam W := MkSTR X;
  48. MkID W >>;
  49. end;
  50. syslsp procedure LookupOrAddToObList U;
  51. %
  52. % U is a String, which IS copied if it is not found on the ObList
  53. % The interned ID with U as print name is returned
  54. %
  55. begin scalar V, W, X, Y;
  56. U := StrInf U;
  57. Y := StrLen U;
  58. if Y < 0 then return StdError '"The null string cannot be interned";
  59. if Y eq 0 then return MkID StrByt(U, 0);
  60. return if OccupiedSlot(V := InObList U) then MkID ObArray V
  61. else
  62. << W := GtID(); % allocate a new ID
  63. ObArray V := W; % plant it in the Oblist
  64. X := GtConstSTR Y; % allocate a string from uncollected
  65. CopyStringToFrom(X, StrInf U); % space
  66. InitNewID(W, MkSTR X) >>;
  67. end;
  68. syslsp procedure NewID S; %. Allocate un-interned ID with print name S
  69. InitNewID(GtID(), S); % Doesn't copy S
  70. syslsp procedure InitNewID(U, V); % Initialize cells of an ID to defaults
  71. << SymNam U := V;
  72. U := MkID U;
  73. MakeUnBound U;
  74. SetProp(U, NIL);
  75. MakeFUnBound U;
  76. U >>;
  77. syslsp procedure HashFunction S; % Compute hash function of string
  78. begin scalar Len, HashVal; % Fold together a bunch of bits
  79. S := StrInf S;
  80. HashVal := 0; % from the first BitsPerWord - 8
  81. Len := StrLen S; % chars of the string
  82. if Len > BitsPerWord - 8 then Len := BitsPerWord - 8;
  83. for I := 0 step 1 until Len do
  84. HashVal := LXOR(HashVal, LSH(StrByt(S, I), (BitsPerWord - 8) - I));
  85. return MOD(HashVal, MaxObArray);
  86. end;
  87. syslsp procedure InObList U; % U is a string. Returns an ObArray pointer
  88. begin scalar H, DSlot, WalkObArray;
  89. H := HashFunction U;
  90. WalkObArray := H;
  91. DSlot := -1;
  92. Loop:
  93. if EmptySlot WalkObArray then return
  94. if DSlot neq -1 then
  95. DSlot
  96. else
  97. WalkObArray
  98. else if DeletedSlot WalkObArray and DSlot eq -1 then
  99. DSlot := WalkObArray
  100. else if EqualObArrayEntry(WalkObArray, U) then return
  101. WalkObArray;
  102. WalkObArray := NextSlot WalkObArray;
  103. if WalkObArray eq H then FatalError "Oblist overflow";
  104. goto Loop;
  105. end;
  106. syslsp procedure Intern U; %. Add U to ObList
  107. %
  108. % U is a string or uninterned ID
  109. %
  110. if IDP U then
  111. AddToObList U
  112. else if StringP U then
  113. LookupOrAddToObList U
  114. else
  115. TypeError(U, 'Intern, '"ID or string");
  116. syslsp procedure RemOb U; %. REMove id from OBlist
  117. begin scalar V;
  118. if not IDP U then return
  119. NonIDError(U, 'RemOb);
  120. V := IDInf U;
  121. if V < 128 then return
  122. TypeError(U, 'RemOb, '"non-char");
  123. V := SymNam V;
  124. return
  125. << if OccupiedSlot(V := InObList V) then
  126. ObArray V := DeletedSlotValue;
  127. U >>
  128. end;
  129. % Changed to allow a string as well as a symbol, EB, 15 September 1982
  130. syslsp procedure InternP U; %. Is U an interned ID?
  131. if IDP U then
  132. << U := IDInf U;
  133. U < 128 or U eq ObArray InObList SymNam U >>
  134. else if StringP U then
  135. StrLen StrInf U eq 0 or OccupiedSlot InObList U
  136. else NIL;
  137. internal WString GenSymPName = "G0000";
  138. syslsp procedure GenSym(); %. GENerate unique, uninterned SYMbol
  139. << GenSym1 4;
  140. NewID CopyString GenSymPName >>;
  141. syslsp procedure GenSym1 N; % Auxiliary function for GenSym
  142. begin scalar Ch;
  143. return if N > 0 then
  144. if (Ch := StrByt(GenSymPName, N)) < char !9 then
  145. StrByt(GenSymPName, N) := Ch + 1
  146. else
  147. << StrByt(GenSymPName, N) := char !0;
  148. GenSym1(N - 1) >>
  149. else % start over
  150. << StrByt(GenSymPName, 0) := StrByt(GenSymPName, 0) + 1;
  151. GenSym1 4 >>;
  152. end;
  153. syslsp procedure InternGenSym(); %. GENerate unique, interned SYMbol
  154. << GenSym1 4;
  155. Intern MkSTR GenSymPName >>;
  156. syslsp procedure MapObl F; %. Apply F to every interned ID
  157. << for I := 0 step 1 until 127 do Apply(F, list MkID I);
  158. for I := 0 step 1 until MaxObArray do
  159. if OccupiedSlot I then Apply(F, list MkID ObArray I) >>;
  160. % These functions provide support for multiple oblists
  161. % Cf PACKAGE.RED for their use
  162. internal WVar LastObArrayPtr;
  163. syslsp procedure GlobalLookup S; % Lookup string S in global oblist
  164. if not StringP S then NonStringError(S, 'GlobalLookup)
  165. else if OccupiedSlot(LastObArrayPtr := InObList S) then
  166. MkID ObArray LastObArrayPtr
  167. else '0;
  168. syslsp procedure GlobalInstall S; % Add new ID with PName S to oblist
  169. begin scalar Ind, PN;
  170. Ind := GlobalLookup S;
  171. return if Ind neq '0 then Ind
  172. else
  173. << Ind := GtID();
  174. ObArray LastObArrayPtr := Ind;
  175. PN := GtConstSTR StrLen StrInf S; % allocate a string from uncollected
  176. CopyStringToFrom(PN, StrInf S); % space
  177. InitNewID(Ind, MkSTR PN) >>;
  178. end;
  179. syslsp procedure GlobalRemove S; % Remove ID with PName S from oblist
  180. begin scalar Ind;
  181. Ind := GlobalLookup S;
  182. return if Ind eq '0 then '0
  183. else
  184. << Ind := ObArray LastObArrayPtr;
  185. ObArray LastObArrayPtr := DeletedSlotValue;
  186. MkID Ind >>;
  187. end;
  188. syslsp procedure InitObList();
  189. begin scalar Tmp;
  190. if_system(MC68000, << % 68000 systems don't clear memory statically
  191. for I := 0 step 1 until MaxObArray do
  192. ObArray I := EmptySlotValue >>);
  193. Tmp := NextSymbol - 1;
  194. for I := 128 step 1 until Tmp do
  195. ObArray InObList SymNam I := I;
  196. end;
  197. off SysLisp;
  198. StartupTime InitObList();
  199. END;