mirror of
https://github.com/ganelson/inform.git
synced 2024-07-09 02:24:21 +03:00
175 lines
5.3 KiB
Plaintext
175 lines
5.3 KiB
Plaintext
B/combt: Combinations Template.
|
|
|
|
@Purpose: Code to support the combination kind of value constructor.
|
|
|
|
@-------------------------------------------------------------------------------
|
|
|
|
@p 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.
|
|
|
|
@c
|
|
Constant COMBINATION_KIND_F = 0; ! Strong kind ID
|
|
Constant COMBINATION_ITEM_BASE = 1; ! List items begin at this entry
|
|
|
|
@p KOV Support.
|
|
See the "BlockValues.i6t" segment for the specification of the following
|
|
routines.
|
|
|
|
@c
|
|
[ 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;
|
|
];
|
|
|
|
@p 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.
|
|
|
|
@c
|
|
[ 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);
|
|
];
|
|
|
|
@p Destruction.
|
|
If the comb items are themselves block-values, they must all be freed before
|
|
the comb itself can be freed.
|
|
|
|
@c
|
|
[ 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));
|
|
}
|
|
];
|
|
|
|
@p Copying.
|
|
Again, if the comb contains block-values then they must be duplicated rather
|
|
than bitwise copied as pointers.
|
|
|
|
@c
|
|
[ 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);
|
|
}
|
|
}
|
|
];
|
|
|
|
@p Comparison.
|
|
This is a lexicographic comparison and assumes both combinations have the
|
|
same kind.
|
|
|
|
@c
|
|
[ 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;
|
|
];
|
|
|
|
@p Hashing.
|
|
|
|
@c
|
|
[ 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;
|
|
];
|
|
|
|
@p Printing.
|
|
|
|
@c
|
|
[ 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 ")";
|
|
];
|