mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
[cexpr] Support array indexing
The index is currently limited to ints, and is bounds checked (the array type has a size field indicating the number of elements).
This commit is contained in:
parent
c73e4efcb7
commit
c8846f8007
3 changed files with 63 additions and 0 deletions
|
@ -87,6 +87,11 @@ typedef struct exprtab_s {
|
|||
struct hashtab_s *tab;
|
||||
} exprtab_t;
|
||||
|
||||
typedef struct exprarray_s {
|
||||
exprtype_t *type;
|
||||
unsigned size;
|
||||
} exprarray_t;
|
||||
|
||||
typedef struct exprctx_s {
|
||||
exprval_t *result;
|
||||
exprtab_t *symtab; // directly accessible symbols
|
||||
|
@ -111,6 +116,8 @@ exprval_t *cexpr_value_reference (exprtype_t *type, void *data, exprctx_t *ctx);
|
|||
int cexpr_eval_string (const char *str, exprctx_t *context);
|
||||
void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(PRINTF,2,3)));
|
||||
|
||||
void cexpr_array_getelement (const exprval_t *a, const exprval_t *b,
|
||||
exprval_t *c, exprctx_t *ctx);
|
||||
void cexpr_struct_getfield (const exprval_t *a, const exprval_t *b,
|
||||
exprval_t *c, exprctx_t *ctx);
|
||||
void cexpr_struct_pointer_getfield (const exprval_t *a, const exprval_t *b,
|
||||
|
@ -137,6 +144,7 @@ extern exprtype_t cexpr_field;
|
|||
extern exprtype_t cexpr_function;
|
||||
extern exprtype_t cexpr_plitem;
|
||||
|
||||
extern binop_t cexpr_array_binops[];
|
||||
extern binop_t cexpr_struct_binops[];
|
||||
extern binop_t cexpr_struct_pointer_binops[];
|
||||
|
||||
|
|
|
@ -37,6 +37,29 @@
|
|||
|
||||
#include "libs/util/cexpr-parse.h"
|
||||
|
||||
VISIBLE void
|
||||
cexpr_array_getelement (const exprval_t *a, const exprval_t *b, exprval_t *c,
|
||||
exprctx_t *ctx)
|
||||
{
|
||||
__auto_type array = (exprarray_t *) a->type->data;
|
||||
unsigned index = *(const unsigned *) b->value;
|
||||
exprval_t *val = 0;
|
||||
if (index < array->size) {
|
||||
val = cmemalloc (ctx->memsuper, sizeof (exprval_t));
|
||||
val->type = array->type;
|
||||
val->value = a->value + array->type->size * index;
|
||||
} else {
|
||||
cexpr_error (ctx, "index %d out of bounds for %s", index,
|
||||
a->type->name);
|
||||
}
|
||||
*(exprval_t **) c->value = val;
|
||||
}
|
||||
|
||||
VISIBLE binop_t cexpr_array_binops[] = {
|
||||
{ '[', &cexpr_int, &cexpr_exprval, cexpr_array_getelement },
|
||||
{}
|
||||
};
|
||||
|
||||
VISIBLE void
|
||||
cexpr_struct_getfield (const exprval_t *a, const exprval_t *b, exprval_t *c,
|
||||
exprctx_t *ctx)
|
||||
|
|
|
@ -32,17 +32,31 @@
|
|||
#include "QF/cmem.h"
|
||||
#include "QF/hash.h"
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/va.h"
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
||||
int a = 5;
|
||||
int b = 6;
|
||||
int c;
|
||||
int array[4] = { 9, 16, 25, 36 };
|
||||
vec4f_t point = { 2, 3, 4, 1 }; // a point, so w = 1
|
||||
vec4f_t normal = { 1, 2, 3, 0 }; // a vector, so w = 0
|
||||
vec4f_t direction = { 4, 5, 6, 0 }; // a vector, so w = 0
|
||||
vec4f_t plane;
|
||||
vec4f_t intercept;
|
||||
|
||||
exprarray_t int_array_4_data = {
|
||||
&cexpr_int,
|
||||
sizeof (array) / sizeof (array[0]),
|
||||
};
|
||||
exprtype_t int_array_4 = {
|
||||
"int[4]",
|
||||
4 * sizeof (int),
|
||||
cexpr_array_binops,
|
||||
0,
|
||||
&int_array_4_data,
|
||||
};
|
||||
|
||||
exprtype_t *vector_params[] = {
|
||||
&cexpr_vector,
|
||||
&cexpr_vector,
|
||||
|
@ -117,6 +131,7 @@ exprfunc_t double_func[] = {
|
|||
exprsym_t symbols[] = {
|
||||
{ "a", &cexpr_int, &a },
|
||||
{ "b", &cexpr_int, &b },
|
||||
{ "array", &int_array_4, &array },
|
||||
{ "point", &cexpr_vector, &point },
|
||||
{ "normal", &cexpr_vector, &normal },
|
||||
{ "plane", &cexpr_vector, &plane },
|
||||
|
@ -147,6 +162,7 @@ exprctx_t context = { &test_result, &symtab };
|
|||
#define TEST_BINOP(op) \
|
||||
do { \
|
||||
c = -4096; \
|
||||
context.result = &test_result; \
|
||||
cexpr_eval_string ("a " #op " b", &context); \
|
||||
printf ("c = a %s b -> %d = %d %s %d\n", #op, c, a, #op, b); \
|
||||
if (c != (a op b)) { \
|
||||
|
@ -154,6 +170,17 @@ exprctx_t context = { &test_result, &symtab };
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define TEST_ARRAY(ind) \
|
||||
do { \
|
||||
c = -4096; \
|
||||
context.result = &test_result; \
|
||||
cexpr_eval_string (va (0, "array[%d]", ind), &context); \
|
||||
printf ("c = array[%d] -> %d = %d\n", ind, c, array[ind]); \
|
||||
if (c != array[ind]) { \
|
||||
ret |= 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
|
@ -173,6 +200,11 @@ main(int argc, const char **argv)
|
|||
TEST_BINOP (^);
|
||||
TEST_BINOP (%);
|
||||
|
||||
TEST_ARRAY (0);
|
||||
TEST_ARRAY (1);
|
||||
TEST_ARRAY (2);
|
||||
TEST_ARRAY (3);
|
||||
|
||||
context.result = &plane_result;
|
||||
cexpr_eval_string ("point.wzyx", &context);
|
||||
if (plane[0] != point[3] || plane[1] != point[2]
|
||||
|
|
Loading…
Reference in a new issue