PageRenderTime 95ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/src/opers.c

https://bitbucket.org/dimpase/libgap
C | 6369 lines | 4510 code | 875 blank | 984 comment | 841 complexity | dc13b5f83f338baa78a683c9af96f25f MD5 | raw file
Possible License(s): GPL-3.0
  1. /****************************************************************************
  2. **
  3. *W opers.c GAP source Frank Celler
  4. *W & Martin Schönert
  5. **
  6. **
  7. *Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
  8. *Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
  9. *Y Copyright (C) 2002 The GAP Group
  10. **
  11. ** This file contains the functions of the filters, operations, attributes,
  12. ** and properties package.
  13. */
  14. #include <assert.h>
  15. #include "system.h" /* Ints, UInts */
  16. #include "gasman.h" /* garbage collector */
  17. #include "objects.h" /* objects */
  18. #include "scanner.h" /* scanner */
  19. #include "gvars.h" /* global variables */
  20. #include "gap.h" /* error handling, initialisation */
  21. #include "calls.h" /* generic call mechanism */
  22. #include "opers.h" /* generic operations */
  23. #include "ariths.h" /* basic arithmetic */
  24. #include "lists.h" /* generic lists */
  25. #include "bool.h" /* booleans */
  26. #include "plist.h" /* plain lists */
  27. #include "blister.h" /* boolean lists */
  28. #include "string.h" /* strings */
  29. #include "range.h" /* ranges */
  30. #include "records.h" /* generic records */
  31. #include "precord.h" /* plain records */
  32. #include "saveload.h" /* saving and loading */
  33. #include "listfunc.h"
  34. #include "integer.h"
  35. /****************************************************************************
  36. **
  37. *V TRY_NEXT_METHOD . . . . . . . . . . . . . . . . . `TRY_NEXT_MESSAGE' flag
  38. */
  39. Obj TRY_NEXT_METHOD;
  40. #define CACHE_SIZE 5
  41. /****************************************************************************
  42. **
  43. *F * * * * * * * * * * * * internal flags functions * * * * * * * * * * * * *
  44. */
  45. /****************************************************************************
  46. **
  47. *F PrintFlags( <flags> ) . . . . . . . . . . . . . . . . print a flags list
  48. */
  49. void PrintFlags (
  50. Obj flags )
  51. {
  52. Pr( "<flag list>", 0L, 0L );
  53. }
  54. /****************************************************************************
  55. **
  56. *F TypeFlags( <flags> ) . . . . . . . . . . . . . . . type of a flags list
  57. */
  58. Obj TYPE_FLAGS;
  59. Obj TypeFlags (
  60. Obj flags )
  61. {
  62. return TYPE_FLAGS;
  63. }
  64. /****************************************************************************
  65. **
  66. *F SaveFlags( <flags> ) . . . . . . . . . . . . . . . . . save a flags list
  67. **
  68. */
  69. void SaveFlags (
  70. Obj flags )
  71. {
  72. UInt i, len, *ptr;
  73. SaveSubObj(TRUES_FLAGS(flags));
  74. SaveSubObj(HASH_FLAGS(flags));
  75. SaveSubObj(ADDR_OBJ(flags)[2]); /* length, as an object */
  76. SaveSubObj(AND_CACHE_FLAGS(flags));
  77. len = NRB_FLAGS(flags);
  78. ptr = BLOCKS_FLAGS(flags);
  79. for ( i = 1; i <= len; i++ )
  80. SaveUInt(*ptr++);
  81. return;
  82. }
  83. /****************************************************************************
  84. **
  85. *F LoadFlags( <flags> ) . . . . . . . . . . . . . . . . . load a flags list
  86. **
  87. */
  88. void LoadFlags(
  89. Obj flags )
  90. {
  91. Obj sub;
  92. UInt i, len, *ptr;
  93. sub = LoadSubObj(); SET_TRUES_FLAGS( flags, sub );
  94. sub = LoadSubObj(); SET_HASH_FLAGS( flags, sub );
  95. ADDR_OBJ(flags)[2] = LoadSubObj(); /* length, as an object */
  96. sub = LoadSubObj(); SET_AND_CACHE_FLAGS( flags, sub );
  97. len = NRB_FLAGS(flags);
  98. ptr = BLOCKS_FLAGS(flags);
  99. for ( i = 1; i <= len; i++ )
  100. *ptr++ = LoadUInt();
  101. return;
  102. }
  103. /****************************************************************************
  104. **
  105. *F * * * * * * * * * * * * * GAP flags functions * * * * * * * * * * * * * *
  106. */
  107. /****************************************************************************
  108. **
  109. *F FuncLEN_FLAGS( <self>, <flags> ) . . . . . . . . length of a flags list
  110. **
  111. */
  112. Obj FuncLEN_FLAGS (
  113. Obj self,
  114. Obj flags )
  115. {
  116. /* do some trivial checks */
  117. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  118. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  119. (Int)TNAM_OBJ(flags), 0L,
  120. "you can replace <flags> via 'return <flags>;'" );
  121. }
  122. return INTOBJ_INT( LEN_FLAGS(flags) );
  123. }
  124. /****************************************************************************
  125. **
  126. *F FuncELM_FLAGS( <self>, <flags>, <pos> ) . . . . . element of a flags list
  127. */
  128. Obj FuncELM_FLAGS (
  129. Obj self,
  130. Obj flags,
  131. Obj pos )
  132. {
  133. /* do some trivial checks */
  134. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  135. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  136. (Int)TNAM_OBJ(flags), 0L,
  137. "you can replace <flags> via 'return <flags>;'" );
  138. }
  139. /* select and return the element */
  140. return ELM_FLAGS( flags, INT_INTOBJ(pos) );
  141. }
  142. /****************************************************************************
  143. **
  144. *F FuncHASH_FLAGS( <self>, <flags> ) . . . . . . hash value of a flags list
  145. **
  146. ** The hash value is independent of the size of a machine word (32 or 64).
  147. **
  148. ** The rather peculiar cast in the definition of HASH_FLAGS_SIZE is needed
  149. ** to get the calculation to work right on the alpha.
  150. **
  151. *T The 64 bit version depends on the byte order -- it assumes that
  152. ** the lower addressed half-word is the less significant
  153. **
  154. */
  155. #define HASH_FLAGS_SIZE (Int4)67108879L
  156. Obj FuncHASH_FLAGS (
  157. Obj self,
  158. Obj flags )
  159. {
  160. Int4 hash;
  161. Int4 x;
  162. Int len;
  163. UInt4 * ptr;
  164. Int i;
  165. /* do some trivial checks */
  166. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  167. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  168. (Int)TNAM_OBJ(flags), 0L,
  169. "you can replace <flags> via 'return <flags>;'" );
  170. }
  171. if ( HASH_FLAGS(flags) != 0 ) {
  172. return HASH_FLAGS(flags);
  173. }
  174. /* do the real work*/
  175. #ifndef SYS_IS_64_BIT
  176. /* 32 bit case -- this is the "defining" case, others are
  177. adjusted to comply with this */
  178. len = NRB_FLAGS(flags);
  179. ptr = (UInt4 *)BLOCKS_FLAGS(flags);
  180. hash = 0;
  181. x = 1;
  182. for ( i = len; i >= 1; i-- ) {
  183. hash = (hash + (*ptr % HASH_FLAGS_SIZE) * x) % HASH_FLAGS_SIZE;
  184. x = ((8*sizeof(UInt4)-1) * x) % HASH_FLAGS_SIZE;
  185. ptr++;
  186. }
  187. #else
  188. #ifdef WORDS_BIGENDIAN
  189. /* This is the hardest case */
  190. len = NRB_FLAGS(flags);
  191. ptr = (UInt4 *)BLOCKS_FLAGS(flags);
  192. hash = 0;
  193. x = 1;
  194. for ( i = len; i >= 1; i-- ) {
  195. /* least significant 32 bits first */
  196. hash = (hash + (ptr[1] % HASH_FLAGS_SIZE) * x) % HASH_FLAGS_SIZE;
  197. x = ((8*sizeof(UInt4)-1) * x) % HASH_FLAGS_SIZE;
  198. /* now the more significant */
  199. hash = (hash + (*ptr % HASH_FLAGS_SIZE) * x) % HASH_FLAGS_SIZE;
  200. x = ((8*sizeof(UInt4)-1) * x) % HASH_FLAGS_SIZE;
  201. ptr+= 2;
  202. }
  203. #else
  204. /* and the middle case -- for DEC alpha, the 32 bit chunks are
  205. in the right order, and we merely have to be sure to process them as
  206. 32 bit chunks */
  207. len = NRB_FLAGS(flags)*(sizeof(UInt)/sizeof(UInt4));
  208. ptr = (UInt4 *)BLOCKS_FLAGS(flags);
  209. hash = 0;
  210. x = 1;
  211. for ( i = len; i >= 1; i-- ) {
  212. hash = (hash + (*ptr % HASH_FLAGS_SIZE) * x) % HASH_FLAGS_SIZE;
  213. x = ((8*sizeof(UInt4)-1) * x) % HASH_FLAGS_SIZE;
  214. ptr++;
  215. }
  216. #endif
  217. #endif
  218. SET_HASH_FLAGS( flags, INTOBJ_INT((UInt)hash+1) );
  219. CHANGED_BAG(flags);
  220. return HASH_FLAGS(flags);
  221. }
  222. /****************************************************************************
  223. **
  224. *F FuncTRUES_FLAGS( <self>, <flags> ) . . . true positions of a flags list
  225. **
  226. ** see 'FuncPositionsTruesBlist' in "blister.c" for information.
  227. */
  228. Obj FuncTRUES_FLAGS (
  229. Obj self,
  230. Obj flags )
  231. {
  232. Obj sub; /* handle of the result */
  233. Int len; /* logical length of the list */
  234. UInt * ptr; /* pointer to flags */
  235. UInt nrb; /* number of blocks in flags */
  236. UInt m; /* number of bits in a block */
  237. UInt n; /* number of bits in flags */
  238. UInt nn;
  239. UInt i; /* loop variable */
  240. /* get and check the first argument */
  241. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  242. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  243. (Int)TNAM_OBJ(flags), 0L,
  244. "you can replace <flags> via 'return <flags>;'" );
  245. }
  246. if ( TRUES_FLAGS(flags) != 0 ) {
  247. return TRUES_FLAGS(flags);
  248. }
  249. /* compute the number of 'true'-s just as in 'FuncSizeBlist' */
  250. nrb = NRB_FLAGS(flags);
  251. ptr = (UInt*)BLOCKS_FLAGS(flags);
  252. n = 0;
  253. for ( i = 1; i <= nrb; i++ ) {
  254. m = *ptr++;
  255. COUNT_TRUES_BLOCK(m);
  256. n += m;
  257. }
  258. /* make the sublist (we now know its size exactely) */
  259. sub = NEW_PLIST( T_PLIST+IMMUTABLE, n );
  260. SET_LEN_PLIST( sub, n );
  261. /* loop over the boolean list and stuff elements into <sub> */
  262. len = LEN_FLAGS( flags );
  263. nn = 1;
  264. for ( i = 1; nn <= n && i <= len; i++ ) {
  265. if ( ELM_FLAGS( flags, i ) == True ) {
  266. SET_ELM_PLIST( sub, nn, INTOBJ_INT(i) );
  267. nn++;
  268. }
  269. }
  270. CHANGED_BAG(sub);
  271. /* return the sublist */
  272. SET_TRUES_FLAGS( flags, sub );
  273. CHANGED_BAG(flags);
  274. return sub;
  275. }
  276. /****************************************************************************
  277. **
  278. *F FuncSIZE_FLAGS( <self>, <flags> ) . . . . number of trues of a flags list
  279. **
  280. ** see 'FuncSIZE_FLAGS'
  281. */
  282. Obj FuncSIZE_FLAGS (
  283. Obj self,
  284. Obj flags )
  285. {
  286. UInt * ptr; /* pointer to flags */
  287. UInt nrb; /* number of blocks in flags */
  288. UInt m; /* number of bits in a block */
  289. UInt n; /* number of bits in flags */
  290. UInt i; /* loop variable */
  291. /* get and check the first argument */
  292. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  293. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  294. (Int)TNAM_OBJ(flags), 0L,
  295. "you can replace <flags> via 'return <flags>;'" );
  296. }
  297. if ( TRUES_FLAGS(flags) != 0 ) {
  298. return INTOBJ_INT( LEN_PLIST( TRUES_FLAGS(flags) ) );
  299. }
  300. /* get the number of blocks and a pointer */
  301. nrb = NRB_FLAGS(flags);
  302. ptr = BLOCKS_FLAGS(flags);
  303. /* loop over the blocks, adding the number of bits of each one */
  304. n = 0;
  305. for ( i = 1; i <= nrb; i++ ) {
  306. m = *ptr++;
  307. COUNT_TRUES_BLOCK(m);
  308. n += m;
  309. }
  310. /* return the number of bits */
  311. return INTOBJ_INT( n );
  312. }
  313. /****************************************************************************
  314. **
  315. *F FuncIS_EQUAL_FLAGS( <self>, <flags1>, <flags2> ) equality of flags lists
  316. */
  317. Obj FuncIS_EQUAL_FLAGS (
  318. Obj self,
  319. Obj flags1,
  320. Obj flags2 )
  321. {
  322. Int len1;
  323. Int len2;
  324. UInt * ptr1;
  325. UInt * ptr2;
  326. Int i;
  327. /* do some trivial checks */
  328. while ( TNUM_OBJ(flags1) != T_FLAGS ) {
  329. flags1 = ErrorReturnObj( "<flags1> must be a flags list (not a %s)",
  330. (Int)TNAM_OBJ(flags1), 0L,
  331. "you can replace <flags1> via 'return <flags1>;'" );
  332. }
  333. while ( TNUM_OBJ(flags2) != T_FLAGS ) {
  334. flags2 = ErrorReturnObj( "<flags2> must be a flags list (not a %s)",
  335. (Int)TNAM_OBJ(flags2), 0L,
  336. "you can replace <flags2> via 'return <flags2>;'" );
  337. }
  338. if ( flags1 == flags2 ) {
  339. return True;
  340. }
  341. /* do the real work */
  342. len1 = NRB_FLAGS(flags1);
  343. len2 = NRB_FLAGS(flags2);
  344. ptr1 = BLOCKS_FLAGS(flags1);
  345. ptr2 = BLOCKS_FLAGS(flags2);
  346. if ( len1 <= len2 ) {
  347. for ( i = 1; i <= len1; i++ ) {
  348. if ( *ptr1 != *ptr2 )
  349. return False;
  350. ptr1++; ptr2++;
  351. }
  352. for ( ; i <= len2; i++ ) {
  353. if ( 0 != *ptr2 )
  354. return False;
  355. ptr2++;
  356. }
  357. }
  358. else {
  359. for ( i = 1; i <= len2; i++ ) {
  360. if ( *ptr1 != *ptr2 )
  361. return False;
  362. ptr1++; ptr2++;
  363. }
  364. for ( ; i <= len1; i++ ) {
  365. if ( *ptr1 != 0 )
  366. return False;
  367. ptr1++;
  368. }
  369. }
  370. return True;
  371. }
  372. /****************************************************************************
  373. **
  374. *F FuncIS_SUBSET_FLAGS( <self>, <flags1>, <flags2> ) . . . . . . subset test
  375. */
  376. Int IsSubsetFlagsCalls;
  377. Int IsSubsetFlagsCalls1;
  378. Int IsSubsetFlagsCalls2;
  379. Obj FuncIS_SUBSET_FLAGS (
  380. Obj self,
  381. Obj flags1,
  382. Obj flags2 )
  383. {
  384. Int len1;
  385. Int len2;
  386. UInt * ptr1;
  387. UInt * ptr2;
  388. Int i;
  389. Obj trues;
  390. /* do some trivial checks */
  391. while ( TNUM_OBJ(flags1) != T_FLAGS ) {
  392. flags1 = ErrorReturnObj( "<flags1> must be a flags list (not a %s)",
  393. (Int)TNAM_OBJ(flags1), 0L,
  394. "you can replace <flags1> via 'return <flags1>;'" );
  395. }
  396. while ( TNUM_OBJ(flags2) != T_FLAGS ) {
  397. flags2 = ErrorReturnObj( "<flags2> must be a flags list (not a %s)",
  398. (Int)TNAM_OBJ(flags2), 0L,
  399. "you can replace <flags2> via 'return <flags2>;'" );
  400. }
  401. if ( flags1 == flags2 ) {
  402. return True;
  403. }
  404. /* do the real work */
  405. #ifdef COUNT_OPERS
  406. IsSubsetFlagsCalls++;
  407. #endif
  408. /* first check the trues */
  409. trues = TRUES_FLAGS(flags2);
  410. if ( trues != 0 ) {
  411. len2 = LEN_PLIST(trues);
  412. if ( TRUES_FLAGS(flags1) != 0 ) {
  413. if ( LEN_PLIST(TRUES_FLAGS(flags1)) < len2 ) {
  414. #ifdef COUNT_OPERS
  415. IsSubsetFlagsCalls1++;
  416. #endif
  417. return False;
  418. }
  419. }
  420. if ( len2 < 3 ) {
  421. #ifdef COUNT_OPERS
  422. IsSubsetFlagsCalls2++;
  423. #endif
  424. if ( LEN_FLAGS(flags1) < INT_INTOBJ(ELM_PLIST(trues,len2)) ) {
  425. return False;
  426. }
  427. for ( i = len2; 0 < i; i-- ) {
  428. if (ELM_FLAGS(flags1,INT_INTOBJ(ELM_PLIST(trues,i)))==False) {
  429. return False;
  430. }
  431. }
  432. return True;
  433. }
  434. }
  435. /* compare the bit lists */
  436. len1 = NRB_FLAGS(flags1);
  437. len2 = NRB_FLAGS(flags2);
  438. ptr1 = BLOCKS_FLAGS(flags1);
  439. ptr2 = BLOCKS_FLAGS(flags2);
  440. if ( len1 <= len2 ) {
  441. for ( i = 1; i <= len1; i++ ) {
  442. if ( (*ptr1 & *ptr2) != *ptr2 ) {
  443. return False;
  444. }
  445. ptr1++; ptr2++;
  446. }
  447. for ( ; i <= len2; i++ ) {
  448. if ( 0 != *ptr2 ) {
  449. return False;
  450. }
  451. ptr2++;
  452. }
  453. }
  454. else {
  455. for ( i = 1; i <= len2; i++ ) {
  456. if ( (*ptr1 & *ptr2) != *ptr2 ) {
  457. return False;
  458. }
  459. ptr1++; ptr2++;
  460. }
  461. }
  462. return True;
  463. }
  464. /****************************************************************************
  465. **
  466. *F FuncSUB_FLAGS( <self>, <flags1>, <flags2> ) . . . substract a flags list
  467. */
  468. Obj FuncSUB_FLAGS (
  469. Obj self,
  470. Obj flags1,
  471. Obj flags2 )
  472. {
  473. Obj flags;
  474. Int len1;
  475. Int len2;
  476. Int size1;
  477. Int size2;
  478. UInt * ptr;
  479. UInt * ptr1;
  480. UInt * ptr2;
  481. Int i;
  482. /* do some trivial checks */
  483. while ( TNUM_OBJ(flags1) != T_FLAGS ) {
  484. flags1 = ErrorReturnObj( "<flags1> must be a flags list (not a %s)",
  485. (Int)TNAM_OBJ(flags1), 0L,
  486. "you can replace <flags1> via 'return <flags1>;'" );
  487. }
  488. while ( TNUM_OBJ(flags2) != T_FLAGS ) {
  489. flags2 = ErrorReturnObj( "<flags2> must be a flags list (not a %s)",
  490. (Int)TNAM_OBJ(flags2), 0L,
  491. "you can replace <flags2> via 'return <flags2>;'" );
  492. }
  493. /* do the real work */
  494. len1 = LEN_FLAGS(flags1);
  495. size1 = NRB_FLAGS(flags1);
  496. len2 = LEN_FLAGS(flags2);
  497. size2 = NRB_FLAGS(flags2);
  498. if ( len1 < len2 ) {
  499. NEW_FLAGS( flags, len1 );
  500. SET_LEN_FLAGS( flags, len1 );
  501. ptr1 = BLOCKS_FLAGS(flags1);
  502. ptr2 = BLOCKS_FLAGS(flags2);
  503. ptr = BLOCKS_FLAGS(flags);
  504. for ( i = 1; i <= size1; i++ )
  505. *ptr++ = *ptr1++ & ~ *ptr2++;
  506. }
  507. else {
  508. NEW_FLAGS( flags, len1 );
  509. SET_LEN_FLAGS( flags, len1 );
  510. ptr1 = BLOCKS_FLAGS(flags1);
  511. ptr2 = BLOCKS_FLAGS(flags2);
  512. ptr = BLOCKS_FLAGS(flags);
  513. for ( i = 1; i <= size2; i++ )
  514. *ptr++ = *ptr1++ & ~ *ptr2++;
  515. for ( ; i <= size1; i++ )
  516. *ptr++ = *ptr1++;
  517. }
  518. return flags;
  519. }
  520. /****************************************************************************
  521. **
  522. *F FuncAND_FLAGS( <self>, <flags1>, <flags2> ) . . . . `and' of flags lists
  523. */
  524. #define AND_FLAGS_HASH_SIZE 50
  525. Int AndFlagsCacheHit;
  526. Int AndFlagsCacheMiss;
  527. Int AndFlagsCacheLost;
  528. Obj FuncAND_FLAGS (
  529. Obj self,
  530. Obj flags1,
  531. Obj flags2 )
  532. {
  533. Obj flags;
  534. Int len1;
  535. Int len2;
  536. Int size1;
  537. Int size2;
  538. UInt * ptr;
  539. UInt * ptr1;
  540. UInt * ptr2;
  541. Int i;
  542. #ifdef AND_FLAGS_HASH_SIZE
  543. Obj flagsX;
  544. Obj cache;
  545. Obj entry;
  546. UInt hash;
  547. UInt hash2;
  548. static UInt next = 0;
  549. #endif
  550. /* do some trivial checks */
  551. while ( TNUM_OBJ(flags1) != T_FLAGS ) {
  552. flags1 = ErrorReturnObj( "<flags1> must be a flags list (not a %s)",
  553. (Int)TNAM_OBJ(flags1), 0L,
  554. "you can replace <flags1> via 'return <flags1>;'" );
  555. }
  556. while ( TNUM_OBJ(flags2) != T_FLAGS ) {
  557. flags2 = ErrorReturnObj( "<flags2> must be a flags list (not a %s)",
  558. (Int)TNAM_OBJ(flags2), 0L,
  559. "you can replace <flags2> via 'return <flags2>;'" );
  560. }
  561. /* check the cache */
  562. # ifdef AND_FLAGS_HASH_SIZE
  563. if ( INT_INTOBJ(flags1) < INT_INTOBJ(flags2) ) {
  564. flagsX = flags2;
  565. cache = AND_CACHE_FLAGS(flags1);
  566. if ( cache == 0 ) {
  567. cache = NEW_PLIST( T_PLIST, 2*AND_FLAGS_HASH_SIZE );
  568. SET_AND_CACHE_FLAGS( flags1, cache );
  569. CHANGED_BAG(flags1);
  570. }
  571. }
  572. else {
  573. flagsX = flags1;
  574. cache = AND_CACHE_FLAGS(flags2);
  575. if ( cache == 0 ) {
  576. cache = NEW_PLIST( T_PLIST, 2*AND_FLAGS_HASH_SIZE );
  577. SET_AND_CACHE_FLAGS( flags2, cache );
  578. CHANGED_BAG(flags2);
  579. }
  580. }
  581. hash = (UInt)INT_INTOBJ(flagsX);
  582. for ( i = 0; i < 24; i++ ) {
  583. hash2 = (hash + 97*i) % AND_FLAGS_HASH_SIZE;
  584. entry = ELM_PLIST( cache, 2*hash2+1 );
  585. if ( entry == 0 ) {
  586. break;
  587. }
  588. if ( entry == flagsX ) {
  589. # ifdef COUNT_OPERS
  590. AndFlagsCacheHit++;
  591. # endif
  592. return ELM_PLIST( cache, 2*hash2+2 );
  593. }
  594. }
  595. if ( entry == 0 ) {
  596. hash = hash2;
  597. }
  598. else {
  599. next = (next+1) % 24;
  600. hash = (hash + 97*next) % AND_FLAGS_HASH_SIZE;
  601. }
  602. # ifdef COUNT_OPERS
  603. AndFlagsCacheMiss++;
  604. # endif
  605. # endif
  606. /* do the real work */
  607. len1 = LEN_FLAGS(flags1);
  608. size1 = NRB_FLAGS(flags1);
  609. len2 = LEN_FLAGS(flags2);
  610. size2 = NRB_FLAGS(flags2);
  611. if ( len1 == 0 ) {
  612. return flags2;
  613. }
  614. if ( len2 == 0 ) {
  615. return flags1;
  616. }
  617. if ( len1 < len2 ) {
  618. NEW_FLAGS( flags, len2 );
  619. SET_LEN_FLAGS( flags, len2 );
  620. ptr1 = BLOCKS_FLAGS(flags1);
  621. ptr2 = BLOCKS_FLAGS(flags2);
  622. ptr = BLOCKS_FLAGS(flags);
  623. for ( i = 1; i <= size1; i++ )
  624. *ptr++ = *ptr1++ | *ptr2++;
  625. for ( ; i <= size2; i++ )
  626. *ptr++ = *ptr2++;
  627. }
  628. else {
  629. NEW_FLAGS( flags, len1 );
  630. SET_LEN_FLAGS( flags, len1 );
  631. ptr1 = BLOCKS_FLAGS(flags1);
  632. ptr2 = BLOCKS_FLAGS(flags2);
  633. ptr = BLOCKS_FLAGS(flags);
  634. for ( i = 1; i <= size2; i++ )
  635. *ptr++ = *ptr1++ | *ptr2++;
  636. for ( ; i <= size1; i++ )
  637. *ptr++ = *ptr1++;
  638. }
  639. /* store result in the cache */
  640. # ifdef AND_FLAGS_HASH_SIZE
  641. # ifdef COUNT_OPERS
  642. if ( ELM_PLIST(cache,2*hash+1) != 0 ) {
  643. AndFlagsCacheLost++;
  644. }
  645. # endif
  646. SET_ELM_PLIST( cache, 2*hash+1, flagsX );
  647. SET_ELM_PLIST( cache, 2*hash+2, flags );
  648. CHANGED_BAG(cache);
  649. # endif
  650. /* and return the result */
  651. return flags;
  652. }
  653. /****************************************************************************
  654. **
  655. *F * * * * * * * * * * * internal filter functions * * * * * * * * * * * * *
  656. */
  657. /****************************************************************************
  658. **
  659. *V Countlags . . . . . . . . . . . . . . . . . . . . next free flag number
  660. */
  661. Int CountFlags;
  662. /****************************************************************************
  663. **
  664. *F SetterFilter( <oper> ) . . . . . . . . . . . . . . . setter of a filter
  665. */
  666. Obj SetterFilter (
  667. Obj oper )
  668. {
  669. Obj setter;
  670. setter = SETTR_FILT( oper );
  671. if ( setter == INTOBJ_INT(0xBADBABE) )
  672. setter = SetterAndFilter( oper );
  673. return setter;
  674. }
  675. /****************************************************************************
  676. **
  677. *F SetterAndFilter( <getter> ) . . . . . . setter of a concatenated filter
  678. */
  679. Obj DoSetAndFilter (
  680. Obj self,
  681. Obj obj,
  682. Obj val )
  683. {
  684. Obj op;
  685. while (val != True)
  686. val = ErrorReturnObj(
  687. "You cannot set an \"and-filter\" except to true", 0L, 0L,
  688. "you can type 'return true;' to set all components true\n"
  689. "(but you might really want to reset just one component)");
  690. /* call the first 'and'-ed function */
  691. op = FLAG1_FILT( self );
  692. CALL_2ARGS( op, obj, val );
  693. /* call the second 'and'-ed function */
  694. op = FLAG2_FILT( self );
  695. CALL_2ARGS( op, obj, val );
  696. /* return 'void' */
  697. return 0;
  698. }
  699. Obj SetterAndFilter (
  700. Obj getter )
  701. {
  702. Obj setter;
  703. if ( SETTR_FILT( getter ) == INTOBJ_INT(0xBADBABE) ) {
  704. setter = NewFunctionCT( T_FUNCTION, SIZE_OPER,
  705. "<<setter-and-filter>>", 2L, "obj, val",
  706. DoSetAndFilter );
  707. FLAG1_FILT(setter) = SetterFilter( FLAG1_FILT(getter) );
  708. FLAG2_FILT(setter) = SetterFilter( FLAG2_FILT(getter) );
  709. SETTR_FILT(getter) = setter;
  710. CHANGED_BAG(getter);
  711. }
  712. return SETTR_FILT(getter);
  713. }
  714. /****************************************************************************
  715. **
  716. *F TesterFilter( <oper> ) . . . . . . . . . . . . . . . tester of a filter
  717. */
  718. Obj TesterFilter (
  719. Obj oper )
  720. {
  721. Obj tester;
  722. tester = TESTR_FILT( oper );
  723. if ( tester == INTOBJ_INT(0xBADBABE) )
  724. tester = TesterAndFilter( oper );
  725. return tester;
  726. }
  727. /****************************************************************************
  728. **
  729. *F TestAndFilter( <getter> ) . . . . . . . .tester of a concatenated filter
  730. */
  731. Obj DoTestAndFilter (
  732. Obj self,
  733. Obj obj )
  734. {
  735. Obj val;
  736. Obj op;
  737. /* call the first 'and'-ed function */
  738. op = FLAG1_FILT( self );
  739. val = CALL_1ARGS( op, obj );
  740. if ( val != True ) return False;
  741. /* call the second 'and'-ed function */
  742. op = FLAG2_FILT( self );
  743. val = CALL_1ARGS( op, obj );
  744. if ( val != True ) return False;
  745. /* return 'true' */
  746. return True;
  747. }
  748. Obj TesterAndFilter (
  749. Obj getter )
  750. {
  751. Obj tester;
  752. if ( TESTR_FILT( getter ) == INTOBJ_INT(0xBADBABE) ) {
  753. tester = NewAndFilter( TesterFilter( FLAG1_FILT(getter) ),
  754. TesterFilter( FLAG2_FILT(getter) ) );
  755. TESTR_FILT(getter) = tester;
  756. CHANGED_BAG(getter);
  757. }
  758. return TESTR_FILT(getter);
  759. }
  760. /****************************************************************************
  761. **
  762. *F NewFilter( <name>, <narg>, <nams>, <hdlr> ) . . . . . make a new filter
  763. */
  764. Obj DoTestFilter (
  765. Obj self,
  766. Obj obj )
  767. {
  768. return True;
  769. }
  770. Obj NewTesterFilter (
  771. Obj getter )
  772. {
  773. Obj tester;
  774. tester = ReturnTrueFilter;
  775. return tester;
  776. }
  777. Obj DoSetFilter (
  778. Obj self,
  779. Obj obj,
  780. Obj val )
  781. {
  782. Int flag1;
  783. Obj kind;
  784. Obj flags;
  785. /* get the flag for the getter */
  786. flag1 = INT_INTOBJ( FLAG1_FILT( self ) );
  787. /* get the kind of the object and its flags */
  788. kind = TYPE_OBJ( obj );
  789. flags = FLAGS_TYPE( kind );
  790. /* return the value of the feature */
  791. if ( flag1 <= LEN_FLAGS( flags ) ) {
  792. if ( val != ELM_FLAGS( flags, flag1 ) ) {
  793. ErrorReturnVoid(
  794. "value feature is already set the other way",
  795. 0L, 0L,
  796. "you can 'return;' and ignore it" );
  797. }
  798. }
  799. else {
  800. if ( val != False ) {
  801. ErrorReturnVoid(
  802. "value feature is already set the other way",
  803. 0L, 0L,
  804. "you can 'return;' and ignore it" );
  805. }
  806. }
  807. /* return 'void' */
  808. return 0;
  809. }
  810. static Obj StringFilterSetter;
  811. static Obj ArglistObjVal;
  812. Obj NewSetterFilter (
  813. Obj getter )
  814. {
  815. Obj setter;
  816. setter = NewOperation( StringFilterSetter, 2, ArglistObjVal,
  817. DoSetFilter );
  818. FLAG1_FILT(setter) = FLAG1_FILT(getter);
  819. FLAG2_FILT(setter) = INTOBJ_INT( 0 );
  820. CHANGED_BAG(setter);
  821. return setter;
  822. }
  823. Obj DoFilter (
  824. Obj self,
  825. Obj obj )
  826. {
  827. Obj val;
  828. Int flag1;
  829. Obj kind;
  830. Obj flags;
  831. /* get the flag for the getter */
  832. flag1 = INT_INTOBJ( FLAG1_FILT( self ) );
  833. /* get the kind of the object and its flags */
  834. kind = TYPE_OBJ( obj );
  835. flags = FLAGS_TYPE( kind );
  836. /* return the value of the feature */
  837. if ( flag1 <= LEN_FLAGS( flags ) ) {
  838. val = ELM_FLAGS( flags, flag1 );
  839. }
  840. else {
  841. val = False;
  842. }
  843. /* return the value */
  844. return val;
  845. }
  846. Obj NewFilter (
  847. Obj name,
  848. Int narg,
  849. Obj nams,
  850. ObjFunc hdlr )
  851. {
  852. Obj getter;
  853. Obj setter;
  854. Obj tester;
  855. Int flag1;
  856. Obj flags;
  857. flag1 = ++CountFlags;
  858. getter = NewOperation( name, 1L, nams, (hdlr ? hdlr : DoFilter) );
  859. FLAG1_FILT(getter) = INTOBJ_INT( flag1 );
  860. FLAG2_FILT(getter) = INTOBJ_INT( 0 );
  861. NEW_FLAGS( flags, flag1 );
  862. SET_LEN_FLAGS( flags, flag1 );
  863. SET_ELM_FLAGS( flags, flag1, True );
  864. FLAGS_FILT(getter) = flags;
  865. CHANGED_BAG(getter);
  866. setter = NewSetterFilter( getter );
  867. SETTR_FILT(getter) = setter;
  868. CHANGED_BAG(getter);
  869. tester = NewTesterFilter( getter );
  870. TESTR_FILT(getter) = tester;
  871. CHANGED_BAG(getter);
  872. return getter;
  873. }
  874. /****************************************************************************
  875. **
  876. *F NewFilterC( <name>, <narg>, <nams>, <hdlr> ) . . . . . make a new filter
  877. */
  878. Obj NewFilterC (
  879. const Char * name,
  880. Int narg,
  881. const Char * nams,
  882. ObjFunc hdlr )
  883. {
  884. Obj getter;
  885. Obj setter;
  886. Obj tester;
  887. Int flag1;
  888. Obj flags;
  889. flag1 = ++CountFlags;
  890. getter = NewOperationC( name, 1L, nams, (hdlr ? hdlr : DoFilter) );
  891. FLAG1_FILT(getter) = INTOBJ_INT( flag1 );
  892. FLAG2_FILT(getter) = INTOBJ_INT( 0 );
  893. NEW_FLAGS( flags, flag1 );
  894. SET_LEN_FLAGS( flags, flag1 );
  895. SET_ELM_FLAGS( flags, flag1, True );
  896. FLAGS_FILT(getter) = flags;
  897. CHANGED_BAG(getter);
  898. setter = NewSetterFilter( getter );
  899. SETTR_FILT(getter) = setter;
  900. CHANGED_BAG(getter);
  901. tester = NewTesterFilter( getter );
  902. TESTR_FILT(getter) = tester;
  903. CHANGED_BAG(getter);
  904. return getter;
  905. }
  906. /****************************************************************************
  907. **
  908. *F NewAndFilter( <filt1>, <filt2> ) . . . . . make a new concatenated filter
  909. */
  910. Obj DoAndFilter (
  911. Obj self,
  912. Obj obj )
  913. {
  914. Obj val;
  915. Obj op;
  916. /* call the first 'and'-ed function */
  917. op = FLAG1_FILT( self );
  918. val = CALL_1ARGS( op, obj );
  919. if ( val != True ) return False;
  920. /* call the second 'and'-ed function */
  921. op = FLAG2_FILT( self );
  922. val = CALL_1ARGS( op, obj );
  923. if ( val != True ) return False;
  924. /* return 'true' */
  925. return True;
  926. }
  927. static Obj StringAndFilter;
  928. static Obj ArglistObj;
  929. Obj NewAndFilter (
  930. Obj oper1,
  931. Obj oper2 )
  932. {
  933. Obj getter;
  934. Obj flags;
  935. if ( oper1 == ReturnTrueFilter && oper2 == ReturnTrueFilter )
  936. return ReturnTrueFilter;
  937. getter = NewFunctionT( T_FUNCTION, SIZE_OPER, StringAndFilter, 1,
  938. ArglistObj, DoAndFilter );
  939. FLAG1_FILT(getter) = oper1;
  940. FLAG2_FILT(getter) = oper2;
  941. flags = FuncAND_FLAGS( 0, FLAGS_FILT(oper1), FLAGS_FILT(oper2) );
  942. FLAGS_FILT(getter) = flags;
  943. SETTR_FILT(getter) = INTOBJ_INT(0xBADBABE);
  944. TESTR_FILT(getter) = INTOBJ_INT(0xBADBABE);
  945. CHANGED_BAG(getter);
  946. return getter;
  947. }
  948. Obj FuncIS_AND_FILTER( Obj self, Obj filt )
  949. {
  950. return (IS_FUNC(filt) && HDLR_FUNC(filt, 1) == DoAndFilter) ? True : False;
  951. }
  952. /****************************************************************************
  953. **
  954. *V ReturnTrueFilter . . . . . . . . . . . . . . . . the return 'true' filter
  955. */
  956. Obj ReturnTrueFilter;
  957. /****************************************************************************
  958. **
  959. *F NewReturnTrueFilter() . . . . . . . . . . create a new return true filter
  960. */
  961. Obj DoTestReturnTrueFilter (
  962. Obj self,
  963. Obj obj )
  964. {
  965. return True;
  966. }
  967. Obj TesterReturnTrueFilter (
  968. Obj getter )
  969. {
  970. return getter;
  971. }
  972. Obj DoSetReturnTrueFilter (
  973. Obj self,
  974. Obj obj,
  975. Obj val )
  976. {
  977. if ( val != True ) {
  978. ErrorReturnVoid( "you cannot set this flag to 'false'",
  979. 0L, 0L,
  980. "you can 'return;' and ignore it" );
  981. }
  982. return 0;
  983. }
  984. Obj SetterReturnTrueFilter (
  985. Obj getter )
  986. {
  987. Obj setter;
  988. setter = NewFunctionCT( T_FUNCTION, SIZE_OPER,
  989. "<<setter-true-filter>>", 2L, "obj, val",
  990. DoSetReturnTrueFilter );
  991. FLAG1_FILT(setter) = INTOBJ_INT( 0 );
  992. FLAG2_FILT(setter) = INTOBJ_INT( 0 );
  993. CHANGED_BAG(setter);
  994. return setter;
  995. }
  996. Obj DoReturnTrueFilter (
  997. Obj self,
  998. Obj obj )
  999. {
  1000. return True;
  1001. }
  1002. Obj NewReturnTrueFilter ( void )
  1003. {
  1004. Obj getter;
  1005. Obj setter;
  1006. Obj tester;
  1007. Obj flags;
  1008. getter = NewFunctionCT( T_FUNCTION, SIZE_OPER,
  1009. "ReturnTrueFilter", 1L, "obj",
  1010. DoReturnTrueFilter );
  1011. FLAG1_FILT(getter) = INTOBJ_INT( 0 );
  1012. FLAG2_FILT(getter) = INTOBJ_INT( 0 );
  1013. NEW_FLAGS( flags, 0 );
  1014. SET_LEN_FLAGS( flags, 0 );
  1015. FLAGS_FILT(getter) = flags;
  1016. CHANGED_BAG(getter);
  1017. setter = SetterReturnTrueFilter( getter );
  1018. SETTR_FILT(getter) = setter;
  1019. CHANGED_BAG(getter);
  1020. tester = TesterReturnTrueFilter( getter );
  1021. TESTR_FILT(getter) = tester;
  1022. CHANGED_BAG(getter);
  1023. return getter;
  1024. }
  1025. /****************************************************************************
  1026. **
  1027. *F * * * * * * * * * * * * * GAP filter functions * * * * * * * * * * * * * *
  1028. */
  1029. /****************************************************************************
  1030. **
  1031. *F FuncNEW_FILTER( <self>, <name> ) . . . . . . . . . . . . . new filter
  1032. */
  1033. Obj FuncNEW_FILTER (
  1034. Obj self,
  1035. Obj name )
  1036. {
  1037. /* check the argument */
  1038. if ( ! IsStringConv(name) ) {
  1039. ErrorQuit("usage: NewFilter( <name> )",0L,0L);
  1040. return 0;
  1041. }
  1042. /* make the new operation */
  1043. return NewFilter( name, 1L, (Obj)0, (ObjFunc)0 );
  1044. }
  1045. /****************************************************************************
  1046. **
  1047. *F FuncFLAG1_FILTER( <self>, <oper> ) . . . . . . . . . . . . `FLAG1_FILT'
  1048. */
  1049. Obj FuncFLAG1_FILTER (
  1050. Obj self,
  1051. Obj oper )
  1052. {
  1053. Obj flag1;
  1054. if ( ! IS_OPERATION(oper) ) {
  1055. ErrorQuit("<oper> must be an operation",0L,0L);
  1056. return 0;
  1057. }
  1058. flag1 = FLAG1_FILT( oper );
  1059. if ( flag1 == 0 )
  1060. flag1 = INTOBJ_INT(0);
  1061. return flag1;
  1062. }
  1063. /****************************************************************************
  1064. **
  1065. *F FuncSET_FLAG1_FILTER( <self>, <oper>, <flag1> ) . . . . set `FLAG1_FILT'
  1066. */
  1067. Obj FuncSET_FLAG1_FILTER (
  1068. Obj self,
  1069. Obj oper,
  1070. Obj flag1 )
  1071. {
  1072. if ( ! IS_OPERATION(oper) ) {
  1073. ErrorQuit("<oper> must be an operation",0L,0L);
  1074. return 0;
  1075. }
  1076. FLAG1_FILT( oper ) = flag1;
  1077. return 0;
  1078. }
  1079. /****************************************************************************
  1080. **
  1081. *F FuncFLAG2_FILTER( <self>, <oper> ) . . . . . . . . . . . . `FLAG2_FILT'
  1082. */
  1083. Obj FuncFLAG2_FILTER (
  1084. Obj self,
  1085. Obj oper )
  1086. {
  1087. Obj flag2;
  1088. if ( ! IS_OPERATION(oper) ) {
  1089. ErrorQuit("<oper> must be an operation",0L,0L);
  1090. return 0;
  1091. }
  1092. flag2 = FLAG2_FILT( oper );
  1093. if ( flag2 == 0 )
  1094. flag2 = INTOBJ_INT(0);
  1095. return flag2;
  1096. }
  1097. /****************************************************************************
  1098. **
  1099. *F FuncSET_FLAG2_FILTER( <self>, <oper>, <flag2> ) . . . . set `FLAG2_FILT'
  1100. */
  1101. Obj FuncSET_FLAG2_FILTER (
  1102. Obj self,
  1103. Obj oper,
  1104. Obj flag2 )
  1105. {
  1106. if ( ! IS_OPERATION(oper) ) {
  1107. ErrorQuit("<oper> must be an operation",0L,0L);
  1108. return 0;
  1109. }
  1110. FLAG2_FILT( oper ) = flag2;
  1111. return 0;
  1112. }
  1113. /****************************************************************************
  1114. **
  1115. *F FuncFLAGS_FILTER( <self>, <oper> ) . . . . . . . . . . . . `FLAGS_FILT'
  1116. */
  1117. Obj FuncFLAGS_FILTER (
  1118. Obj self,
  1119. Obj oper )
  1120. {
  1121. Obj flags;
  1122. if ( ! IS_OPERATION(oper) ) {
  1123. ErrorQuit("<oper> must be an operation",0L,0L);
  1124. return 0;
  1125. }
  1126. flags = FLAGS_FILT( oper );
  1127. if ( flags == 0 )
  1128. flags = False;
  1129. return flags;
  1130. }
  1131. /****************************************************************************
  1132. **
  1133. *F FuncSET_FLAGS_FILTER( <self>, <oper>, <flags> ) . . . . set `FLAGS_FILT'
  1134. */
  1135. Obj FuncSET_FLAGS_FILTER (
  1136. Obj self,
  1137. Obj oper,
  1138. Obj flags )
  1139. {
  1140. if ( ! IS_OPERATION(oper) ) {
  1141. ErrorQuit("<oper> must be an operation",0L,0L);
  1142. return 0;
  1143. }
  1144. FLAGS_FILT( oper ) = flags;
  1145. return 0;
  1146. }
  1147. /****************************************************************************
  1148. **
  1149. *F FuncSETTER_FILTER( <self>, <oper> ) . . . . . . . . . setter of a filter
  1150. */
  1151. Obj FuncSETTER_FILTER (
  1152. Obj self,
  1153. Obj oper )
  1154. {
  1155. Obj setter;
  1156. if ( ! IS_OPERATION(oper) ) {
  1157. ErrorQuit("<oper> must be an operation",0L,0L);
  1158. return 0;
  1159. }
  1160. setter = SetterFilter( oper );
  1161. if ( setter == 0 ) setter = False;
  1162. return setter;
  1163. }
  1164. /****************************************************************************
  1165. **
  1166. *F FuncSET_SETTER_FILTER( <self>, <oper>, <setter> ) set setter of a filter
  1167. */
  1168. Obj FuncSET_SETTER_FILTER (
  1169. Obj self,
  1170. Obj oper,
  1171. Obj setter )
  1172. {
  1173. if ( ! IS_OPERATION(oper) ) {
  1174. ErrorQuit("<oper> must be an operation",0L,0L);
  1175. return 0;
  1176. }
  1177. SETTR_FILT( oper ) = setter;
  1178. return 0;
  1179. }
  1180. /****************************************************************************
  1181. **
  1182. *F FuncTESTER_FILTER( <self>, <oper> ) . . . . . . . . . tester of a filter
  1183. */
  1184. Obj FuncTESTER_FILTER (
  1185. Obj self,
  1186. Obj oper )
  1187. {
  1188. Obj tester;
  1189. if ( ! IS_OPERATION(oper) ) {
  1190. ErrorQuit("<oper> must be an operation",0L,0L);
  1191. return 0;
  1192. }
  1193. tester = TesterFilter( oper );
  1194. if ( tester == 0 ) tester = False;
  1195. return tester;
  1196. }
  1197. /****************************************************************************
  1198. **
  1199. *F FuncSET_TESTER_FILTER( <self>, <oper>, <tester> ) set tester of a filter
  1200. */
  1201. Obj FuncSET_TESTER_FILTER (
  1202. Obj self,
  1203. Obj oper,
  1204. Obj tester )
  1205. {
  1206. if ( ! IS_OPERATION(oper) ) {
  1207. ErrorQuit("<oper> must be an operation",0L,0L);
  1208. return 0;
  1209. }
  1210. if ( SIZE_OBJ(oper) != SIZE_OPER ) {
  1211. ResizeBag( oper, SIZE_OPER );
  1212. }
  1213. TESTR_FILT( oper ) = tester;
  1214. return 0;
  1215. }
  1216. /****************************************************************************
  1217. **
  1218. *F * * * * * * * * * * internal operation functions * * * * * * * * * * * *
  1219. */
  1220. /****************************************************************************
  1221. **
  1222. *F CallHandleMethodNotFound( <oper>, <nargs>, <args>, <verbose>, <constructor>)
  1223. **
  1224. */
  1225. static UInt RNamOperation;
  1226. static UInt RNamArguments;
  1227. static UInt RNamIsVerbose;
  1228. static UInt RNamIsConstructor;
  1229. static UInt RNamPrecedence;
  1230. static Obj HandleMethodNotFound;
  1231. Obj CallHandleMethodNotFound( Obj oper,
  1232. Int nargs,
  1233. Obj *args,
  1234. UInt verbose,
  1235. UInt constructor,
  1236. Obj precedence)
  1237. {
  1238. Obj r;
  1239. Obj arglist;
  1240. UInt i;
  1241. r = NEW_PREC(5);
  1242. if (RNamOperation == 0)
  1243. {
  1244. /* we can't do this in initialization because opers
  1245. is initialized BEFORE records */
  1246. RNamIsConstructor = RNamName("isConstructor");
  1247. RNamIsVerbose = RNamName("isVerbose");
  1248. RNamOperation = RNamName("Operation");
  1249. RNamArguments = RNamName("Arguments");
  1250. RNamPrecedence = RNamName("Precedence");
  1251. }
  1252. AssPRec(r,RNamOperation,oper);
  1253. arglist = NEW_PLIST(nargs ? T_PLIST_DENSE+IMMUTABLE:
  1254. T_PLIST_EMPTY+IMMUTABLE, nargs);
  1255. SET_LEN_PLIST(arglist,nargs);
  1256. for (i = 0; i < nargs; i++)
  1257. SET_ELM_PLIST( arglist, i+1, args[i]);
  1258. AssPRec(r,RNamArguments,arglist);
  1259. AssPRec(r,RNamIsVerbose,verbose ? True : False);
  1260. AssPRec(r,RNamIsConstructor,constructor ? True : False);
  1261. AssPRec(r,RNamPrecedence,precedence);
  1262. SortPRecRNam(r,0);
  1263. return CALL_1ARGS(HandleMethodNotFound, r);
  1264. }
  1265. /****************************************************************************
  1266. **
  1267. *F FuncCompactTypeIDs( <self> ) . . . garbage collect the type IDs
  1268. **
  1269. */
  1270. static Int NextTypeID;
  1271. Obj IsType;
  1272. static void FixTypeIDs( Bag b ) {
  1273. if ( (TNUM_OBJ( b ) == T_POSOBJ) &&
  1274. (DoFilter(IsType, b ) == True ))
  1275. {
  1276. ID_TYPE(b) = INTOBJ_INT(NextTypeID);
  1277. NextTypeID++;
  1278. }
  1279. }
  1280. Obj FuncCompactTypeIDs( Obj self )
  1281. {
  1282. NextTypeID = -(1L << NR_SMALL_INT_BITS);
  1283. CallbackForAllBags( FixTypeIDs );
  1284. return INTOBJ_INT(NextTypeID);
  1285. }
  1286. /****************************************************************************
  1287. **
  1288. *F DoOperation( <name> ) . . . . . . . . . . . . . . . make a new operation
  1289. */
  1290. UInt CacheIndex;
  1291. Obj Method0Args;
  1292. Obj NextMethod0Args;
  1293. Obj Method1Args;
  1294. Obj NextMethod1Args;
  1295. Obj Method2Args;
  1296. Obj NextMethod2Args;
  1297. Obj Method3Args;
  1298. Obj NextMethod3Args;
  1299. Obj Method4Args;
  1300. Obj NextMethod4Args;
  1301. Obj Method5Args;
  1302. Obj NextMethod5Args;
  1303. Obj Method6Args;
  1304. Obj NextMethod6Args;
  1305. Obj MethodXArgs;
  1306. Obj NextMethodXArgs;
  1307. Obj VMethod0Args;
  1308. Obj NextVMethod0Args;
  1309. Obj VMethod1Args;
  1310. Obj NextVMethod1Args;
  1311. Obj VMethod2Args;
  1312. Obj NextVMethod2Args;
  1313. Obj VMethod3Args;
  1314. Obj NextVMethod3Args;
  1315. Obj VMethod4Args;
  1316. Obj NextVMethod4Args;
  1317. Obj VMethod5Args;
  1318. Obj NextVMethod5Args;
  1319. Obj VMethod6Args;
  1320. Obj NextVMethod6Args;
  1321. Obj VMethodXArgs;
  1322. Obj NextVMethodXArgs;
  1323. /****************************************************************************
  1324. **
  1325. ** DoOperation0Args( <oper> )
  1326. */
  1327. Int OperationHit;
  1328. Int OperationMiss;
  1329. Int OperationNext;
  1330. /* This avoids a function call in the case of external objects with a
  1331. stored type */
  1332. static inline Obj TYPE_OBJ_FEO (
  1333. Obj obj
  1334. )
  1335. {
  1336. if ( TNUM_OBJ(obj) >= FIRST_EXTERNAL_TNUM &&
  1337. TNUM_OBJ(obj) <= T_DATOBJ) /* avoid T_WPOBJ */
  1338. return TYPE_ANYOBJ(obj);
  1339. else
  1340. return TYPE_OBJ(obj);
  1341. }
  1342. static inline Obj CacheOper (
  1343. Obj oper,
  1344. UInt i )
  1345. {
  1346. Obj cache;
  1347. UInt len;
  1348. cache = CACHE_OPER( oper, i );
  1349. if ( cache == 0 ) {
  1350. len = (i < 7 ? CACHE_SIZE * (i+2) : CACHE_SIZE * (1+2)) ;
  1351. cache = NEW_PLIST( T_PLIST, len);
  1352. SET_LEN_PLIST(cache, len );
  1353. CACHE_OPER( oper, i ) = cache;
  1354. CHANGED_BAG( oper );
  1355. }
  1356. return cache;
  1357. }
  1358. Obj DoOperation0Args (
  1359. Obj oper )
  1360. {
  1361. Obj res;
  1362. Obj * cache;
  1363. Obj method;
  1364. Int i;
  1365. Obj prec;
  1366. /* try to find an applicable method in the cache */
  1367. cache = 1+ADDR_OBJ( CacheOper( oper, 0 ) );
  1368. prec = INTOBJ_INT(-1);
  1369. do {
  1370. /* The next line depends on the implementation of INTOBJS */
  1371. prec = (Obj)(((Int)prec) +4);
  1372. method = 0;
  1373. /* Up to CACHE_SIZE methods might be in the cache */
  1374. if (prec < INTOBJ_INT(CACHE_SIZE))
  1375. {
  1376. for (i = 0; i < 2*CACHE_SIZE; i+= 2) {
  1377. if ( cache[i] != 0 && cache[i+1] == prec) {
  1378. method = cache[i];
  1379. #ifdef COUNT_OPERS
  1380. OperationHit++;
  1381. #endif
  1382. break;
  1383. }
  1384. }
  1385. }
  1386. /* otherwise try to find one in the list of methods */
  1387. if (!method)
  1388. {
  1389. if (prec == INTOBJ_INT(0))
  1390. method = CALL_1ARGS( Method0Args, oper );
  1391. else
  1392. method = CALL_2ARGS( NextMethod0Args, oper, prec );
  1393. /* If there was no method found, then pass the information needed for
  1394. the error reporting. This function rarely returns */
  1395. while (method == Fail)
  1396. method = CallHandleMethodNotFound( oper, 0, (Obj *) 0, 0, 0, prec);
  1397. /* update the cache */
  1398. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  1399. {
  1400. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 0 ) );
  1401. cache[2*CacheIndex] = method;
  1402. cache[2*CacheIndex+1] = prec;
  1403. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  1404. CHANGED_BAG(CACHE_OPER(oper,0));
  1405. }
  1406. #ifdef COUNT_OPERS
  1407. OperationMiss++;
  1408. #endif
  1409. }
  1410. if ( !method ) {
  1411. ErrorQuit( "no method returned", 0L, 0L );
  1412. }
  1413. /* call this method */
  1414. res = CALL_0ARGS( method );
  1415. }
  1416. while (res == TRY_NEXT_METHOD );
  1417. /* return the result */
  1418. return res;
  1419. }
  1420. /****************************************************************************
  1421. **
  1422. ** DoOperation1Args( <oper>, <a1> )
  1423. */
  1424. Obj DoOperation1Args (
  1425. Obj oper,
  1426. Obj arg1 )
  1427. {
  1428. Obj res;
  1429. Obj kind1;
  1430. Obj id1;
  1431. Obj * cache;
  1432. Obj method;
  1433. Int i;
  1434. Obj prec;
  1435. /* get the kinds of the arguments */
  1436. kind1 = TYPE_OBJ_FEO( arg1 ); id1 = ID_TYPE( kind1 );
  1437. /* try to find an applicable method in the cache */
  1438. cache = 1+ADDR_OBJ( CacheOper( oper, 1 ) );
  1439. prec = INTOBJ_INT(-1);
  1440. do {
  1441. /* The next line depends on the implementation of INTOBJS */
  1442. prec = (Obj)(((Int)prec) +4);
  1443. method = 0;
  1444. /* Up to CACHE_SIZE methods might be in the cache */
  1445. if (prec < INTOBJ_INT(CACHE_SIZE))
  1446. {
  1447. for (i = 0; i < 3*CACHE_SIZE; i+= 3) {
  1448. if ( cache[i+1] == prec && cache[i+2] == id1 ) {
  1449. method = cache[i];
  1450. #ifdef COUNT_OPERS
  1451. OperationHit++;
  1452. #endif
  1453. break;
  1454. }
  1455. }
  1456. }
  1457. /* otherwise try to find one in the list of methods */
  1458. if (!method)
  1459. {
  1460. if (prec == INTOBJ_INT(0))
  1461. method = CALL_2ARGS( Method1Args, oper, kind1 );
  1462. else
  1463. method = CALL_3ARGS( NextMethod1Args, oper, prec, kind1 );
  1464. /* If there was no method found, then pass the information needed for
  1465. the error reporting. This function rarely returns */
  1466. if (method == Fail)
  1467. {
  1468. Obj args[1];
  1469. args[0] = arg1;
  1470. while (method == Fail)
  1471. method = CallHandleMethodNotFound( oper, 1, (Obj *) args, 0, 0, prec);
  1472. }
  1473. /* update the cache */
  1474. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  1475. {
  1476. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 1 ) );
  1477. cache[3*CacheIndex] = method;
  1478. cache[3*CacheIndex+1] = prec;
  1479. cache[3*CacheIndex+2] = id1;
  1480. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  1481. CHANGED_BAG(CACHE_OPER(oper,1));
  1482. }
  1483. #ifdef COUNT_OPERS
  1484. OperationMiss++;
  1485. #endif
  1486. }
  1487. if ( !method ) {
  1488. ErrorQuit( "no method returned", 0L, 0L );
  1489. }
  1490. /* call this method */
  1491. res = CALL_1ARGS( method, arg1 );
  1492. }
  1493. while (res == TRY_NEXT_METHOD );
  1494. /* return the result */
  1495. return res;
  1496. }
  1497. /****************************************************************************
  1498. **
  1499. ** DoOperation2Args( <oper>, <a1>, <a2> )
  1500. */
  1501. Obj DoOperation2Args (
  1502. Obj oper,
  1503. Obj arg1,
  1504. Obj arg2 )
  1505. {
  1506. Obj res;
  1507. Obj kind1;
  1508. Obj id1;
  1509. Obj kind2;
  1510. Obj id2;
  1511. Obj * cache;
  1512. Obj method;
  1513. Int i;
  1514. Obj prec;
  1515. /* get the kinds of the arguments */
  1516. kind1 = TYPE_OBJ_FEO( arg1 ); id1 = ID_TYPE( kind1 );
  1517. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  1518. /* try to find an applicable method in the cache */
  1519. cache = 1+ADDR_OBJ( CacheOper( oper, 2 ) );
  1520. prec = INTOBJ_INT(-1);
  1521. do {
  1522. /* The next line depends on the implementation of INTOBJS */
  1523. prec = (Obj)(((Int)prec) +4);
  1524. method = 0;
  1525. /* Up to CACHE_SIZE methods might be in the cache */
  1526. if (prec < INTOBJ_INT(CACHE_SIZE))
  1527. {
  1528. for (i = 0; i < 4*CACHE_SIZE; i+= 4) {
  1529. if ( cache[i+1] == prec && cache[i+2] == id1
  1530. && cache[i+3] == id2 ) {
  1531. method = cache[i];
  1532. #ifdef COUNT_OPERS
  1533. OperationHit++;
  1534. #endif
  1535. break;
  1536. }
  1537. }
  1538. }
  1539. /* otherwise try to find one in the list of methods */
  1540. if (!method)
  1541. {
  1542. if (prec == INTOBJ_INT(0))
  1543. method = CALL_3ARGS( Method2Args, oper, kind1, kind2 );
  1544. else
  1545. method = CALL_4ARGS( NextMethod2Args, oper, prec, kind1, kind2 );
  1546. /* If there was no method found, then pass the information needed for
  1547. the error reporting. This function rarely returns */
  1548. if (method == Fail)
  1549. {
  1550. Obj args[2];
  1551. args[0] = arg1;
  1552. args[1] = arg2;
  1553. while (method == Fail)
  1554. method = CallHandleMethodNotFound( oper, 2, (Obj *) args, 0, 0, prec);
  1555. }
  1556. /* update the cache */
  1557. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  1558. {
  1559. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 2 ) );
  1560. cache[4*CacheIndex] = method;
  1561. cache[4*CacheIndex+1] = prec;
  1562. cache[4*CacheIndex+2] = id1;
  1563. cache[4*CacheIndex+3] = id2;
  1564. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  1565. CHANGED_BAG(CACHE_OPER(oper,2));
  1566. }
  1567. #ifdef COUNT_OPERS
  1568. OperationMiss++;
  1569. #endif
  1570. }
  1571. if ( !method ) {
  1572. ErrorQuit( "no method returned", 0L, 0L );
  1573. }
  1574. /* call this method */
  1575. res = CALL_2ARGS( method, arg1, arg2 );
  1576. }
  1577. while (res == TRY_NEXT_METHOD );
  1578. /* return the result */
  1579. return res;
  1580. }
  1581. /****************************************************************************
  1582. **
  1583. ** DoOperation3Args( <oper>, <a1>, <a2>, <a3> )
  1584. */
  1585. Obj DoOperation3Args (
  1586. Obj oper,
  1587. Obj arg1,
  1588. Obj arg2,
  1589. Obj arg3 )
  1590. {
  1591. Obj res;
  1592. Obj kind1;
  1593. Obj id1;
  1594. Obj kind2;
  1595. Obj id2;
  1596. Obj kind3;
  1597. Obj id3;
  1598. Obj * cache;
  1599. Obj method;
  1600. Int i;
  1601. Obj prec;
  1602. /* get the kinds of the arguments */
  1603. kind1 = TYPE_OBJ_FEO( arg1 ); id1 = ID_TYPE( kind1 );
  1604. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  1605. kind3 = TYPE_OBJ_FEO( arg3 ); id3 = ID_TYPE( kind3 );
  1606. /* try to find an applicable method in the cache */
  1607. cache = 1+ADDR_OBJ( CacheOper( oper, 3 ) );
  1608. prec = INTOBJ_INT(-1);
  1609. do {
  1610. /* The next line depends on the implementation of INTOBJS */
  1611. prec = (Obj)(((Int)prec) +4);
  1612. method = 0;
  1613. /* Up to CACHE_SIZE methods might be in the cache */
  1614. if (prec < INTOBJ_INT(CACHE_SIZE))
  1615. {
  1616. for (i = 0; i < 5*CACHE_SIZE; i+= 5) {
  1617. if ( cache[i+1] == prec && cache[i+2] == id1
  1618. && cache[i+3] == id2 && cache[i+4] == id3 ) {
  1619. method = cache[i];
  1620. #ifdef COUNT_OPERS
  1621. OperationHit++;
  1622. #endif
  1623. break;
  1624. }
  1625. }
  1626. }
  1627. /* otherwise try to find one in the list of methods */
  1628. if (!method)
  1629. {
  1630. if (prec == INTOBJ_INT(0))
  1631. method = CALL_4ARGS( Method3Args, oper, kind1, kind2, kind3 );
  1632. else
  1633. method = CALL_5ARGS( NextMethod3Args, oper, prec, kind1, kind2, kind3 );
  1634. /* If there was no method found, then pass the information needed for
  1635. the error reporting. This function rarely returns */
  1636. if (method == Fail)
  1637. {
  1638. Obj args[3];
  1639. args[0] = arg1;
  1640. args[1] = arg2;
  1641. args[2] = arg3;
  1642. while (method == Fail)
  1643. method = CallHandleMethodNotFound( oper, 3, (Obj *) args, 0, 0, prec);
  1644. }
  1645. /* update the cache */
  1646. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  1647. {
  1648. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 3 ) );
  1649. cache[5*CacheIndex] = method;
  1650. cache[5*CacheIndex+1] = prec;
  1651. cache[5*CacheIndex+2] = id1;
  1652. cache[5*CacheIndex+3] = id2;
  1653. cache[5*CacheIndex+4] = id3;
  1654. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  1655. CHANGED_BAG(CACHE_OPER(oper,3));
  1656. }
  1657. #ifdef COUNT_OPERS
  1658. OperationMiss++;
  1659. #endif
  1660. }
  1661. if ( !method ) {
  1662. ErrorQuit( "no method returned", 0L, 0L );
  1663. }
  1664. /* call this method */
  1665. res = CALL_3ARGS( method, arg1, arg2, arg3 );
  1666. }
  1667. while (res == TRY_NEXT_METHOD );
  1668. /* return the result */
  1669. return res;
  1670. }
  1671. /****************************************************************************
  1672. **
  1673. ** DoOperation4Args( <oper>, <a1>, <a2>, <a3>, <a4> )
  1674. */
  1675. Obj DoOperation4Args (
  1676. Obj oper,
  1677. Obj arg1,
  1678. Obj arg2,
  1679. Obj arg3,
  1680. Obj arg4 )
  1681. {
  1682. Obj res;
  1683. Obj kind1;
  1684. Obj id1;
  1685. Obj kind2;
  1686. Obj id2;
  1687. Obj kind3;
  1688. Obj id3;
  1689. Obj kind4;
  1690. Obj id4;
  1691. Obj * cache;
  1692. Obj method;
  1693. Int i;
  1694. Obj prec;
  1695. /* get the kinds of the arguments */
  1696. kind1 = TYPE_OBJ_FEO( arg1 ); id1 = ID_TYPE( kind1 );
  1697. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  1698. kind3 = TYPE_OBJ_FEO( arg3 ); id3 = ID_TYPE( kind3 );
  1699. kind4 = TYPE_OBJ_FEO( arg4 ); id4 = ID_TYPE( kind4 );
  1700. /* try to find an applicable method in the cache */
  1701. cache = 1+ADDR_OBJ( CacheOper( oper, 4 ) );
  1702. prec = INTOBJ_INT(-1);
  1703. do {
  1704. /* The next line depends on the implementation of INTOBJS */
  1705. prec = (Obj)(((Int)prec) +4);
  1706. method = 0;
  1707. /* Up to CACHE_SIZE methods might be in the cache */
  1708. if (prec < INTOBJ_INT(CACHE_SIZE))
  1709. {
  1710. for (i = 0; i < 6*CACHE_SIZE; i+= 6) {
  1711. if ( cache[i+1] == prec && cache[i+2] == id1 &&
  1712. cache[i+3] == id2 && cache[i+4] == id3 &&
  1713. cache[i+5] == id4 ) {
  1714. method = cache[i];
  1715. #ifdef COUNT_OPERS
  1716. OperationHit++;
  1717. #endif
  1718. break;
  1719. }
  1720. }
  1721. }
  1722. /* otherwise try to find one in the list of methods */
  1723. if (!method)
  1724. {
  1725. if (prec == INTOBJ_INT(0))
  1726. method = CALL_5ARGS( Method4Args, oper, kind1, kind2, kind3, kind4 );
  1727. else
  1728. method = CALL_6ARGS( NextMethod4Args, oper, prec, kind1, kind2, kind3, kind4 );
  1729. /* If there was no method found, then pass the information needed for
  1730. the error reporting. This function rarely returns */
  1731. if (method == Fail)
  1732. {
  1733. Obj args[4];
  1734. args[0] = arg1;
  1735. args[1] = arg2;
  1736. args[2] = arg3;
  1737. args[3] = arg4;
  1738. while (method == Fail)
  1739. method = CallHandleMethodNotFound( oper, 4, (Obj *) args, 0, 0, prec);
  1740. }
  1741. /* update the cache */
  1742. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  1743. {
  1744. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 4 ) );
  1745. cache[6*CacheIndex] = method;
  1746. cache[6*CacheIndex+1] = prec;
  1747. cache[6*CacheIndex+2] = id1;
  1748. cache[6*CacheIndex+3] = id2;
  1749. cache[6*CacheIndex+4] = id3;
  1750. cache[6*CacheIndex+5] = id4;
  1751. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  1752. CHANGED_BAG(CACHE_OPER(oper,4));
  1753. }
  1754. #ifdef COUNT_OPERS
  1755. OperationMiss++;
  1756. #endif
  1757. }
  1758. if ( !method ) {
  1759. ErrorQuit( "no method returned", 0L, 0L );
  1760. }
  1761. /* call this method */
  1762. res = CALL_4ARGS( method, arg1, arg2, arg3, arg4 );
  1763. }
  1764. while (res == TRY_NEXT_METHOD );
  1765. /* return the result */
  1766. return res;
  1767. }
  1768. /****************************************************************************
  1769. **
  1770. ** DoOperation5Args( <oper>, <a1>, <a2>, <a3>, <a4>, <a5> )
  1771. */
  1772. Obj DoOperation5Args (
  1773. Obj oper,
  1774. Obj arg1,
  1775. Obj arg2,
  1776. Obj arg3,
  1777. Obj arg4,
  1778. Obj arg5 )
  1779. {
  1780. Obj res;
  1781. Obj kind1;
  1782. Obj id1;
  1783. Obj kind2;
  1784. Obj id2;
  1785. Obj kind3;
  1786. Obj id3;
  1787. Obj kind4;
  1788. Obj id4;
  1789. Obj kind5;
  1790. Obj id5;
  1791. Obj * cache;
  1792. Obj method;
  1793. Int i;
  1794. Obj prec;
  1795. Obj margs;
  1796. /* get the kinds of the arguments */
  1797. kind1 = TYPE_OBJ_FEO( arg1 ); id1 = ID_TYPE( kind1 );
  1798. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  1799. kind3 = TYPE_OBJ_FEO( arg3 ); id3 = ID_TYPE( kind3 );
  1800. kind4 = TYPE_OBJ_FEO( arg4 ); id4 = ID_TYPE( kind4 );
  1801. kind5 = TYPE_OBJ_FEO( arg5 ); id5 = ID_TYPE( kind5 );
  1802. /* try to find an applicable method in the cache */
  1803. cache = 1+ADDR_OBJ( CacheOper( oper, 5 ) );
  1804. prec = INTOBJ_INT(-1);
  1805. do {
  1806. /* The next line depends on the implementation of INTOBJS */
  1807. prec = (Obj)(((Int)prec) +4);
  1808. method = 0;
  1809. /* Up to CACHE_SIZE methods might be in the cache */
  1810. if (prec < INTOBJ_INT(CACHE_SIZE))
  1811. {
  1812. for (i = 0; i < 7*CACHE_SIZE; i+= 7) {
  1813. if ( cache[i+1] == prec && cache[i+2] == id1 &&
  1814. cache[i+3] == id2 && cache[i+4] == id3 &&
  1815. cache[i+5] == id4 && cache[i+6] == id5 ) {
  1816. method = cache[i];
  1817. #ifdef COUNT_OPERS
  1818. OperationHit++;
  1819. #endif
  1820. break;
  1821. }
  1822. }
  1823. }
  1824. /* otherwise try to find one in the list of methods */
  1825. if (!method)
  1826. {
  1827. if (prec == INTOBJ_INT(0))
  1828. method = CALL_6ARGS( Method5Args, oper, kind1, kind2, kind3, kind4, kind5 );
  1829. else
  1830. {
  1831. margs = NEW_PLIST(T_PLIST, 7);
  1832. SET_ELM_PLIST(margs, 1, oper );
  1833. SET_ELM_PLIST(margs, 2, prec );
  1834. SET_ELM_PLIST(margs, 3, kind1 );
  1835. SET_ELM_PLIST(margs, 4, kind2 );
  1836. SET_ELM_PLIST(margs, 5, kind3 );
  1837. SET_ELM_PLIST(margs, 6, kind4 );
  1838. SET_ELM_PLIST(margs, 7, kind5 );
  1839. SET_LEN_PLIST(margs, 7);
  1840. method = CALL_XARGS( NextMethod5Args, margs );
  1841. }
  1842. /* If there was no method found, then pass the information needed for
  1843. the error reporting. This function rarely returns */
  1844. if (method == Fail)
  1845. {
  1846. Obj args[5];
  1847. args[0] = arg1;
  1848. args[1] = arg2;
  1849. args[2] = arg3;
  1850. args[3] = arg4;
  1851. args[4] = arg5;
  1852. while (method == Fail)
  1853. method = CallHandleMethodNotFound( oper, 5, (Obj *) args, 0, 0, prec);
  1854. }
  1855. /* update the cache */
  1856. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  1857. {
  1858. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 5 ) );
  1859. cache[7*CacheIndex] = method;
  1860. cache[7*CacheIndex+1] = prec;
  1861. cache[7*CacheIndex+2] = id1;
  1862. cache[7*CacheIndex+3] = id2;
  1863. cache[7*CacheIndex+4] = id3;
  1864. cache[7*CacheIndex+5] = id4;
  1865. cache[7*CacheIndex+6] = id5;
  1866. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  1867. CHANGED_BAG(CACHE_OPER(oper,5));
  1868. }
  1869. #ifdef COUNT_OPERS
  1870. OperationMiss++;
  1871. #endif
  1872. }
  1873. if ( !method ) {
  1874. ErrorQuit( "no method returned", 0L, 0L );
  1875. }
  1876. /* call this method */
  1877. res = CALL_5ARGS( method, arg1, arg2, arg3, arg4, arg5 );
  1878. }
  1879. while (res == TRY_NEXT_METHOD );
  1880. /* return the result */
  1881. return res;
  1882. }
  1883. /****************************************************************************
  1884. **
  1885. ** DoOperation6Args( <oper>, <a1>, <a2>, <a3>, <a4>, <a5>, <a6> )
  1886. */
  1887. Obj DoOperation6Args (
  1888. Obj oper,
  1889. Obj arg1,
  1890. Obj arg2,
  1891. Obj arg3,
  1892. Obj arg4,
  1893. Obj arg5,
  1894. Obj arg6 )
  1895. {
  1896. Obj res;
  1897. Obj kind1;
  1898. Obj id1;
  1899. Obj kind2;
  1900. Obj id2;
  1901. Obj kind3;
  1902. Obj id3;
  1903. Obj kind4;
  1904. Obj id4;
  1905. Obj kind5;
  1906. Obj id5;
  1907. Obj kind6;
  1908. Obj id6;
  1909. Obj * cache;
  1910. Obj method;
  1911. Obj margs;
  1912. Int i;
  1913. Obj prec;
  1914. /* get the kinds of the arguments */
  1915. kind1 = TYPE_OBJ_FEO( arg1 ); id1 = ID_TYPE( kind1 );
  1916. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  1917. kind3 = TYPE_OBJ_FEO( arg3 ); id3 = ID_TYPE( kind3 );
  1918. kind4 = TYPE_OBJ_FEO( arg4 ); id4 = ID_TYPE( kind4 );
  1919. kind5 = TYPE_OBJ_FEO( arg5 ); id5 = ID_TYPE( kind5 );
  1920. kind6 = TYPE_OBJ_FEO( arg6 ); id6 = ID_TYPE( kind6 );
  1921. /* try to find an applicable method in the cache */
  1922. cache = 1+ADDR_OBJ( CacheOper( oper, 6 ) );
  1923. prec = INTOBJ_INT(-1);
  1924. do {
  1925. /* The next line depends on the implementation of INTOBJS */
  1926. prec = (Obj)(((Int)prec) +4);
  1927. method = 0;
  1928. /* Up to CACHE_SIZE methods might be in the cache */
  1929. if (prec < INTOBJ_INT(CACHE_SIZE))
  1930. {
  1931. for (i = 0; i < 8*CACHE_SIZE; i+= 8) {
  1932. if ( cache[i+1] == prec && cache[i+2] == id1 &&
  1933. cache[i+3] == id2 && cache[i+4] == id3 &&
  1934. cache[i+5] == id4 && cache[i+6] == id5 &&
  1935. cache[i+7] == id6) {
  1936. method = cache[i];
  1937. #ifdef COUNT_OPERS
  1938. OperationHit++;
  1939. #endif
  1940. break;
  1941. }
  1942. }
  1943. }
  1944. /* otherwise try to find one in the list of methods */
  1945. if (!method)
  1946. {
  1947. if (prec == INTOBJ_INT(0))
  1948. {
  1949. margs = NEW_PLIST(T_PLIST, 7);
  1950. SET_ELM_PLIST(margs, 1, oper );
  1951. SET_ELM_PLIST(margs, 2, kind1 );
  1952. SET_ELM_PLIST(margs, 3, kind2 );
  1953. SET_ELM_PLIST(margs, 4, kind3 );
  1954. SET_ELM_PLIST(margs, 5, kind4 );
  1955. SET_ELM_PLIST(margs, 6, kind5 );
  1956. SET_ELM_PLIST(margs, 7, kind6 );
  1957. SET_LEN_PLIST(margs, 7);
  1958. method = CALL_XARGS( Method6Args, margs );
  1959. }
  1960. else
  1961. {
  1962. margs = NEW_PLIST(T_PLIST, 8);
  1963. SET_ELM_PLIST(margs, 1, oper );
  1964. SET_ELM_PLIST(margs, 2, prec );
  1965. SET_ELM_PLIST(margs, 3, kind1 );
  1966. SET_ELM_PLIST(margs, 4, kind2 );
  1967. SET_ELM_PLIST(margs, 5, kind3 );
  1968. SET_ELM_PLIST(margs, 6, kind4 );
  1969. SET_ELM_PLIST(margs, 7, kind5 );
  1970. SET_ELM_PLIST(margs, 8, kind6 );
  1971. SET_LEN_PLIST(margs, 8);
  1972. method = CALL_XARGS( NextMethod6Args, margs );
  1973. }
  1974. /* If there was no method found, then pass the information needed for
  1975. the error reporting. This function rarely returns */
  1976. if (method == Fail)
  1977. {
  1978. Obj args[6];
  1979. args[0] = arg1;
  1980. args[1] = arg2;
  1981. args[2] = arg3;
  1982. args[3] = arg4;
  1983. args[4] = arg5;
  1984. args[5] = arg6;
  1985. while (method == Fail)
  1986. method = CallHandleMethodNotFound( oper, 6, (Obj *) args, 0, 0, prec);
  1987. }
  1988. /* update the cache */
  1989. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  1990. {
  1991. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 6 ) );
  1992. cache[8*CacheIndex] = method;
  1993. cache[8*CacheIndex+1] = prec;
  1994. cache[8*CacheIndex+2] = id1;
  1995. cache[8*CacheIndex+3] = id2;
  1996. cache[8*CacheIndex+4] = id3;
  1997. cache[8*CacheIndex+5] = id4;
  1998. cache[8*CacheIndex+6] = id5;
  1999. cache[8*CacheIndex+7] = id6;
  2000. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  2001. CHANGED_BAG(CACHE_OPER(oper,6));
  2002. }
  2003. #ifdef COUNT_OPERS
  2004. OperationMiss++;
  2005. #endif
  2006. }
  2007. if ( !method ) {
  2008. ErrorQuit( "no method returned", 0L, 0L );
  2009. }
  2010. /* call this method */
  2011. res = CALL_6ARGS( method, arg1, arg2, arg3, arg4, arg5, arg6 );
  2012. }
  2013. while (res == TRY_NEXT_METHOD );
  2014. /* return the result */
  2015. return res;
  2016. }
  2017. /****************************************************************************
  2018. **
  2019. ** DoOperationXArgs( <oper>, ... )
  2020. */
  2021. Obj DoOperationXArgs (
  2022. Obj self,
  2023. Obj args )
  2024. {
  2025. ErrorQuit("sorry: cannot yet have X argument operations",0L,0L);
  2026. return 0;
  2027. }
  2028. /****************************************************************************
  2029. **
  2030. ** DoVerboseOperation0Args( <oper> )
  2031. */
  2032. Obj DoVerboseOperation0Args (
  2033. Obj oper )
  2034. {
  2035. Obj res;
  2036. Obj method;
  2037. Int i;
  2038. /* try to find one in the list of methods */
  2039. method = CALL_1ARGS( VMethod0Args, oper );
  2040. while (method == Fail)
  2041. {
  2042. method = CallHandleMethodNotFound( oper, 0, (Obj *) 0, 1, 0, INTOBJ_INT(0));
  2043. }
  2044. if ( method == 0 ) {
  2045. ErrorQuit( "no method returned", 0L, 0L );
  2046. }
  2047. /* call this method */
  2048. res = CALL_0ARGS( method );
  2049. /* try until a method doesn't give up */
  2050. if ( res == TRY_NEXT_METHOD ) {
  2051. i = 1;
  2052. while ( res == TRY_NEXT_METHOD ) {
  2053. #ifdef COUNT_OPERS
  2054. OperationNext++;
  2055. #endif
  2056. method = CALL_2ARGS( NextVMethod0Args, oper, INTOBJ_INT(i) );
  2057. while (method == Fail)
  2058. {
  2059. method = CallHandleMethodNotFound( oper, 0, (Obj *) 0, 1, 0, INTOBJ_INT(i));
  2060. }
  2061. i++;
  2062. res = CALL_0ARGS( method );
  2063. }
  2064. }
  2065. /* return the result */
  2066. return res;
  2067. }
  2068. /****************************************************************************
  2069. **
  2070. ** DoVerboseOperation1Args( <oper>, <a1> )
  2071. */
  2072. Obj DoVerboseOperation1Args (
  2073. Obj oper,
  2074. Obj arg1 )
  2075. {
  2076. Obj res;
  2077. Obj kind1;
  2078. Obj method;
  2079. Int i;
  2080. /* get the kinds of the arguments */
  2081. kind1 = TYPE_OBJ_FEO( arg1 );
  2082. /* try to find one in the list of methods */
  2083. method = CALL_2ARGS( VMethod1Args, oper, kind1 );
  2084. while (method == Fail)
  2085. {
  2086. Obj arglist[1];
  2087. arglist[0] = arg1;
  2088. method = CallHandleMethodNotFound( oper, 1, arglist, 1, 0, INTOBJ_INT(0));
  2089. }
  2090. if ( method == 0 ) {
  2091. ErrorQuit( "no method returned", 0L, 0L );
  2092. }
  2093. /* call this method */
  2094. res = CALL_1ARGS( method, arg1 );
  2095. /* try until a method doesn't give up */
  2096. if ( res == TRY_NEXT_METHOD ) {
  2097. i = 1;
  2098. while ( res == TRY_NEXT_METHOD ) {
  2099. #ifdef COUNT_OPERS
  2100. OperationNext++;
  2101. #endif
  2102. method = CALL_3ARGS( NextVMethod1Args, oper, INTOBJ_INT(i),
  2103. kind1 );
  2104. while (method == Fail)
  2105. {
  2106. Obj arglist[1];
  2107. arglist[0] = arg1;
  2108. method = CallHandleMethodNotFound( oper, 1, arglist, 1, 0, INTOBJ_INT(i));
  2109. }
  2110. i++;
  2111. res = CALL_1ARGS( method, arg1 );
  2112. }
  2113. }
  2114. /* return the result */
  2115. return res;
  2116. }
  2117. /****************************************************************************
  2118. **
  2119. ** DoVerboseOperation2Args( <oper>, <a1>, <a2> )
  2120. */
  2121. Obj DoVerboseOperation2Args (
  2122. Obj oper,
  2123. Obj arg1,
  2124. Obj arg2 )
  2125. {
  2126. Obj res;
  2127. Obj kind1;
  2128. Obj kind2;
  2129. Obj method;
  2130. Int i;
  2131. /* get the kinds of the arguments */
  2132. kind1 = TYPE_OBJ_FEO( arg1 );
  2133. kind2 = TYPE_OBJ_FEO( arg2 );
  2134. /* try to find one in the list of methods */
  2135. method = CALL_3ARGS( VMethod2Args, oper, kind1, kind2 );
  2136. while (method == Fail)
  2137. {
  2138. Obj arglist[2];
  2139. arglist[0] = arg1;
  2140. arglist[1] = arg2;
  2141. method = CallHandleMethodNotFound( oper, 2, arglist, 1, 0, INTOBJ_INT(0));
  2142. }
  2143. if ( method == 0 ) {
  2144. ErrorQuit( "no method returned", 0L, 0L );
  2145. }
  2146. /* call this method */
  2147. res = CALL_2ARGS( method, arg1, arg2 );
  2148. /* try until a method doesn't give up */
  2149. if ( res == TRY_NEXT_METHOD ) {
  2150. i = 1;
  2151. while ( res == TRY_NEXT_METHOD ) {
  2152. #ifdef COUNT_OPERS
  2153. OperationNext++;
  2154. #endif
  2155. method = CALL_4ARGS( NextVMethod2Args, oper, INTOBJ_INT(i),
  2156. kind1, kind2 );
  2157. while (method == Fail)
  2158. {
  2159. Obj arglist[2];
  2160. arglist[0] = arg1;
  2161. arglist[1] = arg2;
  2162. method = CallHandleMethodNotFound( oper, 2, arglist, 1, 0, INTOBJ_INT(i));
  2163. }
  2164. i++;
  2165. res = CALL_2ARGS( method, arg1, arg2 );
  2166. }
  2167. }
  2168. /* return the result */
  2169. return res;
  2170. }
  2171. /****************************************************************************
  2172. **
  2173. ** DoVerboseOperation3Args( <oper>, <a1>, <a2>, <a3> )
  2174. */
  2175. Obj DoVerboseOperation3Args (
  2176. Obj oper,
  2177. Obj arg1,
  2178. Obj arg2,
  2179. Obj arg3 )
  2180. {
  2181. Obj res;
  2182. Obj kind1;
  2183. Obj kind2;
  2184. Obj kind3;
  2185. Obj method;
  2186. Int i;
  2187. /* get the kinds of the arguments */
  2188. kind1 = TYPE_OBJ_FEO( arg1 );
  2189. kind2 = TYPE_OBJ_FEO( arg2 );
  2190. kind3 = TYPE_OBJ_FEO( arg3 );
  2191. /* try to find one in the list of methods */
  2192. method = CALL_4ARGS( VMethod3Args, oper, kind1, kind2, kind3 );
  2193. while (method == Fail)
  2194. {
  2195. Obj arglist[3];
  2196. arglist[0] = arg1;
  2197. arglist[1] = arg2;
  2198. arglist[2] = arg3;
  2199. method = CallHandleMethodNotFound( oper, 3, arglist, 1, 0, INTOBJ_INT(0));
  2200. }
  2201. if ( method == 0 ) {
  2202. ErrorQuit( "no method returned", 0L, 0L );
  2203. }
  2204. /* call this method */
  2205. res = CALL_3ARGS( method, arg1, arg2, arg3 );
  2206. /* try until a method doesn't give up */
  2207. if ( res == TRY_NEXT_METHOD ) {
  2208. i = 1;
  2209. while ( res == TRY_NEXT_METHOD ) {
  2210. #ifdef COUNT_OPERS
  2211. OperationNext++;
  2212. #endif
  2213. method = CALL_5ARGS( NextVMethod3Args, oper, INTOBJ_INT(i),
  2214. kind1, kind2, kind3 );
  2215. while (method == Fail)
  2216. {
  2217. Obj arglist[3];
  2218. arglist[0] = arg1;
  2219. arglist[1] = arg2;
  2220. arglist[2] = arg3;
  2221. method = CallHandleMethodNotFound( oper, 3, arglist, 1, 0, INTOBJ_INT(i));
  2222. }
  2223. i++;
  2224. res = CALL_3ARGS( method, arg1, arg2, arg3 );
  2225. }
  2226. }
  2227. /* return the result */
  2228. return res;
  2229. }
  2230. /****************************************************************************
  2231. **
  2232. ** DoVerboseOperation4Args( <oper>, <a1>, <a2>, <a3>, <a4> )
  2233. */
  2234. Obj DoVerboseOperation4Args (
  2235. Obj oper,
  2236. Obj arg1,
  2237. Obj arg2,
  2238. Obj arg3,
  2239. Obj arg4 )
  2240. {
  2241. Obj res;
  2242. Obj kind1;
  2243. Obj kind2;
  2244. Obj kind3;
  2245. Obj kind4;
  2246. Obj method;
  2247. Int i;
  2248. /* get the kinds of the arguments */
  2249. kind1 = TYPE_OBJ_FEO( arg1 );
  2250. kind2 = TYPE_OBJ_FEO( arg2 );
  2251. kind3 = TYPE_OBJ_FEO( arg3 );
  2252. kind4 = TYPE_OBJ_FEO( arg4 );
  2253. /* try to find one in the list of methods */
  2254. method = CALL_5ARGS( VMethod4Args, oper, kind1, kind2, kind3, kind4 );
  2255. while (method == Fail)
  2256. {
  2257. Obj arglist[4];
  2258. arglist[0] = arg1;
  2259. arglist[1] = arg2;
  2260. arglist[2] = arg3;
  2261. arglist[3] = arg4;
  2262. method = CallHandleMethodNotFound( oper, 4, arglist, 1, 0, INTOBJ_INT(0));
  2263. }
  2264. if ( method == 0 ) {
  2265. ErrorQuit( "no method returned", 0L, 0L );
  2266. }
  2267. /* call this method */
  2268. res = CALL_4ARGS( method, arg1, arg2, arg3, arg4 );
  2269. /* try until a method doesn't give up */
  2270. if ( res == TRY_NEXT_METHOD ) {
  2271. i = 1;
  2272. while ( res == TRY_NEXT_METHOD ) {
  2273. #ifdef COUNT_OPERS
  2274. OperationNext++;
  2275. #endif
  2276. method = CALL_6ARGS( NextVMethod4Args, oper, INTOBJ_INT(i),
  2277. kind1, kind2, kind3, kind4 );
  2278. while (method == Fail)
  2279. {
  2280. Obj arglist[4];
  2281. arglist[0] = arg1;
  2282. arglist[1] = arg2;
  2283. arglist[2] = arg3;
  2284. arglist[3] = arg4;
  2285. method = CallHandleMethodNotFound( oper, 4, arglist, 1, 0, INTOBJ_INT(i));
  2286. }
  2287. i++;
  2288. res = CALL_4ARGS( method, arg1, arg2, arg3, arg4 );
  2289. }
  2290. }
  2291. /* return the result */
  2292. return res;
  2293. }
  2294. /****************************************************************************
  2295. **
  2296. ** DoVerboseOperation5Args( <oper>, <a1>, <a2>, <a3>, <a4>, <a5> )
  2297. */
  2298. Obj DoVerboseOperation5Args (
  2299. Obj oper,
  2300. Obj arg1,
  2301. Obj arg2,
  2302. Obj arg3,
  2303. Obj arg4,
  2304. Obj arg5 )
  2305. {
  2306. Obj res;
  2307. Obj kind1;
  2308. Obj kind2;
  2309. Obj kind3;
  2310. Obj kind4;
  2311. Obj kind5;
  2312. Obj method;
  2313. Obj margs;
  2314. Int i;
  2315. /* get the kinds of the arguments */
  2316. kind1 = TYPE_OBJ_FEO( arg1 );
  2317. kind2 = TYPE_OBJ_FEO( arg2 );
  2318. kind3 = TYPE_OBJ_FEO( arg3 );
  2319. kind4 = TYPE_OBJ_FEO( arg4 );
  2320. kind5 = TYPE_OBJ_FEO( arg5 );
  2321. /* try to find one in the list of methods */
  2322. method = CALL_6ARGS( VMethod5Args, oper, kind1, kind2, kind3, kind4,
  2323. kind5 );
  2324. while (method == Fail)
  2325. {
  2326. Obj arglist[5];
  2327. arglist[0] = arg1;
  2328. arglist[1] = arg2;
  2329. arglist[2] = arg3;
  2330. arglist[3] = arg4;
  2331. arglist[4] = arg5;
  2332. method = CallHandleMethodNotFound( oper, 5, arglist, 1, 0, INTOBJ_INT(0));
  2333. }
  2334. if ( method == 0 ) {
  2335. ErrorQuit( "no method returned", 0L, 0L );
  2336. }
  2337. /* call this method */
  2338. res = CALL_5ARGS( method, arg1, arg2, arg3, arg4, arg5 );
  2339. /* try until a method doesn't give up */
  2340. if ( res == TRY_NEXT_METHOD ) {
  2341. i = 1;
  2342. while ( res == TRY_NEXT_METHOD ) {
  2343. #ifdef COUNT_OPERS
  2344. OperationNext++;
  2345. #endif
  2346. margs = NEW_PLIST( T_PLIST, 7 );
  2347. SET_LEN_PLIST( margs, 7 );
  2348. SET_ELM_PLIST( margs, 1, oper );
  2349. SET_ELM_PLIST( margs, 2, INTOBJ_INT(i) );
  2350. SET_ELM_PLIST( margs, 3, kind1 );
  2351. SET_ELM_PLIST( margs, 4, kind2 );
  2352. SET_ELM_PLIST( margs, 5, kind3 );
  2353. SET_ELM_PLIST( margs, 6, kind4 );
  2354. SET_ELM_PLIST( margs, 7, kind5 );
  2355. method = CALL_XARGS( NextVMethod5Args, margs );
  2356. while (method == Fail)
  2357. {
  2358. Obj arglist[5];
  2359. arglist[0] = arg1;
  2360. arglist[1] = arg2;
  2361. arglist[2] = arg3;
  2362. arglist[3] = arg4;
  2363. arglist[4] = arg5;
  2364. method = CallHandleMethodNotFound( oper, 5, arglist, 1, 0, INTOBJ_INT(i));
  2365. }
  2366. i++;
  2367. res = CALL_5ARGS( method, arg1, arg2, arg3, arg4, arg5 );
  2368. }
  2369. }
  2370. /* return the result */
  2371. return res;
  2372. }
  2373. /****************************************************************************
  2374. **
  2375. ** DoVerboseOperation6Args( <oper>, <a1>, <a2>, <a3>, <a4>, <a5>, <a6> )
  2376. */
  2377. Obj DoVerboseOperation6Args (
  2378. Obj oper,
  2379. Obj arg1,
  2380. Obj arg2,
  2381. Obj arg3,
  2382. Obj arg4,
  2383. Obj arg5,
  2384. Obj arg6 )
  2385. {
  2386. Obj res;
  2387. Obj kind1;
  2388. Obj kind2;
  2389. Obj kind3;
  2390. Obj kind4;
  2391. Obj kind5;
  2392. Obj kind6;
  2393. Obj method;
  2394. Obj margs;
  2395. Int i;
  2396. /* get the kinds of the arguments */
  2397. kind1 = TYPE_OBJ_FEO( arg1 );
  2398. kind2 = TYPE_OBJ_FEO( arg2 );
  2399. kind3 = TYPE_OBJ_FEO( arg3 );
  2400. kind4 = TYPE_OBJ_FEO( arg4 );
  2401. kind5 = TYPE_OBJ_FEO( arg5 );
  2402. kind6 = TYPE_OBJ_FEO( arg6 );
  2403. /* try to find one in the list of methods */
  2404. margs = NEW_PLIST( T_PLIST, 7 );
  2405. SET_LEN_PLIST( margs, 7 );
  2406. SET_ELM_PLIST( margs, 1, oper );
  2407. SET_ELM_PLIST( margs, 2, kind1 );
  2408. SET_ELM_PLIST( margs, 3, kind2 );
  2409. SET_ELM_PLIST( margs, 4, kind3 );
  2410. SET_ELM_PLIST( margs, 5, kind4 );
  2411. SET_ELM_PLIST( margs, 6, kind5 );
  2412. SET_ELM_PLIST( margs, 7, kind6 );
  2413. method = CALL_XARGS( VMethod6Args, margs );
  2414. while (method == Fail)
  2415. {
  2416. Obj arglist[6];
  2417. arglist[0] = arg1;
  2418. arglist[1] = arg2;
  2419. arglist[2] = arg3;
  2420. arglist[3] = arg4;
  2421. arglist[4] = arg5;
  2422. arglist[5] = arg6;
  2423. method = CallHandleMethodNotFound( oper, 6, arglist, 1, 0, INTOBJ_INT(0));
  2424. }
  2425. if ( method == 0 ) {
  2426. ErrorQuit( "no method returned", 0L, 0L );
  2427. }
  2428. /* call this method */
  2429. res = CALL_6ARGS( method, arg1, arg2, arg3, arg4, arg5, arg6 );
  2430. /* try until a method doesn't give up */
  2431. if ( res == TRY_NEXT_METHOD ) {
  2432. i = 1;
  2433. while ( res == TRY_NEXT_METHOD ) {
  2434. #ifdef COUNT_OPERS
  2435. OperationNext++;
  2436. #endif
  2437. margs = NEW_PLIST( T_PLIST, 8 );
  2438. SET_LEN_PLIST( margs, 8 );
  2439. SET_ELM_PLIST( margs, 1, oper );
  2440. SET_ELM_PLIST( margs, 2, INTOBJ_INT(i) );
  2441. SET_ELM_PLIST( margs, 3, kind1 );
  2442. SET_ELM_PLIST( margs, 4, kind2 );
  2443. SET_ELM_PLIST( margs, 5, kind3 );
  2444. SET_ELM_PLIST( margs, 6, kind4 );
  2445. SET_ELM_PLIST( margs, 7, kind5 );
  2446. SET_ELM_PLIST( margs, 8, kind6 );
  2447. method = CALL_XARGS( NextVMethod6Args, margs );
  2448. while (method == Fail)
  2449. {
  2450. Obj arglist[6];
  2451. arglist[0] = arg1;
  2452. arglist[1] = arg2;
  2453. arglist[2] = arg3;
  2454. arglist[3] = arg4;
  2455. arglist[4] = arg5;
  2456. arglist[5] = arg6;
  2457. method = CallHandleMethodNotFound( oper, 6, arglist, 1, 0, INTOBJ_INT(i));
  2458. }
  2459. i++;
  2460. res = CALL_6ARGS( method, arg1, arg2, arg3, arg4, arg5, arg6 );
  2461. }
  2462. }
  2463. /* return the result */
  2464. return res;
  2465. }
  2466. /****************************************************************************
  2467. **
  2468. ** DoVerboseOperationXArgs( <oper>, ... )
  2469. */
  2470. Obj DoVerboseOperationXArgs (
  2471. Obj self,
  2472. Obj args )
  2473. {
  2474. ErrorQuit("sorry: cannot yet have X argument operations",0L,0L);
  2475. return 0;
  2476. }
  2477. /****************************************************************************
  2478. **
  2479. *F NewOperation( <name>, <narg>, <nams>, <hdlr> )
  2480. */
  2481. Obj NewOperation (
  2482. Obj name,
  2483. Int narg,
  2484. Obj nams,
  2485. ObjFunc hdlr )
  2486. {
  2487. Obj oper;
  2488. #ifdef PREALLOCATE_TABLES
  2489. Obj cache;
  2490. Obj methods;
  2491. UInt i;
  2492. #endif
  2493. /* create the function */
  2494. oper = NewFunctionT( T_FUNCTION, SIZE_OPER, name, narg, nams, hdlr );
  2495. /* enter the handlers */
  2496. HDLR_FUNC(oper,0) = DoOperation0Args;
  2497. HDLR_FUNC(oper,1) = DoOperation1Args;
  2498. HDLR_FUNC(oper,2) = DoOperation2Args;
  2499. HDLR_FUNC(oper,3) = DoOperation3Args;
  2500. HDLR_FUNC(oper,4) = DoOperation4Args;
  2501. HDLR_FUNC(oper,5) = DoOperation5Args;
  2502. HDLR_FUNC(oper,6) = DoOperation6Args;
  2503. HDLR_FUNC(oper,7) = DoOperationXArgs;
  2504. /* reenter the given handler */
  2505. if (narg != -1)
  2506. HDLR_FUNC(oper,narg) = hdlr;
  2507. /*N 1996/06/06 mschoene this should not be done here */
  2508. FLAG1_FILT(oper) = INT_INTOBJ(0);
  2509. FLAG2_FILT(oper) = INT_INTOBJ(0);
  2510. FLAGS_FILT(oper) = False;
  2511. SETTR_FILT(oper) = False;
  2512. TESTR_FILT(oper) = False;
  2513. /* create caches and methods lists */
  2514. #ifdef PREALLOCATE_TABLES
  2515. for ( i = 0; i <= 7; i++ ) {
  2516. methods = NEW_PLIST( T_PLIST, 0 );
  2517. METHS_OPER( oper, i ) = methods;
  2518. cache = NEW_PLIST( T_PLIST, (i < 7 ? 4 * (i+2) : 4 * (1+2)) );
  2519. CACHE_OPER( oper, i ) = cache;
  2520. CHANGED_BAG(oper);
  2521. }
  2522. #endif
  2523. /* This isn't an attribute (yet) */
  2524. SET_ENABLED_ATTR(oper, 0);
  2525. /* return operation */
  2526. return oper;
  2527. }
  2528. /****************************************************************************
  2529. **
  2530. *F NewOperationC( <name>, <narg>, <nams>, <hdlr> )
  2531. */
  2532. Obj NewOperationC (
  2533. const Char * name,
  2534. Int narg,
  2535. const Char * nams,
  2536. ObjFunc hdlr )
  2537. {
  2538. Obj oper;
  2539. #ifdef PREALLOCATE_TABLES
  2540. Obj cache;
  2541. Obj methods;
  2542. UInt i;
  2543. #endif
  2544. /* create the function */
  2545. oper = NewFunctionCT( T_FUNCTION, SIZE_OPER, name, narg, nams, hdlr );
  2546. /* enter the handlers */
  2547. HDLR_FUNC(oper,0) = DoOperation0Args;
  2548. HDLR_FUNC(oper,1) = DoOperation1Args;
  2549. HDLR_FUNC(oper,2) = DoOperation2Args;
  2550. HDLR_FUNC(oper,3) = DoOperation3Args;
  2551. HDLR_FUNC(oper,4) = DoOperation4Args;
  2552. HDLR_FUNC(oper,5) = DoOperation5Args;
  2553. HDLR_FUNC(oper,6) = DoOperation6Args;
  2554. HDLR_FUNC(oper,7) = DoOperationXArgs;
  2555. /* reenter the given handler */
  2556. if (narg != -1)
  2557. HDLR_FUNC(oper,narg) = hdlr;
  2558. /*N 1996/06/06 mschoene this should not be done here */
  2559. FLAG1_FILT(oper) = INT_INTOBJ(0);
  2560. FLAG2_FILT(oper) = INT_INTOBJ(0);
  2561. FLAGS_FILT(oper) = False;
  2562. SETTR_FILT(oper) = False;
  2563. TESTR_FILT(oper) = False;
  2564. /* This isn't an attribute (yet) */
  2565. SET_ENABLED_ATTR(oper, 0);
  2566. /* create caches and methods lists */
  2567. #ifdef PREALLOCATE_TABLES
  2568. for ( i = 0; i <= 7; i++ ) {
  2569. methods = NEW_PLIST( T_PLIST, 0 );
  2570. METHS_OPER( oper, i ) = methods;
  2571. cache = NEW_PLIST( T_PLIST, (i < 7 ? 4 * (i+2) : 4 * (1+2)) );
  2572. CACHE_OPER( oper, i ) = cache;
  2573. CHANGED_BAG(oper);
  2574. }
  2575. #endif
  2576. /* return operation */
  2577. return oper;
  2578. }
  2579. /****************************************************************************
  2580. **
  2581. *F DoConstructor( <name> ) . . . . . . . . . . . . . make a new constructor
  2582. */
  2583. UInt CacheIndex;
  2584. Obj Constructor0Args;
  2585. Obj NextConstructor0Args;
  2586. Obj Constructor1Args;
  2587. Obj NextConstructor1Args;
  2588. Obj Constructor2Args;
  2589. Obj NextConstructor2Args;
  2590. Obj Constructor3Args;
  2591. Obj NextConstructor3Args;
  2592. Obj Constructor4Args;
  2593. Obj NextConstructor4Args;
  2594. Obj Constructor5Args;
  2595. Obj NextConstructor5Args;
  2596. Obj Constructor6Args;
  2597. Obj NextConstructor6Args;
  2598. Obj ConstructorXArgs;
  2599. Obj NextConstructorXArgs;
  2600. Obj VConstructor0Args;
  2601. Obj NextVConstructor0Args;
  2602. Obj VConstructor1Args;
  2603. Obj NextVConstructor1Args;
  2604. Obj VConstructor2Args;
  2605. Obj NextVConstructor2Args;
  2606. Obj VConstructor3Args;
  2607. Obj NextVConstructor3Args;
  2608. Obj VConstructor4Args;
  2609. Obj NextVConstructor4Args;
  2610. Obj VConstructor5Args;
  2611. Obj NextVConstructor5Args;
  2612. Obj VConstructor6Args;
  2613. Obj NextVConstructor6Args;
  2614. Obj VConstructorXArgs;
  2615. Obj NextVConstructorXArgs;
  2616. /****************************************************************************
  2617. **
  2618. ** DoConstructor0Args( <oper> )
  2619. **
  2620. ** I'm not sure if this makes any sense at all
  2621. */
  2622. Obj DoConstructor0Args (
  2623. Obj oper )
  2624. {
  2625. Obj res;
  2626. Obj * cache;
  2627. Obj method;
  2628. Int i;
  2629. Obj prec;
  2630. /* try to find an applicable method in the cache */
  2631. cache = 1+ADDR_OBJ( CacheOper( oper, 0 ) );
  2632. prec = INTOBJ_INT(-1);
  2633. do {
  2634. /* The next line depends on the implementation of INTOBJS */
  2635. prec = (Obj)(((Int)prec) +4);
  2636. method = 0;
  2637. /* Up to CACHE_SIZE methods might be in the cache */
  2638. if (prec < INTOBJ_INT(CACHE_SIZE))
  2639. {
  2640. for (i = 0; i < 2*CACHE_SIZE; i+= 2) {
  2641. if ( cache[i] != 0 && cache[i+1] == prec) {
  2642. method = cache[i];
  2643. #ifdef COUNT_OPERS
  2644. OperationHit++;
  2645. #endif
  2646. break;
  2647. }
  2648. }
  2649. }
  2650. /* otherwise try to find one in the list of methods */
  2651. if (!method)
  2652. {
  2653. if (prec == INTOBJ_INT(0))
  2654. method = CALL_1ARGS( Constructor0Args, oper );
  2655. else
  2656. method = CALL_2ARGS( NextConstructor0Args, oper, prec );
  2657. while (method == Fail)
  2658. method = CallHandleMethodNotFound( oper, 0, (Obj *)0, 0, 1, prec);
  2659. /* update the cache */
  2660. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  2661. {
  2662. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 0 ) );
  2663. cache[2*CacheIndex] = method;
  2664. cache[2*CacheIndex+1] = prec;
  2665. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  2666. CHANGED_BAG(CACHE_OPER(oper,0));
  2667. }
  2668. #ifdef COUNT_OPERS
  2669. OperationMiss++;
  2670. #endif
  2671. }
  2672. if ( !method ) {
  2673. ErrorQuit( "no method returned", 0L, 0L );
  2674. }
  2675. /* call this method */
  2676. res = CALL_0ARGS( method );
  2677. }
  2678. while (res == TRY_NEXT_METHOD );
  2679. /* return the result */
  2680. return res;
  2681. }
  2682. /****************************************************************************
  2683. **
  2684. ** DoConstructor1Args( <oper>, <a1> )
  2685. */
  2686. Obj DoConstructor1Args (
  2687. Obj oper,
  2688. Obj arg1 )
  2689. {
  2690. Obj res;
  2691. Obj kind1;
  2692. Obj * cache;
  2693. Obj method;
  2694. Int i;
  2695. Obj prec;
  2696. /* get the kinds of the arguments */
  2697. while (!IS_OPERATION(arg1))
  2698. {
  2699. arg1 = ErrorReturnObj(
  2700. "Constructor: the first argument must be a filter not a %s",
  2701. (Int)TNAM_OBJ(arg1), 0L,
  2702. "you can replace the first argument <arg1> via 'return <arg1>;'");
  2703. }
  2704. kind1 = FLAGS_FILT( arg1 );
  2705. /* try to find an applicable method in the cache */
  2706. cache = 1+ADDR_OBJ( CacheOper( oper, 1 ) );
  2707. prec = INTOBJ_INT(-1);
  2708. do {
  2709. /* The next line depends on the implementation of INTOBJS */
  2710. prec = (Obj)(((Int)prec) +4);
  2711. method = 0;
  2712. /* Up to CACHE_SIZE methods might be in the cache */
  2713. if (prec < INTOBJ_INT(CACHE_SIZE))
  2714. {
  2715. for (i = 0; i < 3*CACHE_SIZE; i+= 3) {
  2716. if ( cache[i+1] == prec && cache[i+2] == kind1 ) {
  2717. method = cache[i];
  2718. #ifdef COUNT_OPERS
  2719. ConstructorHit++;
  2720. #endif
  2721. break;
  2722. }
  2723. }
  2724. }
  2725. /* otherwise try to find one in the list of methods */
  2726. if (!method)
  2727. {
  2728. if (prec == INTOBJ_INT(0))
  2729. method = CALL_2ARGS( Constructor1Args, oper, kind1 );
  2730. else
  2731. method = CALL_3ARGS( NextConstructor1Args, oper, prec, kind1 );
  2732. while (method == Fail)
  2733. {
  2734. Obj arglist[1];
  2735. arglist[0] = arg1;
  2736. method = CallHandleMethodNotFound(oper, 1, arglist, 0, 1, prec);
  2737. }
  2738. /* update the cache */
  2739. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  2740. {
  2741. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 1 ) );
  2742. cache[3*CacheIndex] = method;
  2743. cache[3*CacheIndex+1] = prec;
  2744. cache[3*CacheIndex+2] = kind1;
  2745. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  2746. CHANGED_BAG(CACHE_OPER(oper,1));
  2747. }
  2748. #ifdef COUNT_OPERS
  2749. ConstructorMiss++;
  2750. #endif
  2751. }
  2752. if ( !method ) {
  2753. ErrorQuit( "no method returned", 0L, 0L );
  2754. }
  2755. /* call this method */
  2756. res = CALL_1ARGS( method, arg1 );
  2757. }
  2758. while (res == TRY_NEXT_METHOD );
  2759. /* return the result */
  2760. return res;
  2761. }
  2762. /****************************************************************************
  2763. **
  2764. ** DoConstructor2Args( <oper>, <a1>, <a2> )
  2765. */
  2766. Obj DoConstructor2Args (
  2767. Obj oper,
  2768. Obj arg1,
  2769. Obj arg2 )
  2770. {
  2771. Obj res;
  2772. Obj kind1;
  2773. Obj kind2;
  2774. Obj id2;
  2775. Obj * cache;
  2776. Obj method;
  2777. Int i;
  2778. Obj prec;
  2779. /* get the kinds of the arguments */
  2780. while (!IS_OPERATION(arg1))
  2781. {
  2782. arg1 = ErrorReturnObj(
  2783. "Constructor: the first argument must be a filter not a %s",
  2784. (Int)TNAM_OBJ(arg1), 0L,
  2785. "you can replace the first argument <arg1> via 'return <arg1>;'");
  2786. }
  2787. kind1 = FLAGS_FILT( arg1 );
  2788. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  2789. /* try to find an applicable method in the cache */
  2790. cache = 1+ADDR_OBJ( CacheOper( oper, 2 ) );
  2791. prec = INTOBJ_INT(-1);
  2792. do {
  2793. /* The next line depends on the implementation of INTOBJS */
  2794. prec = (Obj)(((Int)prec) +4);
  2795. method = 0;
  2796. /* Up to CACHE_SIZE methods might be in the cache */
  2797. if (prec < INTOBJ_INT(CACHE_SIZE))
  2798. {
  2799. for (i = 0; i < 4*CACHE_SIZE; i+= 4) {
  2800. if ( cache[i+1] == prec && cache[i+2] == kind1
  2801. && cache[i+3] == id2 ) {
  2802. method = cache[i];
  2803. #ifdef COUNT_OPERS
  2804. OperationgHit++;
  2805. #endif
  2806. break;
  2807. }
  2808. }
  2809. }
  2810. /* otherwise try to find one in the list of methods */
  2811. if (!method)
  2812. {
  2813. if (prec == INTOBJ_INT(0))
  2814. method = CALL_3ARGS( Constructor2Args, oper, kind1, kind2 );
  2815. else
  2816. method = CALL_4ARGS( NextConstructor2Args, oper, prec, kind1, kind2 );
  2817. while (method == Fail)
  2818. {
  2819. Obj arglist[2];
  2820. arglist[0] = arg1;
  2821. arglist[1] = arg2;
  2822. method = CallHandleMethodNotFound(oper, 2, arglist, 0, 1, prec);
  2823. }
  2824. /* update the cache */
  2825. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  2826. {
  2827. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 2 ) );
  2828. cache[4*CacheIndex] = method;
  2829. cache[4*CacheIndex+1] = prec;
  2830. cache[4*CacheIndex+2] = kind1;
  2831. cache[4*CacheIndex+3] = id2;
  2832. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  2833. CHANGED_BAG(CACHE_OPER(oper,2));
  2834. }
  2835. #ifdef COUNT_OPERS
  2836. OperationMiss++;
  2837. #endif
  2838. }
  2839. if ( !method ) {
  2840. ErrorQuit( "no method returned", 0L, 0L );
  2841. }
  2842. /* call this method */
  2843. res = CALL_2ARGS( method, arg1, arg2 );
  2844. }
  2845. while (res == TRY_NEXT_METHOD );
  2846. /* return the result */
  2847. return res;
  2848. }
  2849. /****************************************************************************
  2850. **
  2851. ** DoConstructor3Args( <oper>, <a1>, <a2>, <a3> )
  2852. */
  2853. Obj DoConstructor3Args (
  2854. Obj oper,
  2855. Obj arg1,
  2856. Obj arg2,
  2857. Obj arg3 )
  2858. {
  2859. Obj res;
  2860. Obj kind1;
  2861. Obj kind2;
  2862. Obj id2;
  2863. Obj kind3;
  2864. Obj id3;
  2865. Obj * cache;
  2866. Obj method;
  2867. Int i;
  2868. Obj prec;
  2869. /* get the kinds of the arguments */
  2870. while (!IS_OPERATION(arg1))
  2871. {
  2872. arg1 = ErrorReturnObj(
  2873. "Constructor: the first argument must be a filter not a %s",
  2874. (Int)TNAM_OBJ(arg1), 0L,
  2875. "you can replace the first argument <arg1> via 'return <arg1>;'");
  2876. }
  2877. kind1 = FLAGS_FILT( arg1 );
  2878. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  2879. kind3 = TYPE_OBJ_FEO( arg3 ); id3 = ID_TYPE( kind3 );
  2880. /* try to find an applicable method in the cache */
  2881. cache = 1+ADDR_OBJ( CacheOper( oper, 3 ) );
  2882. prec = INTOBJ_INT(-1);
  2883. do {
  2884. /* The next line depends on the implementation of INTOBJS */
  2885. prec = (Obj)(((Int)prec) +4);
  2886. method = 0;
  2887. /* Up to CACHE_SIZE methods might be in the cache */
  2888. if (prec < INTOBJ_INT(CACHE_SIZE))
  2889. {
  2890. for (i = 0; i < 5*CACHE_SIZE; i+= 5) {
  2891. if ( cache[i+1] == prec && cache[i+2] == kind1
  2892. && cache[i+3] == id2 && cache[i+4] == id3 ) {
  2893. method = cache[i];
  2894. #ifdef COUNT_OPERS
  2895. OperationHit++;
  2896. #endif
  2897. break;
  2898. }
  2899. }
  2900. }
  2901. /* otherwise try to find one in the list of methods */
  2902. if (!method)
  2903. {
  2904. if (prec == INTOBJ_INT(0))
  2905. method = CALL_4ARGS( Constructor3Args, oper, kind1, kind2, kind3 );
  2906. else
  2907. method = CALL_5ARGS( NextConstructor3Args, oper, prec, kind1, kind2, kind3 );
  2908. while (method == Fail)
  2909. {
  2910. Obj arglist[3];
  2911. arglist[0] = arg1;
  2912. arglist[1] = arg2;
  2913. arglist[2] = arg3;
  2914. method = CallHandleMethodNotFound(oper, 3, arglist, 0, 1, prec);
  2915. }
  2916. /* update the cache */
  2917. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  2918. {
  2919. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 3 ) );
  2920. cache[5*CacheIndex] = method;
  2921. cache[5*CacheIndex+1] = prec;
  2922. cache[5*CacheIndex+2] = kind1;
  2923. cache[5*CacheIndex+3] = id2;
  2924. cache[5*CacheIndex+4] = id3;
  2925. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  2926. CHANGED_BAG(CACHE_OPER(oper,3));
  2927. }
  2928. #ifdef COUNT_OPERS
  2929. OperationMiss++;
  2930. #endif
  2931. }
  2932. if ( !method ) {
  2933. ErrorQuit( "no method returned", 0L, 0L );
  2934. }
  2935. /* call this method */
  2936. res = CALL_3ARGS( method, arg1, arg2, arg3 );
  2937. }
  2938. while (res == TRY_NEXT_METHOD );
  2939. /* return the result */
  2940. return res;
  2941. }
  2942. /****************************************************************************
  2943. **
  2944. ** DoConstructor4Args( <oper>, <a1>, <a2>, <a3>, <a4> )
  2945. */
  2946. Obj DoConstructor4Args (
  2947. Obj oper,
  2948. Obj arg1,
  2949. Obj arg2,
  2950. Obj arg3,
  2951. Obj arg4 )
  2952. {
  2953. Obj res;
  2954. Obj kind1;
  2955. Obj kind2;
  2956. Obj id2;
  2957. Obj kind3;
  2958. Obj id3;
  2959. Obj kind4;
  2960. Obj id4;
  2961. Obj * cache;
  2962. Obj method;
  2963. Int i;
  2964. Obj prec;
  2965. /* get the kinds of the arguments */
  2966. while (!IS_OPERATION(arg1))
  2967. {
  2968. arg1 = ErrorReturnObj(
  2969. "Constructor: the first argument must be a filter not a %s",
  2970. (Int)TNAM_OBJ(arg1), 0L,
  2971. "you can replace the first argument <arg1> via 'return <arg1>;'");
  2972. }
  2973. kind1 = FLAGS_FILT( arg1 );
  2974. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  2975. kind3 = TYPE_OBJ_FEO( arg3 ); id3 = ID_TYPE( kind3 );
  2976. kind4 = TYPE_OBJ_FEO( arg4 ); id4 = ID_TYPE( kind4 );
  2977. /* try to find an applicable method in the cache */
  2978. cache = 1+ADDR_OBJ( CacheOper( oper, 4 ) );
  2979. prec = INTOBJ_INT(-1);
  2980. do {
  2981. /* The next line depends on the implementation of INTOBJS */
  2982. prec = (Obj)(((Int)prec) +4);
  2983. method = 0;
  2984. /* Up to CACHE_SIZE methods might be in the cache */
  2985. if (prec < INTOBJ_INT(CACHE_SIZE))
  2986. {
  2987. for (i = 0; i < 6*CACHE_SIZE; i+= 6) {
  2988. if ( cache[i+1] == prec && cache[i+2] == kind1 &&
  2989. cache[i+3] == id2 && cache[i+4] == id3 &&
  2990. cache[i+5] == id4 ) {
  2991. method = cache[i];
  2992. #ifdef COUNT_OPERS
  2993. OperationHit++;
  2994. #endif
  2995. break;
  2996. }
  2997. }
  2998. }
  2999. /* otherwise try to find one in the list of methods */
  3000. if (!method)
  3001. {
  3002. if (prec == INTOBJ_INT(0))
  3003. method = CALL_5ARGS( Constructor4Args, oper, kind1, kind2, kind3, kind4 );
  3004. else
  3005. method = CALL_6ARGS( NextConstructor4Args, oper, prec, kind1, kind2, kind3, kind4 );
  3006. while (method == Fail)
  3007. {
  3008. Obj arglist[4];
  3009. arglist[0] = arg1;
  3010. arglist[1] = arg2;
  3011. arglist[2] = arg3;
  3012. arglist[3] = arg4;
  3013. method = CallHandleMethodNotFound(oper, 4, arglist, 0, 1, prec);
  3014. }
  3015. /* update the cache */
  3016. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  3017. {
  3018. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 4 ) );
  3019. cache[6*CacheIndex] = method;
  3020. cache[6*CacheIndex+1] = prec;
  3021. cache[6*CacheIndex+2] = kind1;
  3022. cache[6*CacheIndex+3] = id2;
  3023. cache[6*CacheIndex+4] = id3;
  3024. cache[6*CacheIndex+5] = id4;
  3025. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  3026. CHANGED_BAG(CACHE_OPER(oper,4));
  3027. }
  3028. #ifdef COUNT_OPERS
  3029. OperationMiss++;
  3030. #endif
  3031. }
  3032. if ( !method ) {
  3033. ErrorQuit( "no method returned", 0L, 0L );
  3034. }
  3035. /* call this method */
  3036. res = CALL_4ARGS( method, arg1, arg2, arg3, arg4 );
  3037. }
  3038. while (res == TRY_NEXT_METHOD );
  3039. /* return the result */
  3040. return res;
  3041. }
  3042. /****************************************************************************
  3043. **
  3044. ** DoConstructor5Args( <oper>, <a1>, <a2>, <a3>, <a4>, <a5> )
  3045. */
  3046. Obj DoConstructor5Args (
  3047. Obj oper,
  3048. Obj arg1,
  3049. Obj arg2,
  3050. Obj arg3,
  3051. Obj arg4,
  3052. Obj arg5 )
  3053. {
  3054. Obj res;
  3055. Obj kind1;
  3056. Obj kind2;
  3057. Obj id2;
  3058. Obj kind3;
  3059. Obj id3;
  3060. Obj kind4;
  3061. Obj id4;
  3062. Obj kind5;
  3063. Obj id5;
  3064. Obj * cache;
  3065. Obj method;
  3066. Int i;
  3067. Obj prec;
  3068. Obj margs;
  3069. /* get the kinds of the arguments */
  3070. while (!IS_OPERATION(arg1))
  3071. {
  3072. arg1 = ErrorReturnObj(
  3073. "Constructor: the first argument must be a filter not a %s",
  3074. (Int)TNAM_OBJ(arg1), 0L,
  3075. "you can replace the first argument <arg1> via 'return <arg1>;'");
  3076. }
  3077. kind1 = FLAGS_FILT( arg1 );
  3078. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  3079. kind3 = TYPE_OBJ_FEO( arg3 ); id3 = ID_TYPE( kind3 );
  3080. kind4 = TYPE_OBJ_FEO( arg4 ); id4 = ID_TYPE( kind4 );
  3081. kind5 = TYPE_OBJ_FEO( arg5 ); id5 = ID_TYPE( kind5 );
  3082. /* try to find an applicable method in the cache */
  3083. cache = 1+ADDR_OBJ( CacheOper( oper, 5 ) );
  3084. prec = INTOBJ_INT(-1);
  3085. do {
  3086. /* The next line depends on the implementation of INTOBJS */
  3087. prec = (Obj)(((Int)prec) +4);
  3088. method = 0;
  3089. /* Up to CACHE_SIZE methods might be in the cache */
  3090. if (prec < INTOBJ_INT(CACHE_SIZE))
  3091. {
  3092. for (i = 0; i < 7*CACHE_SIZE; i+= 7) {
  3093. if ( cache[i+1] == prec && cache[i+2] == kind1 &&
  3094. cache[i+3] == id2 && cache[i+4] == id3 &&
  3095. cache[i+5] == id4 && cache[i+6] == id5 ) {
  3096. method = cache[i];
  3097. #ifdef COUNT_OPERS
  3098. OperationHit++;
  3099. #endif
  3100. break;
  3101. }
  3102. }
  3103. }
  3104. /* otherwise try to find one in the list of methods */
  3105. if (!method)
  3106. {
  3107. if (prec == INTOBJ_INT(0))
  3108. method = CALL_6ARGS( Constructor5Args, oper, kind1, kind2, kind3, kind4, kind5 );
  3109. else
  3110. {
  3111. margs = NEW_PLIST(T_PLIST, 7);
  3112. SET_ELM_PLIST(margs, 1, oper );
  3113. SET_ELM_PLIST(margs, 2, prec );
  3114. SET_ELM_PLIST(margs, 3, kind1 );
  3115. SET_ELM_PLIST(margs, 4, kind2 );
  3116. SET_ELM_PLIST(margs, 5, kind3 );
  3117. SET_ELM_PLIST(margs, 6, kind4 );
  3118. SET_ELM_PLIST(margs, 7, kind5 );
  3119. SET_LEN_PLIST(margs, 7);
  3120. method = CALL_XARGS( NextConstructor5Args, margs );
  3121. }
  3122. while (method == Fail)
  3123. {
  3124. Obj arglist[5];
  3125. arglist[0] = arg1;
  3126. arglist[1] = arg2;
  3127. arglist[2] = arg3;
  3128. arglist[3] = arg4;
  3129. arglist[4] = arg5;
  3130. method = CallHandleMethodNotFound(oper, 5, arglist, 0, 1, prec);
  3131. }
  3132. /* update the cache */
  3133. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  3134. {
  3135. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 5 ) );
  3136. cache[7*CacheIndex] = method;
  3137. cache[7*CacheIndex+1] = prec;
  3138. cache[7*CacheIndex+2] = kind1;
  3139. cache[7*CacheIndex+3] = id2;
  3140. cache[7*CacheIndex+4] = id3;
  3141. cache[7*CacheIndex+5] = id4;
  3142. cache[7*CacheIndex+6] = id5;
  3143. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  3144. CHANGED_BAG(CACHE_OPER(oper,5));
  3145. }
  3146. #ifdef COUNT_OPERS
  3147. OperationMiss++;
  3148. #endif
  3149. }
  3150. if ( !method ) {
  3151. ErrorQuit( "no method returned", 0L, 0L );
  3152. }
  3153. /* call this method */
  3154. res = CALL_5ARGS( method, arg1, arg2, arg3, arg4, arg5 );
  3155. }
  3156. while (res == TRY_NEXT_METHOD );
  3157. /* return the result */
  3158. return res;
  3159. }
  3160. /****************************************************************************
  3161. **
  3162. ** DoConstructor6Args( <oper>, <a1>, <a2>, <a3>, <a4>, <a5>, <a6> )
  3163. */
  3164. Obj DoConstructor6Args (
  3165. Obj oper,
  3166. Obj arg1,
  3167. Obj arg2,
  3168. Obj arg3,
  3169. Obj arg4,
  3170. Obj arg5,
  3171. Obj arg6 )
  3172. {
  3173. Obj res;
  3174. Obj kind1;
  3175. Obj kind2;
  3176. Obj id2;
  3177. Obj kind3;
  3178. Obj id3;
  3179. Obj kind4;
  3180. Obj id4;
  3181. Obj kind5;
  3182. Obj id5;
  3183. Obj kind6;
  3184. Obj id6;
  3185. Obj * cache;
  3186. Obj method;
  3187. Obj margs;
  3188. Int i;
  3189. Obj prec;
  3190. /* get the kinds of the arguments */
  3191. while (!IS_OPERATION(arg1))
  3192. {
  3193. arg1 = ErrorReturnObj(
  3194. "Constructor: the first argument must be a filter not a %s",
  3195. (Int)TNAM_OBJ(arg1), 0L,
  3196. "you can replace the first argument <arg1> via 'return <arg1>;'");
  3197. }
  3198. kind1 = FLAGS_FILT( arg1 );
  3199. kind2 = TYPE_OBJ_FEO( arg2 ); id2 = ID_TYPE( kind2 );
  3200. kind3 = TYPE_OBJ_FEO( arg3 ); id3 = ID_TYPE( kind3 );
  3201. kind4 = TYPE_OBJ_FEO( arg4 ); id4 = ID_TYPE( kind4 );
  3202. kind5 = TYPE_OBJ_FEO( arg5 ); id5 = ID_TYPE( kind5 );
  3203. kind6 = TYPE_OBJ_FEO( arg6 ); id6 = ID_TYPE( kind6 );
  3204. /* try to find an applicable method in the cache */
  3205. cache = 1+ADDR_OBJ( CacheOper( oper, 6 ) );
  3206. prec = INTOBJ_INT(-1);
  3207. do {
  3208. /* The next line depends on the implementation of INTOBJS */
  3209. prec = (Obj)(((Int)prec) +4);
  3210. method = 0;
  3211. /* Up to CACHE_SIZE methods might be in the cache */
  3212. if (prec < INTOBJ_INT(CACHE_SIZE))
  3213. {
  3214. for (i = 0; i < 8*CACHE_SIZE; i+= 8) {
  3215. if ( cache[i+1] == prec && cache[i+2] == kind1 &&
  3216. cache[i+3] == id2 && cache[i+4] == id3 &&
  3217. cache[i+5] == id4 && cache[i+6] == id5 &&
  3218. cache[i+7] == id6) {
  3219. method = cache[i];
  3220. #ifdef COUNT_OPERS
  3221. OperationHit++;
  3222. #endif
  3223. break;
  3224. }
  3225. }
  3226. }
  3227. /* otherwise try to find one in the list of methods */
  3228. if (!method)
  3229. {
  3230. if (prec == INTOBJ_INT(0))
  3231. {
  3232. margs = NEW_PLIST(T_PLIST, 7);
  3233. SET_ELM_PLIST(margs, 1, oper );
  3234. SET_ELM_PLIST(margs, 2, kind1 );
  3235. SET_ELM_PLIST(margs, 3, kind2 );
  3236. SET_ELM_PLIST(margs, 4, kind3 );
  3237. SET_ELM_PLIST(margs, 5, kind4 );
  3238. SET_ELM_PLIST(margs, 6, kind5 );
  3239. SET_ELM_PLIST(margs, 7, kind6 );
  3240. SET_LEN_PLIST(margs, 7);
  3241. method = CALL_XARGS( Constructor6Args, margs );
  3242. }
  3243. else
  3244. {
  3245. margs = NEW_PLIST(T_PLIST, 8);
  3246. SET_ELM_PLIST(margs, 1, oper );
  3247. SET_ELM_PLIST(margs, 2, prec );
  3248. SET_ELM_PLIST(margs, 3, kind1 );
  3249. SET_ELM_PLIST(margs, 4, kind2 );
  3250. SET_ELM_PLIST(margs, 5, kind3 );
  3251. SET_ELM_PLIST(margs, 6, kind4 );
  3252. SET_ELM_PLIST(margs, 7, kind5 );
  3253. SET_ELM_PLIST(margs, 8, kind6 );
  3254. SET_LEN_PLIST(margs, 8);
  3255. method = CALL_XARGS( NextConstructor6Args, margs );
  3256. }
  3257. while (method == Fail)
  3258. {
  3259. Obj arglist[6];
  3260. arglist[0] = arg1;
  3261. arglist[1] = arg2;
  3262. arglist[2] = arg3;
  3263. arglist[3] = arg4;
  3264. arglist[4] = arg5;
  3265. arglist[5] = arg6;
  3266. method = CallHandleMethodNotFound(oper, 6, arglist, 0, 1, prec);
  3267. }
  3268. /* update the cache */
  3269. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  3270. {
  3271. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 6 ) );
  3272. cache[8*CacheIndex] = method;
  3273. cache[8*CacheIndex+1] = prec;
  3274. cache[8*CacheIndex+2] = kind1;
  3275. cache[8*CacheIndex+3] = id2;
  3276. cache[8*CacheIndex+4] = id3;
  3277. cache[8*CacheIndex+5] = id4;
  3278. cache[8*CacheIndex+6] = id5;
  3279. cache[8*CacheIndex+7] = id6;
  3280. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  3281. CHANGED_BAG(CACHE_OPER(oper,6));
  3282. }
  3283. #ifdef COUNT_OPERS
  3284. OperationMiss++;
  3285. #endif
  3286. }
  3287. if ( !method ) {
  3288. ErrorQuit( "no method returned", 0L, 0L );
  3289. }
  3290. /* call this method */
  3291. res = CALL_6ARGS( method, arg1, arg2, arg3, arg4, arg5, arg6 );
  3292. }
  3293. while (res == TRY_NEXT_METHOD );
  3294. /* return the result */
  3295. return res;
  3296. }
  3297. /****************************************************************************
  3298. **
  3299. ** DoConstructorXArgs( <oper>, ... )
  3300. */
  3301. Obj DoConstructorXArgs (
  3302. Obj self,
  3303. Obj args )
  3304. {
  3305. ErrorQuit("sorry: cannot yet have X argument constructors",0L,0L);
  3306. return 0;
  3307. }
  3308. /****************************************************************************
  3309. **
  3310. ** DoVerboseConstructor0Args( <oper> )
  3311. */
  3312. Obj DoVerboseConstructor0Args (
  3313. Obj oper )
  3314. {
  3315. Obj res;
  3316. Obj method;
  3317. Int i;
  3318. /* try to find one in the list of methods */
  3319. method = CALL_1ARGS( VConstructor0Args, oper );
  3320. while (method == Fail)
  3321. {
  3322. method = CallHandleMethodNotFound( oper, 0, (Obj *) 0, 1, 0, INTOBJ_INT(0));
  3323. }
  3324. if ( method == 0 ) {
  3325. ErrorQuit( "no method returned", 0L, 0L );
  3326. }
  3327. /* call this method */
  3328. res = CALL_0ARGS( method );
  3329. /* try until a method doesn't give up */
  3330. if ( res == TRY_NEXT_METHOD ) {
  3331. i = 1;
  3332. while ( res == TRY_NEXT_METHOD ) {
  3333. #ifdef COUNT_OPERS
  3334. OperationNext++;
  3335. #endif
  3336. method = CALL_2ARGS( NextVConstructor0Args, oper, INTOBJ_INT(i) );
  3337. while (method == Fail)
  3338. {
  3339. method = CallHandleMethodNotFound( oper, 0, (Obj *) 0, 1, 0, INTOBJ_INT(i));
  3340. }
  3341. i++;
  3342. res = CALL_0ARGS( method );
  3343. }
  3344. }
  3345. /* return the result */
  3346. return res;
  3347. }
  3348. /****************************************************************************
  3349. **
  3350. ** DoVerboseConstructor1Args( <oper>, <a1> )
  3351. */
  3352. Obj DoVerboseConstructor1Args (
  3353. Obj oper,
  3354. Obj arg1 )
  3355. {
  3356. Obj res;
  3357. Obj kind1;
  3358. Obj method;
  3359. Int i;
  3360. /* get the kinds of the arguments */
  3361. while (!IS_OPERATION(arg1))
  3362. {
  3363. arg1 = ErrorReturnObj(
  3364. "Constructor: the first argument must be a filter not a %s",
  3365. (Int)TNAM_OBJ(arg1), 0L,
  3366. "you can replace the first argument <arg1> via 'return <arg1>;'");
  3367. }
  3368. kind1 = FLAGS_FILT( arg1 );
  3369. /* try to find one in the list of methods */
  3370. method = CALL_2ARGS( VConstructor1Args, oper, kind1 );
  3371. while (method == Fail)
  3372. {
  3373. Obj arglist[1];
  3374. arglist[0] = arg1;
  3375. method = CallHandleMethodNotFound( oper, 1, arglist, 1, 0, INTOBJ_INT(0));
  3376. }
  3377. if ( method == 0 ) {
  3378. ErrorQuit( "no method returned", 0L, 0L );
  3379. }
  3380. /* call this method */
  3381. res = CALL_1ARGS( method, arg1 );
  3382. /* try until a method doesn't give up */
  3383. if ( res == TRY_NEXT_METHOD ) {
  3384. i = 1;
  3385. while ( res == TRY_NEXT_METHOD ) {
  3386. #ifdef COUNT_OPERS
  3387. OperationNext++;
  3388. #endif
  3389. method = CALL_3ARGS( NextVConstructor1Args, oper, INTOBJ_INT(i),
  3390. kind1 );
  3391. while (method == Fail)
  3392. {
  3393. Obj arglist[1];
  3394. arglist[0] = arg1;
  3395. method = CallHandleMethodNotFound( oper, 1, arglist, 1, 0, INTOBJ_INT(i));
  3396. }
  3397. i++;
  3398. res = CALL_1ARGS( method, arg1 );
  3399. }
  3400. }
  3401. /* return the result */
  3402. return res;
  3403. }
  3404. /****************************************************************************
  3405. **
  3406. ** DoVerboseConstructor2Args( <oper>, <a1>, <a2> )
  3407. */
  3408. Obj DoVerboseConstructor2Args (
  3409. Obj oper,
  3410. Obj arg1,
  3411. Obj arg2 )
  3412. {
  3413. Obj res;
  3414. Obj kind1;
  3415. Obj kind2;
  3416. Obj method;
  3417. Int i;
  3418. /* get the kinds of the arguments */
  3419. while (!IS_OPERATION(arg1))
  3420. {
  3421. arg1 = ErrorReturnObj(
  3422. "Constructor: the first argument must be a filter not a %s",
  3423. (Int)TNAM_OBJ(arg1), 0L,
  3424. "you can replace the first argument <arg1> via 'return <arg1>;'");
  3425. }
  3426. kind1 = FLAGS_FILT( arg1 );
  3427. kind2 = TYPE_OBJ_FEO( arg2 );
  3428. /* try to find one in the list of methods */
  3429. method = CALL_3ARGS( VConstructor2Args, oper, kind1, kind2 );
  3430. while (method == Fail)
  3431. {
  3432. Obj arglist[2];
  3433. arglist[0] = arg1;
  3434. arglist[1] = arg2;
  3435. method = CallHandleMethodNotFound( oper, 2, arglist, 1, 0, INTOBJ_INT(0));
  3436. }
  3437. if ( method == 0 ) {
  3438. ErrorQuit( "no method returned", 0L, 0L );
  3439. }
  3440. /* call this method */
  3441. res = CALL_2ARGS( method, arg1, arg2 );
  3442. /* try until a method doesn't give up */
  3443. if ( res == TRY_NEXT_METHOD ) {
  3444. i = 1;
  3445. while ( res == TRY_NEXT_METHOD ) {
  3446. #ifdef COUNT_OPERS
  3447. OperationNext++;
  3448. #endif
  3449. method = CALL_4ARGS( NextVConstructor2Args, oper, INTOBJ_INT(i),
  3450. kind1, kind2 );
  3451. while (method == Fail)
  3452. {
  3453. Obj arglist[2];
  3454. arglist[0] = arg1;
  3455. arglist[1] = arg2;
  3456. method = CallHandleMethodNotFound( oper, 2, arglist, 1, 0, INTOBJ_INT(i));
  3457. }
  3458. i++;
  3459. res = CALL_2ARGS( method, arg1, arg2 );
  3460. }
  3461. }
  3462. /* return the result */
  3463. return res;
  3464. }
  3465. /****************************************************************************
  3466. **
  3467. ** DoVerboseConstructor3Args( <oper>, <a1>, <a2>, <a3> )
  3468. */
  3469. Obj DoVerboseConstructor3Args (
  3470. Obj oper,
  3471. Obj arg1,
  3472. Obj arg2,
  3473. Obj arg3 )
  3474. {
  3475. Obj res;
  3476. Obj kind1;
  3477. Obj kind2;
  3478. Obj kind3;
  3479. Obj method;
  3480. Int i;
  3481. /* get the kinds of the arguments */
  3482. while (!IS_OPERATION(arg1))
  3483. {
  3484. arg1 = ErrorReturnObj(
  3485. "Constructor: the first argument must be a filter not a %s",
  3486. (Int)TNAM_OBJ(arg1), 0L,
  3487. "you can replace the first argument <arg1> via 'return <arg1>;'");
  3488. }
  3489. kind1 = FLAGS_FILT( arg1 );
  3490. kind2 = TYPE_OBJ_FEO( arg2 );
  3491. kind3 = TYPE_OBJ_FEO( arg3 );
  3492. /* try to find one in the list of methods */
  3493. method = CALL_4ARGS( VConstructor3Args, oper, kind1, kind2, kind3 );
  3494. while (method == Fail)
  3495. {
  3496. Obj arglist[3];
  3497. arglist[0] = arg1;
  3498. arglist[1] = arg2;
  3499. arglist[2] = arg3;
  3500. method = CallHandleMethodNotFound( oper, 3, arglist, 1, 0, INTOBJ_INT(0));
  3501. }
  3502. if ( method == 0 ) {
  3503. ErrorQuit( "no method returned", 0L, 0L );
  3504. }
  3505. /* call this method */
  3506. res = CALL_3ARGS( method, arg1, arg2, arg3 );
  3507. /* try until a method doesn't give up */
  3508. if ( res == TRY_NEXT_METHOD ) {
  3509. i = 1;
  3510. while ( res == TRY_NEXT_METHOD ) {
  3511. #ifdef COUNT_OPERS
  3512. OperationNext++;
  3513. #endif
  3514. method = CALL_5ARGS( NextVConstructor3Args, oper, INTOBJ_INT(i),
  3515. kind1, kind2, kind3 );
  3516. while (method == Fail)
  3517. {
  3518. Obj arglist[3];
  3519. arglist[0] = arg1;
  3520. arglist[1] = arg2;
  3521. arglist[2] = arg3;
  3522. method = CallHandleMethodNotFound( oper, 3, arglist, 1, 0, INTOBJ_INT(i));
  3523. }
  3524. i++;
  3525. res = CALL_3ARGS( method, arg1, arg2, arg3 );
  3526. }
  3527. }
  3528. /* return the result */
  3529. return res;
  3530. }
  3531. /****************************************************************************
  3532. **
  3533. ** DoVerboseConstructor4Args( <oper>, <a1>, <a2>, <a3>, <a4> )
  3534. */
  3535. Obj DoVerboseConstructor4Args (
  3536. Obj oper,
  3537. Obj arg1,
  3538. Obj arg2,
  3539. Obj arg3,
  3540. Obj arg4 )
  3541. {
  3542. Obj res;
  3543. Obj kind1;
  3544. Obj kind2;
  3545. Obj kind3;
  3546. Obj kind4;
  3547. Obj method;
  3548. Int i;
  3549. /* get the kinds of the arguments */
  3550. while (!IS_OPERATION(arg1))
  3551. {
  3552. arg1 = ErrorReturnObj(
  3553. "Constructor: the first argument must be a filter not a %s",
  3554. (Int)TNAM_OBJ(arg1), 0L,
  3555. "you can replace the first argument <arg1> via 'return <arg1>;'");
  3556. }
  3557. kind1 = FLAGS_FILT( arg1 );
  3558. kind2 = TYPE_OBJ_FEO( arg2 );
  3559. kind3 = TYPE_OBJ_FEO( arg3 );
  3560. kind4 = TYPE_OBJ_FEO( arg4 );
  3561. /* try to find one in the list of methods */
  3562. method = CALL_5ARGS( VConstructor4Args, oper, kind1, kind2, kind3, kind4 );
  3563. while (method == Fail)
  3564. {
  3565. Obj arglist[4];
  3566. arglist[0] = arg1;
  3567. arglist[1] = arg2;
  3568. arglist[2] = arg3;
  3569. arglist[3] = arg4;
  3570. method = CallHandleMethodNotFound( oper, 4, arglist, 1, 0, INTOBJ_INT(0));
  3571. }
  3572. if ( method == 0 ) {
  3573. ErrorQuit( "no method returned", 0L, 0L );
  3574. }
  3575. /* call this method */
  3576. res = CALL_4ARGS( method, arg1, arg2, arg3, arg4 );
  3577. /* try until a method doesn't give up */
  3578. if ( res == TRY_NEXT_METHOD ) {
  3579. i = 1;
  3580. while ( res == TRY_NEXT_METHOD ) {
  3581. #ifdef COUNT_OPERS
  3582. OperationNext++;
  3583. #endif
  3584. method = CALL_6ARGS( NextVConstructor4Args, oper, INTOBJ_INT(i),
  3585. kind1, kind2, kind3, kind4 );
  3586. while (method == Fail)
  3587. {
  3588. Obj arglist[4];
  3589. arglist[0] = arg1;
  3590. arglist[1] = arg2;
  3591. arglist[2] = arg3;
  3592. arglist[3] = arg4;
  3593. method = CallHandleMethodNotFound( oper, 4, arglist, 1, 0, INTOBJ_INT(i));
  3594. }
  3595. i++;
  3596. res = CALL_4ARGS( method, arg1, arg2, arg3, arg4 );
  3597. }
  3598. }
  3599. /* return the result */
  3600. return res;
  3601. }
  3602. /****************************************************************************
  3603. **
  3604. ** DoVerboseConstructor5Args( <oper>, <a1>, <a2>, <a3>, <a4>, <a5> )
  3605. */
  3606. Obj DoVerboseConstructor5Args (
  3607. Obj oper,
  3608. Obj arg1,
  3609. Obj arg2,
  3610. Obj arg3,
  3611. Obj arg4,
  3612. Obj arg5 )
  3613. {
  3614. Obj res;
  3615. Obj kind1;
  3616. Obj kind2;
  3617. Obj kind3;
  3618. Obj kind4;
  3619. Obj kind5;
  3620. Obj method;
  3621. Obj margs;
  3622. Int i;
  3623. /* get the kinds of the arguments */
  3624. while (!IS_OPERATION(arg1))
  3625. {
  3626. arg1 = ErrorReturnObj(
  3627. "Constructor: the first argument must be a filter not a %s",
  3628. (Int)TNAM_OBJ(arg1), 0L,
  3629. "you can replace the first argument <arg1> via 'return <arg1>;'");
  3630. }
  3631. kind1 = FLAGS_FILT( arg1 );
  3632. kind2 = TYPE_OBJ_FEO( arg2 );
  3633. kind3 = TYPE_OBJ_FEO( arg3 );
  3634. kind4 = TYPE_OBJ_FEO( arg4 );
  3635. kind5 = TYPE_OBJ_FEO( arg5 );
  3636. /* try to find one in the list of methods */
  3637. method = CALL_6ARGS( VConstructor5Args, oper, kind1, kind2, kind3, kind4,
  3638. kind5 );
  3639. while (method == Fail)
  3640. {
  3641. Obj arglist[5];
  3642. arglist[0] = arg1;
  3643. arglist[1] = arg2;
  3644. arglist[2] = arg3;
  3645. arglist[3] = arg4;
  3646. arglist[4] = arg5;
  3647. method = CallHandleMethodNotFound( oper, 5, arglist, 1, 0, INTOBJ_INT(0));
  3648. }
  3649. if ( method == 0 ) {
  3650. ErrorQuit( "no method returned", 0L, 0L );
  3651. }
  3652. /* call this method */
  3653. res = CALL_5ARGS( method, arg1, arg2, arg3, arg4, arg5 );
  3654. /* try until a method doesn't give up */
  3655. if ( res == TRY_NEXT_METHOD ) {
  3656. i = 1;
  3657. while ( res == TRY_NEXT_METHOD ) {
  3658. #ifdef COUNT_OPERS
  3659. OperationNext++;
  3660. #endif
  3661. margs = NEW_PLIST( T_PLIST, 7 );
  3662. SET_LEN_PLIST( margs, 7 );
  3663. SET_ELM_PLIST( margs, 1, oper );
  3664. SET_ELM_PLIST( margs, 2, INTOBJ_INT(i) );
  3665. SET_ELM_PLIST( margs, 3, kind1 );
  3666. SET_ELM_PLIST( margs, 4, kind2 );
  3667. SET_ELM_PLIST( margs, 5, kind3 );
  3668. SET_ELM_PLIST( margs, 6, kind4 );
  3669. SET_ELM_PLIST( margs, 7, kind5 );
  3670. method = CALL_XARGS( NextVConstructor5Args, margs );
  3671. while (method == Fail)
  3672. {
  3673. Obj arglist[5];
  3674. arglist[0] = arg1;
  3675. arglist[1] = arg2;
  3676. arglist[2] = arg3;
  3677. arglist[3] = arg4;
  3678. arglist[4] = arg5;
  3679. method = CallHandleMethodNotFound( oper, 5, arglist, 1, 0, INTOBJ_INT(i));
  3680. }
  3681. i++;
  3682. res = CALL_5ARGS( method, arg1, arg2, arg3, arg4, arg5 );
  3683. }
  3684. }
  3685. /* return the result */
  3686. return res;
  3687. }
  3688. /****************************************************************************
  3689. **
  3690. ** DoVerboseConstructor6Args( <oper>, <a1>, <a2>, <a3>, <a4>, <a5>, <a6> )
  3691. */
  3692. Obj DoVerboseConstructor6Args (
  3693. Obj oper,
  3694. Obj arg1,
  3695. Obj arg2,
  3696. Obj arg3,
  3697. Obj arg4,
  3698. Obj arg5,
  3699. Obj arg6 )
  3700. {
  3701. Obj res;
  3702. Obj kind1;
  3703. Obj kind2;
  3704. Obj kind3;
  3705. Obj kind4;
  3706. Obj kind5;
  3707. Obj kind6;
  3708. Obj method;
  3709. Obj margs;
  3710. Int i;
  3711. /* get the kinds of the arguments */
  3712. while (!IS_OPERATION(arg1))
  3713. {
  3714. arg1 = ErrorReturnObj(
  3715. "Constructor: the first argument must be a filter not a %s",
  3716. (Int)TNAM_OBJ(arg1), 0L,
  3717. "you can replace the first argument <arg1> via 'return <arg1>;'");
  3718. }
  3719. kind1 = FLAGS_FILT( arg1 );
  3720. kind2 = TYPE_OBJ_FEO( arg2 );
  3721. kind3 = TYPE_OBJ_FEO( arg3 );
  3722. kind4 = TYPE_OBJ_FEO( arg4 );
  3723. kind5 = TYPE_OBJ_FEO( arg5 );
  3724. kind6 = TYPE_OBJ_FEO( arg6 );
  3725. /* try to find one in the list of methods */
  3726. margs = NEW_PLIST( T_PLIST, 7 );
  3727. SET_LEN_PLIST( margs, 7 );
  3728. SET_ELM_PLIST( margs, 1, oper );
  3729. SET_ELM_PLIST( margs, 2, kind1 );
  3730. SET_ELM_PLIST( margs, 3, kind2 );
  3731. SET_ELM_PLIST( margs, 4, kind3 );
  3732. SET_ELM_PLIST( margs, 5, kind4 );
  3733. SET_ELM_PLIST( margs, 6, kind5 );
  3734. SET_ELM_PLIST( margs, 7, kind6 );
  3735. method = CALL_XARGS( VConstructor6Args, margs );
  3736. while (method == Fail)
  3737. {
  3738. Obj arglist[6];
  3739. arglist[0] = arg1;
  3740. arglist[1] = arg2;
  3741. arglist[2] = arg3;
  3742. arglist[3] = arg4;
  3743. arglist[4] = arg5;
  3744. arglist[5] = arg6;
  3745. method = CallHandleMethodNotFound( oper, 6, arglist, 1, 0, INTOBJ_INT(0));
  3746. }
  3747. if ( method == 0 ) {
  3748. ErrorQuit( "no method returned", 0L, 0L );
  3749. }
  3750. /* call this method */
  3751. res = CALL_6ARGS( method, arg1, arg2, arg3, arg4, arg5, arg6 );
  3752. /* try until a method doesn't give up */
  3753. if ( res == TRY_NEXT_METHOD ) {
  3754. i = 1;
  3755. while ( res == TRY_NEXT_METHOD ) {
  3756. #ifdef COUNT_OPERS
  3757. OperationNext++;
  3758. #endif
  3759. margs = NEW_PLIST( T_PLIST, 8 );
  3760. SET_LEN_PLIST( margs, 8 );
  3761. SET_ELM_PLIST( margs, 1, oper );
  3762. SET_ELM_PLIST( margs, 2, INTOBJ_INT(i) );
  3763. SET_ELM_PLIST( margs, 3, kind1 );
  3764. SET_ELM_PLIST( margs, 4, kind2 );
  3765. SET_ELM_PLIST( margs, 5, kind3 );
  3766. SET_ELM_PLIST( margs, 6, kind4 );
  3767. SET_ELM_PLIST( margs, 7, kind5 );
  3768. SET_ELM_PLIST( margs, 8, kind6 );
  3769. method = CALL_XARGS( NextVConstructor6Args, margs );
  3770. while (method == Fail)
  3771. {
  3772. Obj arglist[6];
  3773. arglist[0] = arg1;
  3774. arglist[1] = arg2;
  3775. arglist[2] = arg3;
  3776. arglist[3] = arg4;
  3777. arglist[4] = arg5;
  3778. arglist[5] = arg6;
  3779. method = CallHandleMethodNotFound( oper, 6, arglist, 1, 0, INTOBJ_INT(i));
  3780. }
  3781. i++;
  3782. res = CALL_6ARGS( method, arg1, arg2, arg3, arg4, arg5, arg6 );
  3783. }
  3784. }
  3785. /* return the result */
  3786. return res;
  3787. }
  3788. /****************************************************************************
  3789. **
  3790. ** DoVerboseConstructorXArgs( <oper>, ... )
  3791. */
  3792. Obj DoVerboseConstructorXArgs (
  3793. Obj self,
  3794. Obj args )
  3795. {
  3796. ErrorQuit("sorry: cannot yet have X argument constructors",0L,0L);
  3797. return 0;
  3798. }
  3799. /****************************************************************************
  3800. **
  3801. *F NewConstructor( <name>, <narg>, <nams>, <hdlr> )
  3802. */
  3803. Obj NewConstructor (
  3804. Obj name,
  3805. Int narg,
  3806. Obj nams,
  3807. ObjFunc hdlr )
  3808. {
  3809. Obj oper;
  3810. #ifdef PREALLOCATE_TABLES
  3811. Obj cache;
  3812. Obj methods;
  3813. UInt i;
  3814. #endif
  3815. /* create the function */
  3816. oper = NewFunctionT( T_FUNCTION, SIZE_OPER, name, narg, nams, hdlr );
  3817. /* enter the handlers */
  3818. if ( narg == -1 ) {
  3819. HDLR_FUNC(oper,0) = DoConstructor0Args;
  3820. HDLR_FUNC(oper,1) = DoConstructor1Args;
  3821. HDLR_FUNC(oper,2) = DoConstructor2Args;
  3822. HDLR_FUNC(oper,3) = DoConstructor3Args;
  3823. HDLR_FUNC(oper,4) = DoConstructor4Args;
  3824. HDLR_FUNC(oper,5) = DoConstructor5Args;
  3825. HDLR_FUNC(oper,6) = DoConstructor6Args;
  3826. HDLR_FUNC(oper,7) = DoConstructorXArgs;
  3827. }
  3828. /*N 1996/06/06 mschoene this should not be done here */
  3829. FLAG1_FILT(oper) = INT_INTOBJ(0);
  3830. FLAG2_FILT(oper) = INT_INTOBJ(0);
  3831. FLAGS_FILT(oper) = False;
  3832. SETTR_FILT(oper) = False;
  3833. TESTR_FILT(oper) = False;
  3834. #ifdef PREALLOCATE_TABLES
  3835. /* create caches and methods lists */
  3836. for ( i = 0; i <= 7; i++ ) {
  3837. methods = NEW_PLIST( T_PLIST, 0 );
  3838. METHS_OPER( oper, i ) = methods;
  3839. cache = NEW_PLIST( T_PLIST, (i < 7 ? 4 * (i+1) : 4 * (1+1)) );
  3840. CACHE_OPER( oper, i ) = cache;
  3841. CHANGED_BAG(oper);
  3842. }
  3843. #endif
  3844. /* return constructor */
  3845. return oper;
  3846. }
  3847. /****************************************************************************
  3848. **
  3849. *F NewConstructorC( <name>, <narg>, <nams>, <hdlr> )
  3850. */
  3851. Obj NewConstructorC (
  3852. Char * name,
  3853. Int narg,
  3854. Char * nams,
  3855. ObjFunc hdlr )
  3856. {
  3857. Obj oper;
  3858. #ifdef PREALLOCATE_TABLES
  3859. Obj cache;
  3860. Obj methods;
  3861. UInt i;
  3862. #endif
  3863. /* create the function */
  3864. oper = NewFunctionCT( T_FUNCTION, SIZE_OPER, name, narg, nams, hdlr );
  3865. /* enter the handlers */
  3866. if ( narg == -1 ) {
  3867. HDLR_FUNC(oper,0) = DoConstructor0Args;
  3868. HDLR_FUNC(oper,1) = DoConstructor1Args;
  3869. HDLR_FUNC(oper,2) = DoConstructor2Args;
  3870. HDLR_FUNC(oper,3) = DoConstructor3Args;
  3871. HDLR_FUNC(oper,4) = DoConstructor4Args;
  3872. HDLR_FUNC(oper,5) = DoConstructor5Args;
  3873. HDLR_FUNC(oper,6) = DoConstructor6Args;
  3874. HDLR_FUNC(oper,7) = DoConstructorXArgs;
  3875. }
  3876. /*N 1996/06/06 mschoene this should not be done here */
  3877. FLAG1_FILT(oper) = INT_INTOBJ(0);
  3878. FLAG2_FILT(oper) = INT_INTOBJ(0);
  3879. FLAGS_FILT(oper) = False;
  3880. SETTR_FILT(oper) = False;
  3881. TESTR_FILT(oper) = False;
  3882. #ifdef PREALLOCATE_TABLES
  3883. /* create caches and methods lists */
  3884. for ( i = 0; i <= 7; i++ ) {
  3885. methods = NEW_PLIST( T_PLIST, 0 );
  3886. METHS_OPER( oper, i ) = methods;
  3887. cache = NEW_PLIST( T_PLIST, (i < 7 ? 4 * (i+1) : 4 * (1+1)) );
  3888. CACHE_OPER( oper, i ) = cache;
  3889. CHANGED_BAG(oper);
  3890. }
  3891. #endif
  3892. /* return constructor */
  3893. return oper;
  3894. }
  3895. /****************************************************************************
  3896. **
  3897. *F DoAttribute( <name> ) . . . . . . . . . . . . . . . make a new attribute
  3898. */
  3899. /****************************************************************************
  3900. **
  3901. ** DoTestAttribute( <attr>, <obj> )
  3902. */
  3903. Obj DoTestAttribute (
  3904. Obj self,
  3905. Obj obj )
  3906. {
  3907. Int flag2;
  3908. Obj kind;
  3909. Obj flags;
  3910. /* get the flag for the tester */
  3911. flag2 = INT_INTOBJ( FLAG2_FILT( self ) );
  3912. /* get kind of the object and its flags */
  3913. kind = TYPE_OBJ_FEO( obj );
  3914. flags = FLAGS_TYPE( kind );
  3915. /* if the value of the property is already known, return 'true' */
  3916. if ( flag2 <= LEN_FLAGS( flags ) && ELM_FLAGS( flags, flag2 ) == True ) {
  3917. return True;
  3918. }
  3919. /* return the 'false' */
  3920. return False;
  3921. }
  3922. /****************************************************************************
  3923. **
  3924. ** DoAttribute( <attr>, <obj> )
  3925. */
  3926. #define DoSetAttribute DoOperation2Args
  3927. Obj DoAttribute (
  3928. Obj self,
  3929. Obj obj )
  3930. {
  3931. Obj val;
  3932. Int flag2;
  3933. Obj kind;
  3934. Obj flags;
  3935. /* get the flag for the tester */
  3936. flag2 = INT_INTOBJ( FLAG2_FILT( self ) );
  3937. /* get kind of the object and its flags */
  3938. kind = TYPE_OBJ_FEO( obj );
  3939. flags = FLAGS_TYPE( kind );
  3940. /* if the value of the property is already known, simply return it */
  3941. if ( flag2 <= LEN_FLAGS( flags ) && ELM_FLAGS( flags, flag2 ) == True ) {
  3942. return DoOperation1Args( self, obj );
  3943. }
  3944. /* call the operation to compute the value */
  3945. val = DoOperation1Args( self, obj );
  3946. while (val == (Obj) 0) {
  3947. val = ErrorReturnObj("Method for an attribute must return a value",
  3948. 0L, 0L,
  3949. "you can supply a value <val> via 'return <val>;'");
  3950. }
  3951. val = CopyObj( val, 0 );
  3952. /* set the value (but not for internal objects) */
  3953. if ( ENABLED_ATTR( self ) == 1 ) {
  3954. switch ( TNUM_OBJ( obj ) ) {
  3955. case T_COMOBJ:
  3956. case T_POSOBJ:
  3957. case T_DATOBJ:
  3958. DoSetAttribute( SETTR_FILT(self), obj, val );
  3959. }
  3960. }
  3961. /* return the value */
  3962. return val;
  3963. }
  3964. /****************************************************************************
  3965. **
  3966. ** DoVerboseAttribute( <attr>, <obj> )
  3967. */
  3968. #define DoVerboseSetAttribute DoVerboseOperation2Args
  3969. Obj DoVerboseAttribute (
  3970. Obj self,
  3971. Obj obj )
  3972. {
  3973. Obj val;
  3974. Int flag2;
  3975. Obj kind;
  3976. Obj flags;
  3977. /* get the flag for the tester */
  3978. flag2 = INT_INTOBJ( FLAG2_FILT( self ) );
  3979. /* get kind of the object and its flags */
  3980. kind = TYPE_OBJ_FEO( obj );
  3981. flags = FLAGS_TYPE( kind );
  3982. /* if the value of the property is already known, simply return it */
  3983. if ( flag2 <= LEN_FLAGS( flags ) && ELM_FLAGS( flags, flag2 ) == True ) {
  3984. return DoVerboseOperation1Args( self, obj );
  3985. }
  3986. /* call the operation to compute the value */
  3987. val = CopyObj( DoVerboseOperation1Args( self, obj ), 0 );
  3988. /* set the value (but not for internal objects) */
  3989. if ( ENABLED_ATTR( self ) == 1 ) {
  3990. switch ( TNUM_OBJ( obj ) ) {
  3991. case T_COMOBJ:
  3992. case T_POSOBJ:
  3993. case T_DATOBJ:
  3994. DoVerboseSetAttribute( SETTR_FILT(self), obj, val );
  3995. }
  3996. }
  3997. /* return the value */
  3998. return val;
  3999. }
  4000. /****************************************************************************
  4001. **
  4002. ** DoMutableAttribute( <attr>, <obj> )
  4003. */
  4004. Obj DoMutableAttribute (
  4005. Obj self,
  4006. Obj obj )
  4007. {
  4008. Obj val;
  4009. Int flag2;
  4010. Obj kind;
  4011. Obj flags;
  4012. /* get the flag for the tester */
  4013. flag2 = INT_INTOBJ( FLAG2_FILT( self ) );
  4014. /* get kind of the object and its flags */
  4015. kind = TYPE_OBJ_FEO( obj );
  4016. flags = FLAGS_TYPE( kind );
  4017. /* if the value of the property is already known, simply return it */
  4018. if ( flag2 <= LEN_FLAGS( flags ) && ELM_FLAGS( flags, flag2 ) == True ) {
  4019. return DoOperation1Args( self, obj );
  4020. }
  4021. /* call the operation to compute the value */
  4022. val = DoOperation1Args( self, obj );
  4023. /* set the value (but not for internal objects) */
  4024. if ( ENABLED_ATTR( self ) == 1 ) {
  4025. switch ( TNUM_OBJ( obj ) ) {
  4026. case T_COMOBJ:
  4027. case T_POSOBJ:
  4028. case T_DATOBJ:
  4029. DoSetAttribute( SETTR_FILT(self), obj, val );
  4030. }
  4031. }
  4032. /* return the value */
  4033. return val;
  4034. }
  4035. /****************************************************************************
  4036. **
  4037. ** DoVerboseMutableAttribute( <attr>, <obj> )
  4038. */
  4039. Obj DoVerboseMutableAttribute (
  4040. Obj self,
  4041. Obj obj )
  4042. {
  4043. Obj val;
  4044. Int flag2;
  4045. Obj kind;
  4046. Obj flags;
  4047. /* get the flag for the tester */
  4048. flag2 = INT_INTOBJ( FLAG2_FILT( self ) );
  4049. /* get kind of the object and its flags */
  4050. kind = TYPE_OBJ_FEO( obj );
  4051. flags = FLAGS_TYPE( kind );
  4052. /* if the value of the property is already known, simply return it */
  4053. if ( flag2 <= LEN_FLAGS( flags ) && ELM_FLAGS( flags, flag2 ) == True ) {
  4054. return DoVerboseOperation1Args( self, obj );
  4055. }
  4056. /* call the operation to compute the value */
  4057. val = DoVerboseOperation1Args( self, obj );
  4058. /* set the value (but not for internal objects) */
  4059. if ( ENABLED_ATTR( self ) == 1 ) {
  4060. switch ( TNUM_OBJ( obj ) ) {
  4061. case T_COMOBJ:
  4062. case T_POSOBJ:
  4063. case T_DATOBJ:
  4064. DoVerboseSetAttribute( SETTR_FILT(self), obj, val );
  4065. }
  4066. }
  4067. /* return the value */
  4068. return val;
  4069. }
  4070. /****************************************************************************
  4071. **
  4072. *F NewAttribute( <name>, <narg>, <nams>, <hdlr> )
  4073. */
  4074. Obj NewAttribute (
  4075. Obj name,
  4076. Int narg,
  4077. Obj nams,
  4078. ObjFunc hdlr )
  4079. {
  4080. Obj getter;
  4081. Obj setter;
  4082. Obj tester;
  4083. Int flag2;
  4084. Obj flags;
  4085. Obj fname;
  4086. flag2 = ++CountFlags;
  4087. fname = NEW_STRING( GET_LEN_STRING(name) + 8 );
  4088. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4089. SyStrncat( CSTR_STRING(fname), "Setter(", 7 );
  4090. SyStrncat( CSTR_STRING(fname), CSTR_STRING(name), GET_LEN_STRING(name) );
  4091. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4092. setter = NewOperation( fname, 2L, 0L, DoSetAttribute );
  4093. FLAG1_FILT(setter) = INTOBJ_INT( 0 );
  4094. FLAG2_FILT(setter) = INTOBJ_INT( flag2 );
  4095. CHANGED_BAG(setter);
  4096. fname = NEW_STRING( GET_LEN_STRING(name) + 8 );
  4097. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4098. SyStrncat( CSTR_STRING(fname), "Tester(", 7 );
  4099. SyStrncat( CSTR_STRING(fname), CSTR_STRING(name), GET_LEN_STRING(name) );
  4100. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4101. tester = NewFunctionT( T_FUNCTION, SIZE_OPER, fname, 1L, 0L,
  4102. DoTestAttribute );
  4103. FLAG1_FILT(tester) = INTOBJ_INT( 0 );
  4104. FLAG2_FILT(tester) = INTOBJ_INT( flag2 );
  4105. NEW_FLAGS( flags, flag2 );
  4106. SET_LEN_FLAGS( flags, flag2 );
  4107. SET_ELM_FLAGS( flags, flag2, True );
  4108. FLAGS_FILT(tester) = flags;
  4109. SETTR_FILT(tester) = 0;
  4110. TESTR_FILT(tester) = ReturnTrueFilter;
  4111. CHANGED_BAG(tester);
  4112. getter = NewOperation( name, 1L, nams, (hdlr ? hdlr : DoAttribute) );
  4113. FLAG1_FILT(getter) = INTOBJ_INT( 0 );
  4114. FLAG2_FILT(getter) = INTOBJ_INT( flag2 );
  4115. NEW_FLAGS( flags, flag2 );
  4116. SET_LEN_FLAGS( flags, flag2 );
  4117. SET_ELM_FLAGS( flags, flag2, True );
  4118. /* FLAGS_FILT(tester) = flags; */
  4119. FLAGS_FILT(getter) = FLAGS_FILT(tester);
  4120. SETTR_FILT(getter) = setter;
  4121. TESTR_FILT(getter) = tester;
  4122. SET_ENABLED_ATTR(getter,1);
  4123. CHANGED_BAG(getter);
  4124. return getter;
  4125. }
  4126. /****************************************************************************
  4127. **
  4128. *F NewAttributeC( <name>, <narg>, <nams>, <hdlr> )
  4129. */
  4130. Obj NewAttributeC (
  4131. const Char * name,
  4132. Int narg,
  4133. const Char * nams,
  4134. ObjFunc hdlr )
  4135. {
  4136. Obj getter;
  4137. Obj setter;
  4138. Obj tester;
  4139. Int flag2;
  4140. Obj flags;
  4141. Obj fname;
  4142. flag2 = ++CountFlags;
  4143. fname = NEW_STRING( strlen(name) + 8 );
  4144. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4145. SyStrncat( CSTR_STRING(fname), "Setter(", 7 );
  4146. SyStrncat( CSTR_STRING(fname), name, strlen(name) );
  4147. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4148. setter = NewOperation( fname, 2L, 0L, DoSetAttribute );
  4149. FLAG1_FILT(setter) = INTOBJ_INT( 0 );
  4150. FLAG2_FILT(setter) = INTOBJ_INT( flag2 );
  4151. CHANGED_BAG(setter);
  4152. fname = NEW_STRING( strlen(name) + 8 );
  4153. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4154. SyStrncat( CSTR_STRING(fname), "Tester(", 7 );
  4155. SyStrncat( CSTR_STRING(fname), name, strlen(name) );
  4156. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4157. tester = NewFunctionT( T_FUNCTION, SIZE_OPER, fname, 1L, 0L,
  4158. DoTestAttribute );
  4159. FLAG1_FILT(tester) = INTOBJ_INT( 0 );
  4160. FLAG2_FILT(tester) = INTOBJ_INT( flag2 );
  4161. NEW_FLAGS( flags, flag2 );
  4162. SET_LEN_FLAGS( flags, flag2 );
  4163. SET_ELM_FLAGS( flags, flag2, True );
  4164. FLAGS_FILT(tester) = flags;
  4165. SETTR_FILT(tester) = 0;
  4166. TESTR_FILT(tester) = ReturnTrueFilter;
  4167. CHANGED_BAG(tester);
  4168. getter = NewOperationC( name, 1L, nams, (hdlr ? hdlr : DoAttribute) );
  4169. FLAG1_FILT(getter) = INTOBJ_INT( 0 );
  4170. FLAG2_FILT(getter) = INTOBJ_INT( flag2 );
  4171. NEW_FLAGS( flags, flag2 );
  4172. SET_LEN_FLAGS( flags, flag2 );
  4173. SET_ELM_FLAGS( flags, flag2, True );
  4174. /* FLAGS_FILT(tester) = flags; */
  4175. FLAGS_FILT(getter) = FLAGS_FILT(tester);
  4176. SETTR_FILT(getter) = setter;
  4177. TESTR_FILT(getter) = tester;
  4178. SET_ENABLED_ATTR(getter,1);
  4179. CHANGED_BAG(getter);
  4180. return getter;
  4181. }
  4182. /****************************************************************************
  4183. **
  4184. *F DoProperty( <name> ) . . . . . . . . . . . . . . . . make a new property
  4185. */
  4186. Obj SET_FILTER_OBJ;
  4187. Obj RESET_FILTER_OBJ;
  4188. /****************************************************************************
  4189. **
  4190. ** DoTestProperty( <prop>, <obj> )
  4191. */
  4192. Obj DoTestProperty (
  4193. Obj self,
  4194. Obj obj )
  4195. {
  4196. Int flag2;
  4197. Obj kind;
  4198. Obj flags;
  4199. /* get the flags for the getter and the tester */
  4200. flag2 = INT_INTOBJ( FLAG2_FILT( self ) );
  4201. /* get kind of the object and its flags */
  4202. kind = TYPE_OBJ_FEO( obj );
  4203. flags = FLAGS_TYPE( kind );
  4204. /* if the value of the property is already known, return 'true' */
  4205. if ( flag2 <= LEN_FLAGS( flags ) && ELM_FLAGS( flags, flag2 ) == True ) {
  4206. return True;
  4207. }
  4208. /* otherwise return 'false' */
  4209. return False;
  4210. }
  4211. /****************************************************************************
  4212. **
  4213. ** DoSetProperty( <prop>, <obj>, <val> )
  4214. */
  4215. Obj DoSetProperty (
  4216. Obj self,
  4217. Obj obj,
  4218. Obj val )
  4219. {
  4220. Int flag1;
  4221. Int flag2;
  4222. Obj kind;
  4223. Obj flags;
  4224. /* get the flags for the getter and the tester */
  4225. flag1 = INT_INTOBJ( FLAG1_FILT( self ) );
  4226. flag2 = INT_INTOBJ( FLAG2_FILT( self ) );
  4227. /* get kind of the object and its flags */
  4228. kind = TYPE_OBJ_FEO( obj );
  4229. flags = FLAGS_TYPE( kind );
  4230. /* if the value of the property is already known, compare it */
  4231. if ( flag2 <= LEN_FLAGS( flags ) && ELM_FLAGS( flags, flag2 ) == True ) {
  4232. if ( val == ELM_FLAGS( flags, flag1 ) ) {
  4233. return 0;
  4234. }
  4235. else {
  4236. ErrorReturnVoid(
  4237. "Value property is already set the other way",
  4238. 0L, 0L,
  4239. "you can 'return;' to set it anyhow" );
  4240. }
  4241. }
  4242. /* set the value */
  4243. /*N 1996/06/28 mschoene <self> is the <setter> here, not the <getter>! */
  4244. /*N 1996/06/28 mschoene see hack below */
  4245. if ( TNUM_OBJ( obj ) == T_COMOBJ ) {
  4246. flags = (val == True ? self : TESTR_FILT(self));
  4247. CALL_2ARGS( SET_FILTER_OBJ, obj, flags );
  4248. }
  4249. else if ( TNUM_OBJ( obj ) == T_POSOBJ ) {
  4250. flags = (val == True ? self : TESTR_FILT(self));
  4251. CALL_2ARGS( SET_FILTER_OBJ, obj, flags );
  4252. }
  4253. else if ( TNUM_OBJ( obj ) == T_DATOBJ ) {
  4254. flags = (val == True ? self : TESTR_FILT(self));
  4255. CALL_2ARGS( SET_FILTER_OBJ, obj, flags );
  4256. }
  4257. else if ( IS_PLIST(obj) || IS_RANGE(obj) || IS_STRING_REP(obj)
  4258. || IS_BLIST_REP(obj) ) {
  4259. if ( val == True ) {
  4260. FuncSET_FILTER_LIST( 0, obj, self );
  4261. }
  4262. }
  4263. else {
  4264. ErrorReturnVoid(
  4265. "Value cannot be set for internal objects",
  4266. 0L, 0L,
  4267. "you can 'return;' without setting it" );
  4268. }
  4269. /* return the value */
  4270. return 0;
  4271. }
  4272. /****************************************************************************
  4273. **
  4274. ** DoProperty( <prop>, <obj> )
  4275. */
  4276. Obj DoProperty (
  4277. Obj self,
  4278. Obj obj )
  4279. {
  4280. Obj val;
  4281. Int flag1;
  4282. Int flag2;
  4283. Obj kind;
  4284. Obj flags;
  4285. /* get the flags for the getter and the tester */
  4286. flag1 = INT_INTOBJ( FLAG1_FILT( self ) );
  4287. flag2 = INT_INTOBJ( FLAG2_FILT( self ) );
  4288. /* get kind of the object and its flags */
  4289. kind = TYPE_OBJ_FEO( obj );
  4290. flags = FLAGS_TYPE( kind );
  4291. /* if the value of the property is already known, simply return it */
  4292. if ( flag2 <= LEN_FLAGS( flags ) && ELM_FLAGS( flags, flag2 ) == True ) {
  4293. return ELM_FLAGS( flags, flag1 );
  4294. }
  4295. /* call the operation to compute the value */
  4296. val = DoOperation1Args( self, obj );
  4297. while ( val != True && val != False ) {
  4298. val = ErrorReturnObj(
  4299. "Method for a property did not return true or false",
  4300. 0L, 0L,
  4301. "you can 'return true;' or 'return false;'");
  4302. }
  4303. /* set the value (but not for internal objects) */
  4304. if ( ENABLED_ATTR(self) == 1 && ! IS_MUTABLE_OBJ(obj) ) {
  4305. switch ( TNUM_OBJ( obj ) ) {
  4306. case T_COMOBJ:
  4307. case T_POSOBJ:
  4308. case T_DATOBJ:
  4309. flags = (val == True ? self : TESTR_FILT(self));
  4310. CALL_2ARGS( SET_FILTER_OBJ, obj, flags );
  4311. }
  4312. }
  4313. /* return the value */
  4314. return val;
  4315. }
  4316. /****************************************************************************
  4317. **
  4318. ** DoVerboseProperty( <prop>, <obj> )
  4319. */
  4320. Obj DoVerboseProperty (
  4321. Obj self,
  4322. Obj obj )
  4323. {
  4324. Obj val;
  4325. Int flag1;
  4326. Int flag2;
  4327. Obj kind;
  4328. Obj flags;
  4329. /* get the flags for the getter and the tester */
  4330. flag1 = INT_INTOBJ( FLAG1_FILT( self ) );
  4331. flag2 = INT_INTOBJ( FLAG2_FILT( self ) );
  4332. /* get kind of the object and its flags */
  4333. kind = TYPE_OBJ_FEO( obj );
  4334. flags = FLAGS_TYPE( kind );
  4335. /* if the value of the property is already known, simply return it */
  4336. if ( flag2 <= LEN_FLAGS( flags ) && ELM_FLAGS( flags, flag2 ) == True ) {
  4337. return ELM_FLAGS( flags, flag1 );
  4338. }
  4339. /* call the operation to compute the value */
  4340. val = DoVerboseOperation1Args( self, obj );
  4341. /* set the value (but not for internal objects) */
  4342. if ( ENABLED_ATTR(self) == 1 && ! IS_MUTABLE_OBJ(obj) ) {
  4343. if ( TNUM_OBJ( obj ) == T_COMOBJ ) {
  4344. flags = (val == True ? self : TESTR_FILT(self));
  4345. CALL_2ARGS( SET_FILTER_OBJ, obj, flags );
  4346. }
  4347. else if ( TNUM_OBJ( obj ) == T_POSOBJ ) {
  4348. flags = (val == True ? self : TESTR_FILT(self));
  4349. CALL_2ARGS( SET_FILTER_OBJ, obj, flags );
  4350. }
  4351. else if ( TNUM_OBJ( obj ) == T_DATOBJ ) {
  4352. flags = (val == True ? self : TESTR_FILT(self));
  4353. CALL_2ARGS( SET_FILTER_OBJ, obj, flags );
  4354. }
  4355. }
  4356. /* return the value */
  4357. return val;
  4358. }
  4359. /****************************************************************************
  4360. **
  4361. *F NewProperty( <name>, <narg>, <nams>, <hdlr> )
  4362. */
  4363. Obj NewProperty (
  4364. Obj name,
  4365. Int narg,
  4366. Obj nams,
  4367. ObjFunc hdlr )
  4368. {
  4369. Obj getter;
  4370. Obj setter;
  4371. Obj tester;
  4372. Int flag1;
  4373. Int flag2;
  4374. Obj flags;
  4375. Obj fname;
  4376. flag1 = ++CountFlags;
  4377. flag2 = ++CountFlags;
  4378. fname = NEW_STRING( GET_LEN_STRING(name) + 8 );
  4379. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4380. SyStrncat( CSTR_STRING(fname), "Setter(", 7 );
  4381. SyStrncat( CSTR_STRING(fname), CSTR_STRING(name), GET_LEN_STRING(name) );
  4382. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4383. setter = NewOperation( fname, 2L, 0L, DoSetProperty );
  4384. FLAG1_FILT(setter) = INTOBJ_INT( flag1 );
  4385. FLAG2_FILT(setter) = INTOBJ_INT( flag2 );
  4386. CHANGED_BAG(setter);
  4387. fname = NEW_STRING( GET_LEN_STRING(name) + 8 );
  4388. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4389. SyStrncat( CSTR_STRING(fname), "Tester(", 7 );
  4390. SyStrncat( CSTR_STRING(fname), CSTR_STRING(name), GET_LEN_STRING(name) );
  4391. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4392. tester = NewFunctionT( T_FUNCTION, SIZE_OPER, fname, 1L, 0L,
  4393. DoTestProperty );
  4394. FLAG1_FILT(tester) = INTOBJ_INT( flag1 );
  4395. FLAG2_FILT(tester) = INTOBJ_INT( flag2 );
  4396. NEW_FLAGS( flags, flag2 );
  4397. SET_LEN_FLAGS( flags, flag2 );
  4398. SET_ELM_FLAGS( flags, flag2, True );
  4399. FLAGS_FILT(tester) = flags;
  4400. SETTR_FILT(tester) = 0;
  4401. TESTR_FILT(tester) = ReturnTrueFilter;
  4402. CHANGED_BAG(tester);
  4403. getter = NewOperation( name, 1L, nams, (hdlr ? hdlr : DoProperty) );
  4404. FLAG1_FILT(getter) = INTOBJ_INT( flag1 );
  4405. FLAG2_FILT(getter) = INTOBJ_INT( flag2 );
  4406. NEW_FLAGS( flags, flag2 );
  4407. SET_LEN_FLAGS( flags, flag2 );
  4408. SET_ELM_FLAGS( flags, flag2, True );
  4409. SET_ELM_FLAGS( flags, flag1, True );
  4410. FLAGS_FILT(getter) = flags;
  4411. SETTR_FILT(getter) = setter;
  4412. TESTR_FILT(getter) = tester;
  4413. SET_ENABLED_ATTR(getter,1);
  4414. CHANGED_BAG(getter);
  4415. /*N 1996/06/28 mschoene bad hack see comment in <setter> */
  4416. FLAGS_FILT(setter) = flags;
  4417. SETTR_FILT(setter) = setter;
  4418. TESTR_FILT(setter) = tester;
  4419. /* return the getter */
  4420. return getter;
  4421. }
  4422. /****************************************************************************
  4423. **
  4424. *F NewPropertyC( <name>, <narg>, <nams>, <hdlr> )
  4425. */
  4426. Obj NewPropertyC (
  4427. const Char * name,
  4428. Int narg,
  4429. const Char * nams,
  4430. ObjFunc hdlr )
  4431. {
  4432. Obj getter;
  4433. Obj setter;
  4434. Obj tester;
  4435. Int flag1;
  4436. Int flag2;
  4437. Obj flags;
  4438. Obj fname;
  4439. flag1 = ++CountFlags;
  4440. flag2 = ++CountFlags;
  4441. fname = NEW_STRING( strlen(name) + 8 );
  4442. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4443. SyStrncat( CSTR_STRING(fname), "Setter(", 7 );
  4444. SyStrncat( CSTR_STRING(fname), name, strlen(name) );
  4445. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4446. setter = NewOperation( fname, 2L, 0L, DoSetProperty );
  4447. FLAG1_FILT(setter) = INTOBJ_INT( flag1 );
  4448. FLAG2_FILT(setter) = INTOBJ_INT( flag2 );
  4449. CHANGED_BAG(setter);
  4450. fname = NEW_STRING( strlen(name) + 8 );
  4451. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4452. SyStrncat( CSTR_STRING(fname), "Tester(", 7 );
  4453. SyStrncat( CSTR_STRING(fname), name, strlen(name) );
  4454. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4455. tester = NewFunctionT( T_FUNCTION, SIZE_OPER, fname, 1L, 0L,
  4456. DoTestProperty );
  4457. FLAG1_FILT(tester) = INTOBJ_INT( flag1 );
  4458. FLAG2_FILT(tester) = INTOBJ_INT( flag2 );
  4459. NEW_FLAGS( flags, flag2 );
  4460. SET_LEN_FLAGS( flags, flag2 );
  4461. SET_ELM_FLAGS( flags, flag2, True );
  4462. FLAGS_FILT(tester) = flags;
  4463. SETTR_FILT(tester) = 0;
  4464. TESTR_FILT(tester) = ReturnTrueFilter;
  4465. CHANGED_BAG(tester);
  4466. getter = NewOperationC( name, 1L, nams, (hdlr ? hdlr : DoProperty) );
  4467. FLAG1_FILT(getter) = INTOBJ_INT( flag1 );
  4468. FLAG2_FILT(getter) = INTOBJ_INT( flag2 );
  4469. NEW_FLAGS( flags, flag2 );
  4470. SET_LEN_FLAGS( flags, flag2 );
  4471. SET_ELM_FLAGS( flags, flag2, True );
  4472. SET_ELM_FLAGS( flags, flag1, True );
  4473. FLAGS_FILT(getter) = flags;
  4474. SETTR_FILT(getter) = setter;
  4475. TESTR_FILT(getter) = tester;
  4476. SET_ENABLED_ATTR(getter,1);
  4477. CHANGED_BAG(getter);
  4478. /*N 1996/06/28 mschoene bad hack see comment in <setter> */
  4479. FLAGS_FILT(setter) = flags;
  4480. SETTR_FILT(setter) = setter;
  4481. TESTR_FILT(setter) = tester;
  4482. /* return the getter */
  4483. return getter;
  4484. }
  4485. /****************************************************************************
  4486. **
  4487. *F DoOperationArgs( <name> ) . . . . . . . . . . . make a new operation args
  4488. */
  4489. /****************************************************************************
  4490. **
  4491. ** DoUninstalledOperationArgs( <oper>, <args> )
  4492. */
  4493. Obj DoUninstalledOperationArgs (
  4494. Obj oper,
  4495. Obj args )
  4496. {
  4497. ErrorQuit( "%s: function is not yet defined",
  4498. (Int)CSTR_STRING(NAME_FUNC(oper)), 0L );
  4499. return 0;
  4500. }
  4501. /****************************************************************************
  4502. **
  4503. *F NewOperationArgs( <name>, <nargs>, <nams> )
  4504. */
  4505. Obj NewOperationArgs (
  4506. Obj name,
  4507. Int narg,
  4508. Obj nams )
  4509. {
  4510. Obj func;
  4511. /* create the function */
  4512. func = NewFunctionT( T_FUNCTION, SIZE_FUNC, name, narg, nams,
  4513. DoUninstalledOperationArgs );
  4514. /* check the number of args */
  4515. if ( narg == -1 ) {
  4516. HDLR_FUNC(func,0) = DoUninstalledOperationArgs;
  4517. HDLR_FUNC(func,1) = DoUninstalledOperationArgs;
  4518. HDLR_FUNC(func,2) = DoUninstalledOperationArgs;
  4519. HDLR_FUNC(func,3) = DoUninstalledOperationArgs;
  4520. HDLR_FUNC(func,4) = DoUninstalledOperationArgs;
  4521. HDLR_FUNC(func,5) = DoUninstalledOperationArgs;
  4522. HDLR_FUNC(func,6) = DoUninstalledOperationArgs;
  4523. HDLR_FUNC(func,7) = DoUninstalledOperationArgs;
  4524. }
  4525. else {
  4526. ErrorQuit("number of args must be -1 in `NewOperationArgs'",0L,0L);
  4527. return 0;
  4528. }
  4529. /* added the name */
  4530. NAME_FUNC(func) = CopyObj( name, 0 );
  4531. /* and return */
  4532. return func;
  4533. }
  4534. /****************************************************************************
  4535. **
  4536. *F InstallMethodArgs( <oper>, <func> ) . . . . . . . . . . . clone function
  4537. **
  4538. ** There is a problem with uncompleted functions: if they are cloned then
  4539. ** only the orignal and not the clone will be completed. Therefore the
  4540. ** clone must postpone the real cloning.
  4541. */
  4542. void InstallMethodArgs (
  4543. Obj oper,
  4544. Obj func )
  4545. {
  4546. Obj name;
  4547. Int i;
  4548. /* get the name */
  4549. name = NAME_FUNC(oper);
  4550. /* clone the function */
  4551. if ( SIZE_OBJ(oper) != SIZE_OBJ(func) ) {
  4552. ErrorQuit( "size mismatch of function bags", 0L, 0L );
  4553. }
  4554. /* clone the functions */
  4555. else {
  4556. for ( i = 0; i < SIZE_OBJ(func)/sizeof(Obj); i++ ) {
  4557. ADDR_OBJ(oper)[i] = ADDR_OBJ(func)[i];
  4558. }
  4559. }
  4560. NAME_FUNC(oper) = name;
  4561. CHANGED_BAG(oper);
  4562. }
  4563. /****************************************************************************
  4564. **
  4565. *F SaveOperationExtras( <oper> ) . . . additional saving for functions which
  4566. **
  4567. ** This is called by SaveFunction when the function bag is too large to be
  4568. ** a simple function, and so must be an operation
  4569. **
  4570. */
  4571. void SaveOperationExtras (
  4572. Obj oper )
  4573. {
  4574. UInt i;
  4575. SaveSubObj(FLAG1_FILT(oper));
  4576. SaveSubObj(FLAG2_FILT(oper));
  4577. SaveSubObj(FLAGS_FILT(oper));
  4578. SaveSubObj(SETTR_FILT(oper));
  4579. SaveSubObj(TESTR_FILT(oper));
  4580. SaveUInt(ENABLED_ATTR(oper));
  4581. for (i = 0; i <= 7; i++)
  4582. SaveSubObj(METHS_OPER(oper,i));
  4583. for (i = 0; i <= 7; i++)
  4584. SaveSubObj(CACHE_OPER(oper,i));
  4585. return;
  4586. }
  4587. /****************************************************************************
  4588. **
  4589. *F LoadOperationExtras( <oper> ) . . additional loading for functions which
  4590. ** are operations
  4591. ** This is called by LoadFunction when the function bag is too large to be
  4592. ** a simple function, and so must be an operation
  4593. **
  4594. */
  4595. void LoadOperationExtras (
  4596. Obj oper )
  4597. {
  4598. UInt i;
  4599. FLAG1_FILT(oper) = LoadSubObj();
  4600. FLAG2_FILT(oper) = LoadSubObj();
  4601. FLAGS_FILT(oper) = LoadSubObj();
  4602. SETTR_FILT(oper) = LoadSubObj();
  4603. TESTR_FILT(oper) = LoadSubObj();
  4604. i = LoadUInt();
  4605. SET_ENABLED_ATTR(oper,i);
  4606. for (i = 0; i <= 7; i++)
  4607. METHS_OPER(oper,i) = LoadSubObj();
  4608. for (i = 0; i <= 7; i++)
  4609. CACHE_OPER(oper,i) = LoadSubObj();
  4610. return;
  4611. }
  4612. /****************************************************************************
  4613. **
  4614. **
  4615. *F * * * * * * * * * * * * GAP operation functions * * * * * * * * * * * * *
  4616. */
  4617. /****************************************************************************
  4618. **
  4619. *F FuncNEW_OPERATION( <self>, <name> ) . . . . . . . . . . . . new operation
  4620. */
  4621. Obj FuncNEW_OPERATION (
  4622. Obj self,
  4623. Obj name )
  4624. {
  4625. /* check the argument */
  4626. if ( ! IsStringConv(name) ) {
  4627. ErrorQuit("usage: NewOperation( <name> )",0L,0L);
  4628. return 0;
  4629. }
  4630. /* make the new operation */
  4631. return NewOperation( name, -1L, (Obj)0, DoOperationXArgs );
  4632. }
  4633. /****************************************************************************
  4634. **
  4635. *F FuncNEW_CONSTRUCTOR( <self>, <name> ) . . . . . . . . . . new constructor
  4636. */
  4637. Obj FuncNEW_CONSTRUCTOR (
  4638. Obj self,
  4639. Obj name )
  4640. {
  4641. /* check the argument */
  4642. if ( ! IsStringConv(name) ) {
  4643. ErrorQuit("usage: NewConstructor( <name> )",0L,0L);
  4644. return 0;
  4645. }
  4646. /* make the new constructor */
  4647. return NewConstructor( name, -1L, (Obj)0, DoConstructorXArgs );
  4648. }
  4649. /****************************************************************************
  4650. **
  4651. *F FuncNEW_ATTRIBUTE( <self>, <name> ) . . . . . . . . . . . . new attribute
  4652. */
  4653. Obj FuncNEW_ATTRIBUTE (
  4654. Obj self,
  4655. Obj name )
  4656. {
  4657. /* check the argument */
  4658. if ( ! IsStringConv(name) ) {
  4659. ErrorQuit("usage: NewAttribute( <name> )",0L,0L);
  4660. return 0;
  4661. }
  4662. /* make the new operation */
  4663. return NewAttribute( name, -1L, (Obj)0, DoAttribute );
  4664. }
  4665. /****************************************************************************
  4666. **
  4667. *F FuncNEW_MUTABLE_ATTRIBUTE( <self>, <name> ) . . . . new mutable attribute
  4668. */
  4669. Obj FuncNEW_MUTABLE_ATTRIBUTE (
  4670. Obj self,
  4671. Obj name )
  4672. {
  4673. /* check the argument */
  4674. if ( ! IsStringConv(name) ) {
  4675. ErrorQuit("usage: NewMutableAttribute( <name> )",0L,0L);
  4676. return 0;
  4677. }
  4678. /* make the new operation */
  4679. return NewAttribute( name, -1L, (Obj)0, DoMutableAttribute );
  4680. }
  4681. /****************************************************************************
  4682. **
  4683. *F FuncNEW_PROPERTY( <self>, <name> ) . . . . . . . . . . . . new property
  4684. */
  4685. Obj FuncNEW_PROPERTY (
  4686. Obj self,
  4687. Obj name )
  4688. {
  4689. /* check the argument */
  4690. if ( ! IsStringConv(name) ) {
  4691. ErrorQuit("usage: NewProperty( <name> )",0L,0L);
  4692. return 0;
  4693. }
  4694. /* make the new operation */
  4695. return NewProperty( name, -1L, (Obj)0, DoProperty );
  4696. }
  4697. /****************************************************************************
  4698. **
  4699. *F FuncNEW_OPERATION_ARGS( <self>, <name> ) . . . . . . new operation args
  4700. */
  4701. Obj FuncNEW_OPERATION_ARGS (
  4702. Obj self,
  4703. Obj name )
  4704. {
  4705. Obj args;
  4706. Obj list;
  4707. /* check the argument */
  4708. if ( ! IsStringConv(name) ) {
  4709. ErrorQuit( "usage: NewOperationArgs( <name> )", 0L, 0L );
  4710. return 0;
  4711. }
  4712. /* make the new operation */
  4713. C_NEW_STRING( args, 4, "args" )
  4714. list = NEW_PLIST( T_PLIST, 1 );
  4715. SET_LEN_PLIST( list, 1 );
  4716. SET_ELM_PLIST( list, 1, args );
  4717. return NewOperationArgs( name, -1, list );
  4718. }
  4719. /****************************************************************************
  4720. **
  4721. *F FuncINSTALL_METHOD_ARGS( <self>, <oper>, <func> ) . . install method args
  4722. */
  4723. static Obj REREADING;
  4724. Obj FuncINSTALL_METHOD_ARGS (
  4725. Obj self,
  4726. Obj oper,
  4727. Obj func )
  4728. {
  4729. /* check the arguments */
  4730. if ( ! IS_FUNC(oper) ) {
  4731. ErrorQuit( "<oper> must be a function (not a %s)",
  4732. (Int)TNAM_OBJ(oper), 0L );
  4733. }
  4734. if ( (REREADING != True) &&
  4735. (HDLR_FUNC(oper,0) != (ObjFunc)DoUninstalledOperationArgs) ) {
  4736. ErrorQuit( "operation already installed",
  4737. 0L, 0L );
  4738. return 0;
  4739. }
  4740. if ( ! IS_FUNC(func) ) {
  4741. ErrorQuit( "<func> must be a function (not a %s)",
  4742. (Int)TNAM_OBJ(func), 0L );
  4743. return 0;
  4744. }
  4745. if ( IS_OPERATION(func) ) {
  4746. ErrorQuit( "<func> must not be an operation", 0L, 0L );
  4747. return 0;
  4748. }
  4749. /* install the new method */
  4750. InstallMethodArgs( oper, func );
  4751. return 0;
  4752. }
  4753. /****************************************************************************
  4754. **
  4755. *F FuncIS_OPERATION( <self>, <obj> ) . . . . . . . . . is <obj> an operation
  4756. */
  4757. Obj IsOperationFilt;
  4758. Obj FuncIS_OPERATION (
  4759. Obj self,
  4760. Obj obj )
  4761. {
  4762. if ( TNUM_OBJ(obj) == T_FUNCTION && IS_OPERATION(obj) ) {
  4763. return True;
  4764. }
  4765. else if ( TNUM_OBJ(obj) < FIRST_EXTERNAL_TNUM ) {
  4766. return False;
  4767. }
  4768. else {
  4769. return DoFilter( self, obj );
  4770. }
  4771. }
  4772. /****************************************************************************
  4773. **
  4774. *F FuncMETHODS_OPERATION( <self>, <oper>, <narg> ) . . . . . list of method
  4775. */
  4776. Obj MethsOper (
  4777. Obj oper,
  4778. UInt i )
  4779. {
  4780. Obj methods;
  4781. methods = METHS_OPER( oper, i );
  4782. if ( methods == 0 ) {
  4783. methods = NEW_PLIST( T_PLIST, 0 );
  4784. METHS_OPER( oper, i ) = methods;
  4785. CHANGED_BAG( oper );
  4786. }
  4787. return methods;
  4788. }
  4789. Obj FuncMETHODS_OPERATION (
  4790. Obj self,
  4791. Obj oper,
  4792. Obj narg )
  4793. {
  4794. Int n;
  4795. Obj meth;
  4796. if ( ! IS_OPERATION(oper) ) {
  4797. ErrorQuit("<oper> must be an operation",0L,0L);
  4798. return 0;
  4799. }
  4800. if ( TNUM_OBJ(narg) != T_INT || INT_INTOBJ(narg) < 0 ) {
  4801. ErrorQuit("<narg> must be a nonnegative integer",0L,0L);
  4802. return 0;
  4803. }
  4804. n = INT_INTOBJ( narg );
  4805. meth = MethsOper( oper, (UInt)n );
  4806. return meth == 0 ? Fail : meth;
  4807. }
  4808. /****************************************************************************
  4809. **
  4810. *F FuncCHANGED_METHODS_OPERATION( <self>, <oper>, <narg> ) . . . clear cache
  4811. */
  4812. Obj FuncCHANGED_METHODS_OPERATION (
  4813. Obj self,
  4814. Obj oper,
  4815. Obj narg )
  4816. {
  4817. Obj * cache;
  4818. Int n;
  4819. Int i;
  4820. if ( ! IS_OPERATION(oper) ) {
  4821. ErrorQuit("<oper> must be an operation",0L,0L);
  4822. return 0;
  4823. }
  4824. if ( TNUM_OBJ(narg) != T_INT || INT_INTOBJ(narg) < 0 ) {
  4825. ErrorQuit("<narg> must be a nonnegative integer",0L,0L);
  4826. return 0;
  4827. }
  4828. n = INT_INTOBJ( narg );
  4829. cache = ADDR_OBJ( CacheOper( oper, (UInt) n ) );
  4830. for ( i = 0; i < SIZE_OBJ(CACHE_OPER(oper,n)) / sizeof(Obj); i++ ) {
  4831. cache[i] = 0;
  4832. }
  4833. return 0;
  4834. }
  4835. /****************************************************************************
  4836. **
  4837. *F FuncSET_METHODS_OPERATION( <self>, <oper>, <narg>, <list> ) . set methods
  4838. */
  4839. Obj FuncSET_METHODS_OPERATION (
  4840. Obj self,
  4841. Obj oper,
  4842. Obj narg,
  4843. Obj meths )
  4844. {
  4845. Int n;
  4846. if ( ! IS_OPERATION(oper) ) {
  4847. ErrorQuit("<oper> must be an operation",0L,0L);
  4848. return 0;
  4849. }
  4850. if ( TNUM_OBJ(narg) != T_INT || INT_INTOBJ(narg) < 0 ) {
  4851. ErrorQuit("<narg> must be a nonnegative integer",0L,0L);
  4852. return 0;
  4853. }
  4854. n = INT_INTOBJ( narg );
  4855. METHS_OPER( oper, n ) = meths;
  4856. return 0;
  4857. }
  4858. /****************************************************************************
  4859. **
  4860. *F FuncSETTER_FUNCTION( <self>, <name> ) . . . . . . default attribut setter
  4861. */
  4862. Obj DoSetterFunction (
  4863. Obj self,
  4864. Obj obj,
  4865. Obj value )
  4866. {
  4867. Obj tmp;
  4868. Obj tester;
  4869. Obj flags;
  4870. UInt flag2;
  4871. Obj kind;
  4872. if ( TNUM_OBJ(obj) != T_COMOBJ ) {
  4873. ErrorQuit( "<obj> must be an component object", 0L, 0L );
  4874. return 0L;
  4875. }
  4876. /* if the attribute is already there *do not* chage it */
  4877. tmp = ENVI_FUNC(self);
  4878. tester = ELM_PLIST( tmp, 2 );
  4879. flag2 = INT_INTOBJ( FLAG2_FILT(tester) );
  4880. kind = TYPE_OBJ_FEO(obj);
  4881. flags = FLAGS_TYPE(kind);
  4882. if ( flag2 <= LEN_FLAGS(flags) && ELM_FLAGS(flags,flag2) == True ) {
  4883. return 0;
  4884. }
  4885. /* set the value */
  4886. AssPRec( obj, (UInt)INT_INTOBJ(ELM_PLIST(tmp,1)), CopyObj(value,0) );
  4887. CALL_2ARGS( SET_FILTER_OBJ, obj, tester );
  4888. return 0;
  4889. }
  4890. Obj FuncSETTER_FUNCTION (
  4891. Obj self,
  4892. Obj name,
  4893. Obj filter )
  4894. {
  4895. Obj func;
  4896. Obj fname;
  4897. Obj tmp;
  4898. fname = NEW_STRING( GET_LEN_STRING(name) + 12 );
  4899. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4900. SyStrncat( CSTR_STRING(fname), "SetterFunc(", 11 );
  4901. SyStrncat( CSTR_STRING(fname), CSTR_STRING(name), GET_LEN_STRING(name) );
  4902. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4903. func = NewFunctionCT( T_FUNCTION, SIZE_FUNC, CSTR_STRING(fname), 2,
  4904. "object, value", DoSetterFunction );
  4905. tmp = NEW_PLIST( T_PLIST, 2 );
  4906. SET_LEN_PLIST( tmp, 2 );
  4907. SET_ELM_PLIST( tmp, 1, INTOBJ_INT( RNamObj(name) ) );
  4908. SET_ELM_PLIST( tmp, 2, filter );
  4909. CHANGED_BAG(tmp);
  4910. ENVI_FUNC(func) = tmp;
  4911. CHANGED_BAG(func);
  4912. return func;
  4913. }
  4914. /****************************************************************************
  4915. **
  4916. *F FuncGETTER_FUNCTION( <self>, <name> ) . . . . . . default attribut getter
  4917. */
  4918. Obj DoGetterFunction (
  4919. Obj self,
  4920. Obj obj )
  4921. {
  4922. if ( TNUM_OBJ(obj) != T_COMOBJ ) {
  4923. ErrorQuit( "<obj> must be an component object", 0L, 0L );
  4924. return 0L;
  4925. }
  4926. return ElmPRec( obj, (UInt)INT_INTOBJ(ENVI_FUNC(self)) );
  4927. }
  4928. Obj FuncGETTER_FUNCTION (
  4929. Obj self,
  4930. Obj name )
  4931. {
  4932. Obj func;
  4933. Obj fname;
  4934. fname = NEW_STRING( GET_LEN_STRING(name) + 12 );
  4935. RetypeBag( fname, IMMUTABLE_TNUM(TNUM_OBJ(fname)) );
  4936. SyStrncat( CSTR_STRING(fname), "GetterFunc(", 11 );
  4937. SyStrncat( CSTR_STRING(fname), CSTR_STRING(name), GET_LEN_STRING(name) );
  4938. SyStrncat( CSTR_STRING(fname), ")", 1 );
  4939. func = NewFunctionCT( T_FUNCTION, SIZE_FUNC, CSTR_STRING(fname), 1,
  4940. "object, value", DoGetterFunction );
  4941. ENVI_FUNC(func) = INTOBJ_INT( RNamObj(name) );
  4942. return func;
  4943. }
  4944. /****************************************************************************
  4945. **
  4946. *F FuncOPERS_CACHE_INFO( <self> ) . . . . . . . return cache stats as list
  4947. */
  4948. Obj FuncOPERS_CACHE_INFO (
  4949. Obj self )
  4950. {
  4951. Obj list;
  4952. list = NEW_PLIST( IMMUTABLE_TNUM(T_PLIST), 9 );
  4953. SET_LEN_PLIST( list, 9 );
  4954. SET_ELM_PLIST( list, 1, INTOBJ_INT(AndFlagsCacheHit) );
  4955. SET_ELM_PLIST( list, 2, INTOBJ_INT(AndFlagsCacheMiss) );
  4956. SET_ELM_PLIST( list, 3, INTOBJ_INT(AndFlagsCacheLost) );
  4957. SET_ELM_PLIST( list, 4, INTOBJ_INT(OperationHit) );
  4958. SET_ELM_PLIST( list, 5, INTOBJ_INT(OperationMiss) );
  4959. SET_ELM_PLIST( list, 6, INTOBJ_INT(IsSubsetFlagsCalls) );
  4960. SET_ELM_PLIST( list, 7, INTOBJ_INT(IsSubsetFlagsCalls1) );
  4961. SET_ELM_PLIST( list, 8, INTOBJ_INT(IsSubsetFlagsCalls2) );
  4962. SET_ELM_PLIST( list, 9, INTOBJ_INT(OperationNext) );
  4963. return list;
  4964. }
  4965. /****************************************************************************
  4966. **
  4967. *F FuncCLEAR_CACHE_INFO( <self> ) . . . . . . . . . . . . clear cache stats
  4968. */
  4969. Obj FuncCLEAR_CACHE_INFO (
  4970. Obj self )
  4971. {
  4972. AndFlagsCacheHit = 0;
  4973. AndFlagsCacheMiss = 0;
  4974. AndFlagsCacheLost = 0;
  4975. OperationHit = 0;
  4976. OperationMiss = 0;
  4977. IsSubsetFlagsCalls = 0;
  4978. IsSubsetFlagsCalls1 = 0;
  4979. IsSubsetFlagsCalls2 = 0;
  4980. OperationNext = 0;
  4981. return 0;
  4982. }
  4983. /****************************************************************************
  4984. **
  4985. *F ChangeDoOperations( <oper>, <verb> ) . . . verbose or silent operations
  4986. */
  4987. static ObjFunc TabSilentVerboseOperations[] =
  4988. {
  4989. (ObjFunc) DoOperation0Args, (ObjFunc) DoVerboseOperation0Args,
  4990. (ObjFunc) DoOperation1Args, (ObjFunc) DoVerboseOperation1Args,
  4991. (ObjFunc) DoOperation2Args, (ObjFunc) DoVerboseOperation2Args,
  4992. (ObjFunc) DoOperation3Args, (ObjFunc) DoVerboseOperation3Args,
  4993. (ObjFunc) DoOperation4Args, (ObjFunc) DoVerboseOperation4Args,
  4994. (ObjFunc) DoOperation5Args, (ObjFunc) DoVerboseOperation5Args,
  4995. (ObjFunc) DoOperation6Args, (ObjFunc) DoVerboseOperation6Args,
  4996. (ObjFunc) DoOperationXArgs, (ObjFunc) DoVerboseOperationXArgs,
  4997. (ObjFunc) DoConstructor0Args, (ObjFunc) DoVerboseConstructor0Args,
  4998. (ObjFunc) DoConstructor1Args, (ObjFunc) DoVerboseConstructor1Args,
  4999. (ObjFunc) DoConstructor2Args, (ObjFunc) DoVerboseConstructor2Args,
  5000. (ObjFunc) DoConstructor3Args, (ObjFunc) DoVerboseConstructor3Args,
  5001. (ObjFunc) DoConstructor4Args, (ObjFunc) DoVerboseConstructor4Args,
  5002. (ObjFunc) DoConstructor5Args, (ObjFunc) DoVerboseConstructor5Args,
  5003. (ObjFunc) DoConstructor6Args, (ObjFunc) DoVerboseConstructor6Args,
  5004. (ObjFunc) DoConstructorXArgs, (ObjFunc) DoVerboseConstructorXArgs,
  5005. (ObjFunc) DoAttribute, (ObjFunc) DoVerboseAttribute,
  5006. (ObjFunc) DoMutableAttribute, (ObjFunc) DoVerboseMutableAttribute,
  5007. (ObjFunc) DoProperty, (ObjFunc) DoVerboseProperty,
  5008. 0, 0
  5009. };
  5010. void ChangeDoOperations (
  5011. Obj oper,
  5012. Int verb )
  5013. {
  5014. Int i;
  5015. Int j;
  5016. /* be verbose */
  5017. if ( verb ) {
  5018. /* catch infix operations */
  5019. if ( oper == EqOper ) { InstallEqObject(1); }
  5020. if ( oper == LtOper ) { InstallLtObject(1); }
  5021. if ( oper == InOper ) { InstallInObject(1); }
  5022. if ( oper == SumOper ) { InstallSumObject(1); }
  5023. if ( oper == DiffOper ) { InstallDiffObject(1); }
  5024. if ( oper == ProdOper ) { InstallProdObject(1); }
  5025. if ( oper == QuoOper ) { InstallQuoObject(1); }
  5026. if ( oper == LQuoOper ) { InstallLQuoObject(1); }
  5027. if ( oper == PowOper ) { InstallPowObject(1); }
  5028. if ( oper == CommOper ) { InstallCommObject(1); }
  5029. if ( oper == ModOper ) { InstallModObject(1); }
  5030. if ( oper == InvOp ) { InstallInvObject(1); }
  5031. if ( oper == OneOp ) { InstallOneObject(1); }
  5032. if ( oper == AInvOp ) { InstallAinvObject(1); }
  5033. if ( oper == ZeroOp ) { InstallZeroObject(1); }
  5034. /* switch do with do verbose */
  5035. for ( j = 0; TabSilentVerboseOperations[j]; j += 2 ) {
  5036. for ( i = 0; i <= 7; i++ ) {
  5037. if ( HDLR_FUNC(oper,i) == TabSilentVerboseOperations[j] ) {
  5038. HDLR_FUNC(oper,i) = TabSilentVerboseOperations[j+1];
  5039. }
  5040. }
  5041. }
  5042. }
  5043. /* be silent */
  5044. else {
  5045. /* catch infix operations */
  5046. if ( oper == EqOper ) { InstallEqObject(0); }
  5047. if ( oper == LtOper ) { InstallLtObject(0); }
  5048. if ( oper == InOper ) { InstallInObject(0); }
  5049. if ( oper == SumOper ) { InstallSumObject(0); }
  5050. if ( oper == DiffOper ) { InstallDiffObject(0); }
  5051. if ( oper == ProdOper ) { InstallProdObject(0); }
  5052. if ( oper == QuoOper ) { InstallQuoObject(0); }
  5053. if ( oper == LQuoOper ) { InstallLQuoObject(0); }
  5054. if ( oper == PowOper ) { InstallPowObject(0); }
  5055. if ( oper == CommOper ) { InstallCommObject(0); }
  5056. if ( oper == ModOper ) { InstallModObject(0); }
  5057. if ( oper == InvOp ) { InstallInvObject(0); }
  5058. if ( oper == OneOp ) { InstallOneObject(0); }
  5059. if ( oper == AInvOp ) { InstallAinvObject(0); }
  5060. if ( oper == ZeroOp ) { InstallZeroObject(0); }
  5061. /* switch do verbose with do */
  5062. for ( j = 1; TabSilentVerboseOperations[j-1]; j += 2 ) {
  5063. for ( i = 0; i <= 7; i++ ) {
  5064. if ( HDLR_FUNC(oper,i) == TabSilentVerboseOperations[j] ) {
  5065. HDLR_FUNC(oper,i) = TabSilentVerboseOperations[j-1];
  5066. }
  5067. }
  5068. }
  5069. }
  5070. }
  5071. /****************************************************************************
  5072. **
  5073. *F FuncTRACE_METHODS( <oper> ) . . . . . . . . switch tracing of methods on
  5074. */
  5075. Obj FuncTRACE_METHODS (
  5076. Obj self,
  5077. Obj oper )
  5078. {
  5079. /* check the argument */
  5080. if ( TNUM_OBJ(oper) != T_FUNCTION || SIZE_OBJ(oper) != SIZE_OPER ) {
  5081. ErrorQuit( "<oper> must be an operation", 0L, 0L );
  5082. return 0;
  5083. }
  5084. /* install trace handler */
  5085. ChangeDoOperations( oper, 1 );
  5086. /* return nothing */
  5087. return 0;
  5088. }
  5089. /****************************************************************************
  5090. **
  5091. *F FuncUNTRACE_METHODS( <oper> ) . . . . . . . switch tracing of methods off
  5092. */
  5093. Obj FuncUNTRACE_METHODS (
  5094. Obj self,
  5095. Obj oper )
  5096. {
  5097. /* check the argument */
  5098. if ( TNUM_OBJ(oper) != T_FUNCTION || SIZE_OBJ(oper) != SIZE_OPER ) {
  5099. ErrorQuit( "<oper> must be an operation", 0L, 0L );
  5100. return 0;
  5101. }
  5102. /* install trace handler */
  5103. ChangeDoOperations( oper, 0 );
  5104. /* return nothing */
  5105. return 0;
  5106. }
  5107. /****************************************************************************
  5108. **
  5109. *F FuncSET_ATTRIBUTE_STORING( <self>, <attr>, <val> )
  5110. ** switch off or on the setter call of an attribute
  5111. */
  5112. Obj FuncSET_ATTRIBUTE_STORING (
  5113. Obj self,
  5114. Obj attr,
  5115. Obj val )
  5116. {
  5117. SET_ENABLED_ATTR(attr, (val == True) ? 1L : 0L);
  5118. return 0;
  5119. }
  5120. /****************************************************************************
  5121. **
  5122. *F FuncDO_NOTHING_SETTER(<self> , <obj>, <val> )
  5123. **
  5124. */
  5125. Obj FuncDO_NOTHING_SETTER( Obj self, Obj obj, Obj val)
  5126. {
  5127. return 0;
  5128. }
  5129. /****************************************************************************
  5130. **
  5131. *F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *
  5132. */
  5133. /****************************************************************************
  5134. **
  5135. *V GVarFilts . . . . . . . . . . . . . . . . . . . list of filters to export
  5136. */
  5137. static StructGVarFilt GVarFilts [] = {
  5138. { "IS_OPERATION", "obj", &IsOperationFilt,
  5139. FuncIS_OPERATION, "src/opers.c:IS_OPERATION" },
  5140. { 0 }
  5141. };
  5142. /****************************************************************************
  5143. **
  5144. *V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export
  5145. */
  5146. static StructGVarFunc GVarFuncs [] = {
  5147. { "AND_FLAGS", 2, "oper1, oper2",
  5148. FuncAND_FLAGS, "src/opers.c:AND_FLAGS" },
  5149. { "SUB_FLAGS", 2, "oper1, oper2",
  5150. FuncSUB_FLAGS, "src/opers.c:SUB_FLAGS" },
  5151. { "HASH_FLAGS", 1, "flags",
  5152. FuncHASH_FLAGS, "src/opers.c:HASH_FLAGS" },
  5153. { "IS_EQUAL_FLAGS", 2, "flags1, flags2",
  5154. FuncIS_EQUAL_FLAGS, "src/opers.c:IS_EQUAL_FLAGS" },
  5155. { "IS_SUBSET_FLAGS", 2, "flags1, flags2",
  5156. FuncIS_SUBSET_FLAGS, "src/opers.c:IS_SUBSET_FLAGS" },
  5157. { "TRUES_FLAGS", 1, "flags",
  5158. FuncTRUES_FLAGS, "src/opers.c:TRUES_FLAGS" },
  5159. { "SIZE_FLAGS", 1, "flags",
  5160. FuncSIZE_FLAGS, "src/opers.c:SIZE_FLAGS" },
  5161. { "LEN_FLAGS", 1, "flags",
  5162. FuncLEN_FLAGS, "src/opers.c:LEN_FLAGS" },
  5163. { "ELM_FLAGS", 2, "flags, pos",
  5164. FuncELM_FLAGS, "src/opers.c:ELM_FLAGS" },
  5165. { "FLAG1_FILTER", 1, "oper",
  5166. FuncFLAG1_FILTER, "src/opers.c:FLAG1_FILTER" },
  5167. { "SET_FLAG1_FILTER", 2, "oper, flag1",
  5168. FuncSET_FLAG1_FILTER, "src/opers.c:SET_FLAG1_FILTER" },
  5169. { "FLAG2_FILTER", 1, "oper",
  5170. FuncFLAG2_FILTER, "src/opers.c:FLAG2_FILTER" },
  5171. { "SET_FLAG2_FILTER", 2, "oper, flag2",
  5172. FuncSET_FLAG2_FILTER, "src/opers.c:SET_FLAG2_FILTER" },
  5173. { "FLAGS_FILTER", 1, "oper",
  5174. FuncFLAGS_FILTER, "src/opers.c:FLAGS_FILTER" },
  5175. { "SET_FLAGS_FILTER", 2, "oper, flags",
  5176. FuncSET_FLAGS_FILTER, "src/opers.c:SET_FLAGS_FILTER" },
  5177. { "SETTER_FILTER", 1, "oper",
  5178. FuncSETTER_FILTER, "src/opers.c:SETTER_FILTER" },
  5179. { "SET_SETTER_FILTER", 2, "oper, other",
  5180. FuncSET_SETTER_FILTER, "src/opers.c:SET_SETTER_FILTER" },
  5181. { "TESTER_FILTER", 1, "oper",
  5182. FuncTESTER_FILTER, "src/opers.c:TESTER_FILTER" },
  5183. { "SET_TESTER_FILTER", 2, "oper, other",
  5184. FuncSET_TESTER_FILTER, "src/opers.c:SET_TESTER_FILTER" },
  5185. { "METHODS_OPERATION", 2, "oper, narg",
  5186. FuncMETHODS_OPERATION, "src/opers.c:METHODS_OPERATION" },
  5187. { "SET_METHODS_OPERATION", 3, "oper, narg, meths",
  5188. FuncSET_METHODS_OPERATION, "src/opers.c:SET_METHODS_OPERATION" },
  5189. { "CHANGED_METHODS_OPERATION", 2, "oper, narg",
  5190. FuncCHANGED_METHODS_OPERATION, "src/opers.c:CHANGED_METHODS_OPERATION" },
  5191. { "NEW_FILTER", 1, "name",
  5192. FuncNEW_FILTER, "src/opers.c:NEW_FILTER" },
  5193. { "NEW_OPERATION", 1, "name",
  5194. FuncNEW_OPERATION, "src/opers.c:NEW_OPERATION" },
  5195. { "NEW_CONSTRUCTOR", 1, "name",
  5196. FuncNEW_CONSTRUCTOR, "src/opers.c:NEW_CONSTRUCTOR" },
  5197. { "NEW_ATTRIBUTE", 1, "name",
  5198. FuncNEW_ATTRIBUTE, "src/opers.c:NEW_ATTRIBUTE" },
  5199. { "NEW_MUTABLE_ATTRIBUTE", 1, "name",
  5200. FuncNEW_MUTABLE_ATTRIBUTE, "src/opers.c:NEW_MUTABLE_ATTRIBUTE" },
  5201. { "NEW_PROPERTY", 1, "name",
  5202. FuncNEW_PROPERTY, "src/opers.c:NEW_PROPERTY" },
  5203. { "SETTER_FUNCTION", 2, "name, filter",
  5204. FuncSETTER_FUNCTION, "src/opers.c:SETTER_FUNCTION" },
  5205. { "GETTER_FUNCTION", 1, "name",
  5206. FuncGETTER_FUNCTION, "src/opers.c:GETTER_FUNCTION" },
  5207. { "NEW_OPERATION_ARGS", 1, "name",
  5208. FuncNEW_OPERATION_ARGS, "src/opers.c:NEW_OPERATION_ARGS" },
  5209. { "INSTALL_METHOD_ARGS", 2, "oper, func",
  5210. FuncINSTALL_METHOD_ARGS, "src/opers.c:INSTALL_METHOD_ARGS" },
  5211. { "TRACE_METHODS", 1, "oper",
  5212. FuncTRACE_METHODS, "src/opers.c:TRACE_METHODS" },
  5213. { "UNTRACE_METHODS", 1, "oper",
  5214. FuncUNTRACE_METHODS, "src/opers.c:UNTRACE_METHODS" },
  5215. { "OPERS_CACHE_INFO", 0, "",
  5216. FuncOPERS_CACHE_INFO, "src/opers.c:OPERS_CACHE_INFO" },
  5217. { "CLEAR_CACHE_INFO", 0, "",
  5218. FuncCLEAR_CACHE_INFO, "src/opers.c:CLEAR_CACHE_INFO" },
  5219. { "SET_ATTRIBUTE_STORING", 2, "attr, val",
  5220. FuncSET_ATTRIBUTE_STORING, "src/opers.c:SET_ATTRIBUTE_STORING" },
  5221. { "DO_NOTHING_SETTER", 2, "obj, val",
  5222. FuncDO_NOTHING_SETTER, "src/opers.c:DO_NOTHING_SETTER" },
  5223. { "IS_AND_FILTER", 1, "filter",
  5224. FuncIS_AND_FILTER, "src/opers.c:IS_AND_FILTER" },
  5225. { "COMPACT_TYPE_IDS", 0, "",
  5226. FuncCompactTypeIDs, "src/opers.c:COMPACT_TYPE_IDS" },
  5227. { 0 }
  5228. };
  5229. /****************************************************************************
  5230. **
  5231. *F InitKernel( <module> ) . . . . . . . . initialise kernel data structures
  5232. */
  5233. static Int InitKernel (
  5234. StructInitInfo * module )
  5235. {
  5236. NextTypeID = 0;
  5237. CountFlags = 0;
  5238. InitGlobalBag( &StringAndFilter, "src/opers.c:StringAndFilter" );
  5239. InitGlobalBag( &StringFilterSetter, "src/opers.c:StringFilterSetter" );
  5240. InitGlobalBag( &ArglistObj, "src/opers.c:ArglistObj" );
  5241. InitGlobalBag( &ArglistObjVal, "src/opers.c:ArglistObjVal" );
  5242. /* Declare the handlers used in various places. Some of the commonest */
  5243. /* ones are abbreviated to save space in saved workspace. */
  5244. InitHandlerFunc( DoFilter, "df" );
  5245. InitHandlerFunc( DoSetFilter, "dsf" );
  5246. InitHandlerFunc( DoAndFilter, "daf" );
  5247. InitHandlerFunc( DoSetAndFilter, "dsaf" );
  5248. InitHandlerFunc( DoReturnTrueFilter, "src/opers.c:DoReturnTrueFilter" );
  5249. InitHandlerFunc( DoSetReturnTrueFilter, "src/opers.c:DoSetReturnTrueFilter" );
  5250. InitHandlerFunc( DoAttribute, "da" );
  5251. InitHandlerFunc( DoSetAttribute, "dsa" );
  5252. InitHandlerFunc( DoTestAttribute, "src/opers.c:DoTestAttribute" );
  5253. InitHandlerFunc( DoVerboseAttribute, "src/opers.c:DoVerboseAttribute" );
  5254. InitHandlerFunc( DoMutableAttribute, "src/opers.c:DoMutableAttribute" );
  5255. InitHandlerFunc( DoVerboseMutableAttribute, "src/opers.c:DoVerboseMutableAttribute" );
  5256. InitHandlerFunc( DoProperty, "src/opers.c:DoProperty" );
  5257. InitHandlerFunc( DoSetProperty, "src/opers.c:DoSetProperty" );
  5258. InitHandlerFunc( DoTestProperty, "src/opers.c:DoTestProperty" );
  5259. InitHandlerFunc( DoVerboseProperty, "src/opers.c:DoVerboseProperty" );
  5260. InitHandlerFunc( DoSetterFunction, "dtf" );
  5261. InitHandlerFunc( DoGetterFunction, "dgf" );
  5262. InitHandlerFunc( DoOperation0Args, "o0" );
  5263. InitHandlerFunc( DoOperation1Args, "o1" );
  5264. InitHandlerFunc( DoOperation2Args, "o2" );
  5265. InitHandlerFunc( DoOperation3Args, "o3" );
  5266. InitHandlerFunc( DoOperation4Args, "o4" );
  5267. InitHandlerFunc( DoOperation5Args, "o5" );
  5268. InitHandlerFunc( DoOperation6Args, "o6" );
  5269. InitHandlerFunc( DoOperationXArgs, "o7" );
  5270. InitHandlerFunc( DoVerboseOperation0Args, "src/opers.c:DoVerboseOperation0Args" );
  5271. InitHandlerFunc( DoVerboseOperation1Args, "src/opers.c:DoVerboseOperation1Args" );
  5272. InitHandlerFunc( DoVerboseOperation2Args, "src/opers.c:DoVerboseOperation2Args" );
  5273. InitHandlerFunc( DoVerboseOperation3Args, "src/opers.c:DoVerboseOperation3Args" );
  5274. InitHandlerFunc( DoVerboseOperation4Args, "src/opers.c:DoVerboseOperation4Args" );
  5275. InitHandlerFunc( DoVerboseOperation5Args, "src/opers.c:DoVerboseOperation5Args" );
  5276. InitHandlerFunc( DoVerboseOperation6Args, "src/opers.c:DoVerboseOperation6Args" );
  5277. InitHandlerFunc( DoVerboseOperationXArgs, "src/opers.c:DoVerboseOperationXArgs" );
  5278. InitHandlerFunc( DoConstructor0Args, "src/opers.c:DoConstructor0Args" );
  5279. InitHandlerFunc( DoConstructor1Args, "src/opers.c:DoConstructor1Args" );
  5280. InitHandlerFunc( DoConstructor2Args, "src/opers.c:DoConstructor2Args" );
  5281. InitHandlerFunc( DoConstructor3Args, "src/opers.c:DoConstructor3Args" );
  5282. InitHandlerFunc( DoConstructor4Args, "src/opers.c:DoConstructor4Args" );
  5283. InitHandlerFunc( DoConstructor5Args, "src/opers.c:DoConstructor5Args" );
  5284. InitHandlerFunc( DoConstructor6Args, "src/opers.c:DoConstructor6Args" );
  5285. InitHandlerFunc( DoConstructorXArgs, "src/opers.c:DoConstructorXArgs" );
  5286. InitHandlerFunc( DoVerboseConstructor0Args, "src/opers.c:DoVerboseConstructor0Args" );
  5287. InitHandlerFunc( DoVerboseConstructor1Args, "src/opers.c:DoVerboseConstructor1Args" );
  5288. InitHandlerFunc( DoVerboseConstructor2Args, "src/opers.c:DoVerboseConstructor2Args" );
  5289. InitHandlerFunc( DoVerboseConstructor3Args, "src/opers.c:DoVerboseConstructor3Args" );
  5290. InitHandlerFunc( DoVerboseConstructor4Args, "src/opers.c:DoVerboseConstructor4Args" );
  5291. InitHandlerFunc( DoVerboseConstructor5Args, "src/opers.c:DoVerboseConstructor5Args" );
  5292. InitHandlerFunc( DoVerboseConstructor6Args, "src/opers.c:DoVerboseConstructor6Args" );
  5293. InitHandlerFunc( DoVerboseConstructorXArgs, "src/opers.c:DoVerboseConstructorXArgs" );
  5294. InitHandlerFunc( DoUninstalledOperationArgs, "src/opers.c:DoUninstalledOperationArgs" );
  5295. /* install the kind function */
  5296. ImportGVarFromLibrary( "TYPE_FLAGS", &TYPE_FLAGS );
  5297. TypeObjFuncs[ T_FLAGS ] = TypeFlags;
  5298. /* make the 'true' operation */
  5299. InitGlobalBag( &ReturnTrueFilter, "src/opers.c:ReturnTrueFilter" );
  5300. /* install the (function) copies of global variables */
  5301. /* for the inside-out (kernel to library) interface */
  5302. InitGlobalBag( &TRY_NEXT_METHOD, "src/opers.c:TRY_NEXT_METHOD" );
  5303. ImportFuncFromLibrary( "METHOD_0ARGS", &Method0Args );
  5304. ImportFuncFromLibrary( "METHOD_1ARGS", &Method1Args );
  5305. ImportFuncFromLibrary( "METHOD_2ARGS", &Method2Args );
  5306. ImportFuncFromLibrary( "METHOD_3ARGS", &Method3Args );
  5307. ImportFuncFromLibrary( "METHOD_4ARGS", &Method4Args );
  5308. ImportFuncFromLibrary( "METHOD_5ARGS", &Method5Args );
  5309. ImportFuncFromLibrary( "METHOD_6ARGS", &Method6Args );
  5310. ImportFuncFromLibrary( "METHOD_XARGS", &MethodXArgs );
  5311. ImportFuncFromLibrary( "NEXT_METHOD_0ARGS", &NextMethod0Args );
  5312. ImportFuncFromLibrary( "NEXT_METHOD_1ARGS", &NextMethod1Args );
  5313. ImportFuncFromLibrary( "NEXT_METHOD_2ARGS", &NextMethod2Args );
  5314. ImportFuncFromLibrary( "NEXT_METHOD_3ARGS", &NextMethod3Args );
  5315. ImportFuncFromLibrary( "NEXT_METHOD_4ARGS", &NextMethod4Args );
  5316. ImportFuncFromLibrary( "NEXT_METHOD_5ARGS", &NextMethod5Args );
  5317. ImportFuncFromLibrary( "NEXT_METHOD_6ARGS", &NextMethod6Args );
  5318. ImportFuncFromLibrary( "NEXT_METHOD_XARGS", &NextMethodXArgs );
  5319. ImportFuncFromLibrary( "VMETHOD_0ARGS", &VMethod0Args );
  5320. ImportFuncFromLibrary( "VMETHOD_1ARGS", &VMethod1Args );
  5321. ImportFuncFromLibrary( "VMETHOD_2ARGS", &VMethod2Args );
  5322. ImportFuncFromLibrary( "VMETHOD_3ARGS", &VMethod3Args );
  5323. ImportFuncFromLibrary( "VMETHOD_4ARGS", &VMethod4Args );
  5324. ImportFuncFromLibrary( "VMETHOD_5ARGS", &VMethod5Args );
  5325. ImportFuncFromLibrary( "VMETHOD_6ARGS", &VMethod6Args );
  5326. ImportFuncFromLibrary( "VMETHOD_XARGS", &VMethodXArgs );
  5327. ImportFuncFromLibrary( "NEXT_VMETHOD_0ARGS", &NextVMethod0Args );
  5328. ImportFuncFromLibrary( "NEXT_VMETHOD_1ARGS", &NextVMethod1Args );
  5329. ImportFuncFromLibrary( "NEXT_VMETHOD_2ARGS", &NextVMethod2Args );
  5330. ImportFuncFromLibrary( "NEXT_VMETHOD_3ARGS", &NextVMethod3Args );
  5331. ImportFuncFromLibrary( "NEXT_VMETHOD_4ARGS", &NextVMethod4Args );
  5332. ImportFuncFromLibrary( "NEXT_VMETHOD_5ARGS", &NextVMethod5Args );
  5333. ImportFuncFromLibrary( "NEXT_VMETHOD_6ARGS", &NextVMethod6Args );
  5334. ImportFuncFromLibrary( "NEXT_VMETHOD_XARGS", &NextVMethodXArgs );
  5335. ImportFuncFromLibrary( "CONSTRUCTOR_0ARGS", &Constructor0Args );
  5336. ImportFuncFromLibrary( "CONSTRUCTOR_1ARGS", &Constructor1Args );
  5337. ImportFuncFromLibrary( "CONSTRUCTOR_2ARGS", &Constructor2Args );
  5338. ImportFuncFromLibrary( "CONSTRUCTOR_3ARGS", &Constructor3Args );
  5339. ImportFuncFromLibrary( "CONSTRUCTOR_4ARGS", &Constructor4Args );
  5340. ImportFuncFromLibrary( "CONSTRUCTOR_5ARGS", &Constructor5Args );
  5341. ImportFuncFromLibrary( "CONSTRUCTOR_6ARGS", &Constructor6Args );
  5342. ImportFuncFromLibrary( "CONSTRUCTOR_XARGS", &ConstructorXArgs );
  5343. ImportFuncFromLibrary( "NEXT_CONSTRUCTOR_0ARGS", &NextConstructor0Args );
  5344. ImportFuncFromLibrary( "NEXT_CONSTRUCTOR_1ARGS", &NextConstructor1Args );
  5345. ImportFuncFromLibrary( "NEXT_CONSTRUCTOR_2ARGS", &NextConstructor2Args );
  5346. ImportFuncFromLibrary( "NEXT_CONSTRUCTOR_3ARGS", &NextConstructor3Args );
  5347. ImportFuncFromLibrary( "NEXT_CONSTRUCTOR_4ARGS", &NextConstructor4Args );
  5348. ImportFuncFromLibrary( "NEXT_CONSTRUCTOR_5ARGS", &NextConstructor5Args );
  5349. ImportFuncFromLibrary( "NEXT_CONSTRUCTOR_6ARGS", &NextConstructor6Args );
  5350. ImportFuncFromLibrary( "NEXT_CONSTRUCTOR_XARGS", &NextConstructorXArgs );
  5351. ImportFuncFromLibrary( "VCONSTRUCTOR_0ARGS", &VConstructor0Args );
  5352. ImportFuncFromLibrary( "VCONSTRUCTOR_1ARGS", &VConstructor1Args );
  5353. ImportFuncFromLibrary( "VCONSTRUCTOR_2ARGS", &VConstructor2Args );
  5354. ImportFuncFromLibrary( "VCONSTRUCTOR_3ARGS", &VConstructor3Args );
  5355. ImportFuncFromLibrary( "VCONSTRUCTOR_4ARGS", &VConstructor4Args );
  5356. ImportFuncFromLibrary( "VCONSTRUCTOR_5ARGS", &VConstructor5Args );
  5357. ImportFuncFromLibrary( "VCONSTRUCTOR_6ARGS", &VConstructor6Args );
  5358. ImportFuncFromLibrary( "VCONSTRUCTOR_XARGS", &VConstructorXArgs );
  5359. ImportFuncFromLibrary( "NEXT_VCONSTRUCTOR_0ARGS", &NextVConstructor0Args );
  5360. ImportFuncFromLibrary( "NEXT_VCONSTRUCTOR_1ARGS", &NextVConstructor1Args );
  5361. ImportFuncFromLibrary( "NEXT_VCONSTRUCTOR_2ARGS", &NextVConstructor2Args );
  5362. ImportFuncFromLibrary( "NEXT_VCONSTRUCTOR_3ARGS", &NextVConstructor3Args );
  5363. ImportFuncFromLibrary( "NEXT_VCONSTRUCTOR_4ARGS", &NextVConstructor4Args );
  5364. ImportFuncFromLibrary( "NEXT_VCONSTRUCTOR_5ARGS", &NextVConstructor5Args );
  5365. ImportFuncFromLibrary( "NEXT_VCONSTRUCTOR_6ARGS", &NextVConstructor6Args );
  5366. ImportFuncFromLibrary( "NEXT_VCONSTRUCTOR_XARGS", &NextVConstructorXArgs );
  5367. ImportFuncFromLibrary( "SET_FILTER_OBJ", &SET_FILTER_OBJ );
  5368. ImportFuncFromLibrary( "RESET_FILTER_OBJ", &RESET_FILTER_OBJ );
  5369. ImportFuncFromLibrary( "HANDLE_METHOD_NOT_FOUND", &HandleMethodNotFound );
  5370. ImportGVarFromLibrary( "IsType", &IsType );
  5371. /* init filters and functions */
  5372. InitHdlrFiltsFromTable( GVarFilts );
  5373. InitHdlrFuncsFromTable( GVarFuncs );
  5374. /* install the marking function */
  5375. InfoBags[T_FLAGS].name = "flags list";
  5376. InitMarkFuncBags( T_FLAGS, MarkFourSubBags );
  5377. /* install the printing function */
  5378. PrintObjFuncs[ T_FLAGS ] = PrintFlags;
  5379. /* and the saving function */
  5380. SaveObjFuncs[ T_FLAGS ] = SaveFlags;
  5381. LoadObjFuncs[ T_FLAGS ] = LoadFlags;
  5382. /* import copy of REREADING */
  5383. ImportGVarFromLibrary( "REREADING", &REREADING );
  5384. /* return success */
  5385. return 0;
  5386. }
  5387. /****************************************************************************
  5388. **
  5389. *F postRestore( <module> ) . . . . . . . initialise library data structures
  5390. **
  5391. */
  5392. static Int postRestore (
  5393. StructInitInfo * module )
  5394. {
  5395. CountFlags = LEN_LIST(VAL_GVAR(GVarName("FILTERS")))+1;
  5396. return 0;
  5397. }
  5398. /****************************************************************************
  5399. **
  5400. *F InitLibrary( <module> ) . . . . . . . initialise library data structures
  5401. */
  5402. static Int InitLibrary (
  5403. StructInitInfo * module )
  5404. {
  5405. Obj str;
  5406. /* share between uncompleted functions */
  5407. C_NEW_STRING( StringAndFilter, 14, "<<and-filter>>" );
  5408. RESET_FILT_LIST( StringAndFilter, FN_IS_MUTABLE );
  5409. C_NEW_STRING( StringFilterSetter, 17, "<<filter-setter>>" );
  5410. RESET_FILT_LIST( StringFilterSetter, FN_IS_MUTABLE );
  5411. ArglistObj = NEW_PLIST( T_PLIST+IMMUTABLE, 1 );
  5412. SET_LEN_PLIST( ArglistObj, 1 );
  5413. C_NEW_STRING( str, 3, "obj" );
  5414. RESET_FILT_LIST( str, FN_IS_MUTABLE );
  5415. SET_ELM_PLIST( ArglistObj, 1, str );
  5416. ArglistObjVal = NEW_PLIST( T_PLIST+IMMUTABLE, 2 );
  5417. SET_LEN_PLIST( ArglistObjVal, 2 );
  5418. C_NEW_STRING( str, 3, "obj" );
  5419. RESET_FILT_LIST( str, FN_IS_MUTABLE );
  5420. SET_ELM_PLIST( ArglistObjVal, 1, str );
  5421. C_NEW_STRING( str, 3, "val" );
  5422. RESET_FILT_LIST( str, FN_IS_MUTABLE );
  5423. SET_ELM_PLIST( ArglistObjVal, 2, str );
  5424. /* make the 'true' operation */
  5425. ReturnTrueFilter = NewReturnTrueFilter();
  5426. AssGVar( GVarName( "IS_OBJECT" ), ReturnTrueFilter );
  5427. /* install the (function) copies of global variables */
  5428. /* for the inside-out (kernel to library) interface */
  5429. /*CCC TRY_NEXT_METHOD = NEW_STRING( 16 );
  5430. SyStrncat( CSTR_STRING(TRY_NEXT_METHOD), "TRY_NEXT_METHOD", 16 );CCC*/
  5431. C_NEW_STRING(TRY_NEXT_METHOD, 15, "TRY_NEXT_METHOD");
  5432. AssGVar( GVarName("TRY_NEXT_METHOD"), TRY_NEXT_METHOD );
  5433. /* init filters and functions */
  5434. InitGVarFiltsFromTable( GVarFilts );
  5435. InitGVarFuncsFromTable( GVarFuncs );
  5436. /* return success */
  5437. return 0;
  5438. }
  5439. /****************************************************************************
  5440. **
  5441. *F InitInfoOpers() . . . . . . . . . . . . . . . . . table of init functions
  5442. */
  5443. static StructInitInfo module = {
  5444. MODULE_BUILTIN, /* type */
  5445. "opers", /* name */
  5446. 0, /* revision entry of c file */
  5447. 0, /* revision entry of h file */
  5448. 0, /* version */
  5449. 0, /* crc */
  5450. InitKernel, /* initKernel */
  5451. InitLibrary, /* initLibrary */
  5452. 0, /* checkInit */
  5453. 0, /* preSave */
  5454. 0, /* postSave */
  5455. postRestore /* postRestore */
  5456. };
  5457. StructInitInfo * InitInfoOpers ( void )
  5458. {
  5459. FillInVersion( &module );
  5460. return &module;
  5461. }
  5462. /****************************************************************************
  5463. **
  5464. *E opers.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
  5465. */