implement pictured numbers

master
Ondřej Hruška 3 years ago
parent 9b7f780d91
commit 5600c4d106
  1. 1
      include/fh_config.h
  2. 1
      include/fh_error.h
  3. 3
      include/fh_runtime.h
  4. 137
      src/fh_builtins_text.c
  5. 1
      src/fh_error.c
  6. 2
      testfiles/combinedtest.f

@ -21,6 +21,7 @@
#define HEAP_END (HEAP_SIZE - WORDBUF_SIZE - INPUT_BUFFER_SIZE) #define HEAP_END (HEAP_SIZE - WORDBUF_SIZE - INPUT_BUFFER_SIZE)
#define WORDBUF_ADDR HEAP_END #define WORDBUF_ADDR HEAP_END
#define WORDBUF_LASTCHAR_ADDR (WORDBUF_ADDR + WORDBUF_SIZE - 1)
#define INPUTBUF_ADDR (HEAP_END + WORDBUF_SIZE) #define INPUTBUF_ADDR (HEAP_END + WORDBUF_SIZE)
// SFR and magic addresses are "negative" // SFR and magic addresses are "negative"

@ -28,6 +28,7 @@ enum fh_error {
FH_ERR_ARITH, FH_ERR_ARITH,
FH_ERR_SYNTAX, FH_ERR_SYNTAX,
FH_ERR_NOT_APPLICABLE, FH_ERR_NOT_APPLICABLE,
FH_ERR_PICTNUM_FULL,
FH_ERR_MAX, FH_ERR_MAX,
}; };

@ -176,6 +176,9 @@ struct fh_thread_s {
/** Address of the last dict word */ /** Address of the last dict word */
uint32_t dict_last; uint32_t dict_last;
/** Pictured numeric output buffer write cursor (used for prepend) */
uint32_t pictnumptr;
/** Input buffer parse position */ /** Input buffer parse position */
uint32_t inputptr; uint32_t inputptr;
/** Input buffer total content size */ /** 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; 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[] = { const struct name_and_handler fh_builtins_text[] = {
{"s\"", w_s_quote, 1, 0}, {"s\"", w_s_quote, 1, 0},
{"s\\\"", w_s_quote, 1, 1}, // escaped {"s\\\"", w_s_quote, 1, 1}, // escaped
@ -232,5 +362,12 @@ const struct name_and_handler fh_builtins_text[] = {
{"??", w_debug_dump, 0, 0}, {"??", w_debug_dump, 0, 0},
{"emit", w_emit, 0, 0}, {"emit", w_emit, 0, 0},
{"see", w_see, 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 */ } { /* end marker */ }
}; };

@ -20,6 +20,7 @@ static const char *errornames[FH_ERR_MAX] = {
[FH_ERR_ILLEGAL_STORE] = "ILLEGAL_STORE", [FH_ERR_ILLEGAL_STORE] = "ILLEGAL_STORE",
[FH_ERR_ARITH] = "ARITHMETIC_ERROR", [FH_ERR_ARITH] = "ARITHMETIC_ERROR",
[FH_ERR_SYNTAX] = "SYNTAX_ERROR", [FH_ERR_SYNTAX] = "SYNTAX_ERROR",
[FH_ERR_PICTNUM_FULL] = "PICTNUM_FULL",
[FH_ERR_NOT_APPLICABLE] = "NOT_APPLICABLE", [FH_ERR_NOT_APPLICABLE] = "NOT_APPLICABLE",
}; };

@ -838,6 +838,7 @@ T{ ' W1 >BODY -> HERE }T
T{ W1 -> HERE 1 + }T T{ W1 -> HERE 1 + }T
T{ W1 -> HERE 2 + }T T{ W1 -> HERE 2 + }T
0 [if] \ TODO
\ ------------------------------------------------------------------------ \ ------------------------------------------------------------------------
TESTING EVALUATE TESTING EVALUATE
@ -882,6 +883,7 @@ DROP -> 0 }T \ BLANK LINE RETURN ZERO-LENGTH STRING
: GS4 SOURCE >IN ! DROP ; : GS4 SOURCE >IN ! DROP ;
T{ GS4 123 456 T{ GS4 123 456
-> }T -> }T
[then]
\ ------------------------------------------------------------------------ \ ------------------------------------------------------------------------
TESTING <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL TESTING <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL

Loading…
Cancel
Save