Skip to content

Commit

Permalink
vm: implement conditionals in user defined functions
Browse files Browse the repository at this point in the history
  • Loading branch information
LBCrion committed Dec 24, 2024
1 parent ea029c1 commit 235ceb6
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 21 deletions.
17 changes: 13 additions & 4 deletions src/config/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@

gboolean config_action ( GScanner *scanner, GBytes **action_dst )
{
*action_dst = parser_closure_parse(scanner);
GByteArray *code;

code = g_byte_array_new();
if(parser_block_parse(scanner, code))
*action_dst = g_byte_array_free_to_bytes(code);
else
g_byte_array_unref(code);

return !!*action_dst;
}
Expand Down Expand Up @@ -151,7 +157,7 @@ void config_menu_clear ( GScanner *scanner )
void config_function ( GScanner *scanner )
{
gchar *name;
GBytes *action;
GByteArray *code;

config_parse_sequence(scanner,
SEQ_REQ, '(', NULL, NULL, "missing '(' after 'function'",
Expand All @@ -161,8 +167,11 @@ void config_function ( GScanner *scanner )

if(!scanner->max_parse_errors)
{
action = parser_closure_parse(scanner);
vm_func_add_user(name, action);
code = g_byte_array_new();
if(parser_block_parse(scanner, code))
vm_func_add_user(name, g_byte_array_free_to_bytes(code));
else
g_byte_array_unref(code);
}

g_free(name);
Expand Down
44 changes: 28 additions & 16 deletions src/vm/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ static void parser_emit_na ( GByteArray *code )

static void parser_jump_backpatch ( GByteArray *code, gint olen, gint clen )
{
gint data = clen - olen;
gint data = clen - olen - sizeof(gint);
memcpy(code->data + olen, &data, sizeof(gint));
}

Expand Down Expand Up @@ -105,13 +105,13 @@ static gboolean parser_if ( GScanner *scanner, GByteArray *code )
return FALSE;

/* JZ over len change + JMP instruction (1 + sizeof(gint)) */
parser_jump_backpatch(code, alen, code->len + 1);
parser_jump_backpatch(code, alen, code->len + sizeof(gint) + 1);
alen = parser_emit_jump(code, EXPR_OP_JMP);

if(!parser_expr_parse(scanner, code))
return FALSE;
/* JMP over len change */
parser_jump_backpatch(code, alen, code->len - sizeof(gint));
parser_jump_backpatch(code, alen, code->len);

if(g_scanner_get_next_token(scanner)!=')')
return FALSE;
Expand Down Expand Up @@ -394,40 +394,52 @@ gboolean parser_action_parse ( GScanner *scanner, GByteArray *code )

if(cond)
{
parser_jump_backpatch(code, alen, code->len + 1);
parser_jump_backpatch(code, alen, code->len + sizeof(gint) + 1);
alen = parser_emit_jump(code, EXPR_OP_JMP);
parser_emit_na(code);
parser_jump_backpatch(code, alen, code->len - sizeof(gint));
parser_jump_backpatch(code, alen, code->len);
}

return TRUE;
}

GBytes *parser_closure_parse ( GScanner *scanner )
gboolean parser_block_parse ( GScanner *scanner, GByteArray *code )
{
GByteArray *code;
gint alen;
static guint8 discard = EXPR_OP_DISCARD;
code = g_byte_array_new();

if(!config_check_and_consume(scanner, '{'))
{
if(!parser_action_parse(scanner, code))
{
g_byte_array_free(code, TRUE);
return NULL;
}
return FALSE;
}
else
{
while(!config_check_and_consume(scanner, '}'))
if(!parser_action_parse(scanner, code))
if(g_scanner_peek_next_token(scanner) == G_TOKEN_IDENTIFIER &&
!g_ascii_strcasecmp(scanner->next_value.v_identifier, "if"))
{
g_byte_array_free(code, TRUE);
return NULL;
g_scanner_get_next_token(scanner);
parser_expr_parse(scanner, code);
alen = parser_emit_jump(code, EXPR_OP_JZ);
parser_block_parse(scanner, code);
if(g_scanner_peek_next_token(scanner) == G_TOKEN_IDENTIFIER &&
!g_ascii_strcasecmp(scanner->next_value.v_identifier, "else"))
{
g_scanner_get_next_token(scanner);
parser_jump_backpatch(code, alen, code->len + sizeof(gint) + 1);
alen = parser_emit_jump(code, EXPR_OP_JMP);
parser_block_parse(scanner, code);
parser_jump_backpatch(code, alen, code->len);
}
else
parser_jump_backpatch(code, alen, code->len);
}
else if(!parser_action_parse(scanner, code))
return FALSE;
else
g_byte_array_append(code, &discard, 1);
}

return g_byte_array_free_to_bytes(code);
return TRUE;
}
2 changes: 1 addition & 1 deletion src/vm/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ typedef struct {
#define vm_param_check_numeric(vm, p, n, fname) { if(!value_like_numeric(p[n])) { return value_na; } }

GBytes *parser_expr_compile ( gchar *expr );
GBytes *parser_closure_parse ( GScanner *scanner );
gboolean parser_block_parse ( GScanner *scanner, GByteArray *code );
gboolean parser_expr_parse ( GScanner *scanner, GByteArray *code );
gboolean parser_macro_add ( GScanner *scanner );
const gchar *parser_identifier_lookup ( gchar *identifier );
Expand Down

0 comments on commit 235ceb6

Please sign in to comment.