expr: split expression types and allocate them separately
authorRan Benita <ran234@gmail.com>
Sun, 1 Dec 2013 10:08:47 +0000 (12:08 +0200)
committerRan Benita <ran234@gmail.com>
Sun, 1 Dec 2013 10:58:01 +0000 (12:58 +0200)
Currently, we have one ExprDef type, which contains a tagged union with
the value of all expression types. Turns out, this union is quite
wasteful memory-wise. Instead, create separate types for all expressions
(e.g ExprBinary, ExprInteger) which embed the common fields
(ExprCommon), and malloc them per their size; ExprDef then becomes a
union of all these types, but is just used as a generic pointer.

[Instead of making ExprDef a union, another option is to use
ExprCommon as the generic pointer type and then do up-castings, like we
do with ParseCommon. But this makes the code much uglier.]

The diff is mostly straightforward mechanical adaptations. It could have
been much smaller with the help of C11 anonymous structs (which were
previously a gnu extension). This will have saved all of the 'op' ->
'expr->op', etc changes. But if we can be a bit more portable for a
little effort, we should.

Before (./test/rulescomp, x86 32 bit, -O2):
==12974==   total heap usage: 145,217 allocs, 145,217 frees, 10,476,238 bytes allocated

After:
==11145==   total heap usage: 145,217 allocs, 145,217 frees, 8,270,358 bytes allocated

Signed-off-by: Ran Benita <ran234@gmail.com>
src/xkbcomp/action.c
src/xkbcomp/ast-build.c
src/xkbcomp/ast.h
src/xkbcomp/compat.c
src/xkbcomp/expr.c
src/xkbcomp/parser.y
src/xkbcomp/symbols.c

index 37b9338..fed108f 100644 (file)
 #include "expr.h"
 #include "action.h"
 
-static const ExprDef constTrue = {
-    .common = { .type = STMT_EXPR, .next = NULL },
-    .op = EXPR_VALUE,
-    .value_type = EXPR_TYPE_BOOLEAN,
-    .value = { .set = true },
+static const ExprBoolean constTrue = {
+    .expr = {
+        .common = { .type = STMT_EXPR, .next = NULL },
+        .op = EXPR_VALUE,
+        .value_type = EXPR_TYPE_BOOLEAN,
+    },
+    .set = true,
 };
 
-static const ExprDef constFalse = {
-    .common = { .type = STMT_EXPR, .next = NULL },
-    .op = EXPR_VALUE,
-    .value_type = EXPR_TYPE_BOOLEAN,
-    .value = { .set = false },
+static const ExprBoolean constFalse = {
+    .expr = {
+        .common = { .type = STMT_EXPR, .next = NULL },
+        .op = EXPR_VALUE,
+        .value_type = EXPR_TYPE_BOOLEAN,
+    },
+    .set = false,
 };
 
 enum action_field {
@@ -265,9 +269,9 @@ CheckModifierField(struct xkb_keymap *keymap, enum xkb_action_type action,
                    const ExprDef *value, enum xkb_action_flags *flags_inout,
                    xkb_mod_mask_t *mods_rtrn)
 {
-    if (value->op == EXPR_IDENT) {
+    if (value->expr.op == EXPR_IDENT) {
         const char *valStr;
-        valStr = xkb_atom_text(keymap->ctx, value->value.ident);
+        valStr = xkb_atom_text(keymap->ctx, value->ident.ident);
         if (valStr && (istreq(valStr, "usemodmapmods") ||
                        istreq(valStr, "modmapmods"))) {
 
@@ -367,9 +371,9 @@ CheckGroupField(struct xkb_keymap *keymap, unsigned action,
 {
     const ExprDef *spec;
 
-    if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) {
+    if (value->expr.op == EXPR_NEGATE || value->expr.op == EXPR_UNARY_PLUS) {
         *flags_inout &= ~ACTION_ABSOLUTE_SWITCH;
-        spec = value->value.child;
+        spec = value->unary.child;
     }
     else {
         *flags_inout |= ACTION_ABSOLUTE_SWITCH;
@@ -380,9 +384,9 @@ CheckGroupField(struct xkb_keymap *keymap, unsigned action,
         return ReportMismatch(keymap, action, ACTION_FIELD_GROUP,
                               "integer (range 1..8)");
 
-    if (value->op == EXPR_NEGATE)
+    if (value->expr.op == EXPR_NEGATE)
         *grp_rtrn = -*grp_rtrn;
-    else if (value->op != EXPR_UNARY_PLUS)
+    else if (value->expr.op != EXPR_UNARY_PLUS)
         (*grp_rtrn)--;
 
     return true;
@@ -472,7 +476,7 @@ HandleMovePtr(struct xkb_keymap *keymap, union xkb_action *action,
     if (field == ACTION_FIELD_X || field == ACTION_FIELD_Y) {
         int val;
 
-        if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS)
+        if (value->expr.op == EXPR_NEGATE || value->expr.op == EXPR_UNARY_PLUS)
             absolute = false;
         else
             absolute = true;
@@ -613,9 +617,10 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
         if (array_ndx)
             return ReportActionNotArray(keymap, action->type, field);
 
-        if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) {
+        if (value->expr.op == EXPR_NEGATE ||
+            value->expr.op == EXPR_UNARY_PLUS) {
             act->flags &= ~ACTION_ABSOLUTE_SWITCH;
-            button = value->value.child;
+            button = value->unary.child;
         }
         else {
             act->flags |= ACTION_ABSOLUTE_SWITCH;
@@ -639,7 +644,7 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
             return false;
         }
 
-        act->value = (value->op == EXPR_NEGATE ? -btn: btn);
+        act->value = (value->expr.op == EXPR_NEGATE ? -btn: btn);
         return true;
     }
 
@@ -660,9 +665,10 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
         if (array_ndx)
             return ReportActionNotArray(keymap, action->type, field);
 
-        if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) {
+        if (value->expr.op == EXPR_NEGATE ||
+            value->expr.op == EXPR_UNARY_PLUS) {
             act->flags &= ~ACTION_ABSOLUTE_SWITCH;
-            scrn = value->value.child;
+            scrn = value->unary.child;
         }
         else {
             act->flags |= ACTION_ABSOLUTE_SWITCH;
@@ -680,7 +686,7 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
             return false;
         }
 
-        act->screen = (value->op == EXPR_NEGATE ? -val : val);
+        act->screen = (value->expr.op == EXPR_NEGATE ? -val : val);
         return true;
     }
     else if (field == ACTION_FIELD_SAME) {
@@ -861,13 +867,13 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
     const char *str;
     unsigned handler_type;
 
-    if (def->op != EXPR_ACTION_DECL) {
+    if (def->expr.op != EXPR_ACTION_DECL) {
         log_err(keymap->ctx, "Expected an action definition, found %s\n",
-                expr_op_type_to_string(def->op));
+                expr_op_type_to_string(def->expr.op));
         return false;
     }
 
-    str = xkb_atom_text(keymap->ctx, def->value.action.name);
+    str = xkb_atom_text(keymap->ctx, def->action.name);
     if (!stringToAction(str, &handler_type)) {
         log_err(keymap->ctx, "Unknown action %s\n", str);
         return false;
@@ -885,24 +891,24 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
      * particular instance, e.g. "modifiers" and "clearLocks" in:
      *     SetMods(modifiers=Alt,clearLocks);
      */
-    for (arg = def->value.action.args; arg != NULL;
+    for (arg = def->action.args; arg != NULL;
          arg = (ExprDef *) arg->common.next) {
         const ExprDef *value;
         ExprDef *field, *arrayRtrn;
         const char *elemRtrn, *fieldRtrn;
         enum action_field fieldNdx;
 
-        if (arg->op == EXPR_ASSIGN) {
-            field = arg->value.binary.left;
-            value = arg->value.binary.right;
+        if (arg->expr.op == EXPR_ASSIGN) {
+            field = arg->binary.left;
+            value = arg->binary.right;
         }
-        else if (arg->op == EXPR_NOT || arg->op == EXPR_INVERT) {
-            field = arg->value.child;
-            value = &constFalse;
+        else if (arg->expr.op == EXPR_NOT || arg->expr.op == EXPR_INVERT) {
+            field = arg->unary.child;
+            value = (const ExprDef *) &constFalse;
         }
         else {
             field = arg;
-            value = &constTrue;
+            value = (const ExprDef *) &constTrue;
         }
 
         if (!ExprResolveLhs(keymap->ctx, field, &elemRtrn, &fieldRtrn,
index 9f429d9..8e0b0c6 100644 (file)
@@ -71,16 +71,16 @@ AppendStmt(ParseCommon *to, ParseCommon *append)
 }
 
 static ExprDef *
-ExprCreate(enum expr_op_type op, enum expr_value_type type)
+ExprCreate(enum expr_op_type op, enum expr_value_type type, size_t size)
 {
-    ExprDef *expr = malloc(sizeof(*expr));
+    ExprDef *expr = malloc(size);
     if (!expr)
         return NULL;
 
     expr->common.type = STMT_EXPR;
     expr->common.next = NULL;
-    expr->op = op;
-    expr->value_type = type;
+    expr->expr.op = op;
+    expr->expr.value_type = type;
 
     return expr;
 }
@@ -88,11 +88,12 @@ ExprCreate(enum expr_op_type op, enum expr_value_type type)
 ExprDef *
 ExprCreateString(xkb_atom_t str)
 {
-    ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_STRING);
+    ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_STRING,
+                               sizeof(ExprString));
     if (!expr)
         return NULL;
 
-    expr->value.str = str;
+    expr->string.str = str;
 
     return expr;
 }
@@ -100,11 +101,12 @@ ExprCreateString(xkb_atom_t str)
 ExprDef *
 ExprCreateInteger(int ival)
 {
-    ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_INT);
+    ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_INT,
+                               sizeof(ExprInteger));
     if (!expr)
         return NULL;
 
-    expr->value.ival = ival;
+    expr->integer.ival = ival;
 
     return expr;
 }
@@ -112,11 +114,12 @@ ExprCreateInteger(int ival)
 ExprDef *
 ExprCreateBoolean(bool set)
 {
-    ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_BOOLEAN);
+    ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_BOOLEAN,
+                               sizeof(ExprBoolean));
     if (!expr)
         return NULL;
 
-    expr->value.set = set;
+    expr->boolean.set = set;
 
     return expr;
 }
@@ -124,11 +127,12 @@ ExprCreateBoolean(bool set)
 ExprDef *
 ExprCreateKeyName(xkb_atom_t key_name)
 {
-    ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_KEYNAME);
+    ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_KEYNAME,
+                               sizeof(ExprKeyName));
     if (!expr)
         return NULL;
 
-    expr->value.keyName = key_name;
+    expr->key_name.key_name = key_name;
 
     return expr;
 }
@@ -136,11 +140,12 @@ ExprCreateKeyName(xkb_atom_t key_name)
 ExprDef *
 ExprCreateIdent(xkb_atom_t ident)
 {
-    ExprDef *expr = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN);
+    ExprDef *expr = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN,
+                                 sizeof(ExprIdent));
     if (!expr)
         return NULL;
 
-    expr->value.ident = ident;
+    expr->ident.ident = ident;
 
     return expr;
 }
@@ -149,11 +154,12 @@ ExprDef *
 ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
                 ExprDef *child)
 {
-    ExprDef *expr = ExprCreate(op, type);
+    ExprDef *expr = ExprCreate(op, type,
+                               sizeof(ExprUnary));
     if (!expr)
         return NULL;
 
-    expr->value.child = child;
+    expr->unary.child = child;
 
     return expr;
 }
@@ -161,17 +167,18 @@ ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
 ExprDef *
 ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right)
 {
-    ExprDef *expr = ExprCreate(op, EXPR_TYPE_UNKNOWN);
+    ExprDef *expr = ExprCreate(op, EXPR_TYPE_UNKNOWN,
+                               sizeof(ExprBinary));
     if (!expr)
         return NULL;
 
-    if (op == EXPR_ASSIGN || left->value_type == EXPR_TYPE_UNKNOWN)
-        expr->value_type = right->value_type;
-    else if (left->value_type == right->value_type ||
-             right->value_type == EXPR_TYPE_UNKNOWN)
-        expr->value_type = left->value_type;
-    expr->value.binary.left = left;
-    expr->value.binary.right = right;
+    if (op == EXPR_ASSIGN || left->expr.value_type == EXPR_TYPE_UNKNOWN)
+        expr->expr.value_type = right->expr.value_type;
+    else if (left->expr.value_type == right->expr.value_type ||
+             right->expr.value_type == EXPR_TYPE_UNKNOWN)
+        expr->expr.value_type = left->expr.value_type;
+    expr->binary.left = left;
+    expr->binary.right = right;
 
     return expr;
 }
@@ -179,12 +186,13 @@ ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right)
 ExprDef *
 ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field)
 {
-    ExprDef *expr = ExprCreate(EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN);
+    ExprDef *expr = ExprCreate(EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN,
+                               sizeof(ExprFieldRef));
     if (!expr)
         return NULL;
 
-    expr->value.field.element = element;
-    expr->value.field.field = field;
+    expr->field_ref.element = element;
+    expr->field_ref.field = field;
 
     return expr;
 }
@@ -192,13 +200,14 @@ ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field)
 ExprDef *
 ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry)
 {
-    ExprDef *expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
+    ExprDef *expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN,
+                               sizeof(ExprArrayRef));
     if (!expr)
         return NULL;
 
-    expr->value.array.element = element;
-    expr->value.array.field = field;
-    expr->value.array.entry = entry;
+    expr->array_ref.element = element;
+    expr->array_ref.field = field;
+    expr->array_ref.entry = entry;
 
     return expr;
 }
@@ -266,8 +275,8 @@ VarCreate(ExprDef *name, ExprDef *value)
 VarDef *
 BoolVarCreate(xkb_atom_t ident, bool set)
 {
-    return VarCreate(ExprCreateIdent(ident),
-                     ExprCreateBoolean(set));
+    return VarCreate((ExprDef *) ExprCreateIdent(ident),
+                     (ExprDef *) ExprCreateBoolean(set));
 }
 
 InterpDef *
@@ -385,75 +394,76 @@ LedNameCreate(int ndx, ExprDef *name, bool virtual)
 ExprDef *
 ActionCreate(xkb_atom_t name, ExprDef *args)
 {
-    ExprDef *act = ExprCreate(EXPR_ACTION_DECL, EXPR_TYPE_UNKNOWN);
-    if (!act)
+    ExprDef *expr = ExprCreate(EXPR_ACTION_DECL, EXPR_TYPE_UNKNOWN,
+                               sizeof(ExprAction));
+    if (!expr)
         return NULL;
 
-    act->value.action.name = name;
-    act->value.action.args = args;
+    expr->action.name = name;
+    expr->action.args = args;
 
-    return act;
+    return expr;
 }
 
 ExprDef *
 CreateKeysymList(xkb_keysym_t sym)
 {
-    ExprDef *def = ExprCreate(EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS);
-    if (!def)
+    ExprDef *expr = ExprCreate(EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS,
+                               sizeof(ExprKeysymList));
+    if (!expr)
         return NULL;
 
-    darray_init(def->value.list.syms);
-    darray_init(def->value.list.symsMapIndex);
-    darray_init(def->value.list.symsNumEntries);
+    darray_init(expr->keysym_list.syms);
+    darray_init(expr->keysym_list.symsMapIndex);
+    darray_init(expr->keysym_list.symsNumEntries);
 
-    darray_append(def->value.list.syms, sym);
-    darray_append(def->value.list.symsMapIndex, 0);
-    darray_append(def->value.list.symsNumEntries, 1);
+    darray_append(expr->keysym_list.syms, sym);
+    darray_append(expr->keysym_list.symsMapIndex, 0);
+    darray_append(expr->keysym_list.symsNumEntries, 1);
 
-    return def;
+    return expr;
 }
 
 ExprDef *
-CreateMultiKeysymList(ExprDef *list)
+CreateMultiKeysymList(ExprDef *expr)
 {
-    size_t nLevels = darray_size(list->value.list.symsMapIndex);
+    size_t nLevels = darray_size(expr->keysym_list.symsMapIndex);
 
-    darray_resize(list->value.list.symsMapIndex, 1);
-    darray_resize(list->value.list.symsNumEntries, 1);
-    darray_item(list->value.list.symsMapIndex, 0) = 0;
-    darray_item(list->value.list.symsNumEntries, 0) = nLevels;
+    darray_resize(expr->keysym_list.symsMapIndex, 1);
+    darray_resize(expr->keysym_list.symsNumEntries, 1);
+    darray_item(expr->keysym_list.symsMapIndex, 0) = 0;
+    darray_item(expr->keysym_list.symsNumEntries, 0) = nLevels;
 
-    return list;
+    return expr;
 }
 
 ExprDef *
-AppendKeysymList(ExprDef *list, xkb_keysym_t sym)
+AppendKeysymList(ExprDef *expr, xkb_keysym_t sym)
 {
-    size_t nSyms = darray_size(list->value.list.syms);
+    size_t nSyms = darray_size(expr->keysym_list.syms);
 
-    darray_append(list->value.list.symsMapIndex, nSyms);
-    darray_append(list->value.list.symsNumEntries, 1);
-    darray_append(list->value.list.syms, sym);
+    darray_append(expr->keysym_list.symsMapIndex, nSyms);
+    darray_append(expr->keysym_list.symsNumEntries, 1);
+    darray_append(expr->keysym_list.syms, sym);
 
-    return list;
+    return expr;
 }
 
 ExprDef *
-AppendMultiKeysymList(ExprDef *list, ExprDef *append)
+AppendMultiKeysymList(ExprDef *expr, ExprDef *append)
 {
-    size_t nSyms = darray_size(list->value.list.syms);
-    size_t numEntries = darray_size(append->value.list.syms);
+    size_t nSyms = darray_size(expr->keysym_list.syms);
+    size_t numEntries = darray_size(append->keysym_list.syms);
 
-    darray_append(list->value.list.symsMapIndex, nSyms);
-    darray_append(list->value.list.symsNumEntries, numEntries);
-    darray_append_items(list->value.list.syms,
-                        darray_mem(append->value.list.syms, 0),
-                        numEntries);
+    darray_append(expr->keysym_list.symsMapIndex, nSyms);
+    darray_append(expr->keysym_list.symsNumEntries, numEntries);
+    darray_append_items(expr->keysym_list.syms,
+                        darray_mem(append->keysym_list.syms, 0), numEntries);
 
-    darray_resize(append->value.list.syms, 0);
+    darray_resize(append->keysym_list.syms, 0);
     FreeStmt(&append->common);
 
-    return list;
+    return expr;
 }
 
 static void
@@ -619,13 +629,13 @@ FreeExpr(ExprDef *expr)
     if (!expr)
         return;
 
-    switch (expr->op) {
+    switch (expr->expr.op) {
     case EXPR_ACTION_LIST:
     case EXPR_NEGATE:
     case EXPR_UNARY_PLUS:
     case EXPR_NOT:
     case EXPR_INVERT:
-        FreeStmt(&expr->value.child->common);
+        FreeStmt(&expr->unary.child->common);
         break;
 
     case EXPR_DIVIDE:
@@ -633,22 +643,22 @@ FreeExpr(ExprDef *expr)
     case EXPR_SUBTRACT:
     case EXPR_MULTIPLY:
     case EXPR_ASSIGN:
-        FreeStmt(&expr->value.binary.left->common);
-        FreeStmt(&expr->value.binary.right->common);
+        FreeStmt(&expr->binary.left->common);
+        FreeStmt(&expr->binary.right->common);
         break;
 
     case EXPR_ACTION_DECL:
-        FreeStmt(&expr->value.action.args->common);
+        FreeStmt(&expr->action.args->common);
         break;
 
     case EXPR_ARRAY_REF:
-        FreeStmt(&expr->value.array.entry->common);
+        FreeStmt(&expr->array_ref.entry->common);
         break;
 
     case EXPR_KEYSYM_LIST:
-        darray_free(expr->value.list.syms);
-        darray_free(expr->value.list.symsMapIndex);
-        darray_free(expr->value.list.symsNumEntries);
+        darray_free(expr->keysym_list.syms);
+        darray_free(expr->keysym_list.symsMapIndex);
+        darray_free(expr->keysym_list.symsNumEntries);
         break;
 
     default:
index c63b796..36f777a 100644 (file)
@@ -158,41 +158,92 @@ typedef struct _IncludeStmt {
     struct _IncludeStmt *next_incl;
 } IncludeStmt;
 
-typedef struct _Expr {
+typedef struct {
     ParseCommon common;
     enum expr_op_type op;
     enum expr_value_type value_type;
-    union {
-        struct {
-            struct _Expr *left;
-            struct _Expr *right;
-        } binary;
-        struct {
-            xkb_atom_t element;
-            xkb_atom_t field;
-        } field;
-        struct {
-            xkb_atom_t element;
-            xkb_atom_t field;
-            struct _Expr *entry;
-        } array;
-        struct {
-            xkb_atom_t name;
-            struct _Expr *args;
-        } action;
-        struct {
-            darray(xkb_keysym_t) syms;
-            darray(int) symsMapIndex;
-            darray(unsigned int) symsNumEntries;
-        } list;
-        struct _Expr *child;
-        xkb_atom_t ident;
-        xkb_atom_t str;
-        bool set;
-        int ival;
-        xkb_atom_t keyName;
-    } value;
-} ExprDef;
+} ExprCommon;
+
+typedef union ExprDef ExprDef;
+
+typedef struct {
+    ExprCommon expr;
+    xkb_atom_t ident;
+} ExprIdent;
+
+typedef struct {
+    ExprCommon expr;
+    xkb_atom_t str;
+} ExprString;
+
+typedef struct {
+    ExprCommon expr;
+    bool set;
+} ExprBoolean;
+
+typedef struct {
+    ExprCommon expr;
+    int ival;
+} ExprInteger;
+
+typedef struct {
+    ExprCommon expr;
+    xkb_atom_t key_name;
+} ExprKeyName;
+
+typedef struct {
+    ExprCommon expr;
+    ExprDef *left;
+    ExprDef *right;
+} ExprBinary;
+
+typedef struct {
+    ExprCommon expr;
+    ExprDef *child;
+} ExprUnary;
+
+typedef struct {
+    ExprCommon expr;
+    xkb_atom_t element;
+    xkb_atom_t field;
+} ExprFieldRef;
+
+typedef struct {
+    ExprCommon expr;
+    xkb_atom_t element;
+    xkb_atom_t field;
+    ExprDef *entry;
+} ExprArrayRef;
+
+typedef struct {
+    ExprCommon expr;
+    xkb_atom_t name;
+    ExprDef *args;
+} ExprAction;
+
+typedef struct {
+    ExprCommon expr;
+    darray(xkb_keysym_t) syms;
+    darray(int) symsMapIndex;
+    darray(unsigned int) symsNumEntries;
+} ExprKeysymList;
+
+union ExprDef {
+    ParseCommon common;
+    /* Maybe someday we can use C11 anonymous struct for ExprCommon here. */
+    ExprCommon expr;
+    ExprIdent ident;
+    ExprString string;
+    ExprBoolean boolean;
+    ExprInteger integer;
+    ExprKeyName key_name;
+    ExprBinary binary;
+    ExprUnary unary;
+    ExprFieldRef field_ref;
+    ExprArrayRef array_ref;
+    ExprAction action;
+    ExprKeysymList keysym_list;
+};
 
 typedef struct {
     ParseCommon common;
index 0775a98..fffb2d3 100644 (file)
@@ -432,19 +432,19 @@ ResolveStateAndPredicate(ExprDef *expr, enum xkb_match_operation *pred_rtrn,
     }
 
     *pred_rtrn = MATCH_EXACTLY;
-    if (expr->op == EXPR_ACTION_DECL) {
+    if (expr->expr.op == EXPR_ACTION_DECL) {
         const char *pred_txt = xkb_atom_text(info->keymap->ctx,
-                                             expr->value.action.name);
+                                             expr->action.name);
         if (!LookupString(symInterpretMatchMaskNames, pred_txt, pred_rtrn)) {
             log_err(info->keymap->ctx,
                     "Illegal modifier predicate \"%s\"; Ignored\n", pred_txt);
             return false;
         }
-        expr = expr->value.action.args;
+        expr = expr->action.args;
     }
-    else if (expr->op == EXPR_IDENT) {
+    else if (expr->expr.op == EXPR_IDENT) {
         const char *pred_txt = xkb_atom_text(info->keymap->ctx,
-                                             expr->value.ident);
+                                             expr->ident.ident);
         if (pred_txt && istreq(pred_txt, "any")) {
             *pred_rtrn = MATCH_ANY;
             *mods_rtrn = MOD_REAL_MASK_ALL;
@@ -805,7 +805,7 @@ HandleInterpBody(CompatInfo *info, VarDef *def, SymInterpInfo *si)
     ExprDef *arrayNdx;
 
     for (; def; def = (VarDef *) def->common.next) {
-        if (def->name && def->name->op == EXPR_FIELD_REF) {
+        if (def->name && def->name->expr.op == EXPR_FIELD_REF) {
             log_err(info->keymap->ctx,
                     "Cannot set a global default value from within an interpret statement; "
                     "Move statements to the global file scope\n");
index 227f351..ba71208 100644 (file)
@@ -37,26 +37,26 @@ ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
                const char **elem_rtrn, const char **field_rtrn,
                ExprDef **index_rtrn)
 {
-    switch (expr->op) {
+    switch (expr->expr.op) {
     case EXPR_IDENT:
         *elem_rtrn = NULL;
-        *field_rtrn = xkb_atom_text(ctx, expr->value.ident);
+        *field_rtrn = xkb_atom_text(ctx, expr->ident.ident);
         *index_rtrn = NULL;
         return true;
     case EXPR_FIELD_REF:
-        *elem_rtrn = xkb_atom_text(ctx, expr->value.field.element);
-        *field_rtrn = xkb_atom_text(ctx, expr->value.field.field);
+        *elem_rtrn = xkb_atom_text(ctx, expr->field_ref.element);
+        *field_rtrn = xkb_atom_text(ctx, expr->field_ref.field);
         *index_rtrn = NULL;
         return true;
     case EXPR_ARRAY_REF:
-        *elem_rtrn = xkb_atom_text(ctx, expr->value.array.element);
-        *field_rtrn = xkb_atom_text(ctx, expr->value.array.field);
-        *index_rtrn = expr->value.array.entry;
+        *elem_rtrn = xkb_atom_text(ctx, expr->array_ref.element);
+        *field_rtrn = xkb_atom_text(ctx, expr->array_ref.field);
+        *index_rtrn = expr->array_ref.entry;
         return true;
     default:
         break;
     }
-    log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->op);
+    log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->expr.op);
     return false;
 }
 
@@ -127,19 +127,19 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
     bool ok = false;
     const char *ident;
 
-    switch (expr->op) {
+    switch (expr->expr.op) {
     case EXPR_VALUE:
-        if (expr->value_type != EXPR_TYPE_BOOLEAN) {
+        if (expr->expr.value_type != EXPR_TYPE_BOOLEAN) {
             log_err(ctx,
                     "Found constant of type %s where boolean was expected\n",
-                    expr_value_type_to_string(expr->value_type));
+                    expr_value_type_to_string(expr->expr.value_type));
             return false;
         }
-        *set_rtrn = expr->value.set;
+        *set_rtrn = expr->boolean.set;
         return true;
 
     case EXPR_IDENT:
-        ident = xkb_atom_text(ctx, expr->value.ident);
+        ident = xkb_atom_text(ctx, expr->ident.ident);
         if (ident) {
             if (istreq(ident, "true") ||
                 istreq(ident, "yes") ||
@@ -154,14 +154,13 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
                 return true;
             }
         }
-        log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n",
-                xkb_atom_text(ctx, expr->value.ident));
+        log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n", ident);
         return false;
 
     case EXPR_FIELD_REF:
         log_err(ctx, "Default \"%s.%s\" of type boolean is unknown\n",
-                xkb_atom_text(ctx, expr->value.field.element),
-                xkb_atom_text(ctx, expr->value.field.field));
+                xkb_atom_text(ctx, expr->field_ref.element),
+                xkb_atom_text(ctx, expr->field_ref.field));
         return false;
 
     case EXPR_INVERT:
@@ -178,11 +177,12 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
     case EXPR_NEGATE:
     case EXPR_UNARY_PLUS:
         log_err(ctx, "%s of boolean values not permitted\n",
-                expr_op_type_to_string(expr->op));
+                expr_op_type_to_string(expr->expr.op));
         break;
 
     default:
-        log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n", expr->op);
+        log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n",
+                 expr->expr.op);
         break;
     }
 
@@ -194,32 +194,28 @@ ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr,
                    xkb_keycode_t *kc)
 {
     xkb_keycode_t leftRtrn, rightRtrn;
-    ExprDef *left, *right;
 
-    switch (expr->op) {
+    switch (expr->expr.op) {
     case EXPR_VALUE:
-        if (expr->value_type != EXPR_TYPE_INT) {
+        if (expr->expr.value_type != EXPR_TYPE_INT) {
             log_err(ctx,
                     "Found constant of type %s where an int was expected\n",
-                    expr_value_type_to_string(expr->value_type));
+                    expr_value_type_to_string(expr->expr.value_type));
             return false;
         }
 
-        *kc = (xkb_keycode_t) expr->value.ival;
+        *kc = (xkb_keycode_t) expr->integer.ival;
         return true;
 
     case EXPR_ADD:
     case EXPR_SUBTRACT:
     case EXPR_MULTIPLY:
     case EXPR_DIVIDE:
-        left = expr->value.binary.left;
-        right = expr->value.binary.right;
-
-        if (!ExprResolveKeyCode(ctx, left, &leftRtrn) ||
-            !ExprResolveKeyCode(ctx, right, &rightRtrn))
+        if (!ExprResolveKeyCode(ctx, expr->binary.left, &leftRtrn) ||
+            !ExprResolveKeyCode(ctx, expr->binary.right, &rightRtrn))
             return false;
 
-        switch (expr->op) {
+        switch (expr->expr.op) {
         case EXPR_ADD:
             *kc = leftRtrn + rightRtrn;
             break;
@@ -245,19 +241,18 @@ ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr,
         return true;
 
     case EXPR_NEGATE:
-        left = expr->value.child;
-        if (!ExprResolveKeyCode(ctx, left, &leftRtrn))
+        if (!ExprResolveKeyCode(ctx, expr->unary.child, &leftRtrn))
             return false;
 
         *kc = ~leftRtrn;
         return true;
 
     case EXPR_UNARY_PLUS:
-        left = expr->value.child;
-        return ExprResolveKeyCode(ctx, left, kc);
+        return ExprResolveKeyCode(ctx, expr->unary.child, kc);
 
     default:
-        log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n", expr->op);
+        log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n",
+                 expr->expr.op);
         break;
     }
 
@@ -284,25 +279,25 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
     unsigned u;
     ExprDef *left, *right;
 
-    switch (expr->op) {
+    switch (expr->expr.op) {
     case EXPR_VALUE:
-        if (expr->value_type != EXPR_TYPE_INT) {
+        if (expr->expr.value_type != EXPR_TYPE_INT) {
             log_err(ctx,
                     "Found constant of type %s where an int was expected\n",
-                    expr_value_type_to_string(expr->value_type));
+                    expr_value_type_to_string(expr->expr.value_type));
             return false;
         }
 
-        *val_rtrn = expr->value.ival;
+        *val_rtrn = expr->integer.ival;
         return true;
 
     case EXPR_IDENT:
         if (lookup)
-            ok = lookup(ctx, lookupPriv, expr->value.ident, EXPR_TYPE_INT, &u);
+            ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, &u);
 
         if (!ok)
             log_err(ctx, "Identifier \"%s\" of type int is unknown\n",
-                    xkb_atom_text(ctx, expr->value.ident));
+                    xkb_atom_text(ctx, expr->ident.ident));
         else
             *val_rtrn = (int) u;
 
@@ -310,21 +305,21 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
 
     case EXPR_FIELD_REF:
         log_err(ctx, "Default \"%s.%s\" of type int is unknown\n",
-                xkb_atom_text(ctx, expr->value.field.element),
-                xkb_atom_text(ctx, expr->value.field.field));
+                xkb_atom_text(ctx, expr->field_ref.element),
+                xkb_atom_text(ctx, expr->field_ref.field));
         return false;
 
     case EXPR_ADD:
     case EXPR_SUBTRACT:
     case EXPR_MULTIPLY:
     case EXPR_DIVIDE:
-        left = expr->value.binary.left;
-        right = expr->value.binary.right;
+        left = expr->binary.left;
+        right = expr->binary.right;
         if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv) ||
             !ExprResolveIntegerLookup(ctx, right, &r, lookup, lookupPriv))
             return false;
 
-        switch (expr->op) {
+        switch (expr->expr.op) {
         case EXPR_ADD:
             *val_rtrn = l + r;
             break;
@@ -357,20 +352,21 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
 
     case EXPR_INVERT:
     case EXPR_NEGATE:
-        left = expr->value.child;
+        left = expr->unary.child;
         if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv))
             return false;
 
-        *val_rtrn = (expr->op == EXPR_NEGATE ? -l : ~l);
+        *val_rtrn = (expr->expr.op == EXPR_NEGATE ? -l : ~l);
         return true;
 
     case EXPR_UNARY_PLUS:
-        left = expr->value.child;
+        left = expr->unary.child;
         return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup,
                                         lookupPriv);
 
     default:
-        log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n", expr->op);
+        log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n",
+                 expr->expr.op);
         break;
     }
 
@@ -445,26 +441,26 @@ bool
 ExprResolveString(struct xkb_context *ctx, const ExprDef *expr,
                   xkb_atom_t *val_rtrn)
 {
-    switch (expr->op) {
+    switch (expr->expr.op) {
     case EXPR_VALUE:
-        if (expr->value_type != EXPR_TYPE_STRING) {
+        if (expr->expr.value_type != EXPR_TYPE_STRING) {
             log_err(ctx, "Found constant of type %s, expected a string\n",
-                    expr_value_type_to_string(expr->value_type));
+                    expr_value_type_to_string(expr->expr.value_type));
             return false;
         }
 
-        *val_rtrn = expr->value.str;
+        *val_rtrn = expr->string.str;
         return true;
 
     case EXPR_IDENT:
         log_err(ctx, "Identifier \"%s\" of type string not found\n",
-                xkb_atom_text(ctx, expr->value.ident));
+                xkb_atom_text(ctx, expr->ident.ident));
         return false;
 
     case EXPR_FIELD_REF:
         log_err(ctx, "Default \"%s.%s\" of type string not found\n",
-                xkb_atom_text(ctx, expr->value.field.element),
-                xkb_atom_text(ctx, expr->value.field.field));
+                xkb_atom_text(ctx, expr->field_ref.element),
+                xkb_atom_text(ctx, expr->field_ref.field));
         return false;
 
     case EXPR_ADD:
@@ -477,11 +473,12 @@ ExprResolveString(struct xkb_context *ctx, const ExprDef *expr,
     case EXPR_NOT:
     case EXPR_UNARY_PLUS:
         log_err(ctx, "%s of strings not permitted\n",
-                expr_op_type_to_string(expr->op));
+                expr_op_type_to_string(expr->expr.op));
         return false;
 
     default:
-        log_wsgo(ctx, "Unknown operator %d in ResolveString\n", expr->op);
+        log_wsgo(ctx, "Unknown operator %d in ResolveString\n",
+                 expr->expr.op);
         break;
     }
     return false;
@@ -491,16 +488,16 @@ bool
 ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr,
                 unsigned int *val_rtrn, const LookupEntry *values)
 {
-    if (expr->op != EXPR_IDENT) {
+    if (expr->expr.op != EXPR_IDENT) {
         log_err(ctx, "Found a %s where an enumerated value was expected\n",
-                expr_op_type_to_string(expr->op));
+                expr_op_type_to_string(expr->expr.op));
         return false;
     }
 
-    if (!SimpleLookup(ctx, values, expr->value.ident, EXPR_TYPE_INT,
+    if (!SimpleLookup(ctx, values, expr->ident.ident, EXPR_TYPE_INT,
                       val_rtrn)) {
         log_err(ctx, "Illegal identifier %s; expected one of:\n",
-                xkb_atom_text(ctx, expr->value.ident));
+                xkb_atom_text(ctx, expr->ident.ident));
         while (values && values->name)
         {
             log_err(ctx, "\t%s\n", values->name);
@@ -523,29 +520,29 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
     ExprDef *left, *right;
     const char *bogus = NULL;
 
-    switch (expr->op) {
+    switch (expr->expr.op) {
     case EXPR_VALUE:
-        if (expr->value_type != EXPR_TYPE_INT) {
+        if (expr->expr.value_type != EXPR_TYPE_INT) {
             log_err(ctx,
                     "Found constant of type %s where a mask was expected\n",
-                    expr_value_type_to_string(expr->value_type));
+                    expr_value_type_to_string(expr->expr.value_type));
             return false;
         }
-        *val_rtrn = (unsigned int) expr->value.ival;
+        *val_rtrn = (unsigned int) expr->integer.ival;
         return true;
 
     case EXPR_IDENT:
-        ok = lookup(ctx, lookupPriv, expr->value.ident, EXPR_TYPE_INT,
+        ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT,
                     val_rtrn);
         if (!ok)
             log_err(ctx, "Identifier \"%s\" of type int is unknown\n",
-                    xkb_atom_text(ctx, expr->value.ident));
+                    xkb_atom_text(ctx, expr->ident.ident));
         return ok;
 
     case EXPR_FIELD_REF:
         log_err(ctx, "Default \"%s.%s\" of type int is unknown\n",
-                xkb_atom_text(ctx, expr->value.field.element),
-                xkb_atom_text(ctx, expr->value.field.field));
+                xkb_atom_text(ctx, expr->field_ref.element),
+                xkb_atom_text(ctx, expr->field_ref.field));
         return false;
 
     case EXPR_ARRAY_REF:
@@ -563,13 +560,13 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
     case EXPR_SUBTRACT:
     case EXPR_MULTIPLY:
     case EXPR_DIVIDE:
-        left = expr->value.binary.left;
-        right = expr->value.binary.right;
+        left = expr->binary.left;
+        right = expr->binary.right;
         if (!ExprResolveMaskLookup(ctx, left, &l, lookup, lookupPriv) ||
             !ExprResolveMaskLookup(ctx, right, &r, lookup, lookupPriv))
             return false;
 
-        switch (expr->op) {
+        switch (expr->expr.op) {
         case EXPR_ADD:
             *val_rtrn = l | r;
             break;
@@ -579,7 +576,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
         case EXPR_MULTIPLY:
         case EXPR_DIVIDE:
             log_err(ctx, "Cannot %s masks; Illegal operation ignored\n",
-                    (expr->op == EXPR_DIVIDE ? "divide" : "multiply"));
+                    (expr->expr.op == EXPR_DIVIDE ? "divide" : "multiply"));
             return false;
         default:
             break;
@@ -592,7 +589,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
         break;
 
     case EXPR_INVERT:
-        left = expr->value.child;
+        left = expr->unary.child;
         if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv))
             return false;
 
@@ -602,14 +599,15 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
     case EXPR_UNARY_PLUS:
     case EXPR_NEGATE:
     case EXPR_NOT:
-        left = expr->value.child;
+        left = expr->unary.child;
         if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv))
             log_err(ctx, "The %s operator cannot be used with a mask\n",
-                    (expr->op == EXPR_NEGATE ? "-" : "!"));
+                    (expr->expr.op == EXPR_NEGATE ? "-" : "!"));
         return false;
 
     default:
-        log_wsgo(ctx, "Unknown operator %d in ResolveMask\n", expr->op);
+        log_wsgo(ctx, "Unknown operator %d in ResolveMask\n",
+                 expr->expr.op);
         break;
     }
 
@@ -638,9 +636,8 @@ ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr,
 {
     int val;
 
-    if (expr->op == EXPR_IDENT) {
-        const char *str;
-        str = xkb_atom_text(ctx, expr->value.ident);
+    if (expr->expr.op == EXPR_IDENT) {
+        const char *str = xkb_atom_text(ctx, expr->ident.ident);
         *sym_rtrn = xkb_keysym_from_name(str, 0);
         if (*sym_rtrn != XKB_KEY_NoSymbol)
             return true;
@@ -652,7 +649,7 @@ ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr,
     if (val < 0 || val >= 10)
         return false;
 
-    *sym_rtrn = ((xkb_keysym_t) val) + '0';
+    *sym_rtrn = XKB_KEY_0 + (xkb_keysym_t) val;
     return true;
 }
 
@@ -661,16 +658,17 @@ ExprResolveMod(struct xkb_keymap *keymap, const ExprDef *def,
                enum mod_type mod_type, xkb_mod_index_t *ndx_rtrn)
 {
     xkb_mod_index_t ndx;
-    xkb_atom_t name = def->value.ident;
+    xkb_atom_t name;
 
-    if (def->op != EXPR_IDENT) {
+    if (def->expr.op != EXPR_IDENT) {
         log_err(keymap->ctx,
                 "Cannot resolve virtual modifier: "
                 "found %s where a virtual modifier name was expected\n",
-                expr_op_type_to_string(def->op));
+                expr_op_type_to_string(def->expr.op));
         return false;
     }
 
+    name = def->ident.ident;
     ndx = ModNameToIndex(keymap, name, mod_type);
     if (ndx == XKB_MOD_INVALID) {
         log_err(keymap->ctx,
index 272562f..167af8e 100644 (file)
@@ -636,13 +636,13 @@ Expr            :       Expr DIVIDE Expr
                 ;
 
 Term            :       MINUS Term
-                        { $$ = ExprCreateUnary(EXPR_NEGATE, $2->value_type, $2); }
+                        { $$ = ExprCreateUnary(EXPR_NEGATE, $2->expr.value_type, $2); }
                 |       PLUS Term
-                        { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->value_type, $2); }
+                        { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->expr.value_type, $2); }
                 |       EXCLAM Term
                         { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); }
                 |       INVERT Term
-                        { $$ = ExprCreateUnary(EXPR_INVERT, $2->value_type, $2); }
+                        { $$ = ExprCreateUnary(EXPR_INVERT, $2->expr.value_type, $2); }
                 |       Lhs
                         { $$ = $1;  }
                 |       FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
index 075516d..36d87b8 100644 (file)
@@ -646,11 +646,11 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
         return true;
     }
 
-    if (value->op != EXPR_KEYSYM_LIST) {
+    if (value->expr.op != EXPR_KEYSYM_LIST) {
         log_err(info->keymap->ctx,
                 "Expected a list of symbols, found %s; "
                 "Ignoring symbols for group %u of %s\n",
-                expr_op_type_to_string(value->op), ndx + 1,
+                expr_op_type_to_string(value->expr.op), ndx + 1,
                 KeyInfoText(info, keyi));
         return false;
     }
@@ -663,7 +663,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
         return false;
     }
 
-    nLevels = darray_size(value->value.list.symsMapIndex);
+    nLevels = darray_size(value->keysym_list.symsMapIndex);
     if (darray_size(groupi->levels) < nLevels)
         darray_resize0(groupi->levels, nLevels);
 
@@ -673,13 +673,13 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
         unsigned int sym_index;
         struct xkb_level *leveli = &darray_item(groupi->levels, i);
 
-        sym_index = darray_item(value->value.list.symsMapIndex, i);
-        leveli->num_syms = darray_item(value->value.list.symsNumEntries, i);
+        sym_index = darray_item(value->keysym_list.symsMapIndex, i);
+        leveli->num_syms = darray_item(value->keysym_list.symsNumEntries, i);
         if (leveli->num_syms > 1)
             leveli->u.syms = calloc(leveli->num_syms, sizeof(*leveli->u.syms));
 
         for (j = 0; j < leveli->num_syms; j++) {
-            xkb_keysym_t keysym = darray_item(value->value.list.syms,
+            xkb_keysym_t keysym = darray_item(value->keysym_list.syms,
                                               sym_index + j);
 
             if (leveli->num_syms == 1) {
@@ -718,11 +718,11 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
         return true;
     }
 
-    if (value->op != EXPR_ACTION_LIST) {
+    if (value->expr.op != EXPR_ACTION_LIST) {
         log_wsgo(info->keymap->ctx,
                  "Bad expression type (%d) for action list value; "
                  "Ignoring actions for group %u of %s\n",
-                 value->op, ndx, KeyInfoText(info, keyi));
+                 value->expr.op, ndx, KeyInfoText(info, keyi));
         return false;
     }
 
@@ -734,7 +734,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
     }
 
     nActs = 0;
-    for (act = value->value.child; act; act = (ExprDef *) act->common.next)
+    for (act = value->unary.child; act; act = (ExprDef *) act->common.next)
         nActs++;
 
     if (darray_size(groupi->levels) < nActs)
@@ -742,7 +742,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
 
     groupi->defined |= GROUP_FIELD_ACTS;
 
-    act = value->value.child;
+    act = value->unary.child;
     for (i = 0; i < nActs; i++) {
         toAct = &darray_item(groupi->levels, i).action;
 
@@ -822,7 +822,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
             log_err(info->keymap->ctx,
                     "Expected a virtual modifier mask, found %s; "
                     "Ignoring virtual modifiers definition for key %s\n",
-                    expr_op_type_to_string(value->op),
+                    expr_op_type_to_string(value->expr.op),
                     KeyInfoText(info, keyi));
         }
     }
@@ -1038,7 +1038,7 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
     ExprDef *arrayNdx;
 
     for (; def; def = (VarDef *) def->common.next) {
-        if (def->name && def->name->op == EXPR_FIELD_REF) {
+        if (def->name && def->name->expr.op == EXPR_FIELD_REF) {
             log_err(info->keymap->ctx,
                     "Cannot set a global default value from within a key statement; "
                     "Move statements to the global file scope\n");
@@ -1046,7 +1046,7 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
         }
 
         if (!def->name) {
-            if (!def->value || def->value->op == EXPR_KEYSYM_LIST)
+            if (!def->value || def->value->expr.op == EXPR_KEYSYM_LIST)
                 field = "symbols";
             else
                 field = "actions";
@@ -1157,9 +1157,10 @@ HandleModMapDef(SymbolsInfo *info, ModMapDef *def)
     for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) {
         xkb_keysym_t sym;
 
-        if (key->op == EXPR_VALUE && key->value_type == EXPR_TYPE_KEYNAME) {
+        if (key->expr.op == EXPR_VALUE &&
+            key->expr.value_type == EXPR_TYPE_KEYNAME) {
             tmp.haveSymbol = false;
-            tmp.u.keyName = key->value.keyName;
+            tmp.u.keyName = key->key_name.key_name;
         }
         else if (ExprResolveKeySym(ctx, key, &sym)) {
             tmp.haveSymbol = true;