fixes and more comments, cleaning

master
Ondřej Hruška 3 years ago
parent 15848e203b
commit 6f9ffc7d20
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      hello.forth
  2. 109
      main.c

@ -1,2 +1,4 @@
: hi ." Hello, World!" ; : hi ." Hello, World!" ;
hi hi
: hi2 s" Hello, World!" TYPE ;
hi2

109
main.c

@ -43,9 +43,9 @@ _Static_assert(WORDALIGNED(1023) == 1024, "word align");
_Static_assert(WORDALIGNED(1024) == 1024, "word align"); _Static_assert(WORDALIGNED(1024) == 1024, "word align");
/* logging */ /* logging */
#define LOG(format, ...) do { if(fh_globals.verbose) { fprintf(stderr, format "\r\n", ##__VA_ARGS__); } } while (0) #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\r\n", ##__VA_ARGS__) #define LOGI(format, ...) fprintf(stderr, "\x1b[32m" format "\x1b[m\n", ##__VA_ARGS__)
#define LOGE(format, ...) fprintf(stderr, "\x1b[31;1m" format "\x1b[m\r\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 */ /* 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(format, ...) fprintf(stderr, "\x1b[33;1m" format "\x1b[m", ##__VA_ARGS__)
#define FHPRINT_SVC(format, ...) fprintf(stderr, "" format "", ##__VA_ARGS__) #define FHPRINT_SVC(format, ...) fprintf(stderr, "" format "", ##__VA_ARGS__)
@ -136,6 +136,8 @@ struct fh_instruction_s {
uint32_t data; uint32_t data;
}; };
#define INSTR_SIZE (sizeof(struct fh_instruction_s))
/** Bytecode word indices that are not in the dict, have special effect */ /** Bytecode word indices that are not in the dict, have special effect */
enum compiler_word { enum compiler_word {
/** End of a user defined word, pop address and jump back */ /** End of a user defined word, pop address and jump back */
@ -194,14 +196,17 @@ struct fh_thread_s {
/** Control stack */ /** Control stack */
uint32_t control_stack[CONTROL_STACK_DEPTH]; uint32_t control_stack[CONTROL_STACK_DEPTH];
size_t control_stack_top; size_t control_stack_top;
size_t control_stack_hwm;
/** Data stack */ /** Data stack */
uint32_t data_stack[DATA_STACK_DEPTH]; uint32_t data_stack[DATA_STACK_DEPTH];
size_t data_stack_top; size_t data_stack_top;
size_t data_stack_hwm;
/** Return stack */ /** Return stack */
uint32_t return_stack[RETURN_STACK_DEPTH]; uint32_t return_stack[RETURN_STACK_DEPTH];
size_t return_stack_top; size_t return_stack_top;
size_t return_stack_hwm;
/** Data heap */ /** Data heap */
uint8_t heap[HEAP_SIZE]; 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; return FH_OK;
} }
#define UPDATE_HWM(hwm, top) \
do { \
if((hwm) < (top)) { \
(hwm) = (top); \
} \
} while(0)
/** Push to data stack */ /** Push to data stack */
static inline enum fh_error ds_push(struct fh_thread_s *fh, uint32_t in) 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; return FH_ERR_DS_OVERFLOW;
} }
fh->data_stack[fh->data_stack_top++] = in; fh->data_stack[fh->data_stack_top++] = in;
UPDATE_HWM(fh->data_stack_hwm, fh->data_stack_top);
return FH_OK; 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; return FH_ERR_RS_OVERFLOW;
} }
fh->return_stack[fh->return_stack_top++] = in; fh->return_stack[fh->return_stack_top++] = in;
UPDATE_HWM(fh->return_stack_hwm, fh->return_stack_top);
return FH_OK; 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; return FH_ERR_CS_OVERFLOW;
} }
fh->control_stack[fh->control_stack_top++] = in; fh->control_stack[fh->control_stack_top++] = in;
UPDATE_HWM(fh->control_stack_hwm, fh->control_stack_top);
return FH_OK; return FH_OK;
} }
@ -357,6 +372,28 @@ enum fh_error fh_heap_reserve(
return FH_OK; 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 */ /** Reserve space in the compile memory area */
enum fh_error fh_compile_reserve( enum fh_error fh_compile_reserve(
struct fh_thread_s *fh, struct fh_thread_s *fh,
@ -377,6 +414,22 @@ enum fh_error fh_compile_reserve(
return FH_OK; 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 w_add(struct fh_thread_s *fh)
{ {
enum fh_error rv; enum fh_error rv;
@ -442,17 +495,18 @@ enum fh_error w_user_word(struct fh_thread_s *fh)
case CPLWORD_ALLOCSTR: case CPLWORD_ALLOCSTR:
case CPLWORD_TYPESTR: case CPLWORD_TYPESTR:
strl = *((uint32_t *) &fh->compile[fh->execptr]); 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) { if (wn == CPLWORD_ALLOCSTR) {
TRY(fh_heap_reserve(fh, strl, &addr)); 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]); LOG("Exec: alloc-str \"%.*s\"", strl, &fh->heap[addr]);
TRY(ds_push(fh, addr)); TRY(ds_push(fh, addr));
TRY(ds_push(fh, strl)); TRY(ds_push(fh, strl));
fh->execptr += strl; fh->execptr += strl;
} else { } else {
FHPRINT("%.*s", (int) strl, &fh->compile[fh->execptr]); 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; goto instr;
@ -508,10 +562,9 @@ enum fh_error w_semicolon(struct fh_thread_s *fh)
return FH_ERR_INVALID_STATE; return FH_ERR_INVALID_STATE;
} }
TRY(fh_compile_reserve(fh, sizeof(struct fh_instruction_s), &addr));
instr.kind = FH_INSTR_WORD; instr.kind = FH_INSTR_WORD;
instr.data = CPLWORD_ENDWORD; 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 */ /* Return to interpret state */
fh_setstate(fh, FH_STATE_INTERPRET, 0); 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) enum fh_error w_cr(struct fh_thread_s *fh)
{ {
(void) fh; (void) fh;
FHPRINT("\r\n"); FHPRINT("\n");
return FH_OK; return FH_OK;
} }
@ -595,8 +648,8 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh)
}; };
const struct name_and_handler builtins[] = { const struct name_and_handler builtins[] = {
{"s\"", w_s_quote}, {"s\"", w_s_quote, 1},
{".\"", w_dot_quote}, {".\"", w_dot_quote, 1},
/* Compiler control words */ /* Compiler control words */
{"bye", w_bye}, {"bye", w_bye},
/* Basic arithmetics */ /* Basic arithmetics */
@ -658,14 +711,12 @@ static enum fh_error fh_handle_quoted_string(
{ {
enum fh_error rv; enum fh_error rv;
uint32_t addr = 0; uint32_t addr = 0;
uint32_t addr2 = 0;
struct fh_instruction_s instr; struct fh_instruction_s instr;
if (fh->state == FH_STATE_INTERPRET) { if (fh->state == FH_STATE_INTERPRET) {
switch (fh->substate) { switch (fh->substate) {
case FH_SUBSTATE_SQUOTE: case FH_SUBSTATE_SQUOTE:
TRY(fh_heap_reserve(fh, len, &addr)); TRY(fh_heap_put(fh, start, len));
memcpy(&fh->heap[addr], start, len);
TRY(ds_push(fh, addr)); TRY(ds_push(fh, addr));
TRY(ds_push(fh, len)); TRY(ds_push(fh, len));
break; break;
@ -677,9 +728,8 @@ static enum fh_error fh_handle_quoted_string(
LOGE("Bad substate in interpret mode: %s", substatenames[fh->substate]); LOGE("Bad substate in interpret mode: %s", substatenames[fh->substate]);
} }
} else { } else {
LOG("Compile a string");
/* compile */ /* 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.kind = FH_INSTR_WORD;
instr.data = fh->substate == FH_SUBSTATE_SQUOTE ? instr.data = fh->substate == FH_SUBSTATE_SQUOTE ?
CPLWORD_ALLOCSTR : CPLWORD_ALLOCSTR :
@ -687,9 +737,11 @@ static enum fh_error fh_handle_quoted_string(
uint32_t len32 = len; uint32_t len32 = len;
/* string is encoded as a special compiler command, the size, /* string is encoded as a special compiler command, the size,
* and then the string, all 4-byte aligned. */ * and then the string, all 4-byte aligned. */
memcpy(&fh->compile[addr], &instr, sizeof(struct fh_instruction_s)); TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
memcpy(&fh->compile[addr2], &len32, 4);
memcpy(&fh->compile[addr2 + 4], &start, len); 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; return FH_OK;
} }
@ -716,10 +768,9 @@ static enum fh_error fh_handle_word(
// word found! // word found!
if (fh->state == FH_STATE_COMPILE && !w->immediate) { if (fh->state == FH_STATE_COMPILE && !w->immediate) {
LOG("Compile word call: %s", w->name); LOG("Compile word call: %s", w->name);
TRY(fh_compile_reserve(fh, sizeof(struct fh_instruction_s), &addr));
instr.kind = FH_INSTR_WORD; instr.kind = FH_INSTR_WORD;
instr.data = cnt; instr.data = cnt;
memcpy(&fh->compile[addr], &instr, sizeof(struct fh_instruction_s)); TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
} else { } else {
/* interpret */ /* interpret */
LOG("Interpret word: %s", w->name); LOG("Interpret word: %s", w->name);
@ -743,10 +794,9 @@ static enum fh_error fh_handle_word(
if (fh->state == FH_STATE_COMPILE) { if (fh->state == FH_STATE_COMPILE) {
LOG("Compile number: %ld", v); LOG("Compile number: %ld", v);
TRY(fh_compile_reserve(fh, sizeof(struct fh_instruction_s), &addr));
instr.kind = FH_INSTR_NUMBER; instr.kind = FH_INSTR_NUMBER;
instr.data = (uint32_t) v; instr.data = (uint32_t) v;
memcpy(&fh->compile[addr], &instr, sizeof(struct fh_instruction_s)); TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
} else { } else {
/* interpret */ /* interpret */
LOG("Interpret number: %ld", v); LOG("Interpret number: %ld", v);
@ -923,7 +973,7 @@ int main(int argc, char *argv[])
rv = fh_process_line(&fh, linebuf); rv = fh_process_line(&fh, linebuf);
if (rv == FH_OK) { if (rv == FH_OK) {
FHPRINT_SVC(" ok\r\n"); FHPRINT_SVC(" ok\n");
} else { } else {
LOGE("ERROR %s on line %d", fherr_name(rv), linecnt); LOGE("ERROR %s on line %d", fherr_name(rv), linecnt);
if (!fh_globals.interactive) { 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; return 0;
} }

Loading…
Cancel
Save