]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
making ast nodes derive from ast_expression
authorWolfgang Bumiller <wry.git@bumiller.com>
Mon, 19 Jan 2015 13:00:04 +0000 (14:00 +0100)
committerWolfgang Bumiller <wry.git@bumiller.com>
Mon, 19 Jan 2015 13:00:04 +0000 (14:00 +0100)
ast.cpp
ast.h
fold.cpp
intrin.cpp
parser.cpp

diff --git a/ast.cpp b/ast.cpp
index d71c4715d7190ddd99915e544a497e358786ca89..948e2548259b3fef31b5815edb72ec7e2abf568f 100644 (file)
--- a/ast.cpp
+++ b/ast.cpp
@@ -118,14 +118,12 @@ static void ast_expression_delete_full(ast_expression *self)
 
 ast_value* ast_value_copy(const ast_value *self)
 {
-    const ast_expression *fromex;
-    ast_expression *selfex;
-    ast_value *cp = ast_value_new(self->expression.context, self->name, self->expression.vtype);
-    if (self->expression.next) {
-        cp->expression.next = ast_type_copy(self->expression.context, self->expression.next);
+    ast_value *cp = ast_value_new(self->context, self->name, self->vtype);
+    if (self->next) {
+        cp->next = ast_type_copy(self->context, self->next);
     }
-    fromex = &self->expression;
-    selfex = &cp->expression;
+    const ast_expression *fromex = self;
+    ast_expression *selfex = cp;
     selfex->count = fromex->count;
     selfex->flags = fromex->flags;
     for (auto &it : fromex->type_params) {
@@ -325,11 +323,11 @@ ast_value* ast_value_new(lex_ctx_t ctx, const char *name, int t)
     ast_instantiate(ast_value, ctx, ast_value_delete);
     ast_expression_init((ast_expression*)self,
                         (ast_expression_codegen*)&ast_value_codegen);
-    self->expression.keep_node = true; /* keep */
+    self->keep_node = true; /* keep */
 
     self->name = name ? util_strdup(name) : nullptr;
-    self->expression.vtype = t;
-    self->expression.next  = nullptr;
+    self->vtype    = t;
+    self->next     = nullptr;
     self->isfield  = false;
     self->cvq      = CV_NONE;
     self->hasvalue = false;
@@ -359,7 +357,7 @@ void ast_value_delete(ast_value* self)
     if (self->argcounter)
         mem_d((void*)self->argcounter);
     if (self->hasvalue) {
-        switch (self->expression.vtype)
+        switch (self->vtype)
         {
         case TYPE_STRING:
             mem_d((void*)self->constval.vstring);
@@ -382,7 +380,7 @@ void ast_value_delete(ast_value* self)
         mem_d(self->desc);
 
     // initlist imples an array which implies .next in the expression exists.
-    if (self->initlist.size() && self->expression.next->vtype == TYPE_STRING) {
+    if (self->initlist.size() && self->next->vtype == TYPE_STRING) {
         for (auto &it : self->initlist)
             if (it.vstring)
                 mem_d(it.vstring);
@@ -394,7 +392,7 @@ void ast_value_delete(ast_value* self)
 
 void ast_value_params_add(ast_value *self, ast_value *p)
 {
-    self->expression.type_params.push_back(p);
+    self->type_params.push_back(p);
 }
 
 bool ast_value_set_name(ast_value *self, const char *name)
@@ -438,21 +436,21 @@ ast_binary* ast_binary_new(lex_ctx_t ctx, int op,
     ast_propagate_effects(self, right);
 
     if (op >= INSTR_EQ_F && op <= INSTR_GT)
-        self->expression.vtype = TYPE_FLOAT;
+        self->vtype = TYPE_FLOAT;
     else if (op == INSTR_AND || op == INSTR_OR) {
         if (OPTS_FLAG(PERL_LOGIC))
             ast_type_adopt(self, right);
         else
-            self->expression.vtype = TYPE_FLOAT;
+            self->vtype = TYPE_FLOAT;
     }
     else if (op == INSTR_BITAND || op == INSTR_BITOR)
-        self->expression.vtype = TYPE_FLOAT;
+        self->vtype = TYPE_FLOAT;
     else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV)
-        self->expression.vtype = TYPE_VECTOR;
+        self->vtype = TYPE_VECTOR;
     else if (op == INSTR_MUL_V)
-        self->expression.vtype = TYPE_FLOAT;
+        self->vtype = TYPE_FLOAT;
     else
-        self->expression.vtype = left->vtype;
+        self->vtype = left->vtype;
 
     /* references all */
     self->refs = AST_REF_ALL;
@@ -525,9 +523,9 @@ ast_unary* ast_unary_new(lex_ctx_t ctx, int op,
     ast_propagate_effects(self, expr);
 
     if ((op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) || op == VINSTR_NEG_F) {
-        self->expression.vtype = TYPE_FLOAT;
+        self->vtype = TYPE_FLOAT;
     } else if (op == VINSTR_NEG_V) {
-        self->expression.vtype = TYPE_VECTOR;
+        self->vtype = TYPE_VECTOR;
     } else {
         compile_error(ctx, "cannot determine type of unary operation %s", util_instr_str[op]);
     }
@@ -617,14 +615,14 @@ ast_member* ast_member_new(lex_ctx_t ctx, ast_expression *owner, unsigned int fi
     }
 
     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
-    self->expression.keep_node = true; /* keep */
+    self->keep_node = true; /* keep */
 
     if (owner->vtype == TYPE_VECTOR) {
-        self->expression.vtype = TYPE_FLOAT;
-        self->expression.next  = nullptr;
+        self->vtype = TYPE_FLOAT;
+        self->next  = nullptr;
     } else {
-        self->expression.vtype = TYPE_FIELD;
-        self->expression.next = ast_shallow_type(ctx, TYPE_FLOAT);
+        self->vtype = TYPE_FIELD;
+        self->next = ast_shallow_type(ctx, TYPE_FLOAT);
     }
 
     self->rvalue = false;
@@ -684,13 +682,13 @@ ast_array_index* ast_array_index_new(lex_ctx_t ctx, ast_expression *array, ast_e
 
     ast_type_adopt(self, outtype);
     if (array->vtype == TYPE_FIELD && outtype->vtype == TYPE_ARRAY) {
-        if (self->expression.vtype != TYPE_ARRAY) {
+        if (self->vtype != TYPE_ARRAY) {
             compile_error(ast_ctx(self), "array_index node on type");
             ast_array_index_delete(self);
             return nullptr;
         }
         self->array = outtype;
-        self->expression.vtype = TYPE_FIELD;
+        self->vtype = TYPE_FIELD;
     }
 
     return self;
@@ -711,7 +709,7 @@ ast_argpipe* ast_argpipe_new(lex_ctx_t ctx, ast_expression *index)
     ast_instantiate(ast_argpipe, ctx, ast_argpipe_delete);
     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_argpipe_codegen);
     self->index = index;
-    self->expression.vtype = TYPE_NOEXPR;
+    self->vtype = TYPE_NOEXPR;
     return self;
 }
 
@@ -890,7 +888,7 @@ ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined)
     ast_instantiate(ast_label, ctx, ast_label_delete);
     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_label_codegen);
 
-    self->expression.vtype = TYPE_NOEXPR;
+    self->vtype = TYPE_NOEXPR;
 
     self->name      = util_strdup(name);
     self->irblock   = nullptr;
@@ -1128,9 +1126,9 @@ bool ast_block_add_expr(ast_block *self, ast_expression *e)
 {
     ast_propagate_effects(self, e);
     self->exprs.push_back(e);
-    if (self->expression.next) {
-        ast_delete(self->expression.next);
-        self->expression.next = nullptr;
+    if (self->next) {
+        ast_delete(self->next);
+        self->next = nullptr;
     }
     ast_type_adopt(self, e);
     return true;
@@ -1153,8 +1151,8 @@ void ast_block_delete(ast_block *self)
 
 void ast_block_set_type(ast_block *self, ast_expression *from)
 {
-    if (self->expression.next)
-        ast_delete(self->expression.next);
+    if (self->next)
+        ast_delete(self->next);
     ast_type_adopt(self, from);
 }
 
@@ -1165,11 +1163,11 @@ ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype
     if (!vtype) {
         compile_error(ast_ctx(self), "internal error: ast_function_new condition 0");
         goto cleanup;
-    } else if (vtype->hasvalue || vtype->expression.vtype != TYPE_FUNCTION) {
+    } else if (vtype->hasvalue || vtype->vtype != TYPE_FUNCTION) {
         compile_error(ast_ctx(self), "internal error: ast_function_new condition %i %i type=%i (probably 2 bodies?)",
                  (int)!vtype,
                  (int)vtype->hasvalue,
-                 vtype->expression.vtype);
+                 vtype->vtype);
         goto cleanup;
     }
 
@@ -1268,17 +1266,17 @@ static void _ast_codegen_output_type(ast_expression *self, ir_value *out)
         out->outtype = self->next->vtype;
 }
 
-#define codegen_output_type(a,o) (_ast_codegen_output_type(&((a)->expression),(o)))
+#define codegen_output_type(a,o) (_ast_codegen_output_type(static_cast<ast_expression*>((a)),(o)))
 
 bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out)
 {
     (void)func;
     (void)lvalue;
-    if (self->expression.vtype == TYPE_NIL) {
+    if (self->vtype == TYPE_NIL) {
         *out = func->ir_func->owner->nil;
         return true;
     }
-    /* NOTE: This is the codegen for a variable used in an expression.
+    /* NOTE: This is the codegen for a variable used in an 
      * It is not the codegen to generate the value. For this purpose,
      * ast_local_codegen and ast_global_codegen are to be used before this
      * is executed. ast_function_codegen should take care of its locals,
@@ -1300,18 +1298,18 @@ static bool ast_global_array_set(ast_value *self)
     size_t count = self->initlist.size();
     size_t i;
 
-    if (count > self->expression.count) {
+    if (count > self->count) {
         compile_error(ast_ctx(self), "too many elements in initializer");
-        count = self->expression.count;
+        count = self->count;
     }
-    else if (count < self->expression.count) {
+    else if (count < self->count) {
         /* add this?
         compile_warning(ast_ctx(self), "not all elements are initialized");
         */
     }
 
     for (i = 0; i != count; ++i) {
-        switch (self->expression.next->vtype) {
+        switch (self->next->vtype) {
             case TYPE_FLOAT:
                 if (!ir_value_set_float(self->ir_values[i], self->initlist[i].vfloat))
                     return false;
@@ -1345,7 +1343,7 @@ static bool ast_global_array_set(ast_value *self)
                     return false;
                 break;
             default:
-                compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype);
+                compile_error(ast_ctx(self), "TODO: global constant type %i", self->vtype);
                 break;
         }
     }
@@ -1354,13 +1352,13 @@ static bool ast_global_array_set(ast_value *self)
 
 static bool check_array(ast_value *self, ast_value *array)
 {
-    if (array->expression.flags & AST_FLAG_ARRAY_INIT && array->initlist.empty()) {
+    if (array->flags & AST_FLAG_ARRAY_INIT && array->initlist.empty()) {
         compile_error(ast_ctx(self), "array without size: %s", self->name);
         return false;
     }
     /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */
-    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);
+    if (!array->count || array->count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) {
+        compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)array->count);
         return false;
     }
     return true;
@@ -1370,14 +1368,14 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
 {
     ir_value *v = nullptr;
 
-    if (self->expression.vtype == TYPE_NIL) {
+    if (self->vtype == TYPE_NIL) {
         compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
         return false;
     }
 
-    if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
+    if (self->hasvalue && self->vtype == TYPE_FUNCTION)
     {
-        ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->vtype);
+        ir_function *func = ir_builder_create_function(ir, self->name, self->next->vtype);
         if (!func)
             return false;
         func->context = ast_ctx(self);
@@ -1385,18 +1383,18 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
 
         self->constval.vfunc->ir_func = func;
         self->ir_v = func->value;
-        if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+        if (self->flags & AST_FLAG_INCLUDE_DEF)
             self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
-        if (self->expression.flags & AST_FLAG_ERASEABLE)
+        if (self->flags & AST_FLAG_ERASEABLE)
             self->ir_v->flags |= IR_FLAG_ERASABLE;
-        if (self->expression.flags & AST_FLAG_BLOCK_COVERAGE)
+        if (self->flags & AST_FLAG_BLOCK_COVERAGE)
             func->flags |= IR_FLAG_BLOCK_COVERAGE;
         /* The function is filled later on ast_function_codegen... */
         return true;
     }
 
-    if (isfield && self->expression.vtype == TYPE_FIELD) {
-        ast_expression *fieldtype = self->expression.next;
+    if (isfield && self->vtype == TYPE_FIELD) {
+        ast_expression *fieldtype = self->next;
 
         if (self->hasvalue) {
             compile_error(ast_ctx(self), "TODO: constant field pointers with value");
@@ -1420,7 +1418,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             if (!check_array(self, array))
                 return false;
 
-            elemtype = array->expression.next;
+            elemtype = array->next;
             vtype = elemtype->vtype;
 
             v = ir_builder_create_field(ir, self->name, vtype);
@@ -1433,18 +1431,18 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             v->locked      = true;
             array->ir_v = self->ir_v = v;
 
-            if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+            if (self->flags & AST_FLAG_INCLUDE_DEF)
                 self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
-            if (self->expression.flags & AST_FLAG_ERASEABLE)
+            if (self->flags & AST_FLAG_ERASEABLE)
                 self->ir_v->flags |= IR_FLAG_ERASABLE;
 
             namelen = strlen(self->name);
             name    = (char*)mem_a(namelen + 16);
             util_strncpy(name, self->name, namelen);
 
-            array->ir_values = (ir_value**)mem_a(sizeof(array->ir_values[0]) * array->expression.count);
+            array->ir_values = (ir_value**)mem_a(sizeof(array->ir_values[0]) * array->count);
             array->ir_values[0] = v;
-            for (ai = 1; ai < array->expression.count; ++ai) {
+            for (ai = 1; ai < array->count; ++ai) {
                 util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
                 array->ir_values[ai] = ir_builder_create_field(ir, name, vtype);
                 if (!array->ir_values[ai]) {
@@ -1455,36 +1453,36 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
                 array->ir_values[ai]->context = ast_ctx(self);
                 array->ir_values[ai]->unique_life = true;
                 array->ir_values[ai]->locked      = true;
-                if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+                if (self->flags & AST_FLAG_INCLUDE_DEF)
                     self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF;
             }
             mem_d(name);
         }
         else
         {
-            v = ir_builder_create_field(ir, self->name, self->expression.next->vtype);
+            v = ir_builder_create_field(ir, self->name, self->next->vtype);
             if (!v)
                 return false;
             v->context = ast_ctx(self);
             self->ir_v = v;
-            if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+            if (self->flags & AST_FLAG_INCLUDE_DEF)
                 self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
 
-            if (self->expression.flags & AST_FLAG_ERASEABLE)
+            if (self->flags & AST_FLAG_ERASEABLE)
                 self->ir_v->flags |= IR_FLAG_ERASABLE;
         }
         return true;
     }
 
-    if (self->expression.vtype == TYPE_ARRAY) {
+    if (self->vtype == TYPE_ARRAY) {
         size_t ai;
         char   *name;
         size_t  namelen;
 
-        ast_expression *elemtype = self->expression.next;
+        ast_expression *elemtype = self->next;
         int vtype = elemtype->vtype;
 
-        if (self->expression.flags & AST_FLAG_ARRAY_INIT && !self->expression.count) {
+        if (self->flags & AST_FLAG_ARRAY_INIT && !self->count) {
             compile_error(ast_ctx(self), "array `%s' has no size", self->name);
             return false;
         }
@@ -1502,18 +1500,18 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
         v->unique_life = true;
         v->locked      = true;
 
-        if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+        if (self->flags & AST_FLAG_INCLUDE_DEF)
             v->flags |= IR_FLAG_INCLUDE_DEF;
-        if (self->expression.flags & AST_FLAG_ERASEABLE)
+        if (self->flags & AST_FLAG_ERASEABLE)
             self->ir_v->flags |= IR_FLAG_ERASABLE;
 
         namelen = strlen(self->name);
         name    = (char*)mem_a(namelen + 16);
         util_strncpy(name, self->name, namelen);
 
-        self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count);
+        self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->count);
         self->ir_values[0] = v;
-        for (ai = 1; ai < self->expression.count; ++ai) {
+        for (ai = 1; ai < self->count; ++ai) {
             util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
             self->ir_values[ai] = ir_builder_create_global(ir, name, vtype);
             if (!self->ir_values[ai]) {
@@ -1524,7 +1522,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             self->ir_values[ai]->context = ast_ctx(self);
             self->ir_values[ai]->unique_life = true;
             self->ir_values[ai]->locked      = true;
-            if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+            if (self->flags & AST_FLAG_INCLUDE_DEF)
                 self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF;
         }
         mem_d(name);
@@ -1534,7 +1532,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
         /* Arrays don't do this since there's no "array" value which spans across the
          * whole thing.
          */
-        v = ir_builder_create_global(ir, self->name, self->expression.vtype);
+        v = ir_builder_create_global(ir, self->name, self->vtype);
         if (!v) {
             compile_error(ast_ctx(self), "ir_builder_create_global failed on `%s`", self->name);
             return false;
@@ -1547,14 +1545,14 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
     v->cvq = self->cvq;
     self->ir_v = v;
 
-    if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+    if (self->flags & AST_FLAG_INCLUDE_DEF)
         self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
-    if (self->expression.flags & AST_FLAG_ERASEABLE)
+    if (self->flags & AST_FLAG_ERASEABLE)
         self->ir_v->flags |= IR_FLAG_ERASABLE;
 
     /* initialize */
     if (self->hasvalue) {
-        switch (self->expression.vtype)
+        switch (self->vtype)
         {
             case TYPE_FLOAT:
                 if (!ir_value_set_float(v, self->constval.vfloat))
@@ -1590,7 +1588,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
                     goto error;
                 break;
             default:
-                compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype);
+                compile_error(ast_ctx(self), "TODO: global constant type %i", self->vtype);
                 break;
         }
     }
@@ -1605,12 +1603,12 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
 {
     ir_value *v = nullptr;
 
-    if (self->expression.vtype == TYPE_NIL) {
+    if (self->vtype == TYPE_NIL) {
         compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
         return false;
     }
 
-    if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
+    if (self->hasvalue && self->vtype == TYPE_FUNCTION)
     {
         /* Do we allow local functions? I think not...
          * this is NOT a function pointer atm.
@@ -1618,17 +1616,17 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
         return false;
     }
 
-    if (self->expression.vtype == TYPE_ARRAY) {
+    if (self->vtype == TYPE_ARRAY) {
         size_t ai;
         char   *name;
         size_t  namelen;
 
-        ast_expression *elemtype = self->expression.next;
+        ast_expression *elemtype = self->next;
         int vtype = elemtype->vtype;
 
         func->flags |= IR_FLAG_HAS_ARRAYS;
 
-        if (param && !(self->expression.flags & AST_FLAG_IS_VARARG)) {
+        if (param && !(self->flags & AST_FLAG_IS_VARARG)) {
             compile_error(ast_ctx(self), "array-parameters are not supported");
             return false;
         }
@@ -1637,7 +1635,7 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
         if (!check_array(self, self))
             return false;
 
-        self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count);
+        self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->count);
         if (!self->ir_values) {
             compile_error(ast_ctx(self), "failed to allocate array values");
             return false;
@@ -1657,7 +1655,7 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
         util_strncpy(name, self->name, namelen);
 
         self->ir_values[0] = v;
-        for (ai = 1; ai < self->expression.count; ++ai) {
+        for (ai = 1; ai < self->count; ++ai) {
             util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
             self->ir_values[ai] = ir_function_create_local(func, name, vtype, param);
             if (!self->ir_values[ai]) {
@@ -1672,7 +1670,7 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
     }
     else
     {
-        v = ir_function_create_local(func, self->name, self->expression.vtype, param);
+        v = ir_function_create_local(func, self->name, self->vtype, param);
         if (!v)
             return false;
         codegen_output_type(self, v);
@@ -1683,7 +1681,7 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
      * I suppose the IR will have to deal with this
      */
     if (self->hasvalue) {
-        switch (self->expression.vtype)
+        switch (self->vtype)
         {
             case TYPE_FLOAT:
                 if (!ir_value_set_float(v, self->constval.vfloat))
@@ -1698,7 +1696,7 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
                     goto error;
                 break;
             default:
-                compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype);
+                compile_error(ast_ctx(self), "TODO: global constant type %i", self->vtype);
                 break;
         }
     }
@@ -1722,7 +1720,7 @@ bool ast_generate_accessors(ast_value *self, ir_builder *ir)
     bool warn = OPTS_WARN(WARN_USED_UNINITIALIZED);
     if (!self->setter || !self->getter)
         return true;
-    for (i = 0; i < self->expression.count; ++i) {
+    for (i = 0; i < self->count; ++i) {
         if (!self->ir_values) {
             compile_error(ast_ctx(self), "internal error: no array values generated for `%s`", self->name);
             return false;
@@ -1758,7 +1756,7 @@ bool ast_generate_accessors(ast_value *self, ir_builder *ir)
             return false;
         }
     }
-    for (i = 0; i < self->expression.count; ++i) {
+    for (i = 0; i < self->count; ++i) {
         vec_free(self->ir_values[i]->life);
     }
     opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
@@ -1781,12 +1779,12 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
     }
 
     /* fill the parameter list */
-    ec = &self->function_type->expression;
+    ec = self->function_type;
     for (auto &it : ec->type_params) {
-        if (it->expression.vtype == TYPE_FIELD)
-            vec_push(irf->params, it->expression.next->vtype);
+        if (it->vtype == TYPE_FIELD)
+            vec_push(irf->params, it->next->vtype);
         else
-            vec_push(irf->params, it->expression.vtype);
+            vec_push(irf->params, it->vtype);
         if (!self->builtin) {
             if (!ast_local_codegen(it, self->ir_func, true))
                 return false;
@@ -1796,7 +1794,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
     if (self->varargs) {
         if (!ast_local_codegen(self->varargs, self->ir_func, true))
             return false;
-        irf->max_varargs = self->varargs->expression.count;
+        irf->max_varargs = self->varargs->count;
     }
 
     if (self->builtin) {
@@ -1827,10 +1825,10 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
         ir_value *sub;
         if (!ast_local_codegen(self->argc, self->ir_func, true))
             return false;
-        cgen = self->argc->expression.codegen;
+        cgen = self->argc->codegen;
         if (!(*cgen)((ast_expression*)(self->argc), self, false, &va_count))
             return false;
-        cgen = self->fixedparams->expression.codegen;
+        cgen = self->fixedparams->codegen;
         if (!(*cgen)((ast_expression*)(self->fixedparams), self, false, &fixed))
             return false;
         sub = ir_block_create_binop(self->curblock, ast_ctx(self),
@@ -1846,7 +1844,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
     }
 
     for (auto &it : self->blocks) {
-        cgen = it->expression.codegen;
+        cgen = it->codegen;
         if (!(*cgen)((ast_expression*)it, self, false, &dummy))
             return false;
     }
@@ -1854,15 +1852,15 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
     /* TODO: check return types */
     if (!self->curblock->final)
     {
-        if (!self->function_type->expression.next ||
-            self->function_type->expression.next->vtype == TYPE_VOID)
+        if (!self->function_type->next ||
+            self->function_type->next->vtype == TYPE_VOID)
         {
             return ir_block_create_return(self->curblock, ast_ctx(self), nullptr);
         }
         else if (vec_size(self->curblock->entries) || self->curblock == irf->first)
         {
             if (self->return_value) {
-                cgen = self->return_value->expression.codegen;
+                cgen = self->return_value->codegen;
                 if (!(*cgen)((ast_expression*)(self->return_value), self, false, &dummy))
                     return false;
                 return ir_block_create_return(self->curblock, ast_ctx(self), dummy);
@@ -1907,8 +1905,8 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu
         return false;
     }
 
-    if (self->expression.outr) {
-        *out = self->expression.outr;
+    if (self->outr) {
+        *out = self->outr;
         return true;
     }
 
@@ -1941,7 +1939,7 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu
             return false;
     }
 
-    self->expression.outr = *out;
+    self->outr = *out;
 
     return true;
 }
@@ -1956,13 +1954,13 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
     ast_value       *idx = 0;
     ast_array_index *ai = nullptr;
 
-    if (lvalue && self->expression.outl) {
-        *out = self->expression.outl;
+    if (lvalue && self->outl) {
+        *out = self->outl;
         return true;
     }
 
-    if (!lvalue && self->expression.outr) {
-        *out = self->expression.outr;
+    if (!lvalue && self->outr) {
+        *out = self->outr;
         return true;
     }
 
@@ -1992,11 +1990,11 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
             return false;
         }
 
-        cgen = idx->expression.codegen;
+        cgen = idx->codegen;
         if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
             return false;
 
-        cgen = arr->setter->expression.codegen;
+        cgen = arr->setter->codegen;
         if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
             return false;
 
@@ -2009,7 +2007,7 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
             return false;
         ir_call_param(call, iridx);
         ir_call_param(call, right);
-        self->expression.outr = right;
+        self->outr = right;
     }
     else
     {
@@ -2019,7 +2017,7 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
         /* lvalue! */
         if (!(*cgen)((ast_expression*)(self->dest), func, true, &left))
             return false;
-        self->expression.outl = left;
+        self->outl = left;
 
         cgen = self->source->codegen;
         /* rvalue! */
@@ -2028,7 +2026,7 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
 
         if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->op, left, right))
             return false;
-        self->expression.outr = right;
+        self->outr = right;
     }
 
     /* Theoretically, an assinment returns its left side as an
@@ -2054,8 +2052,8 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         return false;
     }
 
-    if (self->expression.outr) {
-        *out = self->expression.outr;
+    if (self->outr) {
+        *out = self->outr;
         return true;
     }
 
@@ -2114,7 +2112,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         func->curblock = merge;
         phi = ir_block_create_phi(func->curblock, ast_ctx(self),
                                   ast_function_label(func, "sce_value"),
-                                  self->expression.vtype);
+                                  self->vtype);
         ir_phi_add(phi, from_left, left);
         ir_phi_add(phi, from_right, right);
         *out = ir_phi_value(phi);
@@ -2156,7 +2154,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
             }
         }
 
-        self->expression.outr = *out;
+        self->outr = *out;
         codegen_output_type(self, *out);
         return true;
     }
@@ -2181,7 +2179,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
                                  self->op, left, right);
     if (!*out)
         return false;
-    self->expression.outr = *out;
+    self->outr = *out;
     codegen_output_type(self, *out);
 
     return true;
@@ -2197,13 +2195,13 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
     ast_array_index *ai = nullptr;
     ir_value        *iridx = nullptr;
 
-    if (lvalue && self->expression.outl) {
-        *out = self->expression.outl;
+    if (lvalue && self->outl) {
+        *out = self->outl;
         return true;
     }
 
-    if (!lvalue && self->expression.outr) {
-        *out = self->expression.outr;
+    if (!lvalue && self->outr) {
+        *out = self->outr;
         return true;
     }
 
@@ -2220,7 +2218,7 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
     /* for a binstore we need both an lvalue and an rvalue for the left side */
     /* rvalue of destination! */
     if (ai) {
-        cgen = idx->expression.codegen;
+        cgen = idx->codegen;
         if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
             return false;
     }
@@ -2236,8 +2234,7 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
     /* now the binary */
     bin = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "binst"),
                                 self->opbin, leftr, right);
-    self->expression.outr = bin;
-
+    self->outr = bin;
 
     if (ai) {
         /* we need to call the setter */
@@ -2255,7 +2252,7 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
             return false;
         }
 
-        cgen = arr->setter->expression.codegen;
+        cgen = arr->setter->codegen;
         if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
             return false;
 
@@ -2264,18 +2261,18 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
             return false;
         ir_call_param(call, iridx);
         ir_call_param(call, bin);
-        self->expression.outr = bin;
+        self->outr = bin;
     } else {
         /* now store them */
         cgen = self->dest->codegen;
         /* lvalue of destination */
         if (!(*cgen)((ast_expression*)(self->dest), func, true, &leftl))
             return false;
-        self->expression.outl = leftl;
+        self->outl = leftl;
 
         if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->opstore, leftl, bin))
             return false;
-        self->expression.outr = bin;
+        self->outr = bin;
     }
 
     /* Theoretically, an assinment returns its left side as an
@@ -2301,8 +2298,8 @@ bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_valu
         return false;
     }
 
-    if (self->expression.outr) {
-        *out = self->expression.outr;
+    if (self->outr) {
+        *out = self->outr;
         return true;
     }
 
@@ -2315,7 +2312,7 @@ bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_valu
                                  self->op, operand);
     if (!*out)
         return false;
-    self->expression.outr = *out;
+    self->outr = *out;
 
     return true;
 }
@@ -2335,11 +2332,11 @@ bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_va
         return false;
     }
 
-    if (self->expression.outr) {
+    if (self->outr) {
         compile_error(ast_ctx(self), "internal error: ast_return cannot be reused, it bears no result!");
         return false;
     }
-    self->expression.outr = (ir_value*)1;
+    self->outr = (ir_value*)1;
 
     if (self->operand) {
         cgen = self->operand->codegen;
@@ -2367,13 +2364,13 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i
      * value in a temp.
      */
 
-    if (lvalue && self->expression.outl) {
-        *out = self->expression.outl;
+    if (lvalue && self->outl) {
+        *out = self->outl;
         return true;
     }
 
-    if (!lvalue && self->expression.outr) {
-        *out = self->expression.outr;
+    if (!lvalue && self->outr) {
+        *out = self->outr;
         return true;
     }
 
@@ -2391,7 +2388,7 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i
                                             ent, field);
     } else {
         *out = ir_block_create_load_from_ent(func->curblock, ast_ctx(self), ast_function_label(func, "efv"),
-                                             ent, field, self->expression.vtype);
+                                             ent, field, self->vtype);
         /* Done AFTER error checking:
         codegen_output_type(self, *out);
         */
@@ -2399,16 +2396,16 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i
     if (!*out) {
         compile_error(ast_ctx(self), "failed to create %s instruction (output type %s)",
                  (lvalue ? "ADDRESS" : "FIELD"),
-                 type_name[self->expression.vtype]);
+                 type_name[self->vtype]);
         return false;
     }
     if (!lvalue)
         codegen_output_type(self, *out);
 
     if (lvalue)
-        self->expression.outl = *out;
+        self->outl = *out;
     else
-        self->expression.outr = *out;
+        self->outr = *out;
 
     /* Hm that should be it... */
     return true;
@@ -2424,8 +2421,8 @@ bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_va
         compile_error(ast_ctx(self), "not an l-value (member access)");
         return false;
     }
-    if (self->expression.outl) {
-        *out = self->expression.outl;
+    if (self->outl) {
+        *out = self->outl;
         return true;
     }
 
@@ -2440,7 +2437,7 @@ bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_va
     }
 
     *out = ir_value_vector_member(vec, self->field);
-    self->expression.outl = *out;
+    self->outl = *out;
 
     return (*out != nullptr);
 }
@@ -2450,12 +2447,12 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
     ast_value *arr;
     ast_value *idx;
 
-    if (!lvalue && self->expression.outr) {
-        *out = self->expression.outr;
+    if (!lvalue && self->outr) {
+        *out = self->outr;
         return true;
     }
-    if (lvalue && self->expression.outl) {
-        *out = self->expression.outl;
+    if (lvalue && self->outl) {
+        *out = self->outl;
         return true;
     }
 
@@ -2492,7 +2489,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
         if (!(*cgen)((ast_expression*)(self->index), func, false, &iridx))
             return false;
 
-        cgen = arr->getter->expression.codegen;
+        cgen = arr->getter->codegen;
         if (!(*cgen)((ast_expression*)(arr->getter), func, true, &funval))
             return false;
 
@@ -2502,13 +2499,13 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
         ir_call_param(call, iridx);
 
         *out = ir_call_value(call);
-        self->expression.outr = *out;
-        (*out)->vtype = self->expression.vtype;
+        self->outr = *out;
+        (*out)->vtype = self->vtype;
         codegen_output_type(self, *out);
         return true;
     }
 
-    if (idx->expression.vtype == TYPE_FLOAT) {
+    if (idx->vtype == TYPE_FLOAT) {
         unsigned int arridx = idx->constval.vfloat;
         if (arridx >= self->array->count)
         {
@@ -2517,7 +2514,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
         }
         *out = arr->ir_values[arridx];
     }
-    else if (idx->expression.vtype == TYPE_INTEGER) {
+    else if (idx->vtype == TYPE_INTEGER) {
         unsigned int arridx = idx->constval.vint;
         if (arridx >= self->array->count)
         {
@@ -2530,7 +2527,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
         compile_error(ast_ctx(self), "array indexing here needs an integer constant");
         return false;
     }
-    (*out)->vtype = self->expression.vtype;
+    (*out)->vtype = self->vtype;
     codegen_output_type(self, *out);
     return true;
 }
@@ -2567,11 +2564,11 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
     (void)out;
     (void)lvalue;
 
-    if (self->expression.outr) {
+    if (self->outr) {
         compile_error(ast_ctx(self), "internal error: ast_ifthen cannot be reused, it bears no result!");
         return false;
     }
-    self->expression.outr = (ir_value*)1;
+    self->outr = (ir_value*)1;
 
     /* generate the condition */
     cgen = self->cond->codegen;
@@ -2675,8 +2672,8 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
      * may still happen, thus we remember a created ir_value and simply return one
      * if it already exists.
      */
-    if (self->expression.outr) {
-        *out = self->expression.outr;
+    if (self->outr) {
+        *out = self->outr;
         return true;
     }
 
@@ -2754,7 +2751,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
     }
 
     /* create PHI */
-    phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), self->expression.vtype);
+    phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), self->vtype);
     if (!phi) {
         compile_error(ast_ctx(self), "internal error: failed to generate phi node");
         return false;
@@ -2762,8 +2759,8 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
     ir_phi_add(phi, ontrue_out,  trueval);
     ir_phi_add(phi, onfalse_out, falseval);
 
-    self->expression.outr = ir_phi_value(phi);
-    *out = self->expression.outr;
+    self->outr = ir_phi_value(phi);
+    *out = self->outr;
 
     codegen_output_type(self, *out);
 
@@ -2800,11 +2797,11 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
     (void)lvalue;
     (void)out;
 
-    if (self->expression.outr) {
+    if (self->outr) {
         compile_error(ast_ctx(self), "internal error: ast_loop cannot be reused, it bears no result!");
         return false;
     }
-    self->expression.outr = (ir_value*)1;
+    self->outr = (ir_value*)1;
 
     /* NOTE:
      * Should we ever need some kind of block ordering, better make this function
@@ -3032,11 +3029,11 @@ bool ast_breakcont_codegen(ast_breakcont *self, ast_function *func, bool lvalue,
         return false;
     }
 
-    if (self->expression.outr) {
+    if (self->outr) {
         compile_error(ast_ctx(self), "internal error: ast_breakcont cannot be reused!");
         return false;
     }
-    self->expression.outr = (ir_value*)1;
+    self->outr = (ir_value*)1;
 
     if (self->is_continue)
         target = func->continueblocks[func->continueblocks.size()-1-self->levels];
@@ -3076,11 +3073,11 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
         return false;
     }
 
-    if (self->expression.outr) {
+    if (self->outr) {
         compile_error(ast_ctx(self), "internal error: ast_switch cannot be reused!");
         return false;
     }
-    self->expression.outr = (ir_value*)1;
+    self->outr = (ir_value*)1;
 
     (void)lvalue;
     (void)out;
@@ -3306,7 +3303,7 @@ bool ast_state_codegen(ast_state *self, ast_function *func, bool lvalue, ir_valu
         compile_error(ast_ctx(self), "not an l-value (state operation)");
         return false;
     }
-    if (self->expression.outr) {
+    if (self->outr) {
         compile_error(ast_ctx(self), "internal error: ast_state cannot be reused!");
         return false;
     }
@@ -3329,7 +3326,7 @@ bool ast_state_codegen(ast_state *self, ast_function *func, bool lvalue, ir_valu
         return false;
     }
 
-    self->expression.outr = (ir_value*)1;
+    self->outr = (ir_value*)1;
     return true;
 }
 
@@ -3347,8 +3344,8 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
         return false;
     }
 
-    if (self->expression.outr) {
-        *out = self->expression.outr;
+    if (self->outr) {
+        *out = self->outr;
         return true;
     }
 
@@ -3393,7 +3390,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
         ir_call_param(callinstr, it);
 
     *out = ir_call_value(callinstr);
-    self->expression.outr = *out;
+    self->outr = *out;
 
     codegen_output_type(self, *out);
 
diff --git a/ast.h b/ast.h
index 69e03929ac83220334ef8f4c8814bd29cf80b479..a6ff49b29ffe34181d308edaafff1213956962cb 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -182,10 +182,8 @@ union basic_value_t {
     ast_value *vfield;
 };
 
-struct ast_value
+struct ast_value : ast_expression
 {
-    ast_expression expression;
-
     const char *name;
     const char *desc;
 
@@ -252,9 +250,8 @@ enum ast_binary_ref {
  *
  * A value-returning binary expression.
  */
-struct ast_binary
+struct ast_binary : ast_expression
 {
-    ast_expression expression;
     int op;
     ast_expression *left;
     ast_expression *right;
@@ -271,9 +268,8 @@ ast_binary* ast_binary_new(lex_ctx_t    ctx,
  * An assignment including a binary expression with the source as left operand.
  * Eg. a += b; is a binstore { INSTR_STORE, INSTR_ADD, a, b }
  */
-struct ast_binstore
+struct ast_binstore : ast_expression
 {
-    ast_expression expression;
     int opstore;
     int opbin;
     ast_expression *dest;
@@ -291,9 +287,8 @@ ast_binstore* ast_binstore_new(lex_ctx_t    ctx,
  *
  * Regular unary expressions: not,neg
  */
-struct ast_unary
+struct ast_unary : ast_expression
 {
-    ast_expression expression;
     int op;
     ast_expression *operand;
 };
@@ -307,9 +302,8 @@ ast_unary* ast_unary_new(lex_ctx_t ctx,
  * will refuse to create further instructions.
  * This should be honored by the parser.
  */
-struct ast_return
+struct ast_return : ast_expression
 {
-    ast_expression expression;
     ast_expression *operand;
 };
 ast_return* ast_return_new(lex_ctx_t ctx,
@@ -328,9 +322,8 @@ ast_return* ast_return_new(lex_ctx_t ctx,
  * For this we will have to extend the codegen() functions with
  * a flag saying whether or not we need an L or an R-value.
  */
-struct ast_entfield
+struct ast_entfield : ast_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 */
@@ -344,9 +337,8 @@ ast_entfield* ast_entfield_new_force(lex_ctx_t ctx, ast_expression *entity, ast_
  * For now used for vectors. If we get structs or unions
  * we can have them handled here as well.
  */
-struct ast_member
+struct ast_member : ast_expression
 {
-    ast_expression expression;
     ast_expression *owner;
     unsigned int field;
     const char *name;
@@ -367,9 +359,8 @@ bool ast_member_set_name(ast_member*, const char *name);
  * In any case, accessing an element via a compiletime-constant index will
  * result in quick access to that variable.
  */
-struct ast_array_index
+struct ast_array_index : ast_expression
 {
-    ast_expression expression;
     ast_expression *array;
     ast_expression *index;
 };
@@ -379,9 +370,8 @@ ast_array_index* ast_array_index_new(lex_ctx_t ctx, ast_expression *array, ast_e
  *
  * copy all varargs starting from a specific index
  */
-struct ast_argpipe
+struct ast_argpipe : ast_expression
 {
-    ast_expression expression;
     ast_expression *index;
 };
 ast_argpipe* ast_argpipe_new(lex_ctx_t ctx, ast_expression *index);
@@ -391,9 +381,8 @@ ast_argpipe* ast_argpipe_new(lex_ctx_t ctx, ast_expression *index);
  * Stores left<-right and returns left.
  * Specialized binary expression node
  */
-struct ast_store
+struct ast_store : ast_expression
 {
-    ast_expression expression;
     int op;
     ast_expression *dest;
     ast_expression *source;
@@ -412,9 +401,8 @@ ast_store* ast_store_new(lex_ctx_t ctx, int op,
  * output field though. For ternary expressions an ast_ternary will be
  * added.
  */
-struct ast_ifthen
+struct ast_ifthen : ast_expression
 {
-    ast_expression expression;
     ast_expression *cond;
     /* It's all just 'expressions', since an ast_block is one too. */
     ast_expression *on_true;
@@ -435,9 +423,8 @@ ast_ifthen* ast_ifthen_new(lex_ctx_t ctx, ast_expression *cond, ast_expression *
  * This is the only ast_node beside ast_value which contains
  * an ir_value. Theoretically we don't need to remember it though.
  */
-struct ast_ternary
+struct ast_ternary : ast_expression
 {
-    ast_expression expression;
     ast_expression *cond;
     /* It's all just 'expressions', since an ast_block is one too. */
     ast_expression *on_true;
@@ -468,9 +455,8 @@ continue:      // a 'continue' will jump here
     {inc};
 }
  */
-struct ast_loop
+struct ast_loop : ast_expression
 {
-    ast_expression expression;
     ast_expression *initexpr;
     ast_expression *precond;
     ast_expression *postcond;
@@ -494,10 +480,9 @@ ast_loop* ast_loop_new(lex_ctx_t ctx,
 
 /* Break/Continue
  */
-struct ast_breakcont
+struct ast_breakcont : ast_expression
 {
-    ast_expression expression;
-    bool is_continue;
+    bool         is_continue;
     unsigned int levels;
 };
 ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels);
@@ -517,9 +502,8 @@ struct ast_switch_case {
     ast_expression *code;
 };
 
-struct ast_switch
+struct ast_switch : ast_expression
 {
-    ast_expression expression;
     ast_expression *operand;
     std::vector<ast_switch_case> cases;
 };
@@ -530,9 +514,8 @@ ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op);
  *
  * Introduce a label which can be used together with 'goto'
  */
-struct ast_label
+struct ast_label : ast_expression
 {
-    ast_expression expression;
     const char *name;
     ir_block *irblock;
     std::vector<ast_goto*> gotos;
@@ -547,9 +530,8 @@ ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined);
  *
  * Go to a label, the label node is filled in at a later point!
  */
-struct ast_goto
+struct ast_goto : ast_expression
 {
-    ast_expression expression;
     const char *name;
     ast_label *target;
     ir_block *irblock_from;
@@ -562,9 +544,8 @@ void ast_goto_set_label(ast_goto*, ast_label*);
  *
  * For frame/think state updates: void foo() [framenum, nextthink] {}
  */
-struct ast_state
+struct ast_state : ast_expression
 {
-    ast_expression expression;
     ast_expression *framenum;
     ast_expression *nextthink;
 };
@@ -581,9 +562,8 @@ void ast_state_delete(ast_state*);
  * Additionally it contains a list of ast_expressions as parameters.
  * Since calls can return values, an ast_call is also an ast_expression.
  */
-struct ast_call
+struct ast_call : ast_expression
 {
-    ast_expression expression;
     ast_expression *func;
     std::vector<ast_expression *> params;
     ast_expression *va_count;
@@ -595,11 +575,9 @@ bool ast_call_check_types(ast_call*, ast_expression *this_func_va_type);
 /* Blocks
  *
  */
-struct ast_block
+struct ast_block : ast_expression
 {
-    ast_expression expression;
-
-    std::vector<ast_value*> locals;
+    std::vector<ast_value*>      locals;
     std::vector<ast_expression*> exprs;
     std::vector<ast_expression*> collect;
 };
index d8f9de170e7c6dd91577d89eba7f2096b183cb5f..d2d6b6f143147f4028b72d2cdd17622c11f7d83f 100644 (file)
--- a/fold.cpp
+++ b/fold.cpp
@@ -878,7 +878,7 @@ lex_ctx_t fold::ctx() {
 }
 
 bool fold::immediate_true(ast_value *v) {
-    switch (v->expression.vtype) {
+    switch (v->vtype) {
         case TYPE_FLOAT:
             return !!v->constval.vfloat;
         case TYPE_INTEGER:
@@ -998,7 +998,7 @@ ast_expression *fold::constgen_string(const char *str, bool translate) {
         char name[32];
         util_snprintf(name, sizeof(name), "dotranslate_%zu", m_parser->translated++);
         out = ast_value_new(ctx(), name, TYPE_STRING);
-        out->expression.flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */
+        out->flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */
     } else {
         out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_STRING);
     }
index 80fa2eaefa862f66b3e8364b402c333b74543a3a..fd7fa73a22495df304bf73c867749727066421fb 100644 (file)
@@ -19,9 +19,9 @@ ast_function *intrin::value(ast_value **out, const char *name, qcint_t vtype) {
 
     value = ast_value_new(ctx(), buffer, TYPE_FUNCTION);
     value->intrinsic = true;
-    value->expression.next = (ast_expression*)ast_value_new(ctx(), stype, vtype);
+    value->next = (ast_expression*)ast_value_new(ctx(), stype, vtype);
     func = ast_function_new(ctx(), buffer, value);
-    value->expression.flags |= AST_FLAG_ERASEABLE;
+    value->flags |= AST_FLAG_ERASEABLE;
 
     *out = value;
     return func;
@@ -55,7 +55,7 @@ ast_expression *intrin::isfinite_() {
     ast_block    *block     = ast_block_new(ctx());
 
     /* float x; */
-    val->expression.type_params.push_back(x);
+    val->type_params.push_back(x);
 
     /* <callisnan> = isnan(x); */
     callisnan->params.push_back((ast_expression*)x);
@@ -124,7 +124,7 @@ ast_expression *intrin::isinf_() {
         )
     );
 
-    val->expression.type_params.push_back(x);
+    val->type_params.push_back(x);
     func->blocks.push_back(body);
 
     reg(val, func);
@@ -169,7 +169,7 @@ ast_expression *intrin::isnan_() {
         )
     );
 
-    val->expression.type_params.push_back(arg1);
+    val->type_params.push_back(arg1);
     func->blocks.push_back(body);
 
     reg(val, func);
@@ -189,7 +189,7 @@ ast_expression *intrin::isnormal_() {
     ast_block *body = ast_block_new(ctx());
     ast_function *func = value(&val, "isnormal", TYPE_FLOAT);
 
-    val->expression.type_params.push_back(x);
+    val->type_params.push_back(x);
     callisfinite->params.push_back((ast_expression*)x);
 
     /* return <callisfinite> */
@@ -216,7 +216,7 @@ ast_expression *intrin::signbit_() {
     ast_block *body = ast_block_new(ctx());
     ast_function *func = value(&val, "signbit", TYPE_FLOAT);
 
-    val->expression.type_params.push_back(x);
+    val->type_params.push_back(x);
 
     /* return (x < 0); */
     body->exprs.push_back(
@@ -254,7 +254,7 @@ ast_expression *intrin::acosh_() {
     ast_block    *body     = ast_block_new(ctx());
     ast_function *func     = value(&val, "acosh", TYPE_FLOAT);
 
-    val->expression.type_params.push_back(x);
+    val->type_params.push_back(x);
 
     /* <callsqrt> = sqrt((x * x) - 1); */
     callsqrt->params.push_back(
@@ -307,7 +307,7 @@ ast_expression *intrin::asinh_() {
     ast_block *body = ast_block_new(ctx());
     ast_function *func = value(&val, "asinh", TYPE_FLOAT);
 
-    val->expression.type_params.push_back(x);
+    val->type_params.push_back(x);
 
     /* <callsqrt> = sqrt((x * x) + 1); */
     callsqrt->params.push_back(
@@ -359,7 +359,7 @@ ast_expression *intrin::atanh_() {
     ast_block    *body    = ast_block_new(ctx());
     ast_function *func    = value(&val, "atanh", TYPE_FLOAT);
 
-    val->expression.type_params.push_back(x);
+    val->type_params.push_back(x);
 
     /* <callog> = log((1 + x) / (1 - x)); */
     calllog->params.push_back(
@@ -416,7 +416,7 @@ ast_expression *intrin::exp_() {
     ast_block *body = ast_block_new(ctx());
     ast_function *func = value(&val, "exp", TYPE_FLOAT);
 
-    val->expression.type_params.push_back(x);
+    val->type_params.push_back(x);
 
     body->locals.push_back(sum);
     body->locals.push_back(acc);
@@ -521,7 +521,7 @@ ast_expression *intrin::exp2_() {
     ast_block *body = ast_block_new(ctx());
     ast_function *func = value(&val, "exp2", TYPE_FLOAT);
 
-    val->expression.type_params.push_back(arg1);
+    val->type_params.push_back(arg1);
 
     callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]);
     callpow->params.push_back((ast_expression*)arg1);
@@ -551,7 +551,7 @@ ast_expression *intrin::expm1_() {
     ast_block *body = ast_block_new(ctx());
     ast_function *func = value(&val, "expm1", TYPE_FLOAT);
 
-    val->expression.type_params.push_back(x);
+    val->type_params.push_back(x);
 
     /* <callexp> = exp(x); */
     callexp->params.push_back((ast_expression*)x);
@@ -659,8 +659,8 @@ ast_expression *intrin::pow_() {
     body->locals.push_back(accumulate);
     body->locals.push_back(mid);
 
-    val->expression.type_params.push_back(base);
-    val->expression.type_params.push_back(exp);
+    val->type_params.push_back(base);
+    val->type_params.push_back(exp);
 
     /*
      * if (exp == 0.0)
@@ -1036,8 +1036,8 @@ ast_expression *intrin::mod_() {
     ast_block    *body  = ast_block_new(ctx());
     ast_function *func  = value(&val, "mod", TYPE_FLOAT);
 
-    val->expression.type_params.push_back(a);
-    val->expression.type_params.push_back(b);
+    val->type_params.push_back(a);
+    val->type_params.push_back(b);
 
     body->locals.push_back(div);
     body->locals.push_back(sign);
@@ -1147,7 +1147,7 @@ ast_expression *intrin::fabs_() {
         )
     );
 
-    val->expression.type_params.push_back(arg1);
+    val->type_params.push_back(arg1);
 
     func->blocks.push_back(body);
     reg(val, func);
@@ -1406,8 +1406,8 @@ ast_expression *intrin::ln_() {
     ast_function *func = value(&val, "ln", TYPE_FLOAT);
     size_t i;
 
-    val->expression.type_params.push_back(power);
-    val->expression.type_params.push_back(base);
+    val->type_params.push_back(power);
+    val->type_params.push_back(base);
 
     block->locals.push_back(whole);
     block->locals.push_back(nth);
@@ -1864,7 +1864,7 @@ ast_expression *intrin::log_variant(const char *name, float base) {
     ast_block *body = ast_block_new(ctx());
     ast_function *func = value(&val, name, TYPE_FLOAT);
 
-    val->expression.type_params.push_back(arg1);
+    val->type_params.push_back(arg1);
 
     callln->params.push_back((ast_expression*)arg1);
     callln->params.push_back((ast_expression*)m_fold->constgen_float(base, false));
@@ -1908,8 +1908,8 @@ ast_expression *intrin::shift_variant(const char *name, size_t instr) {
     ast_block *body = ast_block_new(ctx());
     ast_function *func = value(&val, name, TYPE_FLOAT);
 
-    val->expression.type_params.push_back(a);
-    val->expression.type_params.push_back(b);
+    val->type_params.push_back(a);
+    val->type_params.push_back(b);
 
     /* <callpow> = pow(2, b) */
     callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]);
@@ -2025,7 +2025,7 @@ ast_expression *intrin::func_try(size_t offset, const char *compare) {
 ast_expression *intrin::func_self(const char *name, const char *from) {
     ast_expression *find;
     /* try current first */
-    if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION)
+    if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->vtype == TYPE_FUNCTION)
         for (auto &it : m_parser->functions)
             if (((ast_value*)find)->name && !strcmp(it->name, ((ast_value*)find)->name) && it->builtin < 0)
                 return find;
index b5c63a3764b7a1248d8f277a35095693d145a72f..70c81f27201d98b33ae3e01ef710f8939a46b617 100644 (file)
@@ -103,7 +103,7 @@ static ast_expression* parser_find_param(parser_t *parser, const char *name)
     if (!parser->function)
         return nullptr;
     fun = parser->function->function_type;
-    for (auto &it : fun->expression.type_params) {
+    for (auto &it : fun->type_params) {
         if (!strcmp(it->name, name))
             return (ast_expression*)it;
     }
@@ -1269,7 +1269,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
     for (i = 0; i < paramcount; ++i)
         call->params.push_back(sy->out[fid+1 + i].out);
     sy->out.erase(sy->out.end() - paramcount, sy->out.end());
-    (void)!ast_call_check_types(call, parser->function->function_type->expression.varparam);
+    (void)!ast_call_check_types(call, parser->function->function_type->varparam);
     if (parser->max_param_count < paramcount)
         parser->max_param_count = paramcount;
 
@@ -1283,7 +1283,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
     }
 
     /* overwrite fid, the function, with a call */
-    sy->out[fid] = syexp(call->expression.context, (ast_expression*)call);
+    sy->out[fid] = syexp(call->context, (ast_expression*)call);
 
     if (fun->vtype != TYPE_FUNCTION) {
         parseerror(parser, "not a function (%s)", type_name[fun->vtype]);
@@ -1456,13 +1456,13 @@ static ast_expression* parse_vararg_do(parser_t *parser)
         return nullptr;
     }
 
-    if (funtype->expression.varparam &&
-        !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->expression.varparam))
+    if (funtype->varparam &&
+        !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->varparam))
     {
         char ty1[1024];
         char ty2[1024];
         ast_type_to_string((ast_expression*)typevar, ty1, sizeof(ty1));
-        ast_type_to_string((ast_expression*)funtype->expression.varparam, ty2, sizeof(ty2));
+        ast_type_to_string((ast_expression*)funtype->varparam, ty2, sizeof(ty2));
         compile_error(ast_ctx(typevar),
                       "function was declared to take varargs of type `%s`, requested type is: %s",
                       ty2, ty1);
@@ -1890,7 +1890,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 if (ast_istype(lexpr, ast_value)) {
                     ast_value *last = (ast_value*)lexpr;
                     if (last->isimm == true && last->cvq == CV_CONST &&
-                        last->hasvalue && last->expression.vtype == TYPE_STRING)
+                        last->hasvalue && last->vtype == TYPE_STRING)
                     {
                         char *newstr = nullptr;
                         util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser));
@@ -2580,9 +2580,9 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou
             return false;
         }
 
-        if (type_store_instr[expected->expression.next->vtype] == VINSTR_END) {
+        if (type_store_instr[expected->next->vtype] == VINSTR_END) {
             char ty1[1024];
-            ast_type_to_string(expected->expression.next, ty1, sizeof(ty1));
+            ast_type_to_string(expected->next, ty1, sizeof(ty1));
             parseerror(parser, "invalid return type: `%s'", ty1);
             return false;
         }
@@ -2598,21 +2598,21 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou
         /* prepare the return value */
         if (!retval) {
             retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID);
-            ast_type_adopt(retval, expected->expression.next);
+            ast_type_adopt(retval, expected->next);
             parser->function->return_value = retval;
         }
 
         if (!ast_compare_type(exp, (ast_expression*)retval)) {
             char ty1[1024], ty2[1024];
             ast_type_to_string(exp, ty1, sizeof(ty1));
-            ast_type_to_string(&retval->expression, ty2, sizeof(ty2));
+            ast_type_to_string(retval, ty2, sizeof(ty2));
             parseerror(parser, "invalid type for return value: `%s', expected `%s'", ty1, ty2);
         }
 
         /* store to 'return' local variable */
         var = (ast_expression*)ast_store_new(
             ctx,
-            type_store_instr[expected->expression.next->vtype],
+            type_store_instr[expected->next->vtype],
             (ast_expression*)retval, exp);
 
         if (!var) {
@@ -2649,7 +2649,7 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou
         if (!parser_next(parser))
             parseerror(parser, "parse error");
 
-        if (!retval && expected->expression.next->vtype != TYPE_VOID)
+        if (!retval && expected->next->vtype != TYPE_VOID)
         {
             (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
         }
@@ -3784,7 +3784,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
     has_frame_think = false;
     old = parser->function;
 
-    if (var->expression.flags & AST_FLAG_ALIAS) {
+    if (var->flags & AST_FLAG_ALIAS) {
         parseerror(parser, "function aliases cannot have bodies");
         return false;
     }
@@ -3794,7 +3794,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         return false;
     }
 
-    if (!OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
+    if (!OPTS_FLAG(VARIADIC_ARGS) && var->flags & AST_FLAG_VARIADIC) {
         if (parsewarning(parser, WARN_VARIADIC_FUNCTION,
                          "variadic function with implementation will not be able to access additional parameters (try -fvariadic-args)"))
         {
@@ -4007,7 +4007,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
     }
 
     if (var->hasvalue) {
-        if (!(var->expression.flags & AST_FLAG_ACCUMULATE)) {
+        if (!(var->flags & AST_FLAG_ACCUMULATE)) {
             parseerror(parser, "function `%s` declared with multiple bodies", var->name);
             ast_block_delete(block);
             goto enderr;
@@ -4032,13 +4032,13 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
 
     parser_enterblock(parser);
 
-    for (auto &it : var->expression.type_params) {
+    for (auto &it : var->type_params) {
         size_t e;
         ast_member *me[3];
 
-        if (it->expression.vtype != TYPE_VECTOR &&
-            (it->expression.vtype != TYPE_FIELD ||
-             it->expression.next->vtype != TYPE_VECTOR))
+        if (it->vtype != TYPE_VECTOR &&
+            (it->vtype != TYPE_FIELD ||
+             it->next->vtype != TYPE_VECTOR))
         {
             continue;
         }
@@ -4060,12 +4060,12 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         func->argc = argc;
     }
 
-    if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC && !func->varargs) {
+    if (OPTS_FLAG(VARIADIC_ARGS) && var->flags & AST_FLAG_VARIADIC && !func->varargs) {
         char name[1024];
         ast_value *varargs = ast_value_new(ast_ctx(var), "reserved:va_args", TYPE_ARRAY);
-        varargs->expression.flags |= AST_FLAG_IS_VARARG;
-        varargs->expression.next = (ast_expression*)ast_value_new(ast_ctx(var), nullptr, TYPE_VECTOR);
-        varargs->expression.count = 0;
+        varargs->flags |= AST_FLAG_IS_VARARG;
+        varargs->next = (ast_expression*)ast_value_new(ast_ctx(var), nullptr, TYPE_VECTOR);
+        varargs->count = 0;
         util_snprintf(name, sizeof(name), "%s##va##SET", var->name);
         if (!parser_create_array_setter_proto(parser, varargs, name)) {
             ast_delete(varargs);
@@ -4073,13 +4073,13 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
             goto enderrfn;
         }
         util_snprintf(name, sizeof(name), "%s##va##GET", var->name);
-        if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) {
+        if (!parser_create_array_getter_proto(parser, varargs, varargs->next, name)) {
             ast_delete(varargs);
             ast_block_delete(block);
             goto enderrfn;
         }
         func->varargs     = varargs;
-        func->fixedparams = (ast_value*)parser->m_fold.constgen_float(var->expression.type_params.size(), false);
+        func->fixedparams = (ast_value*)parser->m_fold.constgen_float(var->type_params.size(), false);
     }
 
     parser->function = func;
@@ -4165,9 +4165,9 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast
         ast_return      *ret;
         ast_array_index *subscript;
         ast_store       *st;
-        int assignop = type_store_instr[value->expression.vtype];
+        int assignop = type_store_instr[value->vtype];
 
-        if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
+        if (value->vtype == TYPE_FIELD && value->next->vtype == TYPE_VECTOR)
             assignop = INSTR_STORE_V;
 
         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false));
@@ -4231,17 +4231,17 @@ static ast_expression *array_field_setter_node(
         ast_entfield    *entfield;
         ast_array_index *subscript;
         ast_store       *st;
-        int assignop = type_storep_instr[value->expression.vtype];
+        int assignop = type_storep_instr[value->vtype];
 
-        if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
+        if (value->vtype == TYPE_FIELD && value->next->vtype == TYPE_VECTOR)
             assignop = INSTR_STOREP_V;
 
         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false));
         if (!subscript)
             return nullptr;
 
-        subscript->expression.next = ast_type_copy(ast_ctx(subscript), (ast_expression*)subscript);
-        subscript->expression.vtype = TYPE_FIELD;
+        subscript->next = ast_type_copy(ast_ctx(subscript), (ast_expression*)subscript);
+        subscript->vtype = TYPE_FIELD;
 
         entfield = ast_entfield_new_force(ctx,
                                           (ast_expression*)entity,
@@ -4331,7 +4331,7 @@ static bool parser_create_array_accessor(parser_t *parser, ast_value *array, con
         parseerror(parser, "failed to create accessor function value");
         return false;
     }
-    fval->expression.flags &= ~(AST_FLAG_COVERAGE_MASK);
+    fval->flags &= ~(AST_FLAG_COVERAGE_MASK);
 
     func = ast_function_new(ast_ctx(array), funcname, fval);
     if (!func) {
@@ -4363,7 +4363,7 @@ static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *
     ast_function   *func;
     ast_value      *fval;
 
-    if (!ast_istype(array->expression.next, ast_value)) {
+    if (!ast_istype(array->next, ast_value)) {
         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
         return nullptr;
     }
@@ -4371,18 +4371,18 @@ static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *
     if (!parser_create_array_accessor(parser, array, funcname, &fval))
         return nullptr;
     func = fval->constval.vfunc;
-    fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
+    fval->next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
 
     index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
-    value = ast_value_copy((ast_value*)array->expression.next);
+    value = ast_value_copy((ast_value*)array->next);
 
     if (!index || !value) {
         parseerror(parser, "failed to create locals for array accessor");
         goto cleanup;
     }
     (void)!ast_value_set_name(value, "value"); /* not important */
-    fval->expression.type_params.push_back(index);
-    fval->expression.type_params.push_back(value);
+    fval->type_params.push_back(index);
+    fval->type_params.push_back(value);
 
     array->setter = fval;
     return fval;
@@ -4398,9 +4398,9 @@ static bool parser_create_array_setter_impl(parser_t *parser, ast_value *array)
 {
     ast_expression *root = nullptr;
     root = array_setter_node(parser, array,
-                             array->setter->expression.type_params[0],
-                             array->setter->expression.type_params[1],
-                             0, array->expression.count);
+                             array->setter->type_params[0],
+                             array->setter->type_params[1],
+                             0, array->count);
     if (!root) {
         parseerror(parser, "failed to build accessor search tree");
         return false;
@@ -4428,7 +4428,7 @@ static bool parser_create_array_field_setter(parser_t *parser, ast_value *array,
     ast_function   *func;
     ast_value      *fval;
 
-    if (!ast_istype(array->expression.next, ast_value)) {
+    if (!ast_istype(array->next, ast_value)) {
         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
         return false;
     }
@@ -4436,21 +4436,21 @@ static bool parser_create_array_field_setter(parser_t *parser, ast_value *array,
     if (!parser_create_array_accessor(parser, array, funcname, &fval))
         return false;
     func = fval->constval.vfunc;
-    fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
+    fval->next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
 
     entity = ast_value_new(ast_ctx(array), "entity", TYPE_ENTITY);
     index  = ast_value_new(ast_ctx(array), "index",  TYPE_FLOAT);
-    value  = ast_value_copy((ast_value*)array->expression.next);
+    value  = ast_value_copy((ast_value*)array->next);
     if (!entity || !index || !value) {
         parseerror(parser, "failed to create locals for array accessor");
         goto cleanup;
     }
     (void)!ast_value_set_name(value, "value"); /* not important */
-    fval->expression.type_params.push_back(entity);
-    fval->expression.type_params.push_back(index);
-    fval->expression.type_params.push_back(value);
+    fval->type_params.push_back(entity);
+    fval->type_params.push_back(index);
+    fval->type_params.push_back(value);
 
-    root = array_field_setter_node(parser, array, entity, index, value, 0, array->expression.count);
+    root = array_field_setter_node(parser, array, entity, index, value, 0, array->count);
     if (!root) {
         parseerror(parser, "failed to build accessor search tree");
         goto cleanup;
@@ -4474,10 +4474,10 @@ static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *
     ast_value      *fval;
     ast_function   *func;
 
-    /* NOTE: checking array->expression.next rather than elemtype since
+    /* NOTE: checking array->next rather than elemtype since
      * for fields elemtype is a temporary fieldtype.
      */
-    if (!ast_istype(array->expression.next, ast_value)) {
+    if (!ast_istype(array->next, ast_value)) {
         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
         return nullptr;
     }
@@ -4485,7 +4485,7 @@ static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *
     if (!parser_create_array_accessor(parser, array, funcname, &fval))
         return nullptr;
     func = fval->constval.vfunc;
-    fval->expression.next = ast_type_copy(ast_ctx(array), elemtype);
+    fval->next = ast_type_copy(ast_ctx(array), elemtype);
 
     index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
 
@@ -4493,7 +4493,7 @@ static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *
         parseerror(parser, "failed to create locals for array accessor");
         goto cleanup;
     }
-    fval->expression.type_params.push_back(index);
+    fval->type_params.push_back(index);
 
     array->getter = fval;
     return fval;
@@ -4508,7 +4508,7 @@ static bool parser_create_array_getter_impl(parser_t *parser, ast_value *array)
 {
     ast_expression *root = nullptr;
 
-    root = array_getter_node(parser, array, array->getter->expression.type_params[0], 0, array->expression.count);
+    root = array_getter_node(parser, array, array->getter->type_params[0], 0, array->count);
     if (!root) {
         parseerror(parser, "failed to build accessor search tree");
         return false;
@@ -4580,7 +4580,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
             }
         } else {
             params.push_back(param);
-            if (param->expression.vtype >= TYPE_VARIANT) {
+            if (param->vtype >= TYPE_VARIANT) {
                 char tname[1024]; /* typename is reserved in C++ */
                 ast_type_to_string((ast_expression*)param, tname, sizeof(tname));
                 parseerror(parser, "type not supported as part of a parameter list: %s", tname);
@@ -4611,7 +4611,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
         }
     }
 
-    if (params.size() == 1 && params[0]->expression.vtype == TYPE_VOID)
+    if (params.size() == 1 && params[0]->vtype == TYPE_VOID)
         params.clear();
 
     /* sanity check */
@@ -4626,13 +4626,13 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
 
     /* now turn 'var' into a function type */
     fval = ast_value_new(ctx, "<type()>", TYPE_FUNCTION);
-    fval->expression.next = (ast_expression*)var;
+    fval->next = (ast_expression*)var;
     if (variadic)
-        fval->expression.flags |= AST_FLAG_VARIADIC;
+        fval->flags |= AST_FLAG_VARIADIC;
     var = fval;
 
-    var->expression.type_params = move(params);
-    var->expression.varparam = (ast_expression*)varparam;
+    var->type_params = move(params);
+    var->varparam = (ast_expression*)varparam;
     var->argcounter = argcounter;
 
     return var;
@@ -4680,14 +4680,14 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var)
     }
 
     tmp = ast_value_new(ctx, "<type[]>", TYPE_ARRAY);
-    tmp->expression.next = (ast_expression*)var;
+    tmp->next = (ast_expression*)var;
     var = tmp;
 
     if (cval) {
-        if (cval->expression.vtype == TYPE_INTEGER)
-            tmp->expression.count = cval->constval.vint;
-        else if (cval->expression.vtype == TYPE_FLOAT)
-            tmp->expression.count = cval->constval.vfloat;
+        if (cval->vtype == TYPE_INTEGER)
+            tmp->count = cval->constval.vint;
+        else if (cval->vtype == TYPE_FLOAT)
+            tmp->count = cval->constval.vfloat;
         else {
             ast_unref(cexp);
             ast_delete(var);
@@ -4697,8 +4697,8 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var)
 
         ast_unref(cexp);
     } else {
-        var->expression.count = -1;
-        var->expression.flags |= AST_FLAG_ARRAY_INIT;
+        var->count = -1;
+        var->flags |= AST_FLAG_ARRAY_INIT;
     }
 
     if (parser->tok != ']') {
@@ -4795,7 +4795,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
 
     for (; morefields; --morefields) {
         tmp = ast_value_new(ctx, "<.type>", TYPE_FIELD);
-        tmp->expression.next = (ast_expression*)var;
+        tmp->next = (ast_expression*)var;
         var = tmp;
     }
 
@@ -4827,7 +4827,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
         *storebase = ast_value_copy(var);
         if (isfield) {
             tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
-            tmp->expression.next = (ast_expression*)*storebase;
+            tmp->next = (ast_expression*)*storebase;
             *storebase = tmp;
         }
     }
@@ -4865,7 +4865,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
     if (isfield) {
         /* turn it into a field if desired */
         tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
-        tmp->expression.next = (ast_expression*)var;
+        tmp->next = (ast_expression*)var;
         var = tmp;
     }
 
@@ -4969,8 +4969,8 @@ static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, cons
                                  cvq_to_str(proto->cvq));
         }
     }
-    av = (var  ->expression.flags & AST_FLAG_NORETURN);
-    ao = (proto->expression.flags & AST_FLAG_NORETURN);
+    av = (var  ->flags & AST_FLAG_NORETURN);
+    ao = (proto->flags & AST_FLAG_NORETURN);
     if (!av != !ao) {
         return !parsewarning(parser, WARN_DIFFERENT_ATTRIBUTES,
                              "`%s` declared with different attributes%s\n"
@@ -4989,7 +4989,7 @@ static bool create_array_accessors(parser_t *parser, ast_value *var)
     if (!parser_create_array_setter(parser, var, name))
         return false;
     util_snprintf(name, sizeof(name), "%s##GET", var->name);
-    if (!parser_create_array_getter(parser, var, var->expression.next, name))
+    if (!parser_create_array_getter(parser, var, var->next, name))
         return false;
     return true;
 }
@@ -5016,7 +5016,7 @@ static bool parse_array(parser_t *parser, ast_value *array)
             return false;
         }
         array->initlist.push_back(v->constval);
-        if (v->expression.vtype == TYPE_STRING) {
+        if (v->vtype == TYPE_STRING) {
             array->initlist[i].vstring = util_strdupe(array->initlist[i].vstring);
             ++i;
         }
@@ -5039,12 +5039,12 @@ static bool parse_array(parser_t *parser, ast_value *array)
     }
     */
 
-    if (array->expression.flags & AST_FLAG_ARRAY_INIT) {
-        if (array->expression.count != (size_t)-1) {
+    if (array->flags & AST_FLAG_ARRAY_INIT) {
+        if (array->count != (size_t)-1) {
             parseerror(parser, "array `%s' has already been initialized with %u elements",
-                       array->name, (unsigned)array->expression.count);
+                       array->name, (unsigned)array->count);
         }
-        array->expression.count = array->initlist.size();
+        array->count = array->initlist.size();
         if (!create_array_accessors(parser, array))
             return false;
     }
@@ -5128,18 +5128,18 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
 
         var->cvq = qualifier;
         if (qflags & AST_FLAG_COVERAGE) /* specified in QC, drop our default */
-            var->expression.flags &= ~(AST_FLAG_COVERAGE_MASK);
-        var->expression.flags |= qflags;
+            var->flags &= ~(AST_FLAG_COVERAGE_MASK);
+        var->flags |= qflags;
 
         /*
          * store the vstring back to var for alias and
          * deprecation messages.
          */
-        if (var->expression.flags & AST_FLAG_DEPRECATED ||
-            var->expression.flags & AST_FLAG_ALIAS)
+        if (var->flags & AST_FLAG_DEPRECATED ||
+            var->flags & AST_FLAG_ALIAS)
             var->desc = vstring;
 
-        if (parser_find_global(parser, var->name) && var->expression.flags & AST_FLAG_ALIAS) {
+        if (parser_find_global(parser, var->name) && var->flags & AST_FLAG_ALIAS) {
             parseerror(parser, "function aliases cannot be forward declared");
             retval = false;
             goto cleanup;
@@ -5171,7 +5171,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                 parser->crc_fields = parser->fields.size();
                 was_end = true;
             }
-            if (was_end && var->expression.vtype == TYPE_FIELD) {
+            if (was_end && var->vtype == TYPE_FIELD) {
                 if (parsewarning(parser, WARN_END_SYS_FIELDS,
                                  "global '%s' hint should not be a field",
                                  parser_tokval(parser)))
@@ -5181,7 +5181,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                 }
             }
 
-            if (!nofields && var->expression.vtype == TYPE_FIELD)
+            if (!nofields && var->vtype == TYPE_FIELD)
             {
                 /* deal with field declarations */
                 old = parser_find_field(parser, var->name);
@@ -5216,7 +5216,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->vtype == TYPE_FUNCTION)
+                if (old && var->vtype == TYPE_FUNCTION && old->vtype == TYPE_FUNCTION)
                 {
                     /* This is a function which had a prototype */
                     if (!ast_istype(old, ast_value)) {
@@ -5234,8 +5234,8 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                         goto cleanup;
                     }
                     /* we need the new parameter-names */
-                    for (i = 0; i < proto->expression.type_params.size(); ++i)
-                        ast_value_set_name(proto->expression.type_params[i], var->expression.type_params[i]->name);
+                    for (i = 0; i < proto->type_params.size(); ++i)
+                        ast_value_set_name(proto->type_params[i], var->type_params[i]->name);
                     if (!parser_check_qualifiers(parser, var, proto)) {
                         retval = false;
                         if (proto->desc)
@@ -5243,7 +5243,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                         proto = nullptr;
                         goto cleanup;
                     }
-                    proto->expression.flags |= var->expression.flags;
+                    proto->flags |= var->flags;
                     ast_delete(var);
                     var = proto;
                 }
@@ -5276,11 +5276,11 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                             proto = nullptr;
                             goto cleanup;
                         }
-                        proto->expression.flags |= var->expression.flags;
+                        proto->flags |= var->flags;
                         /* copy the context for finals,
                          * so the error can show where it was actually made 'final'
                          */
-                        if (proto->expression.flags & AST_FLAG_FINAL_DECL)
+                        if (proto->flags & AST_FLAG_FINAL_DECL)
                             ast_ctx(old) = ast_ctx(var);
                         ast_delete(var);
                         var = proto;
@@ -5337,10 +5337,10 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
          * Create the global/local, and deal with vector types.
          */
         if (!proto) {
-            if (var->expression.vtype == TYPE_VECTOR)
+            if (var->vtype == TYPE_VECTOR)
                 isvector = true;
-            else if (var->expression.vtype == TYPE_FIELD &&
-                     var->expression.next->vtype == TYPE_VECTOR)
+            else if (var->vtype == TYPE_FIELD &&
+                     var->next->vtype == TYPE_VECTOR)
                 isvector = true;
 
             if (isvector) {
@@ -5352,7 +5352,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
 
             if (!localblock) {
                 /* deal with global variables, fields, functions */
-                if (!nofields && var->expression.vtype == TYPE_FIELD && parser->tok != '=') {
+                if (!nofields && var->vtype == TYPE_FIELD && parser->tok != '=') {
                     var->isfield = true;
                     parser->fields.push_back((ast_expression*)var);
                     util_htset(parser->htfields, var->name, var);
@@ -5364,7 +5364,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                     }
                 }
                 else {
-                    if (!(var->expression.flags & AST_FLAG_ALIAS)) {
+                    if (!(var->flags & AST_FLAG_ALIAS)) {
                         parser_addglobal(parser, var->name, (ast_expression*)var);
                         if (isvector) {
                             for (i = 0; i < 3; ++i) {
@@ -5489,22 +5489,22 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
         /* Part 2.2
          * deal with arrays
          */
-        if (var->expression.vtype == TYPE_ARRAY) {
-            if (var->expression.count != (size_t)-1) {
+        if (var->vtype == TYPE_ARRAY) {
+            if (var->count != (size_t)-1) {
                 if (!create_array_accessors(parser, var))
                     goto cleanup;
             }
         }
         else if (!localblock && !nofields &&
-                 var->expression.vtype == TYPE_FIELD &&
-                 var->expression.next->vtype == TYPE_ARRAY)
+                 var->vtype == TYPE_FIELD &&
+                 var->next->vtype == TYPE_ARRAY)
         {
             char name[1024];
             ast_expression *telem;
             ast_value      *tfield;
-            ast_value      *array = (ast_value*)var->expression.next;
+            ast_value      *array = (ast_value*)var->next;
 
-            if (!ast_istype(var->expression.next, ast_value)) {
+            if (!ast_istype(var->next, ast_value)) {
                 parseerror(parser, "internal error: field element type must be an ast_value");
                 goto cleanup;
             }
@@ -5513,9 +5513,9 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
             if (!parser_create_array_field_setter(parser, array, name))
                 goto cleanup;
 
-            telem = ast_type_copy(ast_ctx(var), array->expression.next);
+            telem = ast_type_copy(ast_ctx(var), array->next);
             tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD);
-            tfield->expression.next = telem;
+            tfield->next = telem;
             util_snprintf(name, sizeof(name), "%s##GETFP", var->name);
             if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) {
                 ast_delete(tfield);
@@ -5538,7 +5538,7 @@ skipvar:
             goto another;
 
         /*
-        if (!var || (!localblock && !nofields && basetype->expression.vtype == TYPE_FIELD)) {
+        if (!var || (!localblock && !nofields && basetype->vtype == TYPE_FIELD)) {
         */
         if (!var) {
             parseerror(parser, "missing comma or semicolon while parsing variables");
@@ -5554,7 +5554,7 @@ skipvar:
             }
         }
 
-        if (parser->tok != '{' || var->expression.vtype != TYPE_FUNCTION) {
+        if (parser->tok != '{' || var->vtype != TYPE_FUNCTION) {
             if (parser->tok != '=') {
                 parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser));
                 break;
@@ -5580,7 +5580,7 @@ skipvar:
                 parseerror(parser, "cannot declare builtins within functions");
                 break;
             }
-            if (var->expression.vtype != TYPE_FUNCTION) {
+            if (var->vtype != TYPE_FUNCTION) {
                 parseerror(parser, "unexpected builtin number, '%s' is not a function", var->name);
                 break;
             }
@@ -5601,9 +5601,9 @@ skipvar:
                     parseerror(parser, "builtin number must be a compile time constant");
                     break;
                 }
-                if (number->expression.vtype == TYPE_INTEGER)
+                if (number->vtype == TYPE_INTEGER)
                     builtin_num = number->constval.vint;
-                else if (number->expression.vtype == TYPE_FLOAT)
+                else if (number->vtype == TYPE_FLOAT)
                     builtin_num = number->constval.vfloat;
                 else {
                     ast_unref(number);
@@ -5656,7 +5656,7 @@ skipvar:
                 break;
             }
         }
-        else if (var->expression.vtype == TYPE_ARRAY && parser->tok == '{')
+        else if (var->vtype == TYPE_ARRAY && parser->tok == '{')
         {
             if (localblock) {
                 /* Note that fteqcc and most others don't even *have*
@@ -5670,7 +5670,7 @@ skipvar:
             if (!parse_array(parser, var))
                 break;
         }
-        else if (var->expression.vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '['))
+        else if (var->vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '['))
         {
             if (localblock) {
                 parseerror(parser, "cannot declare functions within functions");
@@ -5740,13 +5740,13 @@ skipvar:
                         var->cvq = CV_CONST;
                     }
                     if (cval == parser->nil)
-                        var->expression.flags |= AST_FLAG_INITIALIZED;
+                        var->flags |= AST_FLAG_INITIALIZED;
                     else
                     {
                         var->hasvalue = true;
-                        if (cval->expression.vtype == TYPE_STRING)
+                        if (cval->vtype == TYPE_STRING)
                             var->constval.vstring = parser_strdup(cval->constval.vstring);
-                        else if (cval->expression.vtype == TYPE_FIELD)
+                        else if (cval->vtype == TYPE_FIELD)
                             var->constval.vfield = cval;
                         else
                             memcpy(&var->constval, &cval->constval, sizeof(var->constval));
@@ -5774,7 +5774,7 @@ skipvar:
             /* a constant initialized to an inexact value should be marked inexact:
              * const float x = <inexact>; should propagate the inexact flag
              */
-            if (var->cvq == CV_CONST && var->expression.vtype == TYPE_FLOAT) {
+            if (var->cvq == CV_CONST && var->vtype == TYPE_FLOAT) {
                 if (cval && cval->hasvalue && cval->cvq == CV_CONST)
                     var->inexact = cval->inexact;
             }
@@ -5929,7 +5929,7 @@ static void generate_checksum(parser_t *parser, ir_builder *ir)
         if (!ast_istype(parser->globals[i], ast_value))
             continue;
         value = (ast_value*)(parser->globals[i]);
-        switch (value->expression.vtype) {
+        switch (value->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;
@@ -5946,7 +5946,7 @@ static void generate_checksum(parser_t *parser, ir_builder *ir)
         if (!ast_istype(parser->fields[i], ast_value))
             continue;
         value = (ast_value*)(parser->fields[i]);
-        switch (value->expression.next->vtype) {
+        switch (value->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;
@@ -6014,7 +6014,7 @@ parser_t *parser_create()
         parser->reserved_version = ast_value_new(empty_ctx, "reserved:version", TYPE_STRING);
         parser->reserved_version->cvq = CV_CONST;
         parser->reserved_version->hasvalue = true;
-        parser->reserved_version->expression.flags |= AST_FLAG_INCLUDE_DEF;
+        parser->reserved_version->flags |= AST_FLAG_INCLUDE_DEF;
         parser->reserved_version->constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING);
     } else {
         parser->reserved_version = nullptr;
@@ -6197,7 +6197,7 @@ bool parser_finish(parser_t *parser, const char *output)
             ir_value *ifld;
             ast_expression *subtype;
             field->hasvalue = true;
-            subtype = field->expression.next;
+            subtype = field->next;
             ifld = ir_builder_create_field(ir, field->name, subtype->vtype);
             if (subtype->vtype == TYPE_FIELD)
                 ifld->fieldtype = subtype->next->vtype;
@@ -6211,7 +6211,7 @@ bool parser_finish(parser_t *parser, const char *output)
         if (!ast_istype(it, ast_value))
             continue;
         asvalue = (ast_value*)it;
-        if (!asvalue->uses && !asvalue->hasvalue && asvalue->expression.vtype != TYPE_FUNCTION) {
+        if (!asvalue->uses && !asvalue->hasvalue && asvalue->vtype != TYPE_FUNCTION) {
             retval = retval && !compile_warning(ast_ctx(asvalue), WARN_UNUSED_VARIABLE,
                                                 "unused global: `%s`", asvalue->name);
         }
@@ -6226,8 +6226,8 @@ bool parser_finish(parser_t *parser, const char *output)
      */
     for (auto &f : parser->functions) {
         if (f->varargs) {
-            if (parser->max_param_count > f->function_type->expression.type_params.size()) {
-                f->varargs->expression.count = parser->max_param_count - f->function_type->expression.type_params.size();
+            if (parser->max_param_count > f->function_type->type_params.size()) {
+                f->varargs->count = parser->max_param_count - f->function_type->type_params.size();
                 if (!parser_create_array_setter_impl(parser, f->varargs)) {
                     con_out("failed to generate vararg setter for %s\n", f->name);
                     ir_builder_delete(ir);
@@ -6255,7 +6255,7 @@ bool parser_finish(parser_t *parser, const char *output)
         if (!ast_istype(it, ast_value))
             continue;
         ast_value *asvalue = (ast_value*)it;
-        if (!(asvalue->expression.flags & AST_FLAG_INITIALIZED))
+        if (!(asvalue->flags & AST_FLAG_INITIALIZED))
         {
             if (asvalue->cvq == CV_CONST && !asvalue->hasvalue)
                 (void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_CONSTANT,
@@ -6275,7 +6275,7 @@ bool parser_finish(parser_t *parser, const char *output)
         ast_value *asvalue = (ast_value*)it->next;
         if (!ast_istype((ast_expression*)asvalue, ast_value))
             continue;
-        if (asvalue->expression.vtype != TYPE_ARRAY)
+        if (asvalue->vtype != TYPE_ARRAY)
             continue;
         if (!ast_generate_accessors(asvalue, ir)) {
             ir_builder_delete(ir);