implement pictured numbers
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
|
||||
#define HEAP_END (HEAP_SIZE - WORDBUF_SIZE - INPUT_BUFFER_SIZE)
|
||||
#define WORDBUF_ADDR HEAP_END
|
||||
#define WORDBUF_LASTCHAR_ADDR (WORDBUF_ADDR + WORDBUF_SIZE - 1)
|
||||
#define INPUTBUF_ADDR (HEAP_END + WORDBUF_SIZE)
|
||||
|
||||
// SFR and magic addresses are "negative"
|
||||
|
||||
@@ -28,6 +28,7 @@ enum fh_error {
|
||||
FH_ERR_ARITH,
|
||||
FH_ERR_SYNTAX,
|
||||
FH_ERR_NOT_APPLICABLE,
|
||||
FH_ERR_PICTNUM_FULL,
|
||||
FH_ERR_MAX,
|
||||
};
|
||||
|
||||
|
||||
@@ -176,6 +176,9 @@ struct fh_thread_s {
|
||||
/** Address of the last dict word */
|
||||
uint32_t dict_last;
|
||||
|
||||
/** Pictured numeric output buffer write cursor (used for prepend) */
|
||||
uint32_t pictnumptr;
|
||||
|
||||
/** Input buffer parse position */
|
||||
uint32_t inputptr;
|
||||
/** Input buffer total content size */
|
||||
|
||||
@@ -217,6 +217,136 @@ static enum fh_error w_dot_quote(struct fh_thread_s *fh, const struct fh_word_s
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_less_hash(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
fh->pictnumptr = WORDBUF_LASTCHAR_ADDR;
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_hash_greater(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
|
||||
|
||||
uint64_t dummy;
|
||||
TRY(ds_pop_dw(fh, &dummy));
|
||||
|
||||
uint32_t len = WORDBUF_LASTCHAR_ADDR - fh->pictnumptr;
|
||||
uint32_t addr;
|
||||
TRY(fh_heap_reserve(fh, len, &addr));
|
||||
fh_heap_copy(fh, addr, fh->pictnumptr+1, len);
|
||||
LOG("#> output: \"%.*s\"", len, &fh->heap[fh->pictnumptr+1]);
|
||||
TRY(ds_push(fh, addr));
|
||||
TRY(ds_push(fh, len));
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error pictnum_prepend_char(struct fh_thread_s *fh, char c) {
|
||||
enum fh_error rv;
|
||||
if (fh->pictnumptr < WORDBUF_ADDR) {
|
||||
return FH_ERR_PICTNUM_FULL;
|
||||
}
|
||||
LOG("Prepend: %c", c);
|
||||
TRY(fh_store_char(fh, fh->pictnumptr, c));
|
||||
fh->pictnumptr--;
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static char dig2char(uint64_t digit) {
|
||||
char repr;
|
||||
if (digit < 10) {
|
||||
repr = '0' + digit;
|
||||
} else if (digit < 36) {
|
||||
repr = 'A' + (digit - 10);
|
||||
} else {
|
||||
repr = '?'; // XXX bad base?
|
||||
}
|
||||
return repr;
|
||||
}
|
||||
|
||||
static enum fh_error w_hash(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
uint64_t num;
|
||||
TRY(ds_pop_dw(fh, &num));
|
||||
uint64_t digit = num % fh->base;
|
||||
TRY(pictnum_prepend_char(fh, dig2char(digit)));
|
||||
TRY(ds_push_dw(fh, num / (uint64_t)fh->base));
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_hash_s(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
uint64_t num;
|
||||
TRY(ds_pop_dw(fh, &num));
|
||||
|
||||
do {
|
||||
uint64_t digit = num % fh->base;
|
||||
num = num / (uint64_t)fh->base;
|
||||
TRY(pictnum_prepend_char(fh, dig2char(digit)));
|
||||
} while (num > 0);
|
||||
|
||||
TRY(ds_push_dw(fh, num)); // this is zero now
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_sign(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
uint32_t num;
|
||||
TRY(ds_pop(fh, &num));
|
||||
if ((int32_t)num < 0) {
|
||||
TRY(pictnum_prepend_char(fh, '-'));
|
||||
}
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_hold(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
uint32_t ch;
|
||||
TRY(ds_pop(fh, &ch));
|
||||
|
||||
char buf[5];
|
||||
int num = utf8_encode(buf, ch);
|
||||
for(int i=num-1;i>=0;i--) {
|
||||
TRY(pictnum_prepend_char(fh, buf[i]));
|
||||
}
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_holds(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
uint32_t ch;
|
||||
|
||||
uint32_t count = 0, addr = 0;
|
||||
LOG("Get count,addr");
|
||||
TRY(ds_pop(fh, &count));
|
||||
TRY(ds_pop(fh, &addr));
|
||||
|
||||
const char *str = fh_str_at(fh, addr);
|
||||
if (!str) {
|
||||
LOGE("HOLDS addr out of bounds!");
|
||||
return FH_ERR_NOT_APPLICABLE;
|
||||
}
|
||||
|
||||
for(int i=count-1;i>=0;i--) {
|
||||
TRY(pictnum_prepend_char(fh, str[i]));
|
||||
}
|
||||
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
const struct name_and_handler fh_builtins_text[] = {
|
||||
{"s\"", w_s_quote, 1, 0},
|
||||
{"s\\\"", w_s_quote, 1, 1}, // escaped
|
||||
@@ -232,5 +362,12 @@ const struct name_and_handler fh_builtins_text[] = {
|
||||
{"??", w_debug_dump, 0, 0},
|
||||
{"emit", w_emit, 0, 0},
|
||||
{"see", w_see, 0, 0},
|
||||
{"<#", w_less_hash, 0, 0},
|
||||
{"#>", w_hash_greater, 0, 0},
|
||||
{"#", w_hash, 0, 0},
|
||||
{"#s", w_hash_s, 0, 0},
|
||||
{"sign", w_sign, 0, 0},
|
||||
{"hold", w_hold, 0, 0},
|
||||
{"holds", w_holds, 0, 0},
|
||||
{ /* end marker */ }
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ static const char *errornames[FH_ERR_MAX] = {
|
||||
[FH_ERR_ILLEGAL_STORE] = "ILLEGAL_STORE",
|
||||
[FH_ERR_ARITH] = "ARITHMETIC_ERROR",
|
||||
[FH_ERR_SYNTAX] = "SYNTAX_ERROR",
|
||||
[FH_ERR_PICTNUM_FULL] = "PICTNUM_FULL",
|
||||
[FH_ERR_NOT_APPLICABLE] = "NOT_APPLICABLE",
|
||||
};
|
||||
|
||||
|
||||
@@ -838,6 +838,7 @@ T{ ' W1 >BODY -> HERE }T
|
||||
T{ W1 -> HERE 1 + }T
|
||||
T{ W1 -> HERE 2 + }T
|
||||
|
||||
0 [if] \ TODO
|
||||
\ ------------------------------------------------------------------------
|
||||
TESTING EVALUATE
|
||||
|
||||
@@ -882,6 +883,7 @@ DROP -> 0 }T \ BLANK LINE RETURN ZERO-LENGTH STRING
|
||||
: GS4 SOURCE >IN ! DROP ;
|
||||
T{ GS4 123 456
|
||||
-> }T
|
||||
[then]
|
||||
|
||||
\ ------------------------------------------------------------------------
|
||||
TESTING <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL
|
||||
|
||||
Reference in New Issue
Block a user