mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[util] Add plist support to cexpr
This allows plist objects to be accessed directly from cexpr expressions using struct.field syntax for dictionary objects and array[index] syntax for array objects.
This commit is contained in:
parent
846fcc276c
commit
d2536e584f
3 changed files with 114 additions and 0 deletions
|
@ -132,6 +132,7 @@ extern exprtype_t cexpr_quaternion;
|
|||
extern exprtype_t cexpr_exprval;
|
||||
extern exprtype_t cexpr_field;
|
||||
extern exprtype_t cexpr_function;
|
||||
extern exprtype_t cexpr_plitem;
|
||||
|
||||
extern binop_t cexpr_struct_binops[];
|
||||
extern binop_t cexpr_struct_pointer_binops[];
|
||||
|
|
|
@ -56,6 +56,8 @@ static exprval_t *binary_expr (int op, const exprval_t *a, const exprval_t *b,
|
|||
exprctx_t *context);
|
||||
static exprval_t *field_expr (const exprval_t *a, const exprval_t *b,
|
||||
exprctx_t *context);
|
||||
static exprval_t *index_expr (const exprval_t *a, const exprval_t *b,
|
||||
exprctx_t *context);
|
||||
static exprval_t *unary_expr (int op, const exprval_t *val,
|
||||
exprctx_t *context);
|
||||
static exprval_t *vector_expr (exprlist_t *list, exprctx_t *context);
|
||||
|
@ -126,6 +128,7 @@ uexpr
|
|||
| '(' expr ')' { $$ = $2; }
|
||||
| NAME '(' opt_arg_list ')' { $$ = function_expr ($1, $3, context); }
|
||||
| uexpr '.' field { $$ = field_expr ($1, $3, context); }
|
||||
| uexpr '[' field ']' { $$ = index_expr ($1, $3, context); }
|
||||
| '+' uexpr %prec UNARY { $$ = $2; }
|
||||
| '-' uexpr %prec UNARY { $$ = unary_expr ('-', $2, context); }
|
||||
| '!' uexpr %prec UNARY { $$ = unary_expr ('!', $2, context); }
|
||||
|
@ -237,6 +240,10 @@ field_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context)
|
|||
binop_t *binop;
|
||||
exprval_t *result = 0;
|
||||
|
||||
if (!a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (binop = a->type->binops; binop->op; binop++) {
|
||||
if (binop->op == '.' && binop->other == b->type) {
|
||||
break;
|
||||
|
@ -254,6 +261,29 @@ field_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context)
|
|||
return result;
|
||||
}
|
||||
|
||||
static exprval_t *
|
||||
index_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context)
|
||||
{
|
||||
binop_t *binop;
|
||||
exprval_t *result = 0;
|
||||
|
||||
for (binop = a->type->binops; binop->op; binop++) {
|
||||
if (binop->op == '[' && binop->other == b->type) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!binop->op) {
|
||||
cexpr_error (context, "invalid index expression: %s.%s",
|
||||
a->type->name, b->type->name);
|
||||
result = cexpr_value (&cexpr_int, context);
|
||||
*(int *) result->value = 0;
|
||||
} else {
|
||||
exprval_t c = { 0, &result };
|
||||
binop->func (a, b, &c, context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static exprval_t *
|
||||
unary_expr (int op, const exprval_t *val, exprctx_t *context)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <math.h>
|
||||
|
||||
#include "QF/cexpr.h"
|
||||
#include "QF/cmem.h"
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/qfplist.h"
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
@ -594,6 +595,88 @@ exprtype_t cexpr_function = {
|
|||
0,
|
||||
};
|
||||
|
||||
static void
|
||||
plitem_field (const exprval_t *a, const exprval_t *b, exprval_t *c,
|
||||
exprctx_t *ctx)
|
||||
{
|
||||
__auto_type dict = *(plitem_t **) a->value;
|
||||
__auto_type key = (const char *) b->value;
|
||||
|
||||
if (PL_Type (dict) != QFDictionary) {
|
||||
cexpr_error(ctx, "not a dictionary object");
|
||||
return;
|
||||
}
|
||||
plitem_t *item = PL_ObjectForKey (dict, key);
|
||||
exprval_t *val = 0;
|
||||
if (!item) {
|
||||
cexpr_error (ctx, "key not found: %s", key);
|
||||
} else {
|
||||
val = cexpr_value (&cexpr_plitem, ctx);
|
||||
*(plitem_t **) val->value = item;
|
||||
}
|
||||
*(exprval_t **) c->value = val;
|
||||
}
|
||||
|
||||
static void
|
||||
plitem_index (const exprval_t *a, int index, exprval_t *c,
|
||||
exprctx_t *ctx)
|
||||
{
|
||||
__auto_type array = *(plitem_t **) a->type->data;
|
||||
|
||||
if (PL_Type (array) != QFArray) {
|
||||
cexpr_error(ctx, "not an array object");
|
||||
return;
|
||||
}
|
||||
plitem_t *item = PL_ObjectAtIndex (array, index);
|
||||
exprval_t *val = 0;
|
||||
if (!item) {
|
||||
cexpr_error (ctx, "invalid index: %d", index);
|
||||
} else {
|
||||
val = cexpr_value (&cexpr_plitem, ctx);
|
||||
*(plitem_t **) val->value = item;
|
||||
}
|
||||
*(exprval_t **) c->value = val;
|
||||
}
|
||||
|
||||
static void
|
||||
plitem_int (const exprval_t *a, const exprval_t *b, exprval_t *c,
|
||||
exprctx_t *ctx)
|
||||
{
|
||||
int index = *(int *) a->value;
|
||||
plitem_index (a, index, c, ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
plitem_uint (const exprval_t *a, const exprval_t *b, exprval_t *c,
|
||||
exprctx_t *ctx)
|
||||
{
|
||||
int index = *(int *) a->value;
|
||||
plitem_index (a, index, c, ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
plitem_size_t (const exprval_t *a, const exprval_t *b, exprval_t *c,
|
||||
exprctx_t *ctx)
|
||||
{
|
||||
int index = *(int *) a->value;
|
||||
plitem_index (a, index, c, ctx);
|
||||
}
|
||||
|
||||
binop_t plitem_binops[] = {
|
||||
{ '.', &cexpr_field, &cexpr_plitem, plitem_field },
|
||||
{ '[', &cexpr_int, &cexpr_plitem, plitem_int },
|
||||
{ '[', &cexpr_uint, &cexpr_plitem, plitem_uint },
|
||||
{ '[', &cexpr_size_t, &cexpr_plitem, plitem_size_t },
|
||||
{}
|
||||
};
|
||||
|
||||
exprtype_t cexpr_plitem = {
|
||||
"plitem",
|
||||
sizeof (plitem_t *),
|
||||
plitem_binops,
|
||||
0,
|
||||
};
|
||||
|
||||
VISIBLE binop_t *
|
||||
cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue