changed STIX_SMOOI_MIN to -STIX_SMOOI_MAX instead of (-STIX_SMOOI_MAX - 1)

fixed tally range check bugs in dic.c/sym.c/gc.c
simplificed some code resulting from STIX_SMOOI_MIN change.
This commit is contained in:
hyunghwan.chung 2015-11-20 09:05:55 +00:00
parent 5cebf7e8dc
commit f618154aaf
9 changed files with 204 additions and 115 deletions

View File

@ -115,18 +115,15 @@
{ {
} }
#class(#halfword) LargeInteger(Number) #class(#liword) LargeInteger(Number)
## #class(#word) LargeInteger(Number)
{ {
} }
#class(#halfword) LargePositiveInteger(LargeInteger) #class(#liword) LargePositiveInteger(LargeInteger)
## #class(#word) LargePositiveInteger(LargeInteger)
{ {
} }
#class(#halfword) LargeNegativeInteger(LargeInteger) #class(#liword) LargeNegativeInteger(LargeInteger)
## #class(#word) LargeNegativeInteger(LargeInteger)
{ {
} }

View File

@ -267,6 +267,7 @@ PROCESS TESTING
##((-2305843009213693952 * -1) - 1 + 2) dump. ##((-2305843009213693952 * -1) - 1 + 2) dump.
((-2305843009213693952 * -2305843009213693952 * 2305843009213693952 * 2305843009213693952 * 2305843009213693952) - 1 + 2) dump. ((-2305843009213693952 * -2305843009213693952 * 2305843009213693952 * 2305843009213693952 * 2305843009213693952) - 1 + 2) dump.
(2r111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 * 128971234897128931) dump. (2r111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 * 128971234897128931) dump.
" "

View File

@ -304,7 +304,7 @@ static stix_oop_t normalize_bigint (stix_t* stix, stix_oop_t oop)
count = count_effective_digits (oop); count = count_effective_digits (oop);
#if defined(STIX_USE_FULL_WORD) #if defined(STIX_USE_FULL_WORD)
if (count == 1) if (count == 1) /* 1 word */
{ {
stix_oow_t w; stix_oow_t w;
@ -315,13 +315,13 @@ static stix_oop_t normalize_bigint (stix_t* stix, stix_oop_t oop)
} }
else else
{ {
STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN);
STIX_ASSERT (STIX_OBJ_GET_CLASS(oop) == stix->_large_negative_integer); STIX_ASSERT (STIX_OBJ_GET_CLASS(oop) == stix->_large_negative_integer);
/*if (w <= -STIX_SMOOI_MIN) */ if (w <= STIX_SMOOI_MAX) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w);
if (w <= ((stix_oow_t)STIX_SMOOI_MAX + 1)) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w);
} }
} }
#else #else
if (count == 1) if (count == 1) /* 1 half-word */
{ {
if (STIX_OBJ_GET_CLASS(oop) == stix->_large_positive_integer) if (STIX_OBJ_GET_CLASS(oop) == stix->_large_positive_integer)
{ {
@ -330,10 +330,10 @@ static stix_oop_t normalize_bigint (stix_t* stix, stix_oop_t oop)
else else
{ {
STIX_ASSERT (STIX_OBJ_GET_CLASS(oop) == stix->_large_negative_integer); STIX_ASSERT (STIX_OBJ_GET_CLASS(oop) == stix->_large_negative_integer);
return STIX_SMOOI_TO_OOP(-(stix_oow_t)((stix_oop_liword_t)oop)->slot[0]); return STIX_SMOOI_TO_OOP(-(stix_ooi_t)((stix_oop_liword_t)oop)->slot[0]);
} }
} }
else if (count == 2) else if (count == 2) /* 2 half-words */
{ {
stix_oow_t w; stix_oow_t w;
@ -344,9 +344,9 @@ static stix_oop_t normalize_bigint (stix_t* stix, stix_oop_t oop)
} }
else else
{ {
STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN);
STIX_ASSERT (STIX_OBJ_GET_CLASS(oop) == stix->_large_negative_integer); STIX_ASSERT (STIX_OBJ_GET_CLASS(oop) == stix->_large_negative_integer);
/*if (w <= -STIX_SMOOI_MIN) */ if (w <= STIX_SMOOI_MAX) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w);
if (w <= ((stix_oow_t)STIX_SMOOI_MAX + 1)) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w);
} }
} }
#endif #endif
@ -632,6 +632,40 @@ static STIX_INLINE void rshift_unsigned_array (stix_liw_t* x, stix_oow_t xs, sti
STIX_MEMSET (&x[xs - word_shifts], 0, word_shifts * STIX_SIZEOF(stix_liw_t)); STIX_MEMSET (&x[xs - word_shifts], 0, word_shifts * STIX_SIZEOF(stix_liw_t));
} }
static void divide_unsigned_array (
const stix_liw_t* x, stix_oow_t xs,
const stix_liw_t* y, stix_oow_t ys,
stix_liw_t* q, stix_liw_t* r)
{
/* TODO: this function needs to be rewritten for performance improvement. */
/* Perform binary long division.
* http://en.wikipedia.org/wiki/Division_algorithm
* ---------------------------------------------------------------------
* Q := 0 initialize quotient and remainder to zero
* R := 0
* for i = n-1...0 do where n is number of bits in N
* R := R << 1 left-shift R by 1 bit
* R(0) := X(i) set the least-significant bit of R equal to bit i of the numerator
* if R >= Y then
* R = R - Y
* Q(i) := 1
* end
* end
*/
stix_liw_t* d;
stix_oow_t ds;
/* TODO: */
while (!is_less_unsigned_array (d, ds, y, ys)) /* while (y <= d) */
{
}
STIX_MEMCPY (r, d, ds);
}
static stix_oop_t add_unsigned_integers (stix_t* stix, stix_oop_t x, stix_oop_t y) static stix_oop_t add_unsigned_integers (stix_t* stix, stix_oop_t x, stix_oop_t y)
{ {
stix_liw_t* a, * b; stix_liw_t* a, * b;
@ -981,6 +1015,7 @@ printf ("%0*lX ", (int)(STIX_SIZEOF(stix_liw_t) * 2), (unsigned long)((stix_oop_
printf ("\n"); printf ("\n");
} }
/*
lshift_unsigned_array (((stix_oop_liword_t)z)->slot, STIX_OBJ_GET_SIZE(z), 16 * 5 + 4); lshift_unsigned_array (((stix_oop_liword_t)z)->slot, STIX_OBJ_GET_SIZE(z), 16 * 5 + 4);
{ int i; { int i;
printf ("LSHIFT10=>"); printf ("LSHIFT10=>");
@ -989,7 +1024,7 @@ for (i = STIX_OBJ_GET_SIZE(z); i > 0;)
printf ("%0*lX ", (int)(STIX_SIZEOF(stix_liw_t) * 2), (unsigned long)((stix_oop_liword_t)z)->slot[--i]); printf ("%0*lX ", (int)(STIX_SIZEOF(stix_liw_t) * 2), (unsigned long)((stix_oop_liword_t)z)->slot[--i]);
} }
printf ("\n"); printf ("\n");
} }*/
return normalize_bigint (stix, z); return normalize_bigint (stix, z);
@ -1001,6 +1036,80 @@ oops_einval:
stix_oop_t stix_divints (stix_t* stix, stix_oop_t x, stix_oop_t y, stix_oop_t* rem) stix_oop_t stix_divints (stix_t* stix, stix_oop_t x, stix_oop_t y, stix_oop_t* rem)
{ {
stix_oop_t t;
if (STIX_OOP_IS_SMOOI(x) && STIX_OOP_IS_SMOOI(y))
{
stix_ooi_t xv, yv, q, r;
xv = STIX_OOP_TO_SMOOI(x);
yv = STIX_OOP_TO_SMOOI(y);
if (yv == 0)
{
stix->errnum = STIX_EDIVBY0;
return STIX_NULL;
}
q = xv / yv;
STIX_ASSERT (STIX_IN_SMOOI_RANGE(q));
#if 1
/* TODO : verify this... */
r = xv - yv * q;
STIX_ASSERT (STIX_IN_SMOOI_RANGE(r));
/* handle sign difference */
if (r && ((yv ^ r) < 0))
{
/* if the sign bit is different betwen yv and r,
* the sign bit of (yv ^ r) must be set */
r += yv;
--q;
STIX_ASSERT (STIX_IN_SMOOI_RANGE(r));
}
#else
r = xv % yv;
STIX_ASSERT (STIX_IN_SMOOI_RANGE(r));
#endif
*rem = STIX_SMOOI_TO_OOP(r);
return STIX_SMOOI_TO_OOP((stix_ooi_t)q);
}
else if (STIX_OOP_IS_SMOOI(x))
{
if (STIX_OOP_TO_SMOOI(x) == 0)
{
t = clone_bigint (stix, y, STIX_OBJ_GET_SIZE(y));
if (!t) return STIX_NULL;
*rem = t;
return STIX_SMOOI_TO_OOP(0);
}
}
else if (STIX_OOP_IS_SMOOI(y))
{
stix_ooi_t yv;
if (yv == 0)
{
stix->errnum = STIX_EDIVBY0;
return STIX_NULL;
}
else if (yv == 1)
{
t = clone_bigint (stix, x, STIX_OBJ_GET_SIZE(x));
if (!t) return STIX_NULL;
*rem = STIX_SMOOI_TO_OOP(0);
return t;
}
}
else
{
}
return STIX_NULL; return STIX_NULL;
} }
@ -1229,7 +1338,8 @@ printf ("\n");
w = hwp[0]; w = hwp[0];
if (neg) if (neg)
{ {
if (w <= STIX_SMOOI_MAX + 1) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN);
if (w <= STIX_SMOOI_MAX) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w);
} }
else else
{ {
@ -1243,7 +1353,8 @@ printf ("\n");
w = MAKE_WORD(hwp[0], hwp[1]); w = MAKE_WORD(hwp[0], hwp[1]);
if (neg) if (neg)
{ {
if (w <= STIX_SMOOI_MAX + 1) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w); STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN);
if (w <= STIX_SMOOI_MAX) return STIX_SMOOI_TO_OOP(-(stix_ooi_t)w);
} }
else else
{ {

View File

@ -421,7 +421,6 @@ static int string_to_smint (stix_t* stix, stix_oocs_t* str, int radixed, stix_oo
* it assumes a certain pre-sanity check on the string * it assumes a certain pre-sanity check on the string
* done by the lexical analyzer */ * done by the lexical analyzer */
/* TODO: handle floating point numbers, etc, handle radix */
int v, negsign, base; int v, negsign, base;
const stix_ooch_t* ptr, * end; const stix_ooch_t* ptr, * end;
stix_oow_t value, old_value; stix_oow_t value, old_value;
@ -477,26 +476,15 @@ static int string_to_smint (stix_t* stix, stix_oocs_t* str, int radixed, stix_oo
return -1; return -1;
} }
if (negsign) STIX_ASSERT (-STIX_SMOOI_MAX == STIX_SMOOI_MIN);
{
/*if (value > -STIX_SMOOI_MIN) */
if (value > ((stix_oow_t)STIX_SMOOI_MAX + 1))
{
stix->errnum = STIX_ERANGE;
return -1;
}
*num = value;
*num *= -1;
}
else
{
if (value > STIX_SMOOI_MAX) if (value > STIX_SMOOI_MAX)
{ {
stix->errnum = STIX_ERANGE; stix->errnum = STIX_ERANGE;
return -1; return -1;
} }
*num = value; *num = value;
} if (negsign) *num *= -1;
return 0; return 0;
} }
@ -1860,7 +1848,7 @@ static int add_literal (stix_t* stix, stix_oop_t lit, stix_size_t* index)
static STIX_INLINE int add_character_literal (stix_t* stix, stix_ooch_t ch, stix_size_t* index) static STIX_INLINE int add_character_literal (stix_t* stix, stix_ooch_t ch, stix_size_t* index)
{ {
return add_literal (stix, STIX_OOP_FROM_CHAR(ch), index); return add_literal (stix, STIX_CHAR_TO_OOP(ch), index);
} }
static int add_string_literal (stix_t* stix, const stix_oocs_t* str, stix_size_t* index) static int add_string_literal (stix_t* stix, const stix_oocs_t* str, stix_size_t* index)
@ -3181,8 +3169,9 @@ static int __read_byte_array_literal (stix_t* stix, stix_oop_t* xlit)
* than the range error must not occur */ * than the range error must not occur */
STIX_ASSERT (stix->errnum == STIX_ERANGE); STIX_ASSERT (stix->errnum == STIX_ERANGE);
printf ("NOT IMPLEMENTED LARGE_INTEGER or ERROR?\n"); /* if the token is out of the SMOOI range, it's too big or
stix->errnum = STIX_ENOIMPL; * to small to be a byte */
set_syntax_error (stix, STIX_SYNERR_BYTERANGE, &stix->c->tok.loc, &stix->c->tok.name);
return -1; return -1;
} }
else if (tmp < 0 || tmp > 255) else if (tmp < 0 || tmp > 255)
@ -3233,28 +3222,13 @@ static int __read_array_literal (stix_t* stix, stix_oop_t* xlit)
case STIX_IOTOK_NUMLIT: case STIX_IOTOK_NUMLIT:
case STIX_IOTOK_RADNUMLIT: case STIX_IOTOK_RADNUMLIT:
{ lit = string_to_num (stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT);
stix_ooi_t tmp; if (!lit) return -1;
if (string_to_smint(stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT, &tmp) <= -1)
{
/* the token reader reads a valid token. no other errors
* than the range error must not occur */
STIX_ASSERT (stix->errnum == STIX_ERANGE);
/* TODO: IMPLMENET LARGE INTEGER */
printf ("LARGE NOT IMPLEMENTED IN COMPILE_ARRAY_LITERAL\n");
stix->errnum = STIX_ENOIMPL;
return -1;
}
lit = STIX_SMOOI_TO_OOP(tmp);
break; break;
}
case STIX_IOTOK_CHARLIT: case STIX_IOTOK_CHARLIT:
STIX_ASSERT (stix->c->tok.name.len == 1); STIX_ASSERT (stix->c->tok.name.len == 1);
lit = STIX_OOP_FROM_CHAR(stix->c->tok.name.ptr[0]); lit = STIX_CHAR_TO_OOP(stix->c->tok.name.ptr[0]);
break; break;
case STIX_IOTOK_STRLIT: case STIX_IOTOK_STRLIT:
@ -3540,28 +3514,8 @@ printf ("\tpush symbol literal %d\n", (int)index);
case STIX_IOTOK_NUMLIT: case STIX_IOTOK_NUMLIT:
case STIX_IOTOK_RADNUMLIT: case STIX_IOTOK_RADNUMLIT:
{ {
/* TODO: other types of numbers, negative numbers, etc */ /* TODO: floating pointer number */
#if 0 /* TODO: other types of numbers, etc */
/* TODO: proper numbeic literal handling */
stix_ooi_t tmp;
if (string_to_smint(stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT, &tmp) <= -1)
{
/* the token reader reads a valid token. no other errors
* than the range error must not occur */
STIX_ASSERT (stix->errnum == STIX_ERANGE);
printf ("NOT IMPLEMENTED LARGE_INTEGER or ERROR?\n");
stix->errnum = STIX_ENOIMPL;
return -1;
}
else
{
printf ("\tpush int literal\n");
if (emit_push_smint_literal(stix, tmp) <= -1) return -1;
}
#else
stix_oop_t tmp; stix_oop_t tmp;
tmp = string_to_num (stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT); tmp = string_to_num (stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT);
if (!tmp) return -1; if (!tmp) return -1;
@ -3576,7 +3530,6 @@ printf ("\tpush int literal\n");
if (add_literal(stix, tmp, &index) <= -1 || if (add_literal(stix, tmp, &index) <= -1 ||
emit_single_param_instruction(stix, BCODE_PUSH_LITERAL_0, index) <= -1) return -1; emit_single_param_instruction(stix, BCODE_PUSH_LITERAL_0, index) <= -1) return -1;
} }
#endif
GET_TOKEN (stix); GET_TOKEN (stix);
break; break;
@ -4947,7 +4900,7 @@ printf ("\n");
case STIX_IOTOK_CHARLIT: case STIX_IOTOK_CHARLIT:
STIX_ASSERT (stix->c->tok.name.len == 1); STIX_ASSERT (stix->c->tok.name.len == 1);
lit = STIX_OOP_FROM_CHAR(stix->c->tok.name.ptr[0]); lit = STIX_CHAR_TO_OOP(stix->c->tok.name.ptr[0]);
goto add_literal; goto add_literal;
case STIX_IOTOK_STRLIT: case STIX_IOTOK_STRLIT:
@ -4963,27 +4916,8 @@ printf ("\n");
case STIX_IOTOK_NUMLIT: case STIX_IOTOK_NUMLIT:
case STIX_IOTOK_RADNUMLIT: case STIX_IOTOK_RADNUMLIT:
{ {
#if 0
stix_ooi_t tmp;
if (string_to_smint(stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT, &tmp) <= -1)
{
/* the token reader reads a valid token. no other errors
* than the range error must not occur */
STIX_ASSERT (stix->errnum == STIX_ERANGE);
printf ("NOT IMPLEMENTED LARGE_INTEGER or ERROR?\n");
stix->errnum = STIX_ENOIMPL;
return -1;
}
else
{
lit = STIX_SMOOI_TO_OOP(tmp);
}
#else
lit = string_to_num (stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT); lit = string_to_num (stix, &stix->c->tok.name, stix->c->tok.type == STIX_IOTOK_RADNUMLIT);
if (!lit) return -1; if (!lit) return -1;
#endif
goto add_literal; goto add_literal;
} }

View File

@ -63,7 +63,8 @@ static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t oldbuc)
static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic, stix_oop_char_t key, stix_oop_t value) static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic, stix_oop_char_t key, stix_oop_t value)
{ {
stix_oow_t index, tally; stix_ooi_t tally;
stix_oow_t index;
stix_oop_association_t ass; stix_oop_association_t ass;
stix_oow_t tmp_count = 0; stix_oow_t tmp_count = 0;
@ -75,6 +76,7 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic,
index = stix_hashchars(key->slot, STIX_OBJ_GET_SIZE(key)) % STIX_OBJ_GET_SIZE(dic->bucket); index = stix_hashchars(key->slot, STIX_OBJ_GET_SIZE(key)) % STIX_OBJ_GET_SIZE(dic->bucket);
/* find */
while (dic->bucket->slot[index] != stix->_nil) while (dic->bucket->slot[index] != stix->_nil)
{ {
ass = (stix_oop_association_t)dic->bucket->slot[index]; ass = (stix_oop_association_t)dic->bucket->slot[index];
@ -86,7 +88,7 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic,
stix_equalchars (key->slot, ((stix_oop_char_t)ass->key)->slot, STIX_OBJ_GET_SIZE(key))) stix_equalchars (key->slot, ((stix_oop_char_t)ass->key)->slot, STIX_OBJ_GET_SIZE(key)))
{ {
/* the value of STIX_NULL indicates no insertion or update. */ /* the value of STIX_NULL indicates no insertion or update. */
if (value) ass->value = value; if (value) ass->value = value; /* update */
return ass; return ass;
} }
@ -101,11 +103,25 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic,
return STIX_NULL; return STIX_NULL;
} }
/* the key is not found. insert it. */
STIX_ASSERT (STIX_OOP_IS_SMOOI(dic->tally));
tally = STIX_OOP_TO_SMOOI(dic->tally);
if (tally >= STIX_SMOOI_MAX)
{
/* this built-in dictionary is not allowed to hold more than
* STIX_SMOOI_MAX items for efficiency sake */
stix->errnum = STIX_EDFULL;
return STIX_NULL;
}
stix_pushtmp (stix, (stix_oop_t*)&dic); tmp_count++; stix_pushtmp (stix, (stix_oop_t*)&dic); tmp_count++;
stix_pushtmp (stix, (stix_oop_t*)&key); tmp_count++; stix_pushtmp (stix, (stix_oop_t*)&key); tmp_count++;
stix_pushtmp (stix, &value); tmp_count++; stix_pushtmp (stix, &value); tmp_count++;
tally = STIX_OOP_TO_SMOOI(dic->tally); /* no conversion to stix_oow_t is necessary for tally + 1.
* the maximum value of tally is checked to be STIX_SMOOI_MAX - 1.
* tally + 1 can produce at most STIX_SMOOI_MAX. above all,
* STIX_SMOOI_MAX is way smaller than STIX_TYPE_MAX(stix_ooi_t). */
if (tally + 1 >= STIX_OBJ_GET_SIZE(dic->bucket)) if (tally + 1 >= STIX_OBJ_GET_SIZE(dic->bucket))
{ {
stix_oop_oop_t bucket; stix_oop_oop_t bucket;
@ -114,7 +130,7 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic,
it just before it gets full. The polcy can be grow it it just before it gets full. The polcy can be grow it
if it's 70% full */ if it's 70% full */
/* Enlarge the symbol table before it gets full to /* enlarge the bucket before it gets full to
* make sure that it has at least one free slot left * make sure that it has at least one free slot left
* after having added a new symbol. this is to help * after having added a new symbol. this is to help
* traversal end at a _nil slot if no entry is found. */ * traversal end at a _nil slot if no entry is found. */
@ -138,6 +154,8 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic,
ass->key = (stix_oop_t)key; ass->key = (stix_oop_t)key;
ass->value = value; ass->value = value;
/* the current tally must be less than the maximum value. otherwise,
* it overflows after increment below */
STIX_ASSERT (tally < STIX_SMOOI_MAX); STIX_ASSERT (tally < STIX_SMOOI_MAX);
dic->tally = STIX_SMOOI_TO_OOP(tally + 1); dic->tally = STIX_SMOOI_TO_OOP(tally + 1);
dic->bucket->slot[index] = (stix_oop_t)ass; dic->bucket->slot[index] = (stix_oop_t)ass;

View File

@ -688,7 +688,7 @@ static int prim_basic_at (stix_t* stix, stix_ooi_t nargs)
break; break;
case STIX_OBJ_TYPE_CHAR: case STIX_OBJ_TYPE_CHAR:
v = STIX_OOP_FROM_CHAR(((stix_oop_char_t)rcv)->slot[idx]); v = STIX_CHAR_TO_OOP(((stix_oop_char_t)rcv)->slot[idx]);
break; break;
case STIX_OBJ_TYPE_HALFWORD: case STIX_OBJ_TYPE_HALFWORD:
@ -1491,7 +1491,7 @@ printf ("CALL MODE 222 ERROR %d %d\n", dcGetError (dc), DC_ERROR_UNSUPPORTED_MOD
case 'c': case 'c':
{ {
char r = dcCallChar (dc, f); char r = dcCallChar (dc, f);
ACTIVE_STACK_SETTOP (stix, STIX_OOP_FROM_CHAR(r)); ACTIVE_STACK_SETTOP (stix, STIX_CHAR_TO_OOP(r));
break; break;
} }

View File

@ -29,18 +29,25 @@
static void compact_symbol_table (stix_t* stix, stix_oop_t _nil) static void compact_symbol_table (stix_t* stix, stix_oop_t _nil)
{ {
stix_oop_char_t symbol; stix_oop_char_t symbol;
stix_oow_t tally, index, i, x, y, z; stix_oow_t i, x, y, z;
stix_oow_t bucket_size; stix_oow_t bucket_size, index;
stix_ooi_t tally;
#if defined(STIX_SUPPORT_GC_DURING_IGNITION) #if defined(STIX_SUPPORT_GC_DURING_IGNITION)
if (!stix->symtab) return; /* symbol table has not been created */ if (!stix->symtab) return; /* symbol table has not been created */
#endif #endif
bucket_size = STIX_OBJ_GET_SIZE(stix->symtab->bucket); /* the symbol table doesn't allow more data items than STIX_SMOOI_MAX.
* so stix->symtab->tally must always be a small integer */
STIX_ASSERT (STIX_OOP_IS_SMOOI(stix->symtab->tally));
tally = STIX_OOP_TO_SMOOI(stix->symtab->tally); tally = STIX_OOP_TO_SMOOI(stix->symtab->tally);
STIX_ASSERT (tally >= 0); /* it must not be less than 0 */
if (tally <= 0) return; if (tally <= 0) return;
/* NOTE: in theory, the bucket size can be greater than STIX_SMOOI_MAX
* as it is an internal header field and is of an unsigned type */
bucket_size = STIX_OBJ_GET_SIZE(stix->symtab->bucket);
for (index = 0; index < bucket_size; ) for (index = 0; index < bucket_size; )
{ {
if (STIX_OBJ_GET_FLAGS_MOVED(stix->symtab->bucket->slot[index])) if (STIX_OBJ_GET_FLAGS_MOVED(stix->symtab->bucket->slot[index]))
@ -79,6 +86,7 @@ static void compact_symbol_table (stix_t* stix, stix_oop_t _nil)
tally--; tally--;
} }
STIX_ASSERT (tally >= 0);
STIX_ASSERT (tally <= STIX_SMOOI_MAX); STIX_ASSERT (tally <= STIX_SMOOI_MAX);
stix->symtab->tally = STIX_SMOOI_TO_OOP(tally); stix->symtab->tally = STIX_SMOOI_TO_OOP(tally);
} }

View File

@ -49,6 +49,8 @@ enum stix_errnum_t
STIX_EINVAL, /**< invalid parameter or data */ STIX_EINVAL, /**< invalid parameter or data */
STIX_ERANGE, /**< range error. overflow and underflow */ STIX_ERANGE, /**< range error. overflow and underflow */
STIX_ENOENT, /**< no matching entry */ STIX_ENOENT, /**< no matching entry */
STIX_EDFULL, /**< dictionary full */
STIX_EDIVBY0, /**< divide by zero */
STIX_EIOERR, /**< I/O error */ STIX_EIOERR, /**< I/O error */
STIX_EECERR, /**< encoding conversion error */ STIX_EECERR, /**< encoding conversion error */
@ -157,12 +159,15 @@ typedef struct stix_obj_word_t* stix_oop_word_t;
#define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_CHAR) #define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_CHAR)
#define STIX_SMOOI_TO_OOP(num) ((stix_oop_t)((((stix_ooi_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_SMINT)) #define STIX_SMOOI_TO_OOP(num) ((stix_oop_t)((((stix_ooi_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_SMINT))
#define STIX_OOP_TO_SMOOI(oop) (((stix_ooi_t)oop) >> STIX_OOP_TAG_BITS) #define STIX_OOP_TO_SMOOI(oop) (((stix_ooi_t)oop) >> STIX_OOP_TAG_BITS)
#define STIX_OOP_FROM_CHAR(num) ((stix_oop_t)((((stix_oow_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_CHAR)) #define STIX_CHAR_TO_OOP(num) ((stix_oop_t)((((stix_oow_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_CHAR))
#define STIX_OOP_TO_CHAR(oop) (((stix_oow_t)oop) >> STIX_OOP_TAG_BITS) #define STIX_OOP_TO_CHAR(oop) (((stix_oow_t)oop) >> STIX_OOP_TAG_BITS)
#define STIX_SMINT_BITS (STIX_SIZEOF(stix_ooi_t) * 8 - STIX_OOP_TAG_BITS) #define STIX_SMINT_BITS (STIX_SIZEOF(stix_ooi_t) * 8 - STIX_OOP_TAG_BITS)
#define STIX_SMOOI_MAX ((stix_ooi_t)(~((stix_oow_t)0) >> (STIX_OOP_TAG_BITS + 1))) #define STIX_SMOOI_MAX ((stix_ooi_t)(~((stix_oow_t)0) >> (STIX_OOP_TAG_BITS + 1)))
#define STIX_SMOOI_MIN (-STIX_SMOOI_MAX - 1) /* Sacrificing 1 bit pattern for a negative SMOOI makes implementation
* a lot eaisier in many parts */
/*#define STIX_SMOOI_MIN (-STIX_SMOOI_MAX - 1)*/
#define STIX_SMOOI_MIN (-STIX_SMOOI_MAX)
#define STIX_IN_SMOOI_RANGE(ooi) ((ooi) >= STIX_SMOOI_MIN && (ooi) <= STIX_SMOOI_MAX) #define STIX_IN_SMOOI_RANGE(ooi) ((ooi) >= STIX_SMOOI_MIN && (ooi) <= STIX_SMOOI_MAX)
/* TODO: There are untested code where smint is converted to stix_oow_t. /* TODO: There are untested code where smint is converted to stix_oow_t.

View File

@ -60,7 +60,8 @@ static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t oldbuc)
static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_ooch_t* ptr, stix_oow_t len, int create) static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_ooch_t* ptr, stix_oow_t len, int create)
{ {
stix_oow_t index, tally; stix_ooi_t tally;
stix_oow_t index;
stix_oop_char_t symbol; stix_oop_char_t symbol;
STIX_ASSERT (len > 0); STIX_ASSERT (len > 0);
@ -95,7 +96,21 @@ static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_ooch_t* ptr, sti
return STIX_NULL; return STIX_NULL;
} }
/* make a new symbol and insert it */
STIX_ASSERT (STIX_OOP_IS_SMOOI(stix->symtab->tally));
tally = STIX_OOP_TO_SMOOI(stix->symtab->tally); tally = STIX_OOP_TO_SMOOI(stix->symtab->tally);
if (tally >= STIX_SMOOI_MAX)
{
/* this built-in table is not allowed to hold more than
* STIX_SMOOI_MAX items for efficiency sake */
stix->errnum = STIX_EDFULL;
return STIX_NULL;
}
/* no conversion to stix_oow_t is necessary for tally + 1.
* the maximum value of tally is checked to be STIX_SMOOI_MAX - 1.
* tally + 1 can produce at most STIX_SMOOI_MAX. above all,
* STIX_SMOOI_MAX is way smaller than STIX_TYPE_MAX(stix_ooi_t). */
if (tally + 1 >= STIX_OBJ_GET_SIZE(stix->symtab->bucket)) if (tally + 1 >= STIX_OBJ_GET_SIZE(stix->symtab->bucket))
{ {
stix_oop_oop_t bucket; stix_oop_oop_t bucket;
@ -104,7 +119,7 @@ static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_ooch_t* ptr, sti
it just before it gets full. The polcy can be grow it it just before it gets full. The polcy can be grow it
if it's 70% full */ if it's 70% full */
/* Enlarge the symbol table before it gets full to /* enlarge the symbol table before it gets full to
* make sure that it has at least one free slot left * make sure that it has at least one free slot left
* after having added a new symbol. this is to help * after having added a new symbol. this is to help
* traversal end at a _nil slot if no entry is found. */ * traversal end at a _nil slot if no entry is found. */