Combinations contents
A combination is like a list, but simpler; it has a fixed, usually short, size. On the other hand, its entries are not all of the same kind as each other.
The short block for a combination is simply a pointer to the long block. This consists of one word to hold the strong kind ID, and then one word for each entry in the combination. Thus, a triple combination uses 4 words.
17Constant COMBINATION_KIND_F = 0;
18Constant COMBINATION_ITEM_BASE = 1;
KOV Support.
See the BlockValues.i6t segment for the specification of the following routines.
25[ COMBINATION_TY_Support task arg1 arg2 arg3;
26 switch(task) {
27 CREATE_KOVS: return COMBINATION_TY_Create(arg1, arg2);
28 DESTROY_KOVS: COMBINATION_TY_Destroy(arg1);
29 MAKEMUTABLE_KOVS: return 1;
30 COPYKIND_KOVS: return COMBINATION_TY_CopyKind(arg1, arg2);
31 COPYQUICK_KOVS: rtrue;
32 COPYSB_KOVS: BlkValueCopySB1(arg1, arg2);
33 KINDDATA_KOVS: return COMBINATION_TY_KindData(arg1);
34 EXTENT_KOVS: return -1;
35 COPY_KOVS: COMBINATION_TY_Copy(arg1, arg2, arg3);
36 COMPARE_KOVS: return COMBINATION_TY_Compare(arg1, arg2);
37 HASH_KOVS: return COMBINATION_TY_Hash(arg1);
38 DEBUG_KOVS: print " = ", (COMBINATION_TY_Say) arg1;
39 }
40
41 rfalse;
42];
Creation.
A combination is like a list, but simpler; it has a fixed, usually short, size. On the other hand, its entries are not all of the same kind as each other.
Combinations are stored as a fixed-sized block of word entries. The first block is the only header information: a pointer to a further structure in memory, describing the kind. The subsequent blocks are the actual records. Thus, a triple (x, y, z) uses 4 words.
55[ COMBINATION_TY_Create kind sb long_block N i bk v;
56 N = KindBaseArity(kind);
57 long_block = FlexAllocate(
58 (COMBINATION_ITEM_BASE+N)*WORDSIZE, COMBINATION_TY, BLK_FLAG_WORD);
59 BlkValueWrite(long_block, COMBINATION_KIND_F, kind, true);
60 for (i=0: i<N: i++) {
61 bk = KindBaseTerm(kind, i);
62 if (KOVIsBlockValue(bk)) v = BlkValueCreate(bk);
63 else v = DefaultValueOfKOV(bk);
64 BlkValueWrite(long_block, COMBINATION_ITEM_BASE+i, v, true);
65 }
66 return BlkValueCreateSB1(sb, long_block);
67];
Destruction.
If the comb items are themselves block-values, they must all be freed before the comb itself can be freed.
74[ COMBINATION_TY_Destroy comb kind no_items i bk;
75 kind = BlkValueRead(comb, COMBINATION_KIND_F);
76 no_items = KindBaseArity(kind);
77 for (i=0: i<no_items: i++) {
78 bk = KindBaseTerm(kind, i);
79 if (KOVIsBlockValue(bk))
80 BlkValueFree(BlkValueRead(comb, i+COMBINATION_ITEM_BASE));
81 }
82];
Copying.
Again, if the comb contains block-values then they must be duplicated rather than bitwise copied as pointers.
89[ COMBINATION_TY_CopyKind to from;
90 BlkValueWrite(to, COMBINATION_KIND_F, BlkValueRead(from, COMBINATION_KIND_F));
91];
92
93[ COMBINATION_TY_CopySB to from;
94 BlkValueCopySB1(to, from);
95];
96
97[ COMBINATION_TY_KindData comb;
98 return BlkValueRead(comb, COMBINATION_KIND_F);
99];
100
101[ COMBINATION_TY_Copy to_comb from_comb precopied_comb_kov no_items i nv kind bk;
102
103 no_items = KindBaseArity(precopied_comb_kov);
104 BlkValueWrite(to_comb, COMBINATION_KIND_F, precopied_comb_kov);
105 for (i=0: i<no_items: i++) {
106 bk = KindBaseTerm(kind, i);
107 if (KOVIsBlockValue(bk)) {
108 nv = BlkValueCreate(bk);
109 BlkValueCopy(nv, BlkValueRead(from_comb, i+COMBINATION_ITEM_BASE));
110 BlkValueWrite(to_comb, i+COMBINATION_ITEM_BASE, nv);
111 }
112 }
113];
Comparison.
This is a lexicographic comparison and assumes both combinations have the same kind.
120[ COMBINATION_TY_Compare left_comb right_comb delta no_items i cf kind bk;
121 kind = BlkValueRead(left_comb, COMBINATION_KIND_F);
122 no_items = KindBaseArity(kind);
123 for (i=0: i<no_items: i++) {
124 bk = KindBaseTerm(kind, i);
125 cf = KOVComparisonFunction(bk);
126 if (cf == 0 or UnsignedCompare) {
127 delta = BlkValueRead(left_comb, i+COMBINATION_ITEM_BASE) -
128 BlkValueRead(right_comb, i+COMBINATION_ITEM_BASE);
129 if (delta) return delta;
130 } else {
131 delta = cf(BlkValueRead(left_comb, i+COMBINATION_ITEM_BASE),
132 BlkValueRead(right_comb, i+COMBINATION_ITEM_BASE));
133 if (delta) return delta;
134 }
135 }
136 return 0;
137];
138
139[ COMBINATION_TY_Distinguish left_comb right_comb;
140 if (COMBINATION_TY_Compare(left_comb, right_comb) == 0) rfalse;
141 rtrue;
142];
147[ COMBINATION_TY_Hash comb kind rv no_items i bk;
148 rv = 0;
149 kind = BlkValueRead(comb, COMBINATION_KIND_F);
150 no_items = KindBaseArity(kind);
151 for (i=0: i<no_items: i++) {
152 bk = KindBaseTerm(kind, i);
153 rv = rv * 33 + GetHashValue(bk, BlkValueRead(comb, i+COMBINATION_ITEM_BASE));
154 }
155 return rv;
156];
161[ COMBINATION_TY_Say comb format no_items v i kind bk;
162 if ((comb==0) || (BlkValueWeakKind(comb) ~= COMBINATION_TY)) return;
163 kind = BlkValueRead(comb, COMBINATION_KIND_F);
164 no_items = KindBaseArity(kind);
165 print "(";
166 for (i=0: i<no_items: i++) {
167 if (i>0) print ", ";
168 bk = KindBaseTerm(kind, i);
169 v = BlkValueRead(comb, i+COMBINATION_ITEM_BASE);
170 if (bk == LIST_OF_TY) LIST_OF_TY_Say(v, 1);
171 else PrintKindValuePair(bk, v);
172 }
173 print ")";
174];