fixes and more comments, cleaning
This commit is contained in:
@@ -1,2 +1,4 @@
|
||||
: hi ." Hello, World!" ;
|
||||
hi
|
||||
: hi2 s" Hello, World!" TYPE ;
|
||||
hi2
|
||||
|
||||
@@ -43,9 +43,9 @@ _Static_assert(WORDALIGNED(1023) == 1024, "word align");
|
||||
_Static_assert(WORDALIGNED(1024) == 1024, "word align");
|
||||
|
||||
/* logging */
|
||||
#define LOG(format, ...) do { if(fh_globals.verbose) { fprintf(stderr, format "\r\n", ##__VA_ARGS__); } } while (0)
|
||||
#define LOGI(format, ...) fprintf(stderr, "\x1b[32m" format "\x1b[m\r\n", ##__VA_ARGS__)
|
||||
#define LOGE(format, ...) fprintf(stderr, "\x1b[31;1m" format "\x1b[m\r\n", ##__VA_ARGS__)
|
||||
#define LOG(format, ...) do { if(fh_globals.verbose) { fprintf(stderr, format "\n", ##__VA_ARGS__); } } while (0)
|
||||
#define LOGI(format, ...) fprintf(stderr, "\x1b[32m" format "\x1b[m\n", ##__VA_ARGS__)
|
||||
#define LOGE(format, ...) fprintf(stderr, "\x1b[31;1m" format "\x1b[m\n", ##__VA_ARGS__)
|
||||
/* Forth standard output. XXX should be stdout, but then colors get mangled if logging is used */
|
||||
#define FHPRINT(format, ...) fprintf(stderr, "\x1b[33;1m" format "\x1b[m", ##__VA_ARGS__)
|
||||
#define FHPRINT_SVC(format, ...) fprintf(stderr, "" format "", ##__VA_ARGS__)
|
||||
@@ -136,6 +136,8 @@ struct fh_instruction_s {
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
#define INSTR_SIZE (sizeof(struct fh_instruction_s))
|
||||
|
||||
/** Bytecode word indices that are not in the dict, have special effect */
|
||||
enum compiler_word {
|
||||
/** End of a user defined word, pop address and jump back */
|
||||
@@ -194,14 +196,17 @@ struct fh_thread_s {
|
||||
/** Control stack */
|
||||
uint32_t control_stack[CONTROL_STACK_DEPTH];
|
||||
size_t control_stack_top;
|
||||
size_t control_stack_hwm;
|
||||
|
||||
/** Data stack */
|
||||
uint32_t data_stack[DATA_STACK_DEPTH];
|
||||
size_t data_stack_top;
|
||||
size_t data_stack_hwm;
|
||||
|
||||
/** Return stack */
|
||||
uint32_t return_stack[RETURN_STACK_DEPTH];
|
||||
size_t return_stack_top;
|
||||
size_t return_stack_hwm;
|
||||
|
||||
/** Data heap */
|
||||
uint8_t heap[HEAP_SIZE];
|
||||
@@ -279,6 +284,13 @@ static inline enum fh_error cs_pop(struct fh_thread_s *fh, uint32_t *out)
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
#define UPDATE_HWM(hwm, top) \
|
||||
do { \
|
||||
if((hwm) < (top)) { \
|
||||
(hwm) = (top); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/** Push to data stack */
|
||||
static inline enum fh_error ds_push(struct fh_thread_s *fh, uint32_t in)
|
||||
{
|
||||
@@ -287,6 +299,7 @@ static inline enum fh_error ds_push(struct fh_thread_s *fh, uint32_t in)
|
||||
return FH_ERR_DS_OVERFLOW;
|
||||
}
|
||||
fh->data_stack[fh->data_stack_top++] = in;
|
||||
UPDATE_HWM(fh->data_stack_hwm, fh->data_stack_top);
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
@@ -298,6 +311,7 @@ static inline enum fh_error rs_push(struct fh_thread_s *fh, uint32_t in)
|
||||
return FH_ERR_RS_OVERFLOW;
|
||||
}
|
||||
fh->return_stack[fh->return_stack_top++] = in;
|
||||
UPDATE_HWM(fh->return_stack_hwm, fh->return_stack_top);
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
@@ -309,6 +323,7 @@ static inline enum fh_error cs_push(struct fh_thread_s *fh, uint32_t in)
|
||||
return FH_ERR_CS_OVERFLOW;
|
||||
}
|
||||
fh->control_stack[fh->control_stack_top++] = in;
|
||||
UPDATE_HWM(fh->control_stack_hwm, fh->control_stack_top);
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
@@ -357,6 +372,28 @@ enum fh_error fh_heap_reserve(
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
/** Write bytes to heap at a given location. The region must have been previously allocated! */
|
||||
void fh_heap_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint32_t len)
|
||||
{
|
||||
memcpy(&fh->heap[addr], src, len);
|
||||
}
|
||||
|
||||
/** Allocate heap region and write bytes to it */
|
||||
enum fh_error fh_heap_put(struct fh_thread_s *fh, const void *src, uint32_t len)
|
||||
{
|
||||
enum fh_error rv;
|
||||
uint32_t addr;
|
||||
TRY(fh_heap_reserve(fh, len, &addr));
|
||||
fh_heap_write(fh, addr, src, len);
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
/** Copy bytes from compile area to heap. The region must have been previously allocated! */
|
||||
void fh_heap_copy_from_compile(struct fh_thread_s *fh, uint32_t addr, uint32_t srcaddr, uint32_t len)
|
||||
{
|
||||
memcpy(&fh->heap[addr], &fh->compile[srcaddr], len);
|
||||
}
|
||||
|
||||
/** Reserve space in the compile memory area */
|
||||
enum fh_error fh_compile_reserve(
|
||||
struct fh_thread_s *fh,
|
||||
@@ -377,6 +414,22 @@ enum fh_error fh_compile_reserve(
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
/** Write bytes to compile area at a given location. The region must have been previously allocated! */
|
||||
void fh_compile_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint32_t len)
|
||||
{
|
||||
memcpy(&fh->compile[addr], src, len);
|
||||
}
|
||||
|
||||
/** Allocate compile region and write bytes to it */
|
||||
enum fh_error fh_compile_put(struct fh_thread_s *fh, const void *src, uint32_t len)
|
||||
{
|
||||
enum fh_error rv;
|
||||
uint32_t addr;
|
||||
TRY(fh_compile_reserve(fh, len, &addr));
|
||||
fh_compile_write(fh, addr, src, len);
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
enum fh_error w_add(struct fh_thread_s *fh)
|
||||
{
|
||||
enum fh_error rv;
|
||||
@@ -442,17 +495,18 @@ enum fh_error w_user_word(struct fh_thread_s *fh)
|
||||
case CPLWORD_ALLOCSTR:
|
||||
case CPLWORD_TYPESTR:
|
||||
strl = *((uint32_t *) &fh->compile[fh->execptr]);
|
||||
fh->execptr += 4;
|
||||
LOG("strl %d", strl);
|
||||
fh->execptr += 4; // advance past the length
|
||||
if (wn == CPLWORD_ALLOCSTR) {
|
||||
TRY(fh_heap_reserve(fh, strl, &addr));
|
||||
memcpy(&fh->heap[addr], &fh->compile[fh->execptr], strl);
|
||||
fh_heap_copy_from_compile(fh, addr, fh->execptr, strl);
|
||||
LOG("Exec: alloc-str \"%.*s\"", strl, &fh->heap[addr]);
|
||||
TRY(ds_push(fh, addr));
|
||||
TRY(ds_push(fh, strl));
|
||||
fh->execptr += strl;
|
||||
} else {
|
||||
FHPRINT("%.*s", (int) strl, &fh->compile[fh->execptr]);
|
||||
LOG("Exec: type-str \"%.*s\"", strl, &fh->heap[addr]);
|
||||
LOG("Exec: type-str \"%.*s\"", strl, &fh->compile[fh->execptr]);
|
||||
}
|
||||
goto instr;
|
||||
|
||||
@@ -508,10 +562,9 @@ enum fh_error w_semicolon(struct fh_thread_s *fh)
|
||||
return FH_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
TRY(fh_compile_reserve(fh, sizeof(struct fh_instruction_s), &addr));
|
||||
instr.kind = FH_INSTR_WORD;
|
||||
instr.data = CPLWORD_ENDWORD;
|
||||
memcpy(&fh->compile[addr], &instr, sizeof(struct fh_instruction_s));
|
||||
TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
|
||||
|
||||
/* Return to interpret state */
|
||||
fh_setstate(fh, FH_STATE_INTERPRET, 0);
|
||||
@@ -543,7 +596,7 @@ enum fh_error w_type(struct fh_thread_s *fh)
|
||||
enum fh_error w_cr(struct fh_thread_s *fh)
|
||||
{
|
||||
(void) fh;
|
||||
FHPRINT("\r\n");
|
||||
FHPRINT("\n");
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
@@ -595,8 +648,8 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh)
|
||||
};
|
||||
|
||||
const struct name_and_handler builtins[] = {
|
||||
{"s\"", w_s_quote},
|
||||
{".\"", w_dot_quote},
|
||||
{"s\"", w_s_quote, 1},
|
||||
{".\"", w_dot_quote, 1},
|
||||
/* Compiler control words */
|
||||
{"bye", w_bye},
|
||||
/* Basic arithmetics */
|
||||
@@ -658,14 +711,12 @@ static enum fh_error fh_handle_quoted_string(
|
||||
{
|
||||
enum fh_error rv;
|
||||
uint32_t addr = 0;
|
||||
uint32_t addr2 = 0;
|
||||
struct fh_instruction_s instr;
|
||||
|
||||
if (fh->state == FH_STATE_INTERPRET) {
|
||||
switch (fh->substate) {
|
||||
case FH_SUBSTATE_SQUOTE:
|
||||
TRY(fh_heap_reserve(fh, len, &addr));
|
||||
memcpy(&fh->heap[addr], start, len);
|
||||
TRY(fh_heap_put(fh, start, len));
|
||||
TRY(ds_push(fh, addr));
|
||||
TRY(ds_push(fh, len));
|
||||
break;
|
||||
@@ -677,9 +728,8 @@ static enum fh_error fh_handle_quoted_string(
|
||||
LOGE("Bad substate in interpret mode: %s", substatenames[fh->substate]);
|
||||
}
|
||||
} else {
|
||||
LOG("Compile a string");
|
||||
/* compile */
|
||||
TRY(fh_compile_reserve(fh, sizeof(struct fh_instruction_s), &addr));
|
||||
TRY(fh_compile_reserve(fh, len + 4, &addr2));
|
||||
instr.kind = FH_INSTR_WORD;
|
||||
instr.data = fh->substate == FH_SUBSTATE_SQUOTE ?
|
||||
CPLWORD_ALLOCSTR :
|
||||
@@ -687,9 +737,11 @@ static enum fh_error fh_handle_quoted_string(
|
||||
uint32_t len32 = len;
|
||||
/* string is encoded as a special compiler command, the size,
|
||||
* and then the string, all 4-byte aligned. */
|
||||
memcpy(&fh->compile[addr], &instr, sizeof(struct fh_instruction_s));
|
||||
memcpy(&fh->compile[addr2], &len32, 4);
|
||||
memcpy(&fh->compile[addr2 + 4], &start, len);
|
||||
TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
|
||||
|
||||
TRY(fh_compile_reserve(fh, len + 4, &addr));
|
||||
fh_compile_write(fh, addr, &len32, 4);
|
||||
fh_compile_write(fh, addr + 4, start, len);
|
||||
}
|
||||
return FH_OK;
|
||||
}
|
||||
@@ -716,10 +768,9 @@ static enum fh_error fh_handle_word(
|
||||
// word found!
|
||||
if (fh->state == FH_STATE_COMPILE && !w->immediate) {
|
||||
LOG("Compile word call: %s", w->name);
|
||||
TRY(fh_compile_reserve(fh, sizeof(struct fh_instruction_s), &addr));
|
||||
instr.kind = FH_INSTR_WORD;
|
||||
instr.data = cnt;
|
||||
memcpy(&fh->compile[addr], &instr, sizeof(struct fh_instruction_s));
|
||||
TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
|
||||
} else {
|
||||
/* interpret */
|
||||
LOG("Interpret word: %s", w->name);
|
||||
@@ -743,10 +794,9 @@ static enum fh_error fh_handle_word(
|
||||
|
||||
if (fh->state == FH_STATE_COMPILE) {
|
||||
LOG("Compile number: %ld", v);
|
||||
TRY(fh_compile_reserve(fh, sizeof(struct fh_instruction_s), &addr));
|
||||
instr.kind = FH_INSTR_NUMBER;
|
||||
instr.data = (uint32_t) v;
|
||||
memcpy(&fh->compile[addr], &instr, sizeof(struct fh_instruction_s));
|
||||
TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
|
||||
} else {
|
||||
/* interpret */
|
||||
LOG("Interpret number: %ld", v);
|
||||
@@ -923,7 +973,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
rv = fh_process_line(&fh, linebuf);
|
||||
if (rv == FH_OK) {
|
||||
FHPRINT_SVC(" ok\r\n");
|
||||
FHPRINT_SVC(" ok\n");
|
||||
} else {
|
||||
LOGE("ERROR %s on line %d", fherr_name(rv), linecnt);
|
||||
if (!fh_globals.interactive) {
|
||||
@@ -934,6 +984,15 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
FHPRINT_SVC("Bye.\r\n");
|
||||
// Show resource usage
|
||||
LOG("\nResources used: DS %dW, RS %dW, CS %dW, heap %dB, program %dB, dict %dx\n",
|
||||
(int) fh.data_stack_hwm,
|
||||
(int) fh.return_stack_hwm,
|
||||
(int) fh.control_stack_hwm,
|
||||
(int) fh.heap_top,
|
||||
(int) fh.compile_top,
|
||||
(int) fh.dict_top);
|
||||
|
||||
FHPRINT_SVC("Bye.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user