sequence.red 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. %
  2. % SEQUENCE.RED - Useful functions on strings, vectors and lists
  3. %
  4. % Author: Martin Griss and Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 10 September 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % <PSL.KERNEL>SEQUENCE.RED.2, 25-Jan-83 16:11:28, Edit by PERDUE
  12. % Removed Make-String, leaving MkString.
  13. % STRINGS pkg defines Make-String (differently and Common LISP compatibly)
  14. % <PSL.INTERP>SEQUENCE.RED.2, 27-Feb-82 00:46:03, Edit by BENSON
  15. % Started adding more vector types
  16. % <PSL.INTERP>STRING-OPS.RED.11, 6-Jan-82 20:41:16, Edit by BENSON
  17. % Changed String and Vector into Nexprs
  18. on SysLisp;
  19. % Indexing operations
  20. syslsp procedure Indx(R1, R2); %. Element of sequence
  21. begin scalar Tmp1, Tmp2;
  22. if not PosIntP R2 then return IndexError(R2, 'Indx); % Subscript
  23. Tmp1 := Inf R1;
  24. Tmp2 := Tag R1;
  25. return case Tmp2 of
  26. Str, Bytes:
  27. if R2 > StrLen Tmp1 then
  28. RangeError(R1, R2, 'Indx)
  29. else StrByt(Tmp1, R2);
  30. Vect:
  31. if R2 > VecLen Tmp1 then
  32. RangeError(R1, R2, 'Indx)
  33. else VecItm(Tmp1, R2);
  34. Wrds:
  35. if R2 > WrdLen Tmp1 then
  36. RangeError(R1, R2, 'Indx)
  37. else WrdItm(Tmp1, R2);
  38. HalfWords:
  39. if R2 > HalfWordLen Tmp1 then
  40. RangeError(R1, R2, 'Indx)
  41. else HalfWordItm(Tmp1, R2);
  42. Pair:
  43. << Tmp2 := R2;
  44. while Tmp2 > 0 do
  45. << R1 := cdr R1;
  46. if atom R1 then RangeError(R1, R2, 'Indx);
  47. Tmp2 := Tmp2 - 1 >>;
  48. car R1 >>;
  49. default:
  50. NonSequenceError(R1, 'Indx);
  51. end;
  52. end;
  53. syslsp procedure SetIndx(R1, R2, R3); %. Store at index of sequence
  54. begin scalar Tmp1, Tmp2;
  55. if not PosIntP R2 then return IndexError(R2, 'SetIndx); % Subscript
  56. Tmp1 := Inf R1;
  57. Tmp2 := Tag R1;
  58. return case Tmp2 of
  59. Str, Bytes:
  60. if R2 > StrLen Tmp1 then
  61. RangeError(R1, R2, 'SetIndx)
  62. else
  63. << StrByt(Tmp1, R2) := R3;
  64. R3 >>;
  65. Vect:
  66. if R2 > VecLen Tmp1 then
  67. RangeError(R1, R2, 'SetIndx)
  68. else
  69. << VecItm(Tmp1, R2) := R3;
  70. R3 >>;
  71. Wrds:
  72. if R2 > WrdLen Tmp1 then
  73. RangeError(R1, R2, 'SetIndx)
  74. else
  75. << WrdItm(Tmp1, R2) := R3;
  76. R3 >>;
  77. HalfWords:
  78. if R2 > HalfWordLen Tmp1 then
  79. RangeError(R1, R2, 'SetIndx)
  80. else
  81. << HalfWordItm(Tmp1, R2) := R3;
  82. R3 >>;
  83. Pair:
  84. << Tmp2 := R2;
  85. while Tmp2 > 0 do
  86. << R1 := cdr R1;
  87. if atom R1 then RangeError(R1, R2, 'SetIndx);
  88. Tmp2 := Tmp2 - 1 >>;
  89. Rplaca(R1, R3);
  90. R3 >>;
  91. default:
  92. NonSequenceError(R1, 'SetIndx);
  93. end;
  94. end;
  95. % String and vector sub-part operations.
  96. syslsp procedure Sub(R1, R2, R3); %. Obsolete subsequence function
  97. SubSeq(R1, R2, R2 + R3 + 1);
  98. syslsp procedure SubSeq(R1, R2, R3); % R2 is lower bound, R3 upper
  99. begin scalar NewSize, OldSize, NewItem;
  100. if not PosIntP R2 then return IndexError(R2, 'SubSeq);
  101. if not PosIntP R3 then return IndexError(R3, 'SubSeq);
  102. NewSize := R3 - R2 - 1;
  103. if NewSize < -1 then return RangeError(R1, R3, 'SubSeq);
  104. return case Tag R1 of
  105. Str, Bytes:
  106. << OldSize := StrLen StrInf R1;
  107. if R3 - 1 > OldSize then RangeError(R1, R3, 'SubSeq)
  108. else
  109. << NewItem := GtSTR NewSize;
  110. R3 := StrInf R1;
  111. for I := 0 step 1 until NewSize do
  112. StrByt(NewItem, I) := StrByt(R3, R2 + I);
  113. case Tag R1 of
  114. Str:
  115. MkSTR NewItem;
  116. Bytes:
  117. MkBYTES NewItem;
  118. end >> >>;
  119. Vect:
  120. << OldSize := VecLen VecInf R1;
  121. if R3 - 1 > OldSize then RangeError(R1, R3, 'SubSeq)
  122. else
  123. << NewItem := GtVECT NewSize;
  124. R3 := VecInf R1;
  125. for I := 0 step 1 until NewSize do
  126. VecItm(NewItem, I) := VecItm(R3, R2 + I);
  127. MkVEC NewItem >> >>;
  128. Wrds:
  129. << OldSize := WrdLen WrdInf R1;
  130. if R3 - 1 > OldSize then RangeError(R1, R3, 'SubSeq)
  131. else
  132. << NewItem := GtWRDS NewSize;
  133. R3 := WrdInf R1;
  134. for I := 0 step 1 until NewSize do
  135. WrdItm(NewItem, I) := WrdItm(R3, R2 + I);
  136. MkWRDS NewItem >> >>;
  137. HalfWords:
  138. << OldSize := HalfWordLen HalfWordInf R1;
  139. if R3 - 1 > OldSize then RangeError(R1, R3, 'SubSeq)
  140. else
  141. << NewItem := GtHalfWords NewSize;
  142. R3 := HalfWordInf R1;
  143. for I := 0 step 1 until NewSize do
  144. HalfWordItm(NewItem, I) := HalfWordItm(R3, R2 + I);
  145. MkHalfWords NewItem >> >>;
  146. Pair:
  147. << for I := 1 step 1 until R2 do
  148. if PairP R1 then R1 := rest R1
  149. else RangeError(R1, R2, 'SubSeq);
  150. NewItem := NIL . NIL;
  151. for I := 0 step 1 until NewSize do
  152. if PairP R1 then
  153. << TConc(NewItem, first R1);
  154. R1 := rest R1 >>
  155. else RangeError(R1, R3, 'SubSeq);
  156. car NewItem >>;
  157. default:
  158. NonSequenceError(R1, 'SubSeq);
  159. end;
  160. end;
  161. syslsp procedure SetSub(R1, R2, R3, R4); %. Obsolete subsequence function
  162. SetSubSeq(R1, R2, R2 + R3 + 1, R4);
  163. syslsp procedure SetSubSeq(R1, R2, R3, R4); % R2 is lower bound, R3 upper
  164. begin scalar NewSize, OldSize, SubSize, NewItem;
  165. if not PosIntP R2 then return IndexError(R2, 'SetSubSeq);
  166. if not PosIntP R3 then return IndexError(R3, 'SetSubSeq);
  167. NewSize := R3 - R2 - 1;
  168. if NewSize < -1 then return RangeError(R1, R3, 'SetSubSeq);
  169. case Tag R1 of
  170. Str, Bytes:
  171. << if not StringP R4 and not BytesP R4 then return
  172. NonStringError(R4, 'SetSubSeq);
  173. OldSize := StrLen StrInf R1;
  174. NewItem := StrInf R4;
  175. SubSize := StrLen NewItem;
  176. if R3 - 1 > OldSize then RangeError(R1, R3, 'SetSubSeq)
  177. else if not (NewSize eq SubSize) then
  178. RangeError(R4, NewSize, 'SetSubSeq)
  179. else
  180. << R3 := StrInf R1;
  181. for I := 0 step 1 until NewSize do
  182. StrByt(R3, R2 + I) := StrByt(NewItem, I) >> >>;
  183. Vect:
  184. << if not VectorP R4 then return
  185. NonVectorError(R4, 'SetSubSeq);
  186. OldSize := VecLen VecInf R1;
  187. NewItem := VecInf R4;
  188. SubSize := VecLen NewItem;
  189. if R3 - 1 > OldSize then RangeError(R1, R3, 'SetSubSeq)
  190. else if not (NewSize eq SubSize) then
  191. RangeError(R4, NewSize, 'SetSubSeq)
  192. else
  193. << R3 := VecInf R1;
  194. for I := 0 step 1 until NewSize do
  195. VecItm(R3, R2 + I) := VecItm(NewItem, I) >> >>;
  196. Wrds:
  197. << if not WrdsP R4 then return
  198. NonVectorError(R4, 'SetSubSeq);
  199. OldSize := WrdLen WrdInf R1;
  200. NewItem := WrdInf R4;
  201. SubSize := WrdLen NewItem;
  202. if R3 - 1 > OldSize then RangeError(R1, R3, 'SetSubSeq)
  203. else if not (NewSize eq SubSize) then
  204. RangeError(R4, NewSize, 'SetSubSeq)
  205. else
  206. << R3 := WrdInf R1;
  207. for I := 0 step 1 until NewSize do
  208. WrdItm(R3, R2 + I) := WrdItm(NewItem, I) >> >>;
  209. HalfWords:
  210. << if not HalfWordsP R4 then return
  211. NonVectorError(R4, 'SetSubSeq);
  212. OldSize := HalfWordLen HalfWordInf R1;
  213. NewItem := HalfWordInf R4;
  214. SubSize := HalfWordLen NewItem;
  215. if R3 - 1 > OldSize then RangeError(R1, R3, 'SetSubSeq)
  216. else if not (NewSize eq SubSize) then
  217. RangeError(R4, NewSize, 'SetSubSeq)
  218. else
  219. << R3 := HalfWordInf R1;
  220. for I := 0 step 1 until NewSize do
  221. HalfWordItm(R3, R2 + I) := HalfWordItm(NewItem, I) >> >>;
  222. Pair:
  223. << if not PairP R4 and not null R4 then return
  224. NonPairError(R4, 'SetSubSeq);
  225. for I := 1 step 1 until R2 do
  226. if PairP R1 then R1 := rest R1
  227. else RangeError(R1, R2, 'SetSubSeq);
  228. NewItem := R4;
  229. for I := 0 step 1 until NewSize do
  230. if PairP R1 and PairP NewItem then
  231. << RPlaca(R1, first NewItem);
  232. R1 := rest R1;
  233. NewItem := rest NewItem >>
  234. else RangeError(R1, R3, 'SetSubSeq) >>;
  235. default:
  236. NonSequenceError(R1, 'SetSubSeq);
  237. end;
  238. return R4;
  239. end;
  240. syslsp procedure Concat(R1, R2); %. Concatenate 2 sequences
  241. begin scalar I1, I2, Tmp1, Tmp2, Tmp3;
  242. return case Tag R1 of
  243. STR, BYTES:
  244. << if not (StringP R2 or BytesP R2) then return
  245. NonStringError(R2, 'Concat);
  246. Tmp1 := StrInf R1;
  247. Tmp2 := StrInf R2;
  248. I1 := StrLen Tmp1;
  249. I2 := StrLen Tmp2;
  250. Tmp3 := GtSTR(I1 + I2 + 1); % R1 and R2 can move
  251. Tmp1 := StrInf R1;
  252. Tmp2 := StrInf R2;
  253. for I := 0 step 1 until I1 do
  254. StrByt(Tmp3, I) := StrByt(Tmp1, I);
  255. for I := 0 step 1 until I2 do
  256. StrByt(Tmp3, I1 + I + 1) := StrByt(Tmp2, I);
  257. if StringP R1 then MkSTR Tmp3 else MkBYTES Tmp3 >>;
  258. VECT:
  259. << if not VectorP R2 then return
  260. NonVectorError(R2, 'Concat);
  261. Tmp1 := VecInf R1;
  262. Tmp2 := VecInf R2;
  263. I1 := VecLen Tmp1;
  264. I2 := VecLen Tmp2;
  265. Tmp3 := GtVECT(I1 + I2 + 1); % R1 and R2 can move
  266. Tmp1 := VecInf R1;
  267. Tmp2 := VecInf R2;
  268. for I := 0 step 1 until I1 do
  269. VecItm(Tmp3, I) := VecItm(Tmp1, I);
  270. for I := 0 step 1 until I2 do
  271. VecItm(Tmp3, I1 + I + 1) := VecItm(Tmp2, I);
  272. MkVEC Tmp3 >>;
  273. WRDS:
  274. << if not WrdsP R2 then return
  275. NonVectorError(R2, 'Concat);
  276. Tmp1 := WrdInf R1;
  277. Tmp2 := WrdInf R2;
  278. I1 := WrdLen Tmp1;
  279. I2 := WrdLen Tmp2;
  280. Tmp3 := GtWrds(I1 + I2 + 1); % R1 and R2 can move
  281. Tmp1 := WrdInf R1;
  282. Tmp2 := WrdInf R2;
  283. for I := 0 step 1 until I1 do
  284. WrdItm(Tmp3, I) := WrdItm(Tmp1, I);
  285. for I := 0 step 1 until I2 do
  286. WrdItm(Tmp3, I1 + I + 1) := WrdItm(Tmp2, I);
  287. MkWRDS Tmp3 >>;
  288. HALFWORDS:
  289. << if not HalfWordsP R2 then return
  290. NonVectorError(R2, 'Concat);
  291. Tmp1 := HalfWordInf R1;
  292. Tmp2 := HalfWordInf R2;
  293. I1 := HalfWordLen Tmp1;
  294. I2 := HalfWordLen Tmp2;
  295. Tmp3 := GtHalfWords(I1 + I2 + 1); % R1 and R2 can move
  296. Tmp1 := HalfWordInf R1;
  297. Tmp2 := HalfWordInf R2;
  298. for I := 0 step 1 until I1 do
  299. HalfWordItm(Tmp3, I) := HalfWordItm(Tmp1, I);
  300. for I := 0 step 1 until I2 do
  301. HalfWordItm(Tmp3, I1 + I + 1) := HalfWordItm(Tmp2, I);
  302. MkHalfWords Tmp3 >>;
  303. PAIR, ID:
  304. if null R1 or PairP R1 then Append(R1, R2);
  305. default:
  306. NonSequenceError(R1, 'Concat);
  307. end;
  308. end;
  309. syslsp procedure Size S; %. Upper bound of sequence
  310. case Tag S of
  311. STR, BYTES, WRDS, VECT, HALFWORDS:
  312. GetLen Inf S;
  313. ID:
  314. -1;
  315. PAIR:
  316. begin scalar I;
  317. I := -1;
  318. while PairP S do
  319. << I := I + 1;
  320. S := cdr S >>;
  321. return I;
  322. end;
  323. default:
  324. NonSequenceError(S, 'Size);
  325. end;
  326. syslsp procedure MkString(L, C); %. Make str with upb L, all chars C
  327. begin scalar L1, S;
  328. if IntP L then L1 := IntInf L else return NonIntegerError(L, 'MkString);
  329. if L1 < -1 then return NonPositiveIntegerError(L, 'MkString);
  330. S := GtStr L1;
  331. for I := 0 step 1 until L1 do
  332. StrByt(S, I) := C;
  333. return MkSTR S;
  334. end;
  335. syslsp procedure Make!-Bytes(L, C); %. Make byte vector with upb L, all items C
  336. begin scalar L1, S;
  337. if IntP L then L1 := IntInf L else return NonIntegerError(L, 'Make!-Bytes);
  338. if L1 < -1 then return NonPositiveIntegerError(L, 'Make!-Bytes);
  339. S := GtStr L1;
  340. for I := 0 step 1 until L1 do
  341. StrByt(S, I) := C;
  342. return MkBytes S;
  343. end;
  344. syslsp procedure Make!-HalfWords(L, C); %. Make h vect with upb L, all items C
  345. begin scalar L1, S;
  346. if IntP L then L1 := IntInf L else
  347. return NonIntegerError(L, 'Make!-HalfWords);
  348. if L1 < -1 then return NonPositiveIntegerError(L, 'Make!-HalfWords);
  349. S := GtHalfWords L1;
  350. for I := 0 step 1 until L1 do
  351. HalfWordItm(S, I) := C;
  352. return MkHalfWords S;
  353. end;
  354. syslsp procedure Make!-Words(L, C); %. Make w vect with upb L, all items C
  355. begin scalar L1, S;
  356. if IntP L then L1 := IntInf L else return NonIntegerError(L, 'Make!-Words);
  357. if L1 < -1 then return NonPositiveIntegerError(L, 'Make!-Words);
  358. S := GtWrds L1;
  359. for I := 0 step 1 until L1 do
  360. WrdItm(S, I) := C;
  361. return MkWrds S;
  362. end;
  363. syslsp procedure Make!-Vector(L, C); %. Make vect with upb L, all items C
  364. begin scalar L1, S;
  365. if IntP L then L1 := IntInf L else return
  366. NonIntegerError(L, 'Make!-Vector);
  367. if L1 < -1 then return NonPositiveIntegerError(L, 'Make!-Vector);
  368. S := GtVECT L1;
  369. for I := 0 step 1 until L1 do
  370. VecItm(S, I) := C;
  371. return MkVEC S;
  372. end;
  373. off SysLisp;
  374. % Maybe we want to support efficient compilation of these, as with LIST,
  375. % by functions String2, String3, Vector2, Vector3, etc.
  376. nexpr procedure String U; %. Analogous to LIST, string constructor
  377. List2String U;
  378. nexpr procedure Vector U; %. Analogous to LIST, vector constructor
  379. List2Vector U;
  380. END;