aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis Lockwood2021-06-27 12:29:24 -0400
committerAlexis Lockwood2021-06-27 12:29:24 -0400
commit1372bb72db0dfbdf9ac51f8604f8d8b57b2d4946 (patch)
tree72b73672b80d11461249822a6b7c1c08b7df5c2d
parent4a043e4c9980fd5180be3fe22144978742e7c3d0 (diff)
Implement END and ctx.stop
-rw-r--r--README1
-rw-r--r--ls_run.c9
-rw-r--r--src/ls.c8
-rw-r--r--src/ls.h24
-rw-r--r--src/ls_internal.c1
-rw-r--r--src/ls_kw_impl.c9
-rw-r--r--src/ls_types.h1
7 files changed, 38 insertions, 15 deletions
diff --git a/README b/README
index c10b526..e131861 100644
--- a/README
+++ b/README
@@ -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
diff --git a/ls_run.c b/ls_run.c
index 7468a32..28ad4f6 100644
--- a/ls_run.c
+++ b/ls_run.c
@@ -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);
}
diff --git a/src/ls.c b/src/ls.c
index e265ac4..1ad8f29 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -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 ? "" : "----"), \
diff --git a/src/ls.h b/src/ls.h
index 9b1971b..2f6a4d3 100644
--- a/src/ls.h
+++ b/src/ls.h
@@ -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