From 6f9ffc7d20adb8ee46e6191834d308dc3d90fc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 13 Nov 2021 16:28:52 +0100 Subject: [PATCH] fixes and more comments, cleaning --- hello.forth | 2 + main.c | 109 ++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/hello.forth b/hello.forth index b8748e8..085ccd2 100644 --- a/hello.forth +++ b/hello.forth @@ -1,2 +1,4 @@ : hi ." Hello, World!" ; hi +: hi2 s" Hello, World!" TYPE ; +hi2 diff --git a/main.c b/main.c index aef14e7..4c66b7d 100644 --- a/main.c +++ b/main.c @@ -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; }