wip: working on loop infinity checker

This commit is contained in:
samsonium
2026-10-22 18:25:07 +03:00
parent cc5bbd61f2
commit 5dde75523d
3 changed files with 73 additions and 0 deletions
+1
View File
@@ -25,6 +25,7 @@ add_executable(fzc
src/compiler/utils/fzl_linked.c
src/compiler/utils/fzl_options.c
src/compiler/utils/fzl_ctable.c
src/compiler/checkers/fzl_loop_check.c
src/compiler/main.c)
# Virtual machine
+60
View File
@@ -0,0 +1,60 @@
#include <common/fzl_opcodes.h>
#include <common/fzl_types.h>
#include <compiler/fzl_parser.h>
#include <compiler/fzl_walker.h>
#include <compiler/utils/fzl_const_pool.h>
#include <compiler/utils/fzl_symtable.h>
#include <stdbool.h>
#include <stdint.h>
// Check for infinite loop
bool is_infinite_loop(fzl_walker_t *walker, size_t start_ip, size_t end_ip)
{
if (!walker)
return false;
end_ip = (end_ip >= walker->op_count) ? (walker->op_count - 1) : end_ip;
// Can we determine an init block?
size_t maybe_init_start = start_ip + 1;
size_t maybe_init_end = start_ip + 6;
fzl_const_t *declared = NULL;
for (size_t i = maybe_init_start; i <= maybe_init_end; i++)
{
if (walker->ops[i] != FZL_OPCODE_STORE)
continue;
declared = &walker->consts->array[walker->ops[i - 1]];
break;
}
if (declared)
{
fzl_sym_t sym;
bool found = false;
for (ssize_t i = walker->sym_top - 1; i >= 0; i--)
if ((found = fzl_symt_get(walker->syms[i],
(char *)declared->as.string.chars, &sym)))
break;
if (!found)
return false; // suspicious
if (sym.type >= FZL_TYPE_INT8)
{
}
}
// At least has jump outside
for (size_t i = start_ip; i <= end_ip; i++)
{
if (walker->ops[i] != FZL_OPCODE_JMP)
continue;
size_t jump_ip = walker->ops[++i];
if (jump_ip >= end_ip)
return false;
}
return true;
}
+12
View File
@@ -14,6 +14,8 @@
#include <stdlib.h>
#include <string.h>
extern bool is_infinite_loop(fzl_walker_t *walker, size_t ls, size_t le);
char *null_name = "<null>";
char wlast_err[256];
@@ -271,6 +273,16 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
push_word(walker, start_ip);
push_op(walker, FZL_OPCODE_RM_ENVTABLE);
bool is_infinite =
is_infinite_loop(walker, start_ip, walker->op_count - 2);
if (is_infinite)
{
snprintf(wlast_err, sizeof(wlast_err),
"'%s': infinite loop detected at %ld:%ld",
node->token->filename, node->token->ln, node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
for (size_t i = walker->sym_top - 1; i > newctx->initial_env_lvl; i--)
fzl_freesymt(walker->syms[--walker->sym_top]);