Code to support the combination kind of value constructor.
- §1. Block Format
- §2. KOV Support
- §3. Creation
- §4. Destruction
- §5. Copying
- §6. Comparison
- §7. Hashing
- §8. Printing
§1. Block Format. 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.
Constant COMBINATION_KIND_F = 0; Strong kind ID Constant COMBINATION_ITEM_BASE = 1; List items begin at this entry
§2. KOV Support. See the "BlockValues.i6t" segment for the specification of the following routines.
[ COMBINATION_TY_Support task arg1 arg2 arg3; switch(task) { CREATE_KOVS: return COMBINATION_TY_Create(arg1, arg2); DESTROY_KOVS: COMBINATION_TY_Destroy(arg1); MAKEMUTABLE_KOVS: return 1; COPYKIND_KOVS: return COMBINATION_TY_CopyKind(arg1, arg2); COPYQUICK_KOVS: rtrue; COPYSB_KOVS: BlkValueCopySB1(arg1, arg2); KINDDATA_KOVS: return COMBINATION_TY_KindData(arg1); EXTENT_KOVS: return -1; COPY_KOVS: COMBINATION_TY_Copy(arg1, arg2, arg3); COMPARE_KOVS: return COMBINATION_TY_Compare(arg1, arg2); HASH_KOVS: return COMBINATION_TY_Hash(arg1); DEBUG_KOVS: print " = ", (COMBINATION_TY_Say) arg1; } We choose not to respond to: CAST_KOVS, READ_FILE_KOVS, WRITE_FILE_KOVS rfalse; ];
§3. 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.
[ COMBINATION_TY_Create kind sb long_block N i bk v; N = KindBaseArity(kind); long_block = FlexAllocate( (COMBINATION_ITEM_BASE+N)*WORDSIZE, COMBINATION_TY, BLK_FLAG_WORD); BlkValueWrite(long_block, COMBINATION_KIND_F, kind, true); for (i=0: i<N: i++) { bk = KindBaseTerm(kind, i); if (KOVIsBlockValue(bk)) v = BlkValueCreate(bk); else v = DefaultValueOfKOV(bk); BlkValueWrite(long_block, COMBINATION_ITEM_BASE+i, v, true); } return BlkValueCreateSB1(sb, long_block); ];
§4. Destruction. If the comb items are themselves block-values, they must all be freed before the comb itself can be freed.
[ COMBINATION_TY_Destroy comb kind no_items i bk; kind = BlkValueRead(comb, COMBINATION_KIND_F); no_items = KindBaseArity(kind); for (i=0: i<no_items: i++) { bk = KindBaseTerm(kind, i); if (KOVIsBlockValue(bk)) BlkValueFree(BlkValueRead(comb, i+COMBINATION_ITEM_BASE)); } ];
§5. Copying. Again, if the comb contains block-values then they must be duplicated rather than bitwise copied as pointers.
[ COMBINATION_TY_CopyKind to from; BlkValueWrite(to, COMBINATION_KIND_F, BlkValueRead(from, COMBINATION_KIND_F)); ]; [ COMBINATION_TY_CopySB to from; BlkValueCopySB1(to, from); ]; [ COMBINATION_TY_KindData comb; return BlkValueRead(comb, COMBINATION_KIND_F); ]; [ COMBINATION_TY_Copy to_comb from_comb precopied_comb_kov no_items i nv kind bk; kind = BlkValueRead(to_comb, COMBINATION_KIND_F); no_items = KindBaseArity(precopied_comb_kov); BlkValueWrite(to_comb, COMBINATION_KIND_F, precopied_comb_kov); for (i=0: i<no_items: i++) { bk = KindBaseTerm(kind, i); if (KOVIsBlockValue(bk)) { nv = BlkValueCreate(bk); BlkValueCopy(nv, BlkValueRead(from_comb, i+COMBINATION_ITEM_BASE)); BlkValueWrite(to_comb, i+COMBINATION_ITEM_BASE, nv); } } ];
§6. Comparison. This is a lexicographic comparison and assumes both combinations have the same kind.
[ COMBINATION_TY_Compare left_comb right_comb delta no_items i cf kind bk; kind = BlkValueRead(left_comb, COMBINATION_KIND_F); no_items = KindBaseArity(kind); for (i=0: i<no_items: i++) { bk = KindBaseTerm(kind, i); cf = KOVComparisonFunction(bk); if (cf == 0 or UnsignedCompare) { delta = BlkValueRead(left_comb, i+COMBINATION_ITEM_BASE) - BlkValueRead(right_comb, i+COMBINATION_ITEM_BASE); if (delta) return delta; } else { delta = cf(BlkValueRead(left_comb, i+COMBINATION_ITEM_BASE), BlkValueRead(right_comb, i+COMBINATION_ITEM_BASE)); if (delta) return delta; } } return 0; ]; [ COMBINATION_TY_Distinguish left_comb right_comb; if (COMBINATION_TY_Compare(left_comb, right_comb) == 0) rfalse; rtrue; ];
[ COMBINATION_TY_Hash comb kind rv no_items i bk; rv = 0; kind = BlkValueRead(comb, COMBINATION_KIND_F); no_items = KindBaseArity(kind); for (i=0: i<no_items: i++) { bk = KindBaseTerm(kind, i); rv = rv * 33 + GetHashValue(bk, BlkValueRead(comb, i+COMBINATION_ITEM_BASE)); } return rv; ];
[ COMBINATION_TY_Say comb format no_items v i kind bk; if ((comb==0) || (BlkValueWeakKind(comb) ~= COMBINATION_TY)) return; kind = BlkValueRead(comb, COMBINATION_KIND_F); no_items = KindBaseArity(kind); print "("; for (i=0: i<no_items: i++) { if (i>0) print ", "; bk = KindBaseTerm(kind, i); v = BlkValueRead(comb, i+COMBINATION_ITEM_BASE); if (bk == LIST_OF_TY) LIST_OF_TY_Say(v, 1); else PrintKindValuePair(bk, v); } print ")"; ];