Skip to content

Commit

Permalink
vm: implement array concatenation and size query
Browse files Browse the repository at this point in the history
  • Loading branch information
LBCrion committed Dec 31, 2024
1 parent fad7f38 commit 70f9ed2
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 38 deletions.
47 changes: 32 additions & 15 deletions src/exprlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ static value_t expr_ident ( vm_t *vm, value_t p[], int np )
return result;
}

static value_t action_gettext ( vm_t *vm, value_t p[], gint np )
static value_t expr_gettext ( vm_t *vm, value_t p[], gint np )
{
vm_param_check_np_range(vm, np, 1, 2, "GT");
vm_param_check_string(vm, p, 0, "GT");
Expand All @@ -503,7 +503,7 @@ static value_t action_gettext ( vm_t *vm, value_t p[], gint np )
np==2? value_get_string(p[1]) : "sfwbar", value_get_string(p[0]))));
}

static value_t action_array_build ( vm_t *vm, value_t p[], gint np )
static value_t expr_array_build ( vm_t *vm, value_t p[], gint np )
{
GArray *array;
value_t v1;
Expand All @@ -521,23 +521,24 @@ static value_t action_array_build ( vm_t *vm, value_t p[], gint np )
return value_new_array(array);
}

static value_t action_array_index ( vm_t *vm, value_t p[], gint np )
static value_t expr_array_index ( vm_t *vm, value_t p[], gint np )
{
vm_param_check_np(vm, np, 2, "ArrayIndex");
vm_param_check_array(vm, p, 0, "ArrayIndex");
vm_param_check_numeric(vm, p, 1, "ArrayIndex");

if(!value_is_array(p[0]) ||
if(!value_is_array(p[0]) || (gint)value_get_numeric(p[1])<0 ||
p[0].value.array->len <= ((gint)value_get_numeric(p[1])))
return value_na;

return g_array_index(p[0].value.array, value_t,
(gint)value_get_numeric(p[1]));
}

static value_t action_array_assign ( vm_t *vm, value_t p[], gint np )
static value_t expr_array_assign ( vm_t *vm, value_t p[], gint np )
{
value_t *v1, varr;
value_t *v1;
GArray *arr;
gint n;

vm_param_check_np(vm, np, 3, "ArrayAssign");
Expand All @@ -547,16 +548,30 @@ static value_t action_array_assign ( vm_t *vm, value_t p[], gint np )
if(!value_is_array(p[0]))
return value_na;

varr = value_dup(p[0]);
arr = g_array_ref(p[0].value.array);
n = (gint)value_get_numeric(p[1]);
if(p[0].value.array->len <= n)
g_array_set_size(varr.value.array, n+1);
if(n<0 || n>=arr->len)
g_array_set_size(arr, n+1);

v1 = &g_array_index(varr.value.array, value_t, n);
v1 = &g_array_index(arr, value_t, n);
value_free(*v1);
*v1 = value_dup(p[2]);

return varr;
return value_new_array(arr);
}

static value_t expr_array_concat ( vm_t *vm, value_t p[], gint np )
{
vm_param_check_np(vm, np, 2, "ArrayConcat");

return value_array_concat(p[0], p[1]);
}

static value_t expr_array_size ( vm_t *vm, value_t p[], gint np )
{
vm_param_check_np(vm, np, 1, "ArraySize");

return value_new_numeric(value_is_array(p[0])? p[0].value.array->len : 0);
}

void expr_lib_init ( void )
Expand Down Expand Up @@ -588,8 +603,10 @@ void expr_lib_init ( void )
vm_func_add("windowinfo", expr_lib_window_info, FALSE);
vm_func_add("read", expr_lib_read, FALSE);
vm_func_add("interfaceprovider", expr_iface_provider, FALSE);
vm_func_add("gt", action_gettext, FALSE);
vm_func_add("arraybuild", action_array_build, FALSE);
vm_func_add("arrayindex", action_array_index, FALSE);
vm_func_add("arrayassign", action_array_assign, FALSE);
vm_func_add("gt", expr_gettext, FALSE);
vm_func_add("arraybuild", expr_array_build, FALSE);
vm_func_add("arrayindex", expr_array_index, FALSE);
vm_func_add("arrayassign", expr_array_assign, FALSE);
vm_func_add("arrayconcat", expr_array_concat, FALSE);
vm_func_add("arraysize", expr_array_size, FALSE);
}
28 changes: 6 additions & 22 deletions src/vm/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,9 @@ static gboolean parser_identifier ( GScanner *scanner, GByteArray *code )
return TRUE;
}

static gboolean parser_list_handle ( GScanner *scanner, GByteArray *code )
static gboolean parser_array_handle ( GScanner *scanner, GByteArray *code )
{
guint8 data[sizeof(gpointer)+2], np = 0;
gconstpointer ptr;
guint8 np = 0;

if(g_scanner_peek_next_token(scanner)!=']')
do {
Expand All @@ -257,11 +256,7 @@ static gboolean parser_list_handle ( GScanner *scanner, GByteArray *code )
if(!config_expect_token(scanner, ']', "Expected ']' at the end of the list"))
return FALSE;

data[0]=EXPR_OP_FUNCTION;
data[1]=np;
ptr = vm_func_lookup("arraybuild");
memcpy(data+2, &ptr, sizeof(gpointer));
g_byte_array_append(code, data, sizeof(gpointer)+2);
parser_emit_function(code, vm_func_lookup("arraybuild"), np);

return TRUE;
}
Expand All @@ -280,7 +275,7 @@ static gboolean parser_value ( GScanner *scanner, GByteArray *code )
else if(token == G_TOKEN_STRING)
parser_emit_string(code, scanner->value.v_string);
else if(token == '[')
parser_list_handle(scanner, code);
parser_array_handle(scanner, code);
else if(token == G_TOKEN_IDENTIFIER)
return parser_identifier(scanner, code);
else if(token == '+')
Expand Down Expand Up @@ -429,7 +424,6 @@ static gboolean parser_action_parse ( GScanner *scanner, GByteArray *code )
{
gconstpointer ptr;
gboolean neg;
guint8 data[sizeof(gpointer)+2];
static guint8 discard = EXPR_OP_DISCARD;
gint alen, flag, cond = 0, np = 0;

Expand Down Expand Up @@ -457,11 +451,7 @@ static gboolean parser_action_parse ( GScanner *scanner, GByteArray *code )
parser_emit_numeric(code, cond & 0xff);
parser_emit_numeric(code, cond>>8);

ptr = vm_func_lookup("checkstate");
memcpy(data+2, &ptr, sizeof(gpointer));
data[0]=EXPR_OP_FUNCTION;
data[1]=2;
g_byte_array_append(code, data, sizeof(gpointer)+2);
parser_emit_function(code, vm_func_lookup("checkstate"), 2);
alen = parser_emit_jump(code, EXPR_OP_JZ);
}

Expand All @@ -478,9 +468,6 @@ static gboolean parser_action_parse ( GScanner *scanner, GByteArray *code )

if(!cond && parser_local_lookup(scanner))
return parser_assign_parse(scanner, code);
/* if(!cond && scanner->token==G_TOKEN_IDENTIFIER &&
g_scanner_peek_next_token(scanner)=='=')
return parser_assign_parse(scanner, code);*/

if( !config_lookup_next_key(scanner, config_toplevel_keys) &&
!config_lookup_next_key(scanner, config_prop_keys) &&
Expand All @@ -499,10 +486,7 @@ static gboolean parser_action_parse ( GScanner *scanner, GByteArray *code )

config_check_and_consume(scanner, ';');

memcpy(data+2, &ptr, sizeof(gpointer));
data[0]=EXPR_OP_FUNCTION;
data[1]=np;
g_byte_array_append(code, data, sizeof(gpointer)+2);
parser_emit_function(code, ptr, np);

if(cond)
{
Expand Down
15 changes: 15 additions & 0 deletions src/vm/value.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ void value_free ( value_t v1 )
g_array_unref(v1.value.array);
}

value_t value_array_concat ( value_t v1, value_t v2 )
{
if(!value_is_array(v1) && !value_is_array(v1))
return value_na;

if(!value_is_array(v1))
return value_new_array(g_array_prepend_vals(g_array_ref(v2.value.array),
&v1, 1));
if(!value_is_array(v2))
return value_new_array(g_array_append_vals(g_array_ref(v1.value.array),
&v2, 1));
return value_new_array(g_array_append_vals(g_array_ref(v1.value.array),
v2.value.array->data, v2.value.array->len));
}

value_t value_dup_array ( value_t v1 )
{
GArray *array;
Expand Down
2 changes: 1 addition & 1 deletion src/vm/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ extern const value_t value_na;
#define value_as_numeric(v) (value_like_numeric(v)? value_get_numeric(v) : \
(value_is_string(v)? g_ascii_strtod(v.value.string, NULL) : 0))

//#define value_free(v) { if(value_is_string(v)) g_free(v.value.string); }
void value_free ( value_t );
value_t value_dup ( value_t );
value_t value_array_concat ( value_t v1, value_t v2 );

#endif
3 changes: 3 additions & 0 deletions src/vm/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ static gboolean vm_op_binary ( vm_t *vm )
if(value_is_na(v1) && value_is_na(v2))
result = value_na;

else if(value_is_array(v1) || value_is_array(v2))
result = value_array_concat(v1, v2);

else if(value_like_string(v1) && value_like_string(v2))
{
if(op == '+')
Expand Down

0 comments on commit 70f9ed2

Please sign in to comment.