killing the union types
authorWolfgang Bumiller <wry.git@bumiller.com>
Sat, 11 May 2013 20:34:01 +0000 (22:34 +0200)
committerWolfgang Bumiller <wry.git@bumiller.com>
Sat, 11 May 2013 20:34:01 +0000 (22:34 +0200)
ast.c
ast.h
parser.c

diff --git a/ast.c b/ast.c
index 1e2836f..b104073 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -34,7 +34,7 @@
         return NULL;                                                \
     }                                                               \
     ast_node_init((ast_node*)self, ctx, TYPE_##T);                  \
-    ( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn
+    ( (ast_node*)self )->destroy = (ast_node_delete*)destroyfn
 
 
 /* It must not be possible to get here. */
@@ -48,11 +48,11 @@ static GMQCC_NORETURN void _ast_node_destroy(ast_node *self)
 /* Initialize main ast node aprts */
 static void ast_node_init(ast_node *self, lex_ctx ctx, int nodetype)
 {
-    self->node.context = ctx;
-    self->node.destroy = &_ast_node_destroy;
-    self->node.keep    = false;
-    self->node.nodetype = nodetype;
-    self->node.side_effects = false;
+    self->context = ctx;
+    self->destroy = &_ast_node_destroy;
+    self->keep    = false;
+    self->nodetype = nodetype;
+    self->side_effects = false;
 }
 
 /* weight and side effects */
@@ -67,28 +67,28 @@ static void _ast_propagate_effects(ast_node *self, ast_node *other)
 static void ast_expression_init(ast_expression *self,
                                 ast_expression_codegen *codegen)
 {
-    self->expression.codegen  = codegen;
-    self->expression.vtype    = TYPE_VOID;
-    self->expression.next     = NULL;
-    self->expression.outl     = NULL;
-    self->expression.outr     = NULL;
-    self->expression.params   = NULL;
-    self->expression.count    = 0;
-    self->expression.flags    = 0;
-    self->expression.varparam = NULL;
+    self->codegen  = codegen;
+    self->vtype    = TYPE_VOID;
+    self->next     = NULL;
+    self->outl     = NULL;
+    self->outr     = NULL;
+    self->params   = NULL;
+    self->count    = 0;
+    self->flags    = 0;
+    self->varparam = NULL;
 }
 
 static void ast_expression_delete(ast_expression *self)
 {
     size_t i;
-    if (self->expression.next)
-        ast_delete(self->expression.next);
-    for (i = 0; i < vec_size(self->expression.params); ++i) {
-        ast_delete(self->expression.params[i]);
+    if (self->next)
+        ast_delete(self->next);
+    for (i = 0; i < vec_size(self->params); ++i) {
+        ast_delete(self->params[i]);
     }
-    vec_free(self->expression.params);
-    if (self->expression.varparam)
-        ast_delete(self->expression.varparam);
+    vec_free(self->params);
+    if (self->varparam)
+        ast_delete(self->varparam);
 }
 
 static void ast_expression_delete_full(ast_expression *self)
@@ -100,8 +100,8 @@ static void ast_expression_delete_full(ast_expression *self)
 ast_value* ast_value_copy(const ast_value *self)
 {
     size_t i;
-    const ast_expression_common *fromex;
-    ast_expression_common *selfex;
+    const ast_expression *fromex;
+    ast_expression       *selfex;
     ast_value *cp = ast_value_new(self->expression.node.context, self->name, self->expression.vtype);
     if (self->expression.next) {
         cp->expression.next = ast_type_copy(self->expression.node.context, self->expression.next);
@@ -120,14 +120,14 @@ ast_value* ast_value_copy(const ast_value *self)
 void ast_type_adopt_impl(ast_expression *self, const ast_expression *other)
 {
     size_t i;
-    const ast_expression_common *fromex;
-    ast_expression_common *selfex;
-    self->expression.vtype = other->expression.vtype;
-    if (other->expression.next) {
-        self->expression.next = (ast_expression*)ast_type_copy(ast_ctx(self), other->expression.next);
-    }
-    fromex   = &other->expression;
-    selfex = &self->expression;
+    const ast_expression *fromex;
+    ast_expression       *selfex;
+    self->vtype = other->vtype;
+    if (other->next) {
+        self->next = (ast_expression*)ast_type_copy(ast_ctx(self), other->next);
+    }
+    fromex = other;
+    selfex = self;
     selfex->count    = fromex->count;
     selfex->flags    = fromex->flags;
     for (i = 0; i < vec_size(fromex->params); ++i) {
@@ -140,17 +140,17 @@ static ast_expression* ast_shallow_type(lex_ctx ctx, int vtype)
 {
     ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
     ast_expression_init(self, NULL);
-    self->expression.codegen = NULL;
-    self->expression.next    = NULL;
-    self->expression.vtype   = vtype;
+    self->codegen = NULL;
+    self->next    = NULL;
+    self->vtype   = vtype;
     return self;
 }
 
 ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
 {
     size_t i;
-    const ast_expression_common *fromex;
-    ast_expression_common *selfex;
+    const ast_expression *fromex;
+    ast_expression       *selfex;
 
     if (!ex)
         return NULL;
@@ -159,8 +159,8 @@ ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
         ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
         ast_expression_init(self, NULL);
 
-        fromex   = &ex->expression;
-        selfex = &self->expression;
+        fromex = ex;
+        selfex = self;
 
         /* This may never be codegen()d */
         selfex->codegen = NULL;
@@ -184,30 +184,30 @@ ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
 
 bool ast_compare_type(ast_expression *a, ast_expression *b)
 {
-    if (a->expression.vtype == TYPE_NIL ||
-        b->expression.vtype == TYPE_NIL)
+    if (a->vtype == TYPE_NIL ||
+        b->vtype == TYPE_NIL)
         return true;
-    if (a->expression.vtype != b->expression.vtype)
+    if (a->vtype != b->vtype)
         return false;
-    if (!a->expression.next != !b->expression.next)
+    if (!a->next != !b->next)
         return false;
-    if (vec_size(a->expression.params) != vec_size(b->expression.params))
+    if (vec_size(a->params) != vec_size(b->params))
         return false;
-    if ((a->expression.flags & AST_FLAG_TYPE_MASK) !=
-        (b->expression.flags & AST_FLAG_TYPE_MASK) )
+    if ((a->flags & AST_FLAG_TYPE_MASK) !=
+        (b->flags & AST_FLAG_TYPE_MASK) )
     {
         return false;
     }
-    if (vec_size(a->expression.params)) {
+    if (vec_size(a->params)) {
         size_t i;
-        for (i = 0; i < vec_size(a->expression.params); ++i) {
-            if (!ast_compare_type((ast_expression*)a->expression.params[i],
-                                  (ast_expression*)b->expression.params[i]))
+        for (i = 0; i < vec_size(a->params); ++i) {
+            if (!ast_compare_type((ast_expression*)a->params[i],
+                                  (ast_expression*)b->params[i]))
                 return false;
         }
     }
-    if (a->expression.next)
-        return ast_compare_type(a->expression.next, b->expression.next);
+    if (a->next)
+        return ast_compare_type(a->next, b->next);
     return true;
 }
 
@@ -227,43 +227,43 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi
     if (pos + 1 >= bufsize)
         goto full;
 
-    switch (e->expression.vtype) {
+    switch (e->vtype) {
         case TYPE_VARIANT:
             util_strncpy(buf + pos, "(variant)", 9);
             return pos + 9;
 
         case TYPE_FIELD:
             buf[pos++] = '.';
-            return ast_type_to_string_impl(e->expression.next, buf, bufsize, pos);
+            return ast_type_to_string_impl(e->next, buf, bufsize, pos);
 
         case TYPE_POINTER:
             if (pos + 3 >= bufsize)
                 goto full;
             buf[pos++] = '*';
             buf[pos++] = '(';
-            pos = ast_type_to_string_impl(e->expression.next, buf, bufsize, pos);
+            pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
             if (pos + 1 >= bufsize)
                 goto full;
             buf[pos++] = ')';
             return pos;
 
         case TYPE_FUNCTION:
-            pos = ast_type_to_string_impl(e->expression.next, buf, bufsize, pos);
+            pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
             if (pos + 2 >= bufsize)
                 goto full;
-            if (!vec_size(e->expression.params)) {
+            if (!vec_size(e->params)) {
                 buf[pos++] = '(';
                 buf[pos++] = ')';
                 return pos;
             }
             buf[pos++] = '(';
-            pos = ast_type_to_string_impl((ast_expression*)(e->expression.params[0]), buf, bufsize, pos);
-            for (i = 1; i < vec_size(e->expression.params); ++i) {
+            pos = ast_type_to_string_impl((ast_expression*)(e->params[0]), buf, bufsize, pos);
+            for (i = 1; i < vec_size(e->params); ++i) {
                 if (pos + 2 >= bufsize)
                     goto full;
                 buf[pos++] = ',';
                 buf[pos++] = ' ';
-                pos = ast_type_to_string_impl((ast_expression*)(e->expression.params[i]), buf, bufsize, pos);
+                pos = ast_type_to_string_impl((ast_expression*)(e->params[i]), buf, bufsize, pos);
             }
             if (pos + 1 >= bufsize)
                 goto full;
@@ -271,18 +271,18 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi
             return pos;
 
         case TYPE_ARRAY:
-            pos = ast_type_to_string_impl(e->expression.next, buf, bufsize, pos);
+            pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
             if (pos + 1 >= bufsize)
                 goto full;
             buf[pos++] = '[';
-            pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->expression.count);
+            pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count);
             if (pos + 1 >= bufsize)
                 goto full;
             buf[pos++] = ']';
             return pos;
 
         default:
-            typestr = type_name[e->expression.vtype];
+            typestr = type_name[e->vtype];
             typelen = strlen(typestr);
             if (pos + typelen >= bufsize)
                 goto full;
@@ -364,7 +364,7 @@ void ast_value_delete(ast_value* self)
         mem_d(self->desc);
 
     if (self->initlist) {
-        if (self->expression.next->expression.vtype == TYPE_STRING) {
+        if (self->expression.next->vtype == TYPE_STRING) {
             /* strings are allocated, free them */
             size_t i, len = vec_size(self->initlist);
             /* in theory, len should be expression.count
@@ -422,7 +422,7 @@ ast_binary* ast_binary_new(lex_ctx ctx, int op,
     else if (op == INSTR_MUL_V)
         self->expression.vtype = TYPE_FLOAT;
     else
-        self->expression.vtype = left->expression.vtype;
+        self->expression.vtype = left->vtype;
 
     /* references all */
     self->refs = AST_REF_ALL;
@@ -516,11 +516,11 @@ void ast_return_delete(ast_return *self)
 
 ast_entfield* ast_entfield_new(lex_ctx ctx, ast_expression *entity, ast_expression *field)
 {
-    if (field->expression.vtype != TYPE_FIELD) {
+    if (field->vtype != TYPE_FIELD) {
         compile_error(ctx, "ast_entfield_new with expression not of type field");
         return NULL;
     }
-    return ast_entfield_new_force(ctx, entity, field, field->expression.next);
+    return ast_entfield_new_force(ctx, entity, field, field->next);
 }
 
 ast_entfield* ast_entfield_new_force(lex_ctx ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype)
@@ -560,9 +560,9 @@ ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int fiel
         return NULL;
     }
 
-    if (owner->expression.vtype != TYPE_VECTOR &&
-        owner->expression.vtype != TYPE_FIELD) {
-        compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->expression.vtype]);
+    if (owner->vtype != TYPE_VECTOR &&
+        owner->vtype != TYPE_FIELD) {
+        compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->vtype]);
         mem_d(self);
         return NULL;
     }
@@ -570,7 +570,7 @@ ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int fiel
     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
     self->expression.node.keep = true; /* keep */
 
-    if (owner->expression.vtype == TYPE_VECTOR) {
+    if (owner->vtype == TYPE_VECTOR) {
         self->expression.vtype = TYPE_FLOAT;
         self->expression.next  = NULL;
     } else {
@@ -619,7 +619,7 @@ ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_exp
     ast_expression *outtype;
     ast_instantiate(ast_array_index, ctx, ast_array_index_delete);
 
-    outtype = array->expression.next;
+    outtype = array->next;
     if (!outtype) {
         mem_d(self);
         /* Error: field has no type... */
@@ -634,7 +634,7 @@ ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_exp
     ast_propagate_effects(self, index);
 
     ast_type_adopt(self, outtype);
-    if (array->expression.vtype == TYPE_FIELD && outtype->expression.vtype == TYPE_ARRAY) {
+    if (array->vtype == TYPE_FIELD && outtype->vtype == TYPE_ARRAY) {
         if (self->expression.vtype != TYPE_ARRAY) {
             compile_error(ast_ctx(self), "array_index node on type");
             ast_array_index_delete(self);
@@ -708,7 +708,7 @@ ast_ternary* ast_ternary_new(lex_ctx ctx, ast_expression *cond, ast_expression *
     ast_propagate_effects(self, ontrue);
     ast_propagate_effects(self, onfalse);
 
-    if (ontrue->expression.vtype == TYPE_NIL)
+    if (ontrue->vtype == TYPE_NIL)
         exprtype = onfalse;
     ast_type_adopt(self, exprtype);
 
@@ -878,7 +878,7 @@ ast_call* ast_call_new(lex_ctx ctx,
                        ast_expression *funcexpr)
 {
     ast_instantiate(ast_call, ctx, ast_call_delete);
-    if (!funcexpr->expression.next) {
+    if (!funcexpr->next) {
         compile_error(ctx, "not a function");
         mem_d(self);
         return NULL;
@@ -891,7 +891,7 @@ ast_call* ast_call_new(lex_ctx ctx,
     self->func     = funcexpr;
     self->va_count = NULL;
 
-    ast_type_adopt(self, funcexpr->expression.next);
+    ast_type_adopt(self, funcexpr->next);
 
     return self;
 }
@@ -921,14 +921,14 @@ bool ast_call_check_types(ast_call *self)
     bool   retval = true;
     const  ast_expression *func = self->func;
     size_t count = vec_size(self->params);
-    if (count > vec_size(func->expression.params))
-        count = vec_size(func->expression.params);
+    if (count > vec_size(func->params))
+        count = vec_size(func->params);
 
     for (i = 0; i < count; ++i) {
-        if (!ast_compare_type(self->params[i], (ast_expression*)(func->expression.params[i])))
+        if (!ast_compare_type(self->params[i], (ast_expression*)(func->params[i])))
         {
             ast_type_to_string(self->params[i], tgot, sizeof(tgot));
-            ast_type_to_string((ast_expression*)func->expression.params[i], texp, sizeof(texp));
+            ast_type_to_string((ast_expression*)func->params[i], texp, sizeof(texp));
             compile_error(ast_ctx(self), "invalid type for parameter %u in function call: expected %s, got %s",
                      (unsigned int)(i+1), texp, tgot);
             /* we don't immediately return */
@@ -936,12 +936,12 @@ bool ast_call_check_types(ast_call *self)
         }
     }
     count = vec_size(self->params);
-    if (count > vec_size(func->expression.params) && func->expression.varparam) {
+    if (count > vec_size(func->params) && func->varparam) {
         for (; i < count; ++i) {
-            if (!ast_compare_type(self->params[i], func->expression.varparam))
+            if (!ast_compare_type(self->params[i], func->varparam))
             {
                 ast_type_to_string(self->params[i], tgot, sizeof(tgot));
-                ast_type_to_string(func->expression.varparam, texp, sizeof(texp));
+                ast_type_to_string(func->varparam, texp, sizeof(texp));
                 compile_error(ast_ctx(self), "invalid type for parameter %u in function call: expected %s, got %s",
                          (unsigned int)(i+1), texp, tgot);
                 /* we don't immediately return */
@@ -1005,7 +1005,7 @@ bool ast_block_add_expr(ast_block *self, ast_expression *e)
 void ast_block_collect(ast_block *self, ast_expression *expr)
 {
     vec_push(self->collect, expr);
-    expr->expression.node.keep = true;
+    expr->node.keep = true;
 }
 
 void ast_block_delete(ast_block *self)
@@ -1132,12 +1132,12 @@ const char* ast_function_label(ast_function *self, const char *prefix)
  * But I can't imagine a pituation where the output is truly unnecessary.
  */
 
-void _ast_codegen_output_type(ast_expression_common *self, ir_value *out)
+void _ast_codegen_output_type(ast_expression *self, ir_value *out)
 {
     if (out->vtype == TYPE_FIELD)
-        out->fieldtype = self->next->expression.vtype;
+        out->fieldtype = self->next->vtype;
     if (out->vtype == TYPE_FUNCTION)
-        out->outtype = self->next->expression.vtype;
+        out->outtype = self->next->vtype;
 }
 
 #define codegen_output_type(a,o) (_ast_codegen_output_type(&((a)->expression),(o)))
@@ -1178,7 +1178,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
 
     if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
     {
-        ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->expression.vtype);
+        ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->vtype);
         if (!func)
             return false;
         func->context = ast_ctx(self);
@@ -1200,14 +1200,14 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             goto error;
         }
 
-        if (fieldtype->expression.vtype == TYPE_ARRAY) {
+        if (fieldtype->vtype == TYPE_ARRAY) {
             size_t ai;
             char   *name;
             size_t  namelen;
 
-            ast_expression_common *elemtype;
-            int                    vtype;
-            ast_value             *array = (ast_value*)fieldtype;
+            ast_expression *elemtype;
+            int             vtype;
+            ast_value      *array = (ast_value*)fieldtype;
 
             if (!ast_istype(fieldtype, ast_value)) {
                 compile_error(ast_ctx(self), "internal error: ast_value required");
@@ -1218,7 +1218,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             if (!array->expression.count || array->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE))
                 compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)array->expression.count);
 
-            elemtype = &array->expression.next->expression;
+            elemtype = array->expression.next;
             vtype = elemtype->vtype;
 
             v = ir_builder_create_field(ir, self->name, vtype);
@@ -1257,7 +1257,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
         }
         else
         {
-            v = ir_builder_create_field(ir, self->name, self->expression.next->expression.vtype);
+            v = ir_builder_create_field(ir, self->name, self->expression.next->vtype);
             if (!v)
                 return false;
             v->context = ast_ctx(self);
@@ -1273,7 +1273,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
         char   *name;
         size_t  namelen;
 
-        ast_expression_common *elemtype = &self->expression.next->expression;
+        ast_expression *elemtype = self->expression.next;
         int vtype = elemtype->vtype;
 
         /* same as with field arrays */
@@ -1403,7 +1403,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
         char   *name;
         size_t  namelen;
 
-        ast_expression_common *elemtype = &self->expression.next->expression;
+        ast_expression *elemtype = self->expression.next;
         int vtype = elemtype->vtype;
 
         func->flags |= IR_FLAG_HAS_ARRAYS;
@@ -1550,7 +1550,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
 {
     ir_function *irf;
     ir_value    *dummy;
-    ast_expression_common  *ec;
+    ast_expression         *ec;
     ast_expression_codegen *cgen;
     size_t    i;
 
@@ -1567,7 +1567,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
     for (i = 0; i < vec_size(ec->params); ++i)
     {
         if (ec->params[i]->expression.vtype == TYPE_FIELD)
-            vec_push(irf->params, ec->params[i]->expression.next->expression.vtype);
+            vec_push(irf->params, ec->params[i]->expression.next->vtype);
         else
             vec_push(irf->params, ec->params[i]->expression.vtype);
         if (!self->builtin) {
@@ -1632,7 +1632,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
     if (!self->curblock->final)
     {
         if (!self->vtype->expression.next ||
-            self->vtype->expression.next->expression.vtype == TYPE_VOID)
+            self->vtype->expression.next->vtype == TYPE_VOID)
         {
             return ir_block_create_return(self->curblock, ast_ctx(self), NULL);
         }
@@ -1701,7 +1701,7 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu
                 return false;
             continue;
         }
-        gen = self->exprs[i]->expression.codegen;
+        gen = self->exprs[i]->codegen;
         if (!(*gen)(self->exprs[i], func, false, out))
             return false;
     }
@@ -1765,7 +1765,7 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
         if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
             return false;
 
-        cgen = self->source->expression.codegen;
+        cgen = self->source->codegen;
         if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
             return false;
 
@@ -1780,13 +1780,13 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
     {
         /* regular code */
 
-        cgen = self->dest->expression.codegen;
+        cgen = self->dest->codegen;
         /* lvalue! */
         if (!(*cgen)((ast_expression*)(self->dest), func, true, &left))
             return false;
         self->expression.outl = left;
 
-        cgen = self->source->expression.codegen;
+        cgen = self->source->codegen;
         /* rvalue! */
         if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
             return false;
@@ -1838,7 +1838,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         merge    = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
 
         /* generate the left expression */
-        cgen = self->left->expression.codegen;
+        cgen = self->left->codegen;
         if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
             return false;
         /* remember the block */
@@ -1861,7 +1861,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         /* enter the right-expression's block */
         func->curblock = other;
         /* generate */
-        cgen = self->right->expression.codegen;
+        cgen = self->right->codegen;
         if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
             return false;
         /* remember block */
@@ -1924,11 +1924,11 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         return true;
     }
 
-    cgen = self->left->expression.codegen;
+    cgen = self->left->codegen;
     if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
         return false;
 
-    cgen = self->right->expression.codegen;
+    cgen = self->right->codegen;
     if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
         return false;
 
@@ -1979,12 +1979,12 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
         if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
             return false;
     }
-    cgen = self->dest->expression.codegen;
+    cgen = self->dest->codegen;
     if (!(*cgen)((ast_expression*)(self->dest), func, false, &leftr))
         return false;
 
     /* source as rvalue only */
-    cgen = self->source->expression.codegen;
+    cgen = self->source->codegen;
     if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
         return false;
 
@@ -2022,7 +2022,7 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
         self->expression.outr = bin;
     } else {
         /* now store them */
-        cgen = self->dest->expression.codegen;
+        cgen = self->dest->codegen;
         /* lvalue of destination */
         if (!(*cgen)((ast_expression*)(self->dest), func, true, &leftl))
             return false;
@@ -2061,7 +2061,7 @@ bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_valu
         return true;
     }
 
-    cgen = self->operand->expression.codegen;
+    cgen = self->operand->codegen;
     /* lvalue! */
     if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
         return false;
@@ -2097,7 +2097,7 @@ bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_va
     self->expression.outr = (ir_value*)1;
 
     if (self->operand) {
-        cgen = self->operand->expression.codegen;
+        cgen = self->operand->codegen;
         /* lvalue! */
         if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
             return false;
@@ -2132,11 +2132,11 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i
         return true;
     }
 
-    cgen = self->entity->expression.codegen;
+    cgen = self->entity->codegen;
     if (!(*cgen)((ast_expression*)(self->entity), func, false, &ent))
         return false;
 
-    cgen = self->field->expression.codegen;
+    cgen = self->field->codegen;
     if (!(*cgen)((ast_expression*)(self->field), func, false, &field))
         return false;
 
@@ -2184,12 +2184,12 @@ bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_va
         return true;
     }
 
-    cgen = self->owner->expression.codegen;
+    cgen = self->owner->codegen;
     if (!(*cgen)((ast_expression*)(self->owner), func, false, &vec))
         return false;
 
     if (vec->vtype != TYPE_VECTOR &&
-        !(vec->vtype == TYPE_FIELD && self->owner->expression.next->expression.vtype == TYPE_VECTOR))
+        !(vec->vtype == TYPE_FIELD && self->owner->next->vtype == TYPE_VECTOR))
     {
         return false;
     }
@@ -2243,7 +2243,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
             return false;
         }
 
-        cgen = self->index->expression.codegen;
+        cgen = self->index->codegen;
         if (!(*cgen)((ast_expression*)(self->index), func, false, &iridx))
             return false;
 
@@ -2265,7 +2265,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
 
     if (idx->expression.vtype == TYPE_FLOAT) {
         unsigned int arridx = idx->constval.vfloat;
-        if (arridx >= self->array->expression.count)
+        if (arridx >= self->array->count)
         {
             compile_error(ast_ctx(self), "array index out of bounds: %i", arridx);
             return false;
@@ -2274,7 +2274,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
     }
     else if (idx->expression.vtype == TYPE_INTEGER) {
         unsigned int arridx = idx->constval.vint;
-        if (arridx >= self->array->expression.count)
+        if (arridx >= self->array->count)
         {
             compile_error(ast_ctx(self), "array index out of bounds: %i", arridx);
             return false;
@@ -2315,7 +2315,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
     self->expression.outr = (ir_value*)1;
 
     /* generate the condition */
-    cgen = self->cond->expression.codegen;
+    cgen = self->cond->codegen;
     if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
         return false;
     /* update the block which will get the jump - because short-logic or ternaries may have changed this */
@@ -2333,7 +2333,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
         func->curblock = ontrue;
 
         /* generate */
-        cgen = self->on_true->expression.codegen;
+        cgen = self->on_true->codegen;
         if (!(*cgen)((ast_expression*)(self->on_true), func, false, &dummy))
             return false;
 
@@ -2353,7 +2353,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
         func->curblock = onfalse;
 
         /* generate */
-        cgen = self->on_false->expression.codegen;
+        cgen = self->on_false->codegen;
         if (!(*cgen)((ast_expression*)(self->on_false), func, false, &dummy))
             return false;
 
@@ -2422,7 +2422,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
 
     /* generate the condition */
     func->curblock = cond;
-    cgen = self->cond->expression.codegen;
+    cgen = self->cond->codegen;
     if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
         return false;
     cond_out = func->curblock;
@@ -2437,7 +2437,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
         func->curblock = ontrue;
 
         /* generate */
-        cgen = self->on_true->expression.codegen;
+        cgen = self->on_true->codegen;
         if (!(*cgen)((ast_expression*)(self->on_true), func, false, &trueval))
             return false;
 
@@ -2454,7 +2454,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
         func->curblock = onfalse;
 
         /* generate */
-        cgen = self->on_false->expression.codegen;
+        cgen = self->on_false->codegen;
         if (!(*cgen)((ast_expression*)(self->on_false), func, false, &falseval))
             return false;
 
@@ -2551,7 +2551,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
      */
     if (self->initexpr)
     {
-        cgen = self->initexpr->expression.codegen;
+        cgen = self->initexpr->codegen;
         if (!(*cgen)((ast_expression*)(self->initexpr), func, false, &dummy))
             return false;
     }
@@ -2575,7 +2575,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         func->curblock = bprecond;
 
         /* generate */
-        cgen = self->precond->expression.codegen;
+        cgen = self->precond->codegen;
         if (!(*cgen)((ast_expression*)(self->precond), func, false, &precond))
             return false;
 
@@ -2629,7 +2629,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
 
         /* generate */
         if (self->body) {
-            cgen = self->body->expression.codegen;
+            cgen = self->body->codegen;
             if (!(*cgen)((ast_expression*)(self->body), func, false, &dummy))
                 return false;
         }
@@ -2646,7 +2646,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         func->curblock = bpostcond;
 
         /* generate */
-        cgen = self->postcond->expression.codegen;
+        cgen = self->postcond->codegen;
         if (!(*cgen)((ast_expression*)(self->postcond), func, false, &postcond))
             return false;
 
@@ -2660,7 +2660,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         func->curblock = bincrement;
 
         /* generate */
-        cgen = self->increment->expression.codegen;
+        cgen = self->increment->codegen;
         if (!(*cgen)((ast_expression*)(self->increment), func, false, &dummy))
             return false;
 
@@ -2809,7 +2809,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
     (void)lvalue;
     (void)out;
 
-    cgen = self->operand->expression.codegen;
+    cgen = self->operand->codegen;
     if (!(*cgen)((ast_expression*)(self->operand), func, false, &irop))
         return false;
 
@@ -2842,7 +2842,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
         if (swcase->value) {
             /* A regular case */
             /* generate the condition operand */
-            cgen = swcase->value->expression.codegen;
+            cgen = swcase->value->codegen;
             if (!(*cgen)((ast_expression*)(swcase->value), func, false, &val))
                 return false;
             /* generate the condition */
@@ -2870,7 +2870,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
 
             /* enter the case */
             func->curblock = bcase;
-            cgen = swcase->code->expression.codegen;
+            cgen = swcase->code->codegen;
             if (!(*cgen)((ast_expression*)swcase->code, func, false, &dummy))
                 return false;
 
@@ -2915,7 +2915,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
         }
 
         /* Now generate the default code */
-        cgen = def_case->code->expression.codegen;
+        cgen = def_case->code->codegen;
         if (!(*cgen)((ast_expression*)def_case->code, func, false, &dummy))
             return false;
 
@@ -3040,7 +3040,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
         return true;
     }
 
-    cgen = self->func->expression.codegen;
+    cgen = self->func->codegen;
     if (!(*cgen)((ast_expression*)(self->func), func, false, &funval))
         return false;
     if (!funval)
@@ -3054,7 +3054,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
         ir_value *param;
         ast_expression *expr = self->params[i];
 
-        cgen = expr->expression.codegen;
+        cgen = expr->codegen;
         if (!(*cgen)(expr, func, false, &param))
             goto error;
         if (!param)
@@ -3066,7 +3066,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
     if (self->va_count) {
         ir_value   *va_count;
         ir_builder *builder = func->curblock->owner->owner;
-        cgen = self->va_count->expression.codegen;
+        cgen = self->va_count->codegen;
         if (!(*cgen)((ast_expression*)(self->va_count), func, false, &va_count))
             return false;
         if (!ir_block_create_store_op(func->curblock, ast_ctx(self), INSTR_STORE_F,
@@ -3078,7 +3078,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
 
     callinstr = ir_block_create_call(func->curblock, ast_ctx(self),
                                      ast_function_label(func, "call"),
-                                     funval, !!(self->func->expression.flags & AST_FLAG_NORETURN));
+                                     funval, !!(self->func->flags & AST_FLAG_NORETURN));
     if (!callinstr)
         goto error;
 
diff --git a/ast.h b/ast.h
index f18c73e..26d0c0c 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -28,8 +28,8 @@
  * "main" ast node types for now.
  */
 
-typedef union ast_node_u ast_node;
-typedef union ast_expression_u ast_expression;
+typedef struct ast_node_common       ast_node;
+typedef struct ast_expression_common ast_expression;
 
 typedef struct ast_value_s       ast_value;
 typedef struct ast_function_s    ast_function;
@@ -75,14 +75,14 @@ enum {
     TYPE_ast_goto         /* 20 */
 };
 
-#define ast_istype(x, t) ( ((ast_node_common*)x)->nodetype == (TYPE_##t) )
-#define ast_ctx(node) (((ast_node_common*)(node))->context)
-#define ast_side_effects(node) (((ast_node_common*)(node))->side_effects)
+#define ast_istype(x, t) ( ((ast_node*)x)->nodetype == (TYPE_##t) )
+#define ast_ctx(node) (((ast_node*)(node))->context)
+#define ast_side_effects(node) (((ast_node*)(node))->side_effects)
 
 /* Node interface with common components
  */
 typedef void ast_node_delete(ast_node*);
-typedef struct
+struct ast_node_common
 {
     lex_ctx          context;
     /* I don't feel comfortable using keywords like 'delete' as names... */
@@ -93,14 +93,14 @@ typedef struct
      */
     bool             keep;
     bool             side_effects;
-} ast_node_common;
-
-#define ast_delete(x) (*( ((ast_node*)(x))->node.destroy ))((ast_node*)(x))
-#define ast_unref(x) do                     \
-{                                           \
-    if (! (((ast_node*)(x))->node.keep) ) { \
-        ast_delete(x);                      \
-    }                                       \
+};
+
+#define ast_delete(x) (*( ((ast_node*)(x))->destroy ))((ast_node*)(x))
+#define ast_unref(x) do                \
+{                                      \
+    if (! (((ast_node*)(x))->keep) ) { \
+        ast_delete(x);                 \
+    }                                  \
 } while(0)
 
 /* Expression interface
@@ -122,9 +122,9 @@ typedef bool ast_expression_codegen(ast_expression*,
  * type `expression`, so the ast_ident's codegen would search for
  * variables through the environment (or functions, constants...).
  */
-typedef struct
+struct ast_expression_common
 {
-    ast_node_common         node;
+    ast_node                node;
     ast_expression_codegen *codegen;
     int                     vtype;
     ast_expression         *next;
@@ -143,7 +143,7 @@ typedef struct
      */
     ir_value               *outl;
     ir_value               *outr;
-} ast_expression_common;
+};
 #define AST_FLAG_VARIADIC     (1<<0)
 #define AST_FLAG_NORETURN     (1<<1)
 #define AST_FLAG_INLINE       (1<<2)
@@ -172,7 +172,7 @@ typedef union {
 } basic_value_t;
 struct ast_value_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     const char *name;
     const char *desc;
@@ -239,7 +239,7 @@ typedef enum ast_binary_ref_s {
  */
 struct ast_binary_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     int             op;
     ast_expression *left;
@@ -262,7 +262,7 @@ bool ast_binary_codegen(ast_binary*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_binstore_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     int             opstore;
     int             opbin;
@@ -286,7 +286,7 @@ bool ast_binstore_codegen(ast_binstore*, ast_function*, bool lvalue, ir_value**)
  */
 struct ast_unary_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     int             op;
     ast_expression *operand;
@@ -306,7 +306,7 @@ bool ast_unary_codegen(ast_unary*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_return_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *operand;
 };
 ast_return* ast_return_new(lex_ctx    ctx,
@@ -330,7 +330,7 @@ bool ast_return_codegen(ast_return*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_entfield_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     /* The entity can come from an expression of course. */
     ast_expression *entity;
     /* As can the field, it just must result in a value of TYPE_FIELD */
@@ -349,7 +349,7 @@ bool ast_entfield_codegen(ast_entfield*, ast_function*, bool lvalue, ir_value**)
  */
 struct ast_member_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *owner;
     unsigned int    field;
     const char     *name;
@@ -373,7 +373,7 @@ bool ast_member_codegen(ast_member*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_array_index_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *array;
     ast_expression *index;
 };
@@ -389,7 +389,7 @@ bool ast_array_index_codegen(ast_array_index*, ast_function*, bool lvalue, ir_va
  */
 struct ast_store_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     int             op;
     ast_expression *dest;
     ast_expression *source;
@@ -413,7 +413,7 @@ bool ast_store_codegen(ast_store*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_ifthen_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *cond;
     /* It's all just 'expressions', since an ast_block is one too. */
     ast_expression *on_true;
@@ -439,7 +439,7 @@ bool ast_ifthen_codegen(ast_ifthen*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_ternary_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *cond;
     /* It's all just 'expressions', since an ast_block is one too. */
     ast_expression *on_true;
@@ -475,7 +475,7 @@ continue:      // a 'continue' will jump here
  */
 struct ast_loop_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *initexpr;
     ast_expression *precond;
     ast_expression *postcond;
@@ -504,7 +504,7 @@ bool ast_loop_codegen(ast_loop*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_breakcont_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     bool         is_continue;
     unsigned int levels;
 };
@@ -529,7 +529,7 @@ typedef struct {
 } ast_switch_case;
 struct ast_switch_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     ast_expression  *operand;
     ast_switch_case *cases;
@@ -546,7 +546,7 @@ bool ast_switch_codegen(ast_switch*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_label_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     const char *name;
     ir_block   *irblock;
     ast_goto  **gotos;
@@ -566,7 +566,7 @@ bool ast_label_codegen(ast_label*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_goto_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     const char *name;
     ast_label  *target;
     ir_block   *irblock_from;
@@ -590,7 +590,7 @@ bool ast_goto_codegen(ast_goto*, ast_function*, bool lvalue, ir_value**);
  */
 struct ast_call_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *func;
     ast_expression* *params;
     ast_expression *va_count;
@@ -606,7 +606,7 @@ bool ast_call_check_types(ast_call*);
  */
 struct ast_block_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     ast_value*      *locals;
     ast_expression* *exprs;
@@ -633,7 +633,7 @@ bool GMQCC_WARN ast_block_add_expr(ast_block*, ast_expression*);
  */
 struct ast_function_s
 {
-    ast_node_common node;
+    ast_node        node;
 
     ast_value  *vtype;
     const char *name;
@@ -678,18 +678,4 @@ const char* ast_function_label(ast_function*, const char *prefix);
 bool ast_function_codegen(ast_function *self, ir_builder *builder);
 bool ast_generate_accessors(ast_value *asvalue, ir_builder *ir);
 
-/* Expression union
- */
-union ast_expression_u
-{
-    ast_expression_common expression;
-};
-
-/* Node union
- */
-union ast_node_u
-{
-    ast_node_common node;
-};
-
 #endif
index 4d50bad..9fd94f6 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -585,7 +585,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
         blocks[i] = sy->out[vec_size(sy->out)+i].block;
         asvalue[i] = (ast_value*)exprs[i];
 
-        if (exprs[i]->expression.vtype == TYPE_NOEXPR &&
+        if (exprs[i]->vtype == TYPE_NOEXPR &&
             !(i != 0 && op->id == opid2('?',':')) &&
             !(i == 1 && op->id == opid1('.')))
         {
@@ -603,11 +603,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
     }
 
 #define NotSameType(T) \
-             (exprs[0]->expression.vtype != exprs[1]->expression.vtype || \
-              exprs[0]->expression.vtype != T)
+             (exprs[0]->vtype != exprs[1]->vtype || \
+              exprs[0]->vtype != T)
 #define CanConstFold1(A) \
              (ast_istype((A), ast_value) && ((ast_value*)(A))->hasvalue && (((ast_value*)(A))->cvq == CV_CONST) &&\
-              (A)->expression.vtype != TYPE_FUNCTION)
+              (A)->vtype != TYPE_FUNCTION)
 #define CanConstFold(A, B) \
              (CanConstFold1(A) && CanConstFold1(B))
 #define ConstV(i) (asvalue[(i)]->constval.vvec)
@@ -620,8 +620,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             return false;
 
         case opid1('.'):
-            if (exprs[0]->expression.vtype == TYPE_VECTOR &&
-                exprs[1]->expression.vtype == TYPE_NOEXPR)
+            if (exprs[0]->vtype == TYPE_VECTOR &&
+                exprs[1]->vtype == TYPE_NOEXPR)
             {
                 if      (exprs[1] == (ast_expression*)parser->const_vec[0])
                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
@@ -634,14 +634,14 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     return false;
                 }
             }
-            else if (exprs[0]->expression.vtype == TYPE_ENTITY) {
-                if (exprs[1]->expression.vtype != TYPE_FIELD) {
+            else if (exprs[0]->vtype == TYPE_ENTITY) {
+                if (exprs[1]->vtype != TYPE_FIELD) {
                     compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field");
                     return false;
                 }
                 out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]);
             }
-            else if (exprs[0]->expression.vtype == TYPE_VECTOR) {
+            else if (exprs[0]->vtype == TYPE_VECTOR) {
                 compile_error(ast_ctx(exprs[1]), "vectors cannot be accessed this way");
                 return false;
             }
@@ -652,15 +652,15 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             break;
 
         case opid1('['):
-            if (exprs[0]->expression.vtype != TYPE_ARRAY &&
-                !(exprs[0]->expression.vtype == TYPE_FIELD &&
-                  exprs[0]->expression.next->expression.vtype == TYPE_ARRAY))
+            if (exprs[0]->vtype != TYPE_ARRAY &&
+                !(exprs[0]->vtype == TYPE_FIELD &&
+                  exprs[0]->next->vtype == TYPE_ARRAY))
             {
                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                 compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1);
                 return false;
             }
-            if (exprs[1]->expression.vtype != TYPE_FLOAT) {
+            if (exprs[1]->vtype != TYPE_FLOAT) {
                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                 compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1);
                 return false;
@@ -707,7 +707,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             out = exprs[0];
             break;
         case opid2('-','P'):
-            switch (exprs[0]->expression.vtype) {
+            switch (exprs[0]->vtype) {
                 case TYPE_FLOAT:
                     if (CanConstFold1(exprs[0]))
                         out = (ast_expression*)parser_const_float(parser, -ConstF(0));
@@ -727,13 +727,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     break;
                 default:
                 compile_error(ctx, "invalid types used in expression: cannot negate type %s",
-                              type_name[exprs[0]->expression.vtype]);
+                              type_name[exprs[0]->vtype]);
                 return false;
             }
             break;
 
         case opid2('!','P'):
-            switch (exprs[0]->expression.vtype) {
+            switch (exprs[0]->vtype) {
                 case TYPE_FLOAT:
                     if (CanConstFold1(exprs[0]))
                         out = (ast_expression*)parser_const_float(parser, !ConstF(0));
@@ -769,21 +769,21 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     break;
                 default:
                 compile_error(ctx, "invalid types used in expression: cannot logically negate type %s",
-                              type_name[exprs[0]->expression.vtype]);
+                              type_name[exprs[0]->vtype]);
                 return false;
             }
             break;
 
         case opid1('+'):
-            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
-                (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
+            if (exprs[0]->vtype != exprs[1]->vtype ||
+                (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
             {
                 compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
-                              type_name[exprs[0]->expression.vtype],
-                              type_name[exprs[1]->expression.vtype]);
+                              type_name[exprs[0]->vtype],
+                              type_name[exprs[1]->vtype]);
                 return false;
             }
-            switch (exprs[0]->expression.vtype) {
+            switch (exprs[0]->vtype) {
                 case TYPE_FLOAT:
                     if (CanConstFold(exprs[0], exprs[1]))
                     {
@@ -800,21 +800,21 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     break;
                 default:
                     compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
-                                  type_name[exprs[0]->expression.vtype],
-                                  type_name[exprs[1]->expression.vtype]);
+                                  type_name[exprs[0]->vtype],
+                                  type_name[exprs[1]->vtype]);
                     return false;
             };
             break;
         case opid1('-'):
-            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
-                (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
+            if (exprs[0]->vtype != exprs[1]->vtype ||
+                (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
             {
                 compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
-                              type_name[exprs[1]->expression.vtype],
-                              type_name[exprs[0]->expression.vtype]);
+                              type_name[exprs[1]->vtype],
+                              type_name[exprs[0]->vtype]);
                 return false;
             }
-            switch (exprs[0]->expression.vtype) {
+            switch (exprs[0]->vtype) {
                 case TYPE_FLOAT:
                     if (CanConstFold(exprs[0], exprs[1]))
                         out = (ast_expression*)parser_const_float(parser, ConstF(0) - ConstF(1));
@@ -829,27 +829,27 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     break;
                 default:
                     compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
-                                  type_name[exprs[1]->expression.vtype],
-                                  type_name[exprs[0]->expression.vtype]);
+                                  type_name[exprs[1]->vtype],
+                                  type_name[exprs[0]->vtype]);
                     return false;
             };
             break;
         case opid1('*'):
-            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype &&
-                !(exprs[0]->expression.vtype == TYPE_VECTOR &&
-                  exprs[1]->expression.vtype == TYPE_FLOAT) &&
-                !(exprs[1]->expression.vtype == TYPE_VECTOR &&
-                  exprs[0]->expression.vtype == TYPE_FLOAT)
+            if (exprs[0]->vtype != exprs[1]->vtype &&
+                !(exprs[0]->vtype == TYPE_VECTOR &&
+                  exprs[1]->vtype == TYPE_FLOAT) &&
+                !(exprs[1]->vtype == TYPE_VECTOR &&
+                  exprs[0]->vtype == TYPE_FLOAT)
                 )
             {
                 compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
-                              type_name[exprs[1]->expression.vtype],
-                              type_name[exprs[0]->expression.vtype]);
+                              type_name[exprs[1]->vtype],
+                              type_name[exprs[0]->vtype]);
                 return false;
             }
-            switch (exprs[0]->expression.vtype) {
+            switch (exprs[0]->vtype) {
                 case TYPE_FLOAT:
-                    if (exprs[1]->expression.vtype == TYPE_VECTOR)
+                    if (exprs[1]->vtype == TYPE_VECTOR)
                     {
                         if (CanConstFold(exprs[0], exprs[1]))
                             out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(1), ConstF(0)));
@@ -865,7 +865,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     }
                     break;
                 case TYPE_VECTOR:
-                    if (exprs[1]->expression.vtype == TYPE_FLOAT)
+                    if (exprs[1]->vtype == TYPE_FLOAT)
                     {
                         if (CanConstFold(exprs[0], exprs[1]))
                             out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), ConstF(1)));
@@ -881,7 +881,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                             if (!vec.y && !vec.z) { /* 'n 0 0' * v */
                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                 out = (ast_expression*)ast_member_new(ctx, exprs[1], 0, NULL);
-                                out->expression.node.keep = false;
+                                out->node.keep = false;
                                 ((ast_member*)out)->rvalue = true;
                                 if (vec.x != 1)
                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.x), out);
@@ -889,7 +889,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                             else if (!vec.x && !vec.z) { /* '0 n 0' * v */
                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                 out = (ast_expression*)ast_member_new(ctx, exprs[1], 1, NULL);
-                                out->expression.node.keep = false;
+                                out->node.keep = false;
                                 ((ast_member*)out)->rvalue = true;
                                 if (vec.y != 1)
                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.y), out);
@@ -897,7 +897,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                             else if (!vec.x && !vec.y) { /* '0 n 0' * v */
                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                 out = (ast_expression*)ast_member_new(ctx, exprs[1], 2, NULL);
-                                out->expression.node.keep = false;
+                                out->node.keep = false;
                                 ((ast_member*)out)->rvalue = true;
                                 if (vec.z != 1)
                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.z), out);
@@ -910,7 +910,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                             if (!vec.y && !vec.z) { /* v * 'n 0 0' */
                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                 out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
-                                out->expression.node.keep = false;
+                                out->node.keep = false;
                                 ((ast_member*)out)->rvalue = true;
                                 if (vec.x != 1)
                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.x));
@@ -918,7 +918,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                             else if (!vec.x && !vec.z) { /* v * '0 n 0' */
                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                 out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL);
-                                out->expression.node.keep = false;
+                                out->node.keep = false;
                                 ((ast_member*)out)->rvalue = true;
                                 if (vec.y != 1)
                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.y));
@@ -926,7 +926,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                             else if (!vec.x && !vec.y) { /* v * '0 n 0' */
                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                 out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL);
-                                out->expression.node.keep = false;
+                                out->node.keep = false;
                                 ((ast_member*)out)->rvalue = true;
                                 if (vec.z != 1)
                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.z));
@@ -940,25 +940,25 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     break;
                 default:
                     compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
-                                  type_name[exprs[1]->expression.vtype],
-                                  type_name[exprs[0]->expression.vtype]);
+                                  type_name[exprs[1]->vtype],
+                                  type_name[exprs[0]->vtype]);
                     return false;
             };
             break;
         case opid1('/'):
-            if (exprs[1]->expression.vtype != TYPE_FLOAT) {
+            if (exprs[1]->vtype != TYPE_FLOAT) {
                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
                 compile_error(ctx, "invalid types used in expression: cannot divide tyeps %s and %s", ty1, ty2);
                 return false;
             }
-            if (exprs[0]->expression.vtype == TYPE_FLOAT) {
+            if (exprs[0]->vtype == TYPE_FLOAT) {
                 if (CanConstFold(exprs[0], exprs[1]))
                     out = (ast_expression*)parser_const_float(parser, ConstF(0) / ConstF(1));
                 else
                     out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
             }
-            else if (exprs[0]->expression.vtype == TYPE_VECTOR) {
+            else if (exprs[0]->vtype == TYPE_VECTOR) {
                 if (CanConstFold(exprs[0], exprs[1]))
                     out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), 1.0/ConstF(1)));
                 else {
@@ -988,8 +988,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
         case opid1('%'):
             if (NotSameType(TYPE_FLOAT)) {
                 compile_error(ctx, "invalid types used in expression: cannot perform modulo operation between types %s and %s",
-                    type_name[exprs[0]->expression.vtype],
-                    type_name[exprs[1]->expression.vtype]);
+                    type_name[exprs[0]->vtype],
+                    type_name[exprs[1]->vtype]);
                 return false;
             }
             if (CanConstFold(exprs[0], exprs[1])) {
@@ -1017,8 +1017,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
         case opid1('&'):
             if (NotSameType(TYPE_FLOAT)) {
                 compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
-                              type_name[exprs[0]->expression.vtype],
-                              type_name[exprs[1]->expression.vtype]);
+                              type_name[exprs[0]->vtype],
+                              type_name[exprs[1]->vtype]);
                 return false;
             }
             if (CanConstFold(exprs[0], exprs[1]))
@@ -1074,7 +1074,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     return false;
                 }
                 for (i = 0; i < 2; ++i) {
-                    if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->expression.vtype == TYPE_VECTOR) {
+                    if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->vtype == TYPE_VECTOR) {
                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
                         if (!out) break;
                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
@@ -1085,7 +1085,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                             break;
                         }
                     }
-                    else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->expression.vtype == TYPE_STRING) {
+                    else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->vtype == TYPE_STRING) {
                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]);
                         if (!out) break;
                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
@@ -1192,49 +1192,49 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             generated_op += INSTR_LE;
             if (NotSameType(TYPE_FLOAT)) {
                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
-                              type_name[exprs[0]->expression.vtype],
-                              type_name[exprs[1]->expression.vtype]);
+                              type_name[exprs[0]->vtype],
+                              type_name[exprs[1]->vtype]);
                 return false;
             }
             out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
             break;
         case opid2('!', '='):
-            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
+            if (exprs[0]->vtype != exprs[1]->vtype) {
                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
-                              type_name[exprs[0]->expression.vtype],
-                              type_name[exprs[1]->expression.vtype]);
+                              type_name[exprs[0]->vtype],
+                              type_name[exprs[1]->vtype]);
                 return false;
             }
-            out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
+            out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]);
             break;
         case opid2('=', '='):
-            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
+            if (exprs[0]->vtype != exprs[1]->vtype) {
                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
-                              type_name[exprs[0]->expression.vtype],
-                              type_name[exprs[1]->expression.vtype]);
+                              type_name[exprs[0]->vtype],
+                              type_name[exprs[1]->vtype]);
                 return false;
             }
-            out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
+            out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]);
             break;
 
         case opid1('='):
             if (ast_istype(exprs[0], ast_entfield)) {
                 ast_expression *field = ((ast_entfield*)exprs[0])->field;
                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
-                    exprs[0]->expression.vtype == TYPE_FIELD &&
-                    exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
+                    exprs[0]->vtype == TYPE_FIELD &&
+                    exprs[0]->next->vtype == TYPE_VECTOR)
                 {
                     assignop = type_storep_instr[TYPE_VECTOR];
                 }
                 else
-                    assignop = type_storep_instr[exprs[0]->expression.vtype];
-                if (assignop == VINSTR_END || !ast_compare_type(field->expression.next, exprs[1]))
+                    assignop = type_storep_instr[exprs[0]->vtype];
+                if (assignop == VINSTR_END || !ast_compare_type(field->next, exprs[1]))
                 {
-                    ast_type_to_string(field->expression.next, ty1, sizeof(ty1));
+                    ast_type_to_string(field->next, ty1, sizeof(ty1));
                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
-                        field->expression.next->expression.vtype == TYPE_FUNCTION &&
-                        exprs[1]->expression.vtype == TYPE_FUNCTION)
+                        field->next->vtype == TYPE_FUNCTION &&
+                        exprs[1]->vtype == TYPE_FUNCTION)
                     {
                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
@@ -1246,13 +1246,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             else
             {
                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
-                    exprs[0]->expression.vtype == TYPE_FIELD &&
-                    exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
+                    exprs[0]->vtype == TYPE_FIELD &&
+                    exprs[0]->next->vtype == TYPE_VECTOR)
                 {
                     assignop = type_store_instr[TYPE_VECTOR];
                 }
                 else {
-                    assignop = type_store_instr[exprs[0]->expression.vtype];
+                    assignop = type_store_instr[exprs[0]->vtype];
                 }
 
                 if (assignop == VINSTR_END) {
@@ -1265,8 +1265,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
-                        exprs[0]->expression.vtype == TYPE_FUNCTION &&
-                        exprs[1]->expression.vtype == TYPE_FUNCTION)
+                        exprs[0]->vtype == TYPE_FUNCTION &&
+                        exprs[1]->vtype == TYPE_FUNCTION)
                     {
                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
@@ -1283,7 +1283,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
         case opid3('+','+','P'):
         case opid3('-','-','P'):
             /* prefix ++ */
-            if (exprs[0]->expression.vtype != TYPE_FLOAT) {
+            if (exprs[0]->vtype != TYPE_FLOAT) {
                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                 compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1);
                 return false;
@@ -1308,7 +1308,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
         case opid3('S','+','+'):
         case opid3('S','-','-'):
             /* prefix ++ */
-            if (exprs[0]->expression.vtype != TYPE_FLOAT) {
+            if (exprs[0]->vtype != TYPE_FLOAT) {
                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                 compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1);
                 return false;
@@ -1340,8 +1340,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             break;
         case opid2('+','='):
         case opid2('-','='):
-            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
-                (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
+            if (exprs[0]->vtype != exprs[1]->vtype ||
+                (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
             {
                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
@@ -1353,10 +1353,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
             }
             if (ast_istype(exprs[0], ast_entfield))
-                assignop = type_storep_instr[exprs[0]->expression.vtype];
+                assignop = type_storep_instr[exprs[0]->vtype];
             else
-                assignop = type_store_instr[exprs[0]->expression.vtype];
-            switch (exprs[0]->expression.vtype) {
+                assignop = type_store_instr[exprs[0]->vtype];
+            switch (exprs[0]->vtype) {
                 case TYPE_FLOAT:
                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
                                                             (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
@@ -1369,16 +1369,16 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     break;
                 default:
                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
-                                  type_name[exprs[0]->expression.vtype],
-                                  type_name[exprs[1]->expression.vtype]);
+                                  type_name[exprs[0]->vtype],
+                                  type_name[exprs[1]->vtype]);
                     return false;
             };
             break;
         case opid2('*','='):
         case opid2('/','='):
-            if (exprs[1]->expression.vtype != TYPE_FLOAT ||
-                !(exprs[0]->expression.vtype == TYPE_FLOAT ||
-                  exprs[0]->expression.vtype == TYPE_VECTOR))
+            if (exprs[1]->vtype != TYPE_FLOAT ||
+                !(exprs[0]->vtype == TYPE_FLOAT ||
+                  exprs[0]->vtype == TYPE_VECTOR))
             {
                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
@@ -1390,10 +1390,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
             }
             if (ast_istype(exprs[0], ast_entfield))
-                assignop = type_storep_instr[exprs[0]->expression.vtype];
+                assignop = type_storep_instr[exprs[0]->vtype];
             else
-                assignop = type_store_instr[exprs[0]->expression.vtype];
-            switch (exprs[0]->expression.vtype) {
+                assignop = type_store_instr[exprs[0]->vtype];
+            switch (exprs[0]->vtype) {
                 case TYPE_FLOAT:
                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
                                                             (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
@@ -1422,8 +1422,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     break;
                 default:
                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
-                                  type_name[exprs[0]->expression.vtype],
-                                  type_name[exprs[1]->expression.vtype]);
+                                  type_name[exprs[0]->vtype],
+                                  type_name[exprs[1]->vtype]);
                     return false;
             };
             break;
@@ -1440,9 +1440,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
             }
             if (ast_istype(exprs[0], ast_entfield))
-                assignop = type_storep_instr[exprs[0]->expression.vtype];
+                assignop = type_storep_instr[exprs[0]->vtype];
             else
-                assignop = type_store_instr[exprs[0]->expression.vtype];
+                assignop = type_store_instr[exprs[0]->vtype];
             out = (ast_expression*)ast_binstore_new(ctx, assignop,
                                                     (op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
                                                     exprs[0], exprs[1]);
@@ -1460,9 +1460,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 return false;
             }
             if (ast_istype(exprs[0], ast_entfield))
-                assignop = type_storep_instr[exprs[0]->expression.vtype];
+                assignop = type_storep_instr[exprs[0]->vtype];
             else
-                assignop = type_store_instr[exprs[0]->expression.vtype];
+                assignop = type_store_instr[exprs[0]->vtype];
             out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
             if (!out)
                 return false;
@@ -1475,7 +1475,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             break;
 
         case opid2('~', 'P'):
-            if (exprs[0]->expression.vtype != TYPE_FLOAT) {
+            if (exprs[0]->vtype != TYPE_FLOAT) {
                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                 compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1);
                 return false;
@@ -1571,7 +1571,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
 
     if (ast_istype(fun, ast_value)) {
         funval = (ast_value*)fun;
-        if ((fun->expression.flags & AST_FLAG_VARIADIC) &&
+        if ((fun->flags & AST_FLAG_VARIADIC) &&
             !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
         {
             call->va_count = (ast_expression*)parser_const_float(parser, (double)paramcount);
@@ -1581,18 +1581,18 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
     /* overwrite fid, the function, with a call */
     sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
 
-    if (fun->expression.vtype != TYPE_FUNCTION) {
-        parseerror(parser, "not a function (%s)", type_name[fun->expression.vtype]);
+    if (fun->vtype != TYPE_FUNCTION) {
+        parseerror(parser, "not a function (%s)", type_name[fun->vtype]);
         return false;
     }
 
-    if (!fun->expression.next) {
+    if (!fun->next) {
         parseerror(parser, "could not determine function return type");
         return false;
     } else {
         ast_value *fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
 
-        if (fun->expression.flags & AST_FLAG_DEPRECATED) {
+        if (fun->flags & AST_FLAG_DEPRECATED) {
             if (!fval) {
                 return !parsewarning(parser, WARN_DEPRECATED,
                         "call to function (which is marked deprecated)\n",
@@ -1612,22 +1612,22 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
                     ast_ctx(fun).line);
         }
 
-        if (vec_size(fun->expression.params) != paramcount &&
-            !((fun->expression.flags & AST_FLAG_VARIADIC) &&
-              vec_size(fun->expression.params) < paramcount))
+        if (vec_size(fun->params) != paramcount &&
+            !((fun->flags & AST_FLAG_VARIADIC) &&
+              vec_size(fun->params) < paramcount))
         {
-            const char *fewmany = (vec_size(fun->expression.params) > paramcount) ? "few" : "many";
+            const char *fewmany = (vec_size(fun->params) > paramcount) ? "few" : "many";
             if (fval)
                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
                                      "too %s parameters for call to %s: expected %i, got %i\n"
                                      " -> `%s` has been declared here: %s:%i",
-                                     fewmany, fval->name, (int)vec_size(fun->expression.params), (int)paramcount,
+                                     fewmany, fval->name, (int)vec_size(fun->params), (int)paramcount,
                                      fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
             else
                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
                                      "too %s parameters for function call: expected %i, got %i\n"
                                      " -> it has been declared here: %s:%i",
-                                     fewmany, (int)vec_size(fun->expression.params), (int)paramcount,
+                                     fewmany, (int)vec_size(fun->params), (int)paramcount,
                                      ast_ctx(fun).file, (int)ast_ctx(fun).line);
         }
     }
@@ -1881,7 +1881,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
             /* When adding more intrinsics, fix the above condition */
             prev = NULL;
         }
-        if (prev && prev->expression.vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
+        if (prev && prev->vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
         {
             var = (ast_expression*)parser->const_vec[ctoken[0]-'x'];
         } else {
@@ -2363,13 +2363,13 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
     ast_unary *unary;
     ast_expression *prev;
 
-    if (cond->expression.vtype == TYPE_VOID || cond->expression.vtype >= TYPE_VARIANT) {
+    if (cond->vtype == TYPE_VOID || cond->vtype >= TYPE_VARIANT) {
         char ty[1024];
         ast_type_to_string(cond, ty, sizeof(ty));
         compile_error(ast_ctx(cond), "invalid type for if() condition: %s", ty);
     }
 
-    if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING)
+    if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->vtype == TYPE_STRING)
     {
         prev = cond;
         cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
@@ -2380,7 +2380,7 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
         }
         ifnot = !ifnot;
     }
-    else if (OPTS_FLAG(CORRECT_LOGIC) && cond->expression.vtype == TYPE_VECTOR)
+    else if (OPTS_FLAG(CORRECT_LOGIC) && cond->vtype == TYPE_VECTOR)
     {
         /* vector types need to be cast to true booleans */
         ast_binary *bin = (ast_binary*)cond;
@@ -2911,8 +2911,8 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou
         if (!exp)
             return false;
 
-        if (exp->expression.vtype != TYPE_NIL &&
-            exp->expression.vtype != expected->expression.next->expression.vtype)
+        if (exp->vtype != TYPE_NIL &&
+            exp->vtype != ((ast_expression*)expected)->next->vtype)
         {
             parseerror(parser, "return with invalid expression");
         }
@@ -2925,7 +2925,7 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou
     } else {
         if (!parser_next(parser))
             parseerror(parser, "parse error");
-        if (expected->expression.next->expression.vtype != TYPE_VOID) {
+        if (expected->expression.next->vtype != TYPE_VOID) {
             (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
         }
         ret = ast_return_new(ctx, NULL);
@@ -4067,9 +4067,9 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
             /* qc allows the use of not-yet-declared functions here
              * - this automatically creates a prototype */
             ast_value      *thinkfunc;
-            ast_expression *functype = fld_think->expression.next;
+            ast_expression *functype = fld_think->next;
 
-            thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->expression.vtype);
+            thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->vtype);
             if (!thinkfunc) { /* || !ast_type_adopt(thinkfunc, functype)*/
                 ast_unref(framenum);
                 parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
@@ -4224,7 +4224,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
 
         if (param->expression.vtype != TYPE_VECTOR &&
             (param->expression.vtype != TYPE_FIELD ||
-             param->expression.next->expression.vtype != TYPE_VECTOR))
+             param->expression.next->vtype != TYPE_VECTOR))
         {
             continue;
         }
@@ -4354,7 +4354,7 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast
         ast_store       *st;
         int assignop = type_store_instr[value->expression.vtype];
 
-        if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
+        if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
             assignop = INSTR_STORE_V;
 
         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
@@ -4420,7 +4420,7 @@ static ast_expression *array_field_setter_node(
         ast_store       *st;
         int assignop = type_storep_instr[value->expression.vtype];
 
-        if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
+        if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
             assignop = INSTR_STOREP_V;
 
         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
@@ -5271,7 +5271,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
             {
                 /* deal with other globals */
                 old = parser_find_global(parser, var->name);
-                if (old && var->expression.vtype == TYPE_FUNCTION && old->expression.vtype == TYPE_FUNCTION)
+                if (old && var->expression.vtype == TYPE_FUNCTION && old->vtype == TYPE_FUNCTION)
                 {
                     /* This is a function which had a prototype */
                     if (!ast_istype(old, ast_value)) {
@@ -5379,7 +5379,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
             if (var->expression.vtype == TYPE_VECTOR)
                 isvector = true;
             else if (var->expression.vtype == TYPE_FIELD &&
-                     var->expression.next->expression.vtype == TYPE_VECTOR)
+                     var->expression.next->vtype == TYPE_VECTOR)
                 isvector = true;
 
             if (isvector) {
@@ -5418,7 +5418,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                             return false;
                         }
 
-                        if (var->expression.vtype != find->expression.vtype) {
+                        if (var->expression.vtype != find->vtype) {
                             char ty1[1024];
                             char ty2[1024];
 
@@ -5567,7 +5567,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
         }
         else if (!localblock && !nofields &&
                  var->expression.vtype == TYPE_FIELD &&
-                 var->expression.next->expression.vtype == TYPE_ARRAY)
+                 var->expression.next->vtype == TYPE_ARRAY)
         {
             char name[1024];
             ast_expression *telem;
@@ -5984,7 +5984,7 @@ static void generate_checksum(parser_t *parser)
         if (!ast_istype(parser->fields[i], ast_value))
             continue;
         value = (ast_value*)(parser->fields[i]);
-        switch (value->expression.next->expression.vtype) {
+        switch (value->expression.next->vtype) {
             case TYPE_FLOAT:    crc = progdefs_crc_both(crc, "\tfloat\t"); break;
             case TYPE_VECTOR:   crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
             case TYPE_STRING:   crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
@@ -6235,11 +6235,11 @@ bool parser_finish(parser_t *parser, const char *output)
             ast_expression *subtype;
             field->hasvalue = true;
             subtype = field->expression.next;
-            ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
-            if (subtype->expression.vtype == TYPE_FIELD)
-                ifld->fieldtype = subtype->expression.next->expression.vtype;
-            else if (subtype->expression.vtype == TYPE_FUNCTION)
-                ifld->outtype = subtype->expression.next->expression.vtype;
+            ifld = ir_builder_create_field(ir, field->name, subtype->vtype);
+            if (subtype->vtype == TYPE_FIELD)
+                ifld->fieldtype = subtype->next->vtype;
+            else if (subtype->vtype == TYPE_FUNCTION)
+                ifld->outtype = subtype->next->vtype;
             (void)!ir_value_set_field(field->ir_v, ifld);
         }
     }
@@ -6327,7 +6327,7 @@ bool parser_finish(parser_t *parser, const char *output)
     }
     for (i = 0; i < vec_size(parser->fields); ++i) {
         ast_value *asvalue;
-        asvalue = (ast_value*)(parser->fields[i]->expression.next);
+        asvalue = (ast_value*)(parser->fields[i]->next);
 
         if (!ast_istype((ast_expression*)asvalue, ast_value))
             continue;