diff options
author | Alexis Lockwood | 2021-06-27 12:29:24 -0400 |
---|---|---|
committer | Alexis Lockwood | 2021-06-27 12:29:24 -0400 |
commit | 1372bb72db0dfbdf9ac51f8604f8d8b57b2d4946 (patch) | |
tree | 72b73672b80d11461249822a6b7c1c08b7df5c2d | |
parent | 4a043e4c9980fd5180be3fe22144978742e7c3d0 (diff) |
Implement END and ctx.stop
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | ls_run.c | 9 | ||||
-rw-r--r-- | src/ls.c | 8 | ||||
-rw-r--r-- | src/ls.h | 24 | ||||
-rw-r--r-- | src/ls_internal.c | 1 | ||||
-rw-r--r-- | src/ls_kw_impl.c | 9 | ||||
-rw-r--r-- | src/ls_types.h | 1 |
7 files changed, 38 insertions, 15 deletions
@@ -39,7 +39,6 @@ Originally written by Alexis Lockwood in 2021. Ⓐ - Non-integer variable types - String will always be supported - Floating point as optional compile-in -- External abort mechanism - Better testing - Compile-time options for: - Internal asserts for better LS_INTERNAL_ERROR info @@ -137,9 +137,14 @@ int main(int argc, char ** argv) ls_value_t pool[1000]; ls_error_t e = ls_run(&ls_ctx, pool, 1000); - if (e != 0) + if (e == LS_STOPPED) { - fprintf(stderr, "Error %d at line %u\n", + fprintf(stderr, ">stopped at line %u\n", + ls_ctx.line); + } + else if (e != 0) + { + fprintf(stderr, ">error %d at line %u\n", (int) e, ls_ctx.line); } @@ -34,9 +34,13 @@ ls_error_t ls_run(ls_context_t * ctx, ls_value_t * pool, size_t szpool) ls_init_ctx(ctx, pool, szpool); - while (ls_exec_line(ctx)); + while (!ctx->stop) + { + if (!ls_exec_line(ctx)) + return LS_OK; + } - return LS_OK; + return LS_STOPPED; } #define TO_POOL_N(p) (p ? "" : "----"), \ @@ -41,6 +41,22 @@ struct ls_context_s; /// Main LS execution context struct. typedef struct ls_context_s { + /// Fetcher to retrieve data. See ls_run(). + ls_fetcher_t fetcher; + + /// Context for fetcher + void * fetcher_ctx; + + /// Line trace hook. If not null, this will be called for each line. + void (*line_trace_hook)(struct ls_context_s * ctx); + + /// Set true to stop execution on the next line. The interpreter will + /// exit with error LS_STOPPED. Note that LS_STOPPED is also given if + /// the interpreter encounters the END statement. + bool stop; + + // --------- end items relevant to the user --------- + /// Execution stack. ls_value_t * callstack; @@ -62,14 +78,6 @@ typedef struct ls_context_s { /// Current line number, 1-indexed uint16_t line; - /// Fetcher to retrieve data. See ls_run(). - ls_fetcher_t fetcher; - /// Context for fetcher - void * fetcher_ctx; - - /// Line trace hook. If not null, this will be called for each line. - void (*line_trace_hook)(struct ls_context_s * ctx); - /// Top error-handling jmpbuf. When the interpreter encounters an error, /// it should store the error code in .error and jump here. jmp_buf error_jmp_buf; diff --git a/src/ls_internal.c b/src/ls_internal.c index 3027a14..87873f2 100644 --- a/src/ls_internal.c +++ b/src/ls_internal.c @@ -74,6 +74,7 @@ void ls_init_ctx(ls_context_t * ctx, ls_value_t * pool, size_t szpool) ctx->labels = NULL; ctx->pc = 0; ctx->line = 1; + ctx->stop = false; for (size_t i = 0; i < LS_LABEL_CACHE_SIZE; i++) ctx->label_cache[i].pc = LS_ADDR_NULL; diff --git a/src/ls_kw_impl.c b/src/ls_kw_impl.c index ce22cbf..d11e932 100644 --- a/src/ls_kw_impl.c +++ b/src/ls_kw_impl.c @@ -43,14 +43,19 @@ void ls_kw_fun_COUNT(ls_context_t * ctx) { _no_impl(ctx); } void ls_kw_fun_DATA(ls_context_t * ctx) { _no_impl(ctx); } void ls_kw_fun_DEC(ls_context_t * ctx) { _no_impl(ctx); } void ls_kw_fun_DEF(ls_context_t * ctx) { _no_impl(ctx); } -void ls_kw_fun_END(ls_context_t * ctx) { _no_impl(ctx); } + +void ls_kw_fun_END(ls_context_t * ctx) { ls_throw_err(ctx, LS_STOPPED); } + void ls_kw_fun_EQV(ls_context_t * ctx) { _no_impl(ctx); } void ls_kw_fun_ERASE(ls_context_t * ctx) { _no_impl(ctx); } void ls_kw_fun_ERROR(ls_context_t * ctx) { _no_impl(ctx); } void ls_kw_fun_FN(ls_context_t * ctx) { _no_impl(ctx); } void ls_kw_fun_FOR(ls_context_t * ctx) { _no_impl(ctx); } void ls_kw_fun_GOFUN(ls_context_t * ctx) { _no_impl(ctx); } -void ls_kw_fun_GOSUB(ls_context_t * ctx) { _no_impl(ctx); } +void ls_kw_fun_GOSUB(ls_context_t * ctx) { + ls_token_t tok; + ls_lex(ctx, &tok); + return; _no_impl(ctx); } void ls_kw_fun_HEX(ls_context_t * ctx) { _no_impl(ctx); } void ls_kw_fun_IF(ls_context_t * ctx) { diff --git a/src/ls_types.h b/src/ls_types.h index 1b3f111..8296bc2 100644 --- a/src/ls_types.h +++ b/src/ls_types.h @@ -276,6 +276,7 @@ typedef enum { LS_PATH_NOT_FOUND, LS_UNDEFINED_VARIABLE, LS_BAD_KEYWORD, /// Keyword not valid here + LS_STOPPED, /// To be returned by a fetcher if there is no more data. This is not /// strictly an error condition; the parser should be allowed to read |