aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis Lockwood2021-06-27 13:31:54 -0400
committerAlexis Lockwood2021-06-27 13:31:54 -0400
commit77bbb2d9595af3b2738b1a9845eeab63198e15cd (patch)
tree51359f2b88454f48487bbfc823c1092b392c61fd
parent4c54b23471f2da27660f86cfeccdb7916949fede (diff)
Stop tracking line numbers
-rw-r--r--README3
-rw-r--r--ls_run.c26
-rw-r--r--src/ls.c33
-rw-r--r--src/ls.h18
-rw-r--r--src/ls_expr.c2
-rw-r--r--src/ls_goto.c13
-rw-r--r--src/ls_internal.c1
-rw-r--r--src/ls_lex.c4
-rw-r--r--src/ls_types.h2
9 files changed, 65 insertions, 37 deletions
diff --git a/README b/README
index 8e3fa64..ef1bda8 100644
--- a/README
+++ b/README
@@ -50,9 +50,6 @@ Originally written by Alexis Lockwood in 2021. Ⓐ
- Fetcher (always execute in RAM)
- Delete GOFUN, it doesn't exist anymore
- Argument and return value support for GOSUB and RETURN
-- Stop tracking line number, it's getting too messy (esp with function calls,
- etc). It's only needed to report errors. We can just count it out in the
- error handler.
╒════════════════════════╕
│ THE SCRIPTING LANGUAGE │
diff --git a/ls_run.c b/ls_run.c
index 8691ef4..307b751 100644
--- a/ls_run.c
+++ b/ls_run.c
@@ -128,7 +128,6 @@ int main(int argc, char ** argv)
if (action == ACT_TOKENIZE)
{
ls_ctx.pc = 0;
- ls_ctx.line = 1;
ls_ctx.labels = NULL;
_tokenize(&ls_ctx);
exit(EXIT_SUCCESS);
@@ -137,15 +136,16 @@ int main(int argc, char ** argv)
ls_value_t pool[1000];
ls_error_t e = ls_run(&ls_ctx, pool, 1000);
+ uint16_t line = 0, col = 0;
+ ls_translate_pc(&ls_ctx, ls_ctx.pc, &line, &col);
+
if (e == LS_STOPPED)
{
- fprintf(stderr, ">stopped at line %u\n",
- ls_ctx.line);
+ fprintf(stderr, ">stopped at %u:%u\n", line, col);
}
else if (e != 0)
{
- fprintf(stderr, ">error %d at line %u\n",
- (int) e, ls_ctx.line);
+ fprintf(stderr, ">error %d at %u:%u\n", (int) e, line, col);
}
fclose(f);
@@ -159,8 +159,7 @@ int main(int argc, char ** argv)
{
ls_print_value(stdout, &pool[i], &pool[0]);
printf("\n");
- //if (pool[i].ty == LS_TY_PRISTINE)
- if (i == 10)
+ if (pool[i].ty == LS_TY_PRISTINE)
break;
}
}
@@ -258,8 +257,10 @@ static void _tokenize(ls_context_t * ctx)
if (setjmp(ctx->error_jmp_buf))
{
- fprintf(stderr, "error %d at line %"PRIu16"\n",
- (int) ctx->error, ctx->line);
+ uint16_t line = 0, col = 0;
+ ls_translate_pc(ctx, ctx->pc, &line, &col);
+ fprintf(stderr, "error %d at %u:%u",
+ (int) ctx->error, line, col);
exit(EXIT_FAILURE);
}
@@ -343,5 +344,10 @@ static void _tokenize(ls_context_t * ctx)
static void _line_trace_hook(ls_context_t * ctx)
{
- fprintf(stderr, ">line %"PRIu16"\n", ctx->line);
+ uint16_t line = 0, col = 0;
+ bool cachedebug_hold = cachedebug;
+ cachedebug = false;
+ ls_translate_pc(ctx, ctx->pc, &line, &col);
+ cachedebug = cachedebug_hold;
+ fprintf(stderr, ">line %"PRIu16"\n", line);
}
diff --git a/src/ls.c b/src/ls.c
index d6429e8..0f984fb 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -138,4 +138,37 @@ void ls_print_value(FILE * stream, ls_value_t * value, ls_value_t * first)
}
}
+bool ls_translate_pc(ls_context_t * ctx, ls_addr_t pc, uint16_t * line,
+ uint16_t * col)
+{
+ uint16_t n_line = 1, n_col = 1;
+ bool last_was_nl = false;
+
+ for (ls_addr_t i = 0; i <= pc; i++)
+ {
+ int f = ctx->fetcher(ctx->fetcher_ctx, i);
+
+ if (f <= 0)
+ return false;
+
+ ls_uchar uch = (ls_uchar) f;
+
+ if (last_was_nl)
+ {
+ n_line++;
+ n_col = 1;
+ }
+ else
+ {
+ n_col++;
+ }
+
+ last_was_nl = (uch == (ls_uchar) '\n');
+ }
+
+ *line = n_line;
+ *col = n_col;
+ return true;
+}
+
// --- PRIVATE FUNCTION DEFINITIONS --------------------------------------------
diff --git a/src/ls.h b/src/ls.h
index 2f6a4d3..75ff0f2 100644
--- a/src/ls.h
+++ b/src/ls.h
@@ -75,9 +75,6 @@ typedef struct ls_context_s {
/// Program counter
ls_addr_t pc;
- /// Current line number, 1-indexed
- uint16_t line;
-
/// 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;
@@ -105,6 +102,21 @@ typedef struct ls_context_s {
/// @param szpool - number of elements in @a pool
ls_error_t ls_run(ls_context_t * ctx, ls_value_t * pool, size_t szpool);
+/// Convert a program counter value to a line and column number. This is
+/// expensive and should only be called in rare cases (for example, printing
+/// out a line number in an error message).
+///
+/// @param ctx - context
+/// @param pc - program counter to look up
+/// @param[out] line - 1-based line number
+/// @param[out] col - 1-based column number
+/// @retval true - success
+/// @retval false - the PC doesn't exist
+///
+/// If the PC doesn't exist, @a line and @a col are unchanged.
+bool ls_translate_pc(ls_context_t * ctx, ls_addr_t pc, uint16_t * line,
+ uint16_t * col);
+
/// Print out a ls_value_t. For diagnostics.
///
/// @param stream - stream to print it into
diff --git a/src/ls_expr.c b/src/ls_expr.c
index 20eb787..f6bfd2a 100644
--- a/src/ls_expr.c
+++ b/src/ls_expr.c
@@ -157,7 +157,6 @@ void ls_eval_expr(ls_context_t * ctx, ls_value_t * val, ls_token_t * firsttok)
while (!done)
{
ls_addr_t pc_save = ctx->pc;
- uint16_t line_save = ctx->line;
ls_lex(ctx, &tok);
have_token:
@@ -190,7 +189,6 @@ have_token:
if (done) {
// Don't eat the token that ended the line
ctx->pc = pc_save;
- ctx->line = line_save;
}
}
diff --git a/src/ls_goto.c b/src/ls_goto.c
index ef0c9eb..1c198c3 100644
--- a/src/ls_goto.c
+++ b/src/ls_goto.c
@@ -30,7 +30,6 @@ static bool _rewind_line(ls_context_t * ctx);
void ls_goto_num(ls_context_t * ctx, bool backward, uint16_t num)
{
ls_addr_t target = LS_ADDR_NULL;
- uint16_t tline;
for (size_t i = 0; i < LS_LABEL_CACHE_SIZE; i++)
{
@@ -42,16 +41,14 @@ void ls_goto_num(ls_context_t * ctx, bool backward, uint16_t num)
(ctx->label_cache[i].pc <= ctx->pc && backward))
{
target = ctx->label_cache[i].pc;
- tline = ctx->label_cache[i].line;
break;
}
}
}
- // In case we can't find the label, save pc/line to "unwind" for a
+ // In case we can't find the label, save pc to "unwind" for a
// more helpful error later
ls_addr_t pc = ctx->pc;
- uint16_t line = ctx->line;
if (target == LS_ADDR_NULL && !backward)
{
@@ -66,7 +63,6 @@ void ls_goto_num(ls_context_t * ctx, bool backward, uint16_t num)
if (tok.body.number_val == num)
{
target = ctx->pc;
- tline = ctx->line;
break;
}
}
@@ -87,20 +83,17 @@ void ls_goto_num(ls_context_t * ctx, bool backward, uint16_t num)
// Quickly saving and restoring our location avoids
// a costly second rewind to undo the ls_lex().
ls_addr_t bw_pc = ctx->pc++;
- uint16_t bw_line = ctx->line++;
ls_lex(ctx, &tok);
if (tok.ty == LS_TOK_NUM_LABEL)
{
if (tok.body.number_val == num)
{
target = ctx->pc;
- tline = ctx->line;
break;
}
}
ctx->pc = bw_pc;
- ctx->line = bw_line;
}
}
@@ -108,13 +101,11 @@ void ls_goto_num(ls_context_t * ctx, bool backward, uint16_t num)
{
throw:
ctx->pc = pc;
- ctx->line = line;
ls_throw_err(ctx, LS_UNDEFINED_LABEL);
}
else
{
ctx->pc = target;
- ctx->line = tline;
}
}
@@ -161,7 +152,6 @@ void ls_goto_ident(ls_context_t * ctx, char const * ident)
ls_throw_err(ctx, LS_UNDEFINED_LABEL);
ctx->pc = label->body.label.pc;
- ctx->line = (uint16_t) (uintptr_t) label->prev;
}
// --- PRIVATE FUNCTION DEFINITIONS --------------------------------------------
@@ -180,7 +170,6 @@ static bool _rewind_line(ls_context_t * ctx)
if (ch == '\n')
{
ctx->pc = pc;
- --ctx->line;
return true;
}
diff --git a/src/ls_internal.c b/src/ls_internal.c
index 87873f2..8d63fa3 100644
--- a/src/ls_internal.c
+++ b/src/ls_internal.c
@@ -73,7 +73,6 @@ void ls_init_ctx(ls_context_t * ctx, ls_value_t * pool, size_t szpool)
ctx->funcs = NULL;
ctx->labels = NULL;
ctx->pc = 0;
- ctx->line = 1;
ctx->stop = false;
for (size_t i = 0; i < LS_LABEL_CACHE_SIZE; i++)
diff --git a/src/ls_lex.c b/src/ls_lex.c
index f8ff0d0..186e789 100644
--- a/src/ls_lex.c
+++ b/src/ls_lex.c
@@ -103,8 +103,6 @@ void ls_lex(ls_context_t * ctx, ls_token_t * tok)
break;
case CH_KIND_LINESEP:
- ctx->line++;
- // fall through
case CH_KIND_SEP:
tok->ty = LS_TOK_STATEMENT_SEP;
break;
@@ -312,7 +310,6 @@ static void _lex_num(ls_context_t * ctx, ls_token_t * tok, ls_uchar ch[2])
ls_label_cache_t * lc
= &ctx->label_cache[ctx->label_cache_i];
lc->pc = (ls_addr_t)(ctx->pc + 1);
- lc->line = ctx->line;
lc->num = (ls_addr_t)(tok->body.number_val);
tok->ty = LS_TOK_NUM_LABEL;
}
@@ -399,7 +396,6 @@ static void _lex_word(ls_context_t * ctx, ls_token_t * tok, ls_uchar ch[2])
strncpy(label->body.label.ident, tok->body.word_val,
LS_IDENT_LEN);
label->body.label.pc = ctx->pc;
- label->prev = (void *) (uintptr_t) ctx->line;
ctx->labels = label;
}
}
diff --git a/src/ls_types.h b/src/ls_types.h
index 567b926..9df404e 100644
--- a/src/ls_types.h
+++ b/src/ls_types.h
@@ -205,7 +205,6 @@ typedef struct ls_value_s {
/// Internal types:
/// - Stack frames: PREV points at the stack frame above this one.
/// NEXT points at the variable scope.
- /// - Labels: PREV contains a line number cast to a pointer (sorry)
/// - Others: as defined in those types' documentation.
struct ls_value_s * prev, * next;
union {
@@ -231,7 +230,6 @@ typedef struct ls_value_s {
/// needing to scan the code.
typedef struct {
ls_addr_t pc;
- uint16_t line;
uint16_t num;
} ls_label_cache_t;