feat: implement format strings
This commit is contained in:
@@ -5,6 +5,7 @@ skip is
|
|||||||
skip -rfunction fzl_mk*
|
skip -rfunction fzl_mk*
|
||||||
skip -rfunction fzl_free*
|
skip -rfunction fzl_free*
|
||||||
skip -rfunction fzl_symt*
|
skip -rfunction fzl_symt*
|
||||||
|
skip -rfunction fzl_linked*
|
||||||
skip add_const
|
skip add_const
|
||||||
skip push_op
|
skip push_op
|
||||||
skip push_word
|
skip push_word
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ typedef enum
|
|||||||
FZL_OPCODE_MOD = 0xA00006, // Get module of two numbers in dstack
|
FZL_OPCODE_MOD = 0xA00006, // Get module of two numbers in dstack
|
||||||
FZL_OPCODE_NEG = 0xA00007, // Negotiate number in dstack
|
FZL_OPCODE_NEG = 0xA00007, // Negotiate number in dstack
|
||||||
|
|
||||||
|
FZL_OPCODE_BUILD_STR = 0xA10001, // Build a string from N values in dstack
|
||||||
|
|
||||||
FZL_OPCODE_CMP_EQ = 0xB00001, // Equal
|
FZL_OPCODE_CMP_EQ = 0xB00001, // Equal
|
||||||
FZL_OPCODE_CMP_NEQ = 0xB00002, // Not equal
|
FZL_OPCODE_CMP_NEQ = 0xB00002, // Not equal
|
||||||
FZL_OPCODE_CMP_LT = 0xB00003, // Less than
|
FZL_OPCODE_CMP_LT = 0xB00003, // Less than
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ typedef enum
|
|||||||
FZL_NODETYPE_BLOCK,
|
FZL_NODETYPE_BLOCK,
|
||||||
FZL_NODETYPE_CALL,
|
FZL_NODETYPE_CALL,
|
||||||
FZL_NODETYPE_LITERAL,
|
FZL_NODETYPE_LITERAL,
|
||||||
|
FZL_NODETYPE_FMT_STRING,
|
||||||
FZL_NODETYPE_IDENTIFIER,
|
FZL_NODETYPE_IDENTIFIER,
|
||||||
FZL_NODETYPE_CONDITIONAL,
|
FZL_NODETYPE_CONDITIONAL,
|
||||||
FZL_NODETYPE_FUNCTION,
|
FZL_NODETYPE_FUNCTION,
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ typedef enum
|
|||||||
FZL_TOKTYPE_BOOL_LITERAL, // true
|
FZL_TOKTYPE_BOOL_LITERAL, // true
|
||||||
FZL_TOKTYPE_NULL_LITERAL, // null
|
FZL_TOKTYPE_NULL_LITERAL, // null
|
||||||
|
|
||||||
|
FZL_TOKTYPE_STR_FORMAT_START, // `$` before `"`
|
||||||
|
FZL_TOKTYPE_STR_FORMAT_END, // end of string formatting sequence
|
||||||
|
|
||||||
FZL_TOKTYPE_DAMPERSAND, // &&
|
FZL_TOKTYPE_DAMPERSAND, // &&
|
||||||
FZL_TOKTYPE_DVBAR, // ||
|
FZL_TOKTYPE_DVBAR, // ||
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,26 @@ void print_node(fzl_node_t *node, int level)
|
|||||||
|
|
||||||
switch (node->type)
|
switch (node->type)
|
||||||
{
|
{
|
||||||
|
case FZL_NODETYPE_UNARY_MINUS:
|
||||||
|
printf("%s Unary '-':\n", levelbuf);
|
||||||
|
print_node(node->unary_op.operand, level + 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_NODETYPE_UNARY_PLUS:
|
||||||
|
printf("%s Unary '+':\n", levelbuf);
|
||||||
|
print_node(node->unary_op.operand, level + 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_NODETYPE_BREAK:
|
||||||
|
printf("%s Break\n", levelbuf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_NODETYPE_FMT_STRING:
|
||||||
|
printf("%s Format string:\n", levelbuf);
|
||||||
|
for (size_t i = 0; i < node->list.entry_count; i++)
|
||||||
|
print_node(node->list.entries[i], level + 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case FZL_NODETYPE_LOOP:
|
case FZL_NODETYPE_LOOP:
|
||||||
printf("%s Loop:\n", levelbuf);
|
printf("%s Loop:\n", levelbuf);
|
||||||
printf("-%s Init:\n", levelbuf);
|
printf("-%s Init:\n", levelbuf);
|
||||||
@@ -172,9 +192,6 @@ void print_node(fzl_node_t *node, int level)
|
|||||||
case FZL_NODETYPE_IDENTIFIER:
|
case FZL_NODETYPE_IDENTIFIER:
|
||||||
printf("%s Identifier ('%s')\n", levelbuf, (char *)node->token->value);
|
printf("%s Identifier ('%s')\n", levelbuf, (char *)node->token->value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
printf("%s Secure node\n", levelbuf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,91 @@ fzl_node_t *parse_primary(fzl_parser_t *parser)
|
|||||||
fzl_token_t *tok = consume(parser);
|
fzl_token_t *tok = consume(parser);
|
||||||
return fzl_mknode(FZL_NODETYPE_LITERAL, tok);
|
return fzl_mknode(FZL_NODETYPE_LITERAL, tok);
|
||||||
}
|
}
|
||||||
|
else if (is(parser, FZL_TOKTYPE_STR_FORMAT_START))
|
||||||
|
{
|
||||||
|
consume(parser);
|
||||||
|
|
||||||
|
size_t remainder = 2;
|
||||||
|
size_t count = 0;
|
||||||
|
fzl_node_t **entries = malloc(remainder * sizeof(fzl_node_t *));
|
||||||
|
if (!entries)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (peek(parser) && peek(parser)->type != FZL_TOKTYPE_STR_FORMAT_END)
|
||||||
|
{
|
||||||
|
if (remainder <= count)
|
||||||
|
{
|
||||||
|
remainder *= 2;
|
||||||
|
entries = realloc(entries, remainder * sizeof(fzl_node_t *));
|
||||||
|
if (!entries)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is(parser, FZL_TOKTYPE_STR_FORMAT_END))
|
||||||
|
break;
|
||||||
|
|
||||||
|
fzl_node_t *expr = parse_expression(parser);
|
||||||
|
if (!expr)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
fzl_freeast(entries[i]);
|
||||||
|
|
||||||
|
free(entries);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries[count++] = expr;
|
||||||
|
}
|
||||||
|
fzl_token_t *end = consume(parser);
|
||||||
|
if (end->type != FZL_TOKTYPE_STR_FORMAT_END)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"'%s':%zu:%zu => unterminated format string",
|
||||||
|
last_known_tok->filename, last_known_tok->ln,
|
||||||
|
last_known_tok->cn);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
fzl_freeast(entries[i]);
|
||||||
|
|
||||||
|
free(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count < 1)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"'%s':%zu:%zu => do you really need empty format string?",
|
||||||
|
last_known_tok->filename, last_known_tok->ln,
|
||||||
|
last_known_tok->cn);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
fzl_freeast(entries[i]);
|
||||||
|
|
||||||
|
free(entries);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FMT_STRING, entries[0]->token);
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
fzl_freeast(entries[i]);
|
||||||
|
|
||||||
|
free(entries);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->list.entries = entries;
|
||||||
|
node->list.entry_count = count;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
else if (is(parser, FZL_TOKTYPE_LPAREN))
|
else if (is(parser, FZL_TOKTYPE_LPAREN))
|
||||||
{
|
{
|
||||||
consume(parser);
|
consume(parser);
|
||||||
@@ -1308,6 +1393,7 @@ void fzl_freeast(fzl_node_t *root)
|
|||||||
case FZL_NODETYPE_LITERAL:
|
case FZL_NODETYPE_LITERAL:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FZL_NODETYPE_FMT_STRING:
|
||||||
case FZL_NODETYPE_BLOCK:
|
case FZL_NODETYPE_BLOCK:
|
||||||
if (root->list.entries)
|
if (root->list.entries)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -251,11 +251,83 @@ void skip_comment(fzl_reader_t *reader)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse string format
|
||||||
|
fzl_token_t *parse_fmtstring_part(fzl_reader_t *reader)
|
||||||
|
{
|
||||||
|
size_t p = reader->position;
|
||||||
|
char *src = reader->source;
|
||||||
|
|
||||||
|
fzl_file_loc l;
|
||||||
|
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src[p] == '{')
|
||||||
|
{
|
||||||
|
move(reader, 1);
|
||||||
|
fzl_token_t *id = parse_name(reader);
|
||||||
|
|
||||||
|
if (id == NULL || src[reader->position] != '}')
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"'%s':%zu:%zu => failed to parse format string", l.filename,
|
||||||
|
l.line, l.col);
|
||||||
|
fzl_freetoken(id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
move(reader, 1);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src[p] == '"')
|
||||||
|
{
|
||||||
|
move(reader, 1);
|
||||||
|
|
||||||
|
return fzl_mktoken(FZL_TOKTYPE_STR_FORMAT_END, l.line, l.col, NULL, 0,
|
||||||
|
l.filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = 0;
|
||||||
|
size_t lpos = p;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (src[lpos + 1] == '"')
|
||||||
|
break;
|
||||||
|
|
||||||
|
size++;
|
||||||
|
lpos++;
|
||||||
|
} while (lpos < reader->size && reader->source[lpos] != '{' &&
|
||||||
|
reader->source[lpos] != '"');
|
||||||
|
|
||||||
|
ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *value = malloc(size);
|
||||||
|
memcpy(value, reader->source + reader->position, size);
|
||||||
|
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, value,
|
||||||
|
size, l.filename);
|
||||||
|
free(value);
|
||||||
|
move(reader, size);
|
||||||
|
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
int fzl_read(fzl_reader_t *reader)
|
int fzl_read(fzl_reader_t *reader)
|
||||||
{
|
{
|
||||||
if (reader->position >= reader->size)
|
if (reader->position >= reader->size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bool is_format_str = false;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
size_t p = reader->position;
|
size_t p = reader->position;
|
||||||
@@ -268,7 +340,13 @@ int fzl_read(fzl_reader_t *reader)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curr == '\'' || curr == '"')
|
if (is_format_str)
|
||||||
|
{
|
||||||
|
token = parse_fmtstring_part(reader);
|
||||||
|
if (token && token->type == FZL_TOKTYPE_STR_FORMAT_END)
|
||||||
|
is_format_str = false;
|
||||||
|
}
|
||||||
|
else if (curr == '\'' || curr == '"')
|
||||||
token = parse_string_literal(reader);
|
token = parse_string_literal(reader);
|
||||||
else if (curr == '/' && reader->source[p + 1] == '/')
|
else if (curr == '/' && reader->source[p + 1] == '/')
|
||||||
{
|
{
|
||||||
@@ -321,6 +399,12 @@ int fzl_read(fzl_reader_t *reader)
|
|||||||
token = add_single(reader, FZL_TOKTYPE_PERCENT);
|
token = add_single(reader, FZL_TOKTYPE_PERCENT);
|
||||||
else if (curr == '=')
|
else if (curr == '=')
|
||||||
token = add_single(reader, FZL_TOKTYPE_EQ);
|
token = add_single(reader, FZL_TOKTYPE_EQ);
|
||||||
|
else if (curr == '$' && reader->source[p + 1] == '"')
|
||||||
|
{
|
||||||
|
move(reader, 2);
|
||||||
|
is_format_str = true;
|
||||||
|
token = fzl_mktoken(FZL_TOKTYPE_STR_FORMAT_START, 0, 0, NULL, 0, "");
|
||||||
|
}
|
||||||
else if ((curr >= 'A' && curr <= 'Z') || (curr >= 'a' && curr <= 'z') ||
|
else if ((curr >= 'A' && curr <= 'Z') || (curr >= 'a' && curr <= 'z') ||
|
||||||
curr == '_')
|
curr == '_')
|
||||||
token = parse_name(reader);
|
token = parse_name(reader);
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ fzl_token_t *fzl_mktoken(const fzl_toktype_t type, size_t line, size_t col,
|
|||||||
// Free allocated token
|
// Free allocated token
|
||||||
void fzl_freetoken(fzl_token_t *tok)
|
void fzl_freetoken(fzl_token_t *tok)
|
||||||
{
|
{
|
||||||
|
if (!tok)
|
||||||
|
return;
|
||||||
|
|
||||||
if (tok->store_value)
|
if (tok->store_value)
|
||||||
free(tok->value);
|
free(tok->value);
|
||||||
|
|
||||||
free(tok);
|
free(tok);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,6 +203,20 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
|
|||||||
{
|
{
|
||||||
switch (node->type)
|
switch (node->type)
|
||||||
{
|
{
|
||||||
|
case FZL_NODETYPE_FMT_STRING:
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < node->list.entry_count; i++)
|
||||||
|
{
|
||||||
|
fzl_walk_res_t res = walk(walker, node->list.entries[i]);
|
||||||
|
if (res.error)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
push_op(walker, FZL_OPCODE_BUILD_STR);
|
||||||
|
push_word(walker, node->list.entry_count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case FZL_NODETYPE_BREAK:
|
case FZL_NODETYPE_BREAK:
|
||||||
{
|
{
|
||||||
fzl_walk_ctx_t *ctx = walker->ctx;
|
fzl_walk_ctx_t *ctx = walker->ctx;
|
||||||
|
|||||||
+134
@@ -13,6 +13,7 @@
|
|||||||
#include <vm/fzl_vm_env.h>
|
#include <vm/fzl_vm_env.h>
|
||||||
#include <vm/fzl_vm_object.h>
|
#include <vm/fzl_vm_object.h>
|
||||||
|
|
||||||
|
char build_result[512];
|
||||||
char last_err[256];
|
char last_err[256];
|
||||||
size_t last_jmp_ip = 0;
|
size_t last_jmp_ip = 0;
|
||||||
size_t total_jmp_on_same = 0;
|
size_t total_jmp_on_same = 0;
|
||||||
@@ -297,6 +298,139 @@ int fzl_vm_run(fzl_vm_t *vm, bool allow_infinite, uint64_t max_iter)
|
|||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
|
case FZL_OPCODE_BUILD_STR:
|
||||||
|
{
|
||||||
|
uint64_t n = vm->ops[++vm->ip];
|
||||||
|
if (vm->dtop < n)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"runtime error - expected %zu value(s) in dstack", n);
|
||||||
|
print_err_data(vm);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char temp[64];
|
||||||
|
size_t gi = 0;
|
||||||
|
memset(build_result, 0, sizeof(build_result));
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
if (gi >= 512)
|
||||||
|
{
|
||||||
|
for (size_t i = 511; i > 508; i--)
|
||||||
|
build_result[i] = '.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(temp, 0, sizeof(temp));
|
||||||
|
fzl_value_t val = vm->dstack[i];
|
||||||
|
|
||||||
|
switch (val.type)
|
||||||
|
{
|
||||||
|
case FZL_TYPE_UINT:
|
||||||
|
snprintf(temp, sizeof(temp), "%zu", val.as.u);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_UINT64:
|
||||||
|
snprintf(temp, sizeof(temp), "%lu", val.as.u64);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_UINT32:
|
||||||
|
snprintf(temp, sizeof(temp), "%u", val.as.u32);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_UINT16:
|
||||||
|
snprintf(temp, sizeof(temp), "%u", val.as.u16);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_UINT8:
|
||||||
|
snprintf(temp, sizeof(temp), "%u", val.as.u8);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_INT:
|
||||||
|
snprintf(temp, sizeof(temp), "%zd", val.as.i);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_INT64:
|
||||||
|
snprintf(temp, sizeof(temp), "%ld", val.as.i64);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_INT32:
|
||||||
|
snprintf(temp, sizeof(temp), "%d", val.as.i32);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_INT16:
|
||||||
|
snprintf(temp, sizeof(temp), "%d", val.as.i16);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_INT8:
|
||||||
|
snprintf(temp, sizeof(temp), "%d", val.as.i8);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_BOOL:
|
||||||
|
snprintf(build_result + gi, sizeof(build_result) - gi, "%s",
|
||||||
|
val.as.b ? "true" : "false");
|
||||||
|
gi += val.as.b ? 4 : 5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_CHAR:
|
||||||
|
snprintf(build_result + gi, sizeof(build_result) - gi, "%d",
|
||||||
|
val.as.c);
|
||||||
|
gi += 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_STRING:
|
||||||
|
snprintf(build_result + gi, sizeof(build_result) - gi, "%s",
|
||||||
|
val.as.s.value);
|
||||||
|
gi += val.as.s.length;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_EXTERN_FN:
|
||||||
|
snprintf(temp, sizeof(temp), "<extern:%zu>", val.as.u);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_OBJECT:
|
||||||
|
snprintf(temp, sizeof(temp), "<ref:%p>", val.as.obj);
|
||||||
|
strcpy(build_result + gi, temp);
|
||||||
|
gi += strlen(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FZL_TYPE_NULL:
|
||||||
|
snprintf(build_result + gi, sizeof(build_result) - gi, "<null>");
|
||||||
|
gi += 6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->dtop -= n;
|
||||||
|
vm->dstack[vm->dtop++] =
|
||||||
|
(fzl_value_t){.type = FZL_TYPE_STRING,
|
||||||
|
.as.s.length = strlen(build_result),
|
||||||
|
.as.s.value = build_result};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case FZL_OPCODE_DEREFERENCE:
|
case FZL_OPCODE_DEREFERENCE:
|
||||||
{
|
{
|
||||||
if (vm->dtop < 1)
|
if (vm->dtop < 1)
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ void fzl_vm_print_ops(fzl_vm_t *vm)
|
|||||||
|
|
||||||
switch (vm->ops[i])
|
switch (vm->ops[i])
|
||||||
{
|
{
|
||||||
|
case FZL_OPCODE_BUILD_STR:
|
||||||
|
printf("BUILD_STR %zu\n", vm->ops[++i]);
|
||||||
|
break;
|
||||||
|
|
||||||
case FZL_OPCODE_DEREFERENCE:
|
case FZL_OPCODE_DEREFERENCE:
|
||||||
printf("DEREFERENCE\n");
|
printf("DEREFERENCE\n");
|
||||||
break;
|
break;
|
||||||
@@ -163,9 +167,6 @@ void fzl_vm_print_ops(fzl_vm_t *vm)
|
|||||||
case FZL_OPCODE_JMP:
|
case FZL_OPCODE_JMP:
|
||||||
printf("JMP IP: %ld\n", vm->ops[++i]);
|
printf("JMP IP: %ld\n", vm->ops[++i]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
printf("<UNKNOWN>\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user