]> de.git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Merge branch 'master' into cooking
authorWolfgang Bumiller <wry.git@bumiller.com>
Sat, 1 Jun 2013 18:12:27 +0000 (20:12 +0200)
committerWolfgang Bumiller <wry.git@bumiller.com>
Sat, 1 Jun 2013 18:12:27 +0000 (20:12 +0200)
1  2 
parser.c

diff --combined parser.c
index 7d9ac6a353155724928a29a70b10c4e25f27cca9,c6819223cb279d4233ff8af9db6de883d31469ca..97a3ccba57f5c74428312d17b6222380483488ba
+++ b/parser.c
@@@ -185,7 -185,7 +185,7 @@@ vector vec3_mulvf(vector a, float b
   * parsing
   */
  
 -bool parser_next(parser_t *parser)
 +static bool parser_next(parser_t *parser)
  {
      /* lex_do kills the previous token */
      parser->tok = lex_do(parser->lex);
@@@ -280,12 -280,12 +280,12 @@@ static ast_value* parser_const_string(p
          char name[32];
          util_snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(parser->translated++));
          out = ast_value_new(parser_ctx(parser), name, TYPE_STRING);
+         out->expression.flags |= AST_FLAG_INCLUDE_DEF;
      } else
          out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING);
      out->cvq      = CV_CONST;
      out->hasvalue = true;
      out->isimm    = true;
-     out->expression.flags |= AST_FLAG_INCLUDE_DEF;
      out->constval.vstring = parser_strdup(str);
      vec_push(parser->imm_string, out);
      util_htseth(parser->ht_imm_string, str, hash, out);
@@@ -587,7 -587,7 +587,7 @@@ static bool parser_sy_apply_operator(pa
          blocks[i] = sy->out[vec_size(sy->out)+i].block;
          asvalue[i] = (ast_value*)exprs[i];
  
 -        if (exprs[i]->expression.vtype == TYPE_NOEXPR &&
 +        if (exprs[i]->vtype == TYPE_NOEXPR &&
              !(i != 0 && op->id == opid2('?',':')) &&
              !(i == 1 && op->id == opid1('.')))
          {
      }
  
  #define NotSameType(T) \
 -             (exprs[0]->expression.vtype != exprs[1]->expression.vtype || \
 -              exprs[0]->expression.vtype != T)
 +             (exprs[0]->vtype != exprs[1]->vtype || \
 +              exprs[0]->vtype != T)
  #define CanConstFold1(A) \
               (ast_istype((A), ast_value) && ((ast_value*)(A))->hasvalue && (((ast_value*)(A))->cvq == CV_CONST) &&\
 -              (A)->expression.vtype != TYPE_FUNCTION)
 +              (A)->vtype != TYPE_FUNCTION)
  #define CanConstFold(A, B) \
               (CanConstFold1(A) && CanConstFold1(B))
  #define ConstV(i) (asvalue[(i)]->constval.vvec)
              return false;
  
          case opid1('.'):
 -            if (exprs[0]->expression.vtype == TYPE_VECTOR &&
 -                exprs[1]->expression.vtype == TYPE_NOEXPR)
 +            if (exprs[0]->vtype == TYPE_VECTOR &&
 +                exprs[1]->vtype == TYPE_NOEXPR)
              {
                  if      (exprs[1] == (ast_expression*)parser->const_vec[0])
                      out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
                      return false;
                  }
              }
 -            else if (exprs[0]->expression.vtype == TYPE_ENTITY) {
 -                if (exprs[1]->expression.vtype != TYPE_FIELD) {
 +            else if (exprs[0]->vtype == TYPE_ENTITY) {
 +                if (exprs[1]->vtype != TYPE_FIELD) {
                      compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field");
                      return false;
                  }
                  out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]);
              }
 -            else if (exprs[0]->expression.vtype == TYPE_VECTOR) {
 +            else if (exprs[0]->vtype == TYPE_VECTOR) {
                  compile_error(ast_ctx(exprs[1]), "vectors cannot be accessed this way");
                  return false;
              }
              break;
  
          case opid1('['):
 -            if (exprs[0]->expression.vtype != TYPE_ARRAY &&
 -                !(exprs[0]->expression.vtype == TYPE_FIELD &&
 -                  exprs[0]->expression.next->expression.vtype == TYPE_ARRAY))
 +            if (exprs[0]->vtype != TYPE_ARRAY &&
 +                !(exprs[0]->vtype == TYPE_FIELD &&
 +                  exprs[0]->next->vtype == TYPE_ARRAY))
              {
                  ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                  compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1);
                  return false;
              }
 -            if (exprs[1]->expression.vtype != TYPE_FLOAT) {
 +            if (exprs[1]->vtype != TYPE_FLOAT) {
                  ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                  compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1);
                  return false;
              out = exprs[0];
              break;
          case opid2('-','P'):
 -            switch (exprs[0]->expression.vtype) {
 +            switch (exprs[0]->vtype) {
                  case TYPE_FLOAT:
                      if (CanConstFold1(exprs[0]))
                          out = (ast_expression*)parser_const_float(parser, -ConstF(0));
                      break;
                  default:
                  compile_error(ctx, "invalid types used in expression: cannot negate type %s",
 -                              type_name[exprs[0]->expression.vtype]);
 +                              type_name[exprs[0]->vtype]);
                  return false;
              }
              break;
  
          case opid2('!','P'):
 -            switch (exprs[0]->expression.vtype) {
 +            switch (exprs[0]->vtype) {
                  case TYPE_FLOAT:
                      if (CanConstFold1(exprs[0]))
                          out = (ast_expression*)parser_const_float(parser, !ConstF(0));
                      break;
                  default:
                  compile_error(ctx, "invalid types used in expression: cannot logically negate type %s",
 -                              type_name[exprs[0]->expression.vtype]);
 +                              type_name[exprs[0]->vtype]);
                  return false;
              }
              break;
  
          case opid1('+'):
 -            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
 -                (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
 +            if (exprs[0]->vtype != exprs[1]->vtype ||
 +                (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
              {
                  compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
 -                              type_name[exprs[0]->expression.vtype],
 -                              type_name[exprs[1]->expression.vtype]);
 +                              type_name[exprs[0]->vtype],
 +                              type_name[exprs[1]->vtype]);
                  return false;
              }
 -            switch (exprs[0]->expression.vtype) {
 +            switch (exprs[0]->vtype) {
                  case TYPE_FLOAT:
                      if (CanConstFold(exprs[0], exprs[1]))
                      {
                      break;
                  default:
                      compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
 -                                  type_name[exprs[0]->expression.vtype],
 -                                  type_name[exprs[1]->expression.vtype]);
 +                                  type_name[exprs[0]->vtype],
 +                                  type_name[exprs[1]->vtype]);
                      return false;
              };
              break;
          case opid1('-'):
 -            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
 -                (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
 +            if (exprs[0]->vtype != exprs[1]->vtype ||
 +                (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
              {
                  compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
 -                              type_name[exprs[1]->expression.vtype],
 -                              type_name[exprs[0]->expression.vtype]);
 +                              type_name[exprs[1]->vtype],
 +                              type_name[exprs[0]->vtype]);
                  return false;
              }
 -            switch (exprs[0]->expression.vtype) {
 +            switch (exprs[0]->vtype) {
                  case TYPE_FLOAT:
                      if (CanConstFold(exprs[0], exprs[1]))
                          out = (ast_expression*)parser_const_float(parser, ConstF(0) - ConstF(1));
                      break;
                  default:
                      compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
 -                                  type_name[exprs[1]->expression.vtype],
 -                                  type_name[exprs[0]->expression.vtype]);
 +                                  type_name[exprs[1]->vtype],
 +                                  type_name[exprs[0]->vtype]);
                      return false;
              };
              break;
          case opid1('*'):
 -            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype &&
 -                !(exprs[0]->expression.vtype == TYPE_VECTOR &&
 -                  exprs[1]->expression.vtype == TYPE_FLOAT) &&
 -                !(exprs[1]->expression.vtype == TYPE_VECTOR &&
 -                  exprs[0]->expression.vtype == TYPE_FLOAT)
 +            if (exprs[0]->vtype != exprs[1]->vtype &&
 +                !(exprs[0]->vtype == TYPE_VECTOR &&
 +                  exprs[1]->vtype == TYPE_FLOAT) &&
 +                !(exprs[1]->vtype == TYPE_VECTOR &&
 +                  exprs[0]->vtype == TYPE_FLOAT)
                  )
              {
                  compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
 -                              type_name[exprs[1]->expression.vtype],
 -                              type_name[exprs[0]->expression.vtype]);
 +                              type_name[exprs[1]->vtype],
 +                              type_name[exprs[0]->vtype]);
                  return false;
              }
 -            switch (exprs[0]->expression.vtype) {
 +            switch (exprs[0]->vtype) {
                  case TYPE_FLOAT:
 -                    if (exprs[1]->expression.vtype == TYPE_VECTOR)
 +                    if (exprs[1]->vtype == TYPE_VECTOR)
                      {
                          if (CanConstFold(exprs[0], exprs[1]))
                              out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(1), ConstF(0)));
                      }
                      break;
                  case TYPE_VECTOR:
 -                    if (exprs[1]->expression.vtype == TYPE_FLOAT)
 +                    if (exprs[1]->vtype == TYPE_FLOAT)
                      {
                          if (CanConstFold(exprs[0], exprs[1]))
                              out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), ConstF(1)));
                              if (!vec.y && !vec.z) { /* 'n 0 0' * v */
                                  ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                  out = (ast_expression*)ast_member_new(ctx, exprs[1], 0, NULL);
 -                                out->expression.node.keep = false;
 +                                out->node.keep = false;
                                  ((ast_member*)out)->rvalue = true;
                                  if (vec.x != 1)
                                      out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.x), out);
                              else if (!vec.x && !vec.z) { /* '0 n 0' * v */
                                  ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                  out = (ast_expression*)ast_member_new(ctx, exprs[1], 1, NULL);
 -                                out->expression.node.keep = false;
 +                                out->node.keep = false;
                                  ((ast_member*)out)->rvalue = true;
                                  if (vec.y != 1)
                                      out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.y), out);
                              else if (!vec.x && !vec.y) { /* '0 n 0' * v */
                                  ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                  out = (ast_expression*)ast_member_new(ctx, exprs[1], 2, NULL);
 -                                out->expression.node.keep = false;
 +                                out->node.keep = false;
                                  ((ast_member*)out)->rvalue = true;
                                  if (vec.z != 1)
                                      out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.z), out);
                              if (!vec.y && !vec.z) { /* v * 'n 0 0' */
                                  ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                  out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
 -                                out->expression.node.keep = false;
 +                                out->node.keep = false;
                                  ((ast_member*)out)->rvalue = true;
                                  if (vec.x != 1)
                                      out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.x));
                              else if (!vec.x && !vec.z) { /* v * '0 n 0' */
                                  ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                  out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL);
 -                                out->expression.node.keep = false;
 +                                out->node.keep = false;
                                  ((ast_member*)out)->rvalue = true;
                                  if (vec.y != 1)
                                      out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.y));
                              else if (!vec.x && !vec.y) { /* v * '0 n 0' */
                                  ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
                                  out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL);
 -                                out->expression.node.keep = false;
 +                                out->node.keep = false;
                                  ((ast_member*)out)->rvalue = true;
                                  if (vec.z != 1)
                                      out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.z));
                      break;
                  default:
                      compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
 -                                  type_name[exprs[1]->expression.vtype],
 -                                  type_name[exprs[0]->expression.vtype]);
 +                                  type_name[exprs[1]->vtype],
 +                                  type_name[exprs[0]->vtype]);
                      return false;
              };
              break;
          case opid1('/'):
 -            if (exprs[1]->expression.vtype != TYPE_FLOAT) {
 +            if (exprs[1]->vtype != TYPE_FLOAT) {
                  ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                  ast_type_to_string(exprs[1], ty2, sizeof(ty2));
                  compile_error(ctx, "invalid types used in expression: cannot divide tyeps %s and %s", ty1, ty2);
                  return false;
              }
 -            if (exprs[0]->expression.vtype == TYPE_FLOAT) {
 +            if (exprs[0]->vtype == TYPE_FLOAT) {
                  if (CanConstFold(exprs[0], exprs[1]))
                      out = (ast_expression*)parser_const_float(parser, ConstF(0) / ConstF(1));
                  else
                      out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
              }
 -            else if (exprs[0]->expression.vtype == TYPE_VECTOR) {
 +            else if (exprs[0]->vtype == TYPE_VECTOR) {
                  if (CanConstFold(exprs[0], exprs[1]))
                      out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), 1.0/ConstF(1)));
                  else {
          case opid1('%'):
              if (NotSameType(TYPE_FLOAT)) {
                  compile_error(ctx, "invalid types used in expression: cannot perform modulo operation between types %s and %s",
 -                    type_name[exprs[0]->expression.vtype],
 -                    type_name[exprs[1]->expression.vtype]);
 +                    type_name[exprs[0]->vtype],
 +                    type_name[exprs[1]->vtype]);
                  return false;
              }
              if (CanConstFold(exprs[0], exprs[1])) {
          case opid1('&'):
              if (NotSameType(TYPE_FLOAT)) {
                  compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
 -                              type_name[exprs[0]->expression.vtype],
 -                              type_name[exprs[1]->expression.vtype]);
 +                              type_name[exprs[0]->vtype],
 +                              type_name[exprs[1]->vtype]);
                  return false;
              }
              if (CanConstFold(exprs[0], exprs[1]))
          case opid2('>','>'):
              if (CanConstFold(exprs[0], exprs[1]) && ! NotSameType(TYPE_FLOAT)) {
                  if (op->id == opid2('<','<'))
 -                    out = (ast_expression*)parser_const_float(parser, (double)((int)(ConstF(0)) << (int)(ConstF(1))));
 +                    out = (ast_expression*)parser_const_float(parser, (double)((unsigned int)(ConstF(0)) << (unsigned int)(ConstF(1))));
                  else
 -                    out = (ast_expression*)parser_const_float(parser, (double)((int)(ConstF(0)) >> (int)(ConstF(1))));
 +                    out = (ast_expression*)parser_const_float(parser, (double)((unsigned int)(ConstF(0)) >> (unsigned int)(ConstF(1))));
                  break;
              }
          case opid3('<','<','='):
                      return false;
                  }
                  for (i = 0; i < 2; ++i) {
 -                    if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->expression.vtype == TYPE_VECTOR) {
 +                    if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->vtype == TYPE_VECTOR) {
                          out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
                          if (!out) break;
                          out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
                              break;
                          }
                      }
 -                    else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->expression.vtype == TYPE_STRING) {
 +                    else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->vtype == TYPE_STRING) {
                          out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]);
                          if (!out) break;
                          out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
              generated_op += INSTR_LE;
              if (NotSameType(TYPE_FLOAT)) {
                  compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
 -                              type_name[exprs[0]->expression.vtype],
 -                              type_name[exprs[1]->expression.vtype]);
 +                              type_name[exprs[0]->vtype],
 +                              type_name[exprs[1]->vtype]);
                  return false;
              }
              out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
              break;
          case opid2('!', '='):
 -            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
 +            if (exprs[0]->vtype != exprs[1]->vtype) {
                  compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
 -                              type_name[exprs[0]->expression.vtype],
 -                              type_name[exprs[1]->expression.vtype]);
 +                              type_name[exprs[0]->vtype],
 +                              type_name[exprs[1]->vtype]);
                  return false;
              }
 -            out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
 +            out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]);
              break;
          case opid2('=', '='):
 -            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
 +            if (exprs[0]->vtype != exprs[1]->vtype) {
                  compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
 -                              type_name[exprs[0]->expression.vtype],
 -                              type_name[exprs[1]->expression.vtype]);
 +                              type_name[exprs[0]->vtype],
 +                              type_name[exprs[1]->vtype]);
                  return false;
              }
 -            out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
 +            out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]);
              break;
  
          case opid1('='):
              if (ast_istype(exprs[0], ast_entfield)) {
                  ast_expression *field = ((ast_entfield*)exprs[0])->field;
                  if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
 -                    exprs[0]->expression.vtype == TYPE_FIELD &&
 -                    exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
 +                    exprs[0]->vtype == TYPE_FIELD &&
 +                    exprs[0]->next->vtype == TYPE_VECTOR)
                  {
                      assignop = type_storep_instr[TYPE_VECTOR];
                  }
                  else
 -                    assignop = type_storep_instr[exprs[0]->expression.vtype];
 -                if (assignop == VINSTR_END || !ast_compare_type(field->expression.next, exprs[1]))
 +                    assignop = type_storep_instr[exprs[0]->vtype];
 +                if (assignop == VINSTR_END || !ast_compare_type(field->next, exprs[1]))
                  {
 -                    ast_type_to_string(field->expression.next, ty1, sizeof(ty1));
 +                    ast_type_to_string(field->next, ty1, sizeof(ty1));
                      ast_type_to_string(exprs[1], ty2, sizeof(ty2));
                      if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
 -                        field->expression.next->expression.vtype == TYPE_FUNCTION &&
 -                        exprs[1]->expression.vtype == TYPE_FUNCTION)
 +                        field->next->vtype == TYPE_FUNCTION &&
 +                        exprs[1]->vtype == TYPE_FUNCTION)
                      {
                          (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
                                                 "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
              else
              {
                  if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
 -                    exprs[0]->expression.vtype == TYPE_FIELD &&
 -                    exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
 +                    exprs[0]->vtype == TYPE_FIELD &&
 +                    exprs[0]->next->vtype == TYPE_VECTOR)
                  {
                      assignop = type_store_instr[TYPE_VECTOR];
                  }
                  else {
 -                    assignop = type_store_instr[exprs[0]->expression.vtype];
 +                    assignop = type_store_instr[exprs[0]->vtype];
                  }
  
                  if (assignop == VINSTR_END) {
                      ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                      ast_type_to_string(exprs[1], ty2, sizeof(ty2));
                      if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
 -                        exprs[0]->expression.vtype == TYPE_FUNCTION &&
 -                        exprs[1]->expression.vtype == TYPE_FUNCTION)
 +                        exprs[0]->vtype == TYPE_FUNCTION &&
 +                        exprs[1]->vtype == TYPE_FUNCTION)
                      {
                          (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
                                                 "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
          case opid3('+','+','P'):
          case opid3('-','-','P'):
              /* prefix ++ */
 -            if (exprs[0]->expression.vtype != TYPE_FLOAT) {
 +            if (exprs[0]->vtype != TYPE_FLOAT) {
                  ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                  compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1);
                  return false;
          case opid3('S','+','+'):
          case opid3('S','-','-'):
              /* prefix ++ */
 -            if (exprs[0]->expression.vtype != TYPE_FLOAT) {
 +            if (exprs[0]->vtype != TYPE_FLOAT) {
                  ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                  compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1);
                  return false;
              break;
          case opid2('+','='):
          case opid2('-','='):
 -            if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
 -                (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
 +            if (exprs[0]->vtype != exprs[1]->vtype ||
 +                (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
              {
                  ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                  ast_type_to_string(exprs[1], ty2, sizeof(ty2));
                  compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
              }
              if (ast_istype(exprs[0], ast_entfield))
 -                assignop = type_storep_instr[exprs[0]->expression.vtype];
 +                assignop = type_storep_instr[exprs[0]->vtype];
              else
 -                assignop = type_store_instr[exprs[0]->expression.vtype];
 -            switch (exprs[0]->expression.vtype) {
 +                assignop = type_store_instr[exprs[0]->vtype];
 +            switch (exprs[0]->vtype) {
                  case TYPE_FLOAT:
                      out = (ast_expression*)ast_binstore_new(ctx, assignop,
                                                              (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
                      break;
                  default:
                      compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
 -                                  type_name[exprs[0]->expression.vtype],
 -                                  type_name[exprs[1]->expression.vtype]);
 +                                  type_name[exprs[0]->vtype],
 +                                  type_name[exprs[1]->vtype]);
                      return false;
              };
              break;
          case opid2('*','='):
          case opid2('/','='):
 -            if (exprs[1]->expression.vtype != TYPE_FLOAT ||
 -                !(exprs[0]->expression.vtype == TYPE_FLOAT ||
 -                  exprs[0]->expression.vtype == TYPE_VECTOR))
 +            if (exprs[1]->vtype != TYPE_FLOAT ||
 +                !(exprs[0]->vtype == TYPE_FLOAT ||
 +                  exprs[0]->vtype == TYPE_VECTOR))
              {
                  ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                  ast_type_to_string(exprs[1], ty2, sizeof(ty2));
                  compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
              }
              if (ast_istype(exprs[0], ast_entfield))
 -                assignop = type_storep_instr[exprs[0]->expression.vtype];
 +                assignop = type_storep_instr[exprs[0]->vtype];
              else
 -                assignop = type_store_instr[exprs[0]->expression.vtype];
 -            switch (exprs[0]->expression.vtype) {
 +                assignop = type_store_instr[exprs[0]->vtype];
 +            switch (exprs[0]->vtype) {
                  case TYPE_FLOAT:
                      out = (ast_expression*)ast_binstore_new(ctx, assignop,
                                                              (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
                      break;
                  default:
                      compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
 -                                  type_name[exprs[0]->expression.vtype],
 -                                  type_name[exprs[1]->expression.vtype]);
 +                                  type_name[exprs[0]->vtype],
 +                                  type_name[exprs[1]->vtype]);
                      return false;
              };
              break;
                  compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
              }
              if (ast_istype(exprs[0], ast_entfield))
 -                assignop = type_storep_instr[exprs[0]->expression.vtype];
 +                assignop = type_storep_instr[exprs[0]->vtype];
              else
 -                assignop = type_store_instr[exprs[0]->expression.vtype];
 +                assignop = type_store_instr[exprs[0]->vtype];
              out = (ast_expression*)ast_binstore_new(ctx, assignop,
                                                      (op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
                                                      exprs[0], exprs[1]);
                  return false;
              }
              if (ast_istype(exprs[0], ast_entfield))
 -                assignop = type_storep_instr[exprs[0]->expression.vtype];
 +                assignop = type_storep_instr[exprs[0]->vtype];
              else
 -                assignop = type_store_instr[exprs[0]->expression.vtype];
 +                assignop = type_store_instr[exprs[0]->vtype];
              out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
              if (!out)
                  return false;
              break;
  
          case opid2('~', 'P'):
 -            if (exprs[0]->expression.vtype != TYPE_FLOAT) {
 +            if (exprs[0]->vtype != TYPE_FLOAT) {
                  ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                  compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1);
                  return false;
@@@ -1573,7 -1573,7 +1573,7 @@@ static bool parser_close_call(parser_t 
  
      if (ast_istype(fun, ast_value)) {
          funval = (ast_value*)fun;
 -        if ((fun->expression.flags & AST_FLAG_VARIADIC) &&
 +        if ((fun->flags & AST_FLAG_VARIADIC) &&
              !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
          {
              call->va_count = (ast_expression*)parser_const_float(parser, (double)paramcount);
      /* overwrite fid, the function, with a call */
      sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
  
 -    if (fun->expression.vtype != TYPE_FUNCTION) {
 -        parseerror(parser, "not a function (%s)", type_name[fun->expression.vtype]);
 +    if (fun->vtype != TYPE_FUNCTION) {
 +        parseerror(parser, "not a function (%s)", type_name[fun->vtype]);
          return false;
      }
  
 -    if (!fun->expression.next) {
 +    if (!fun->next) {
          parseerror(parser, "could not determine function return type");
          return false;
      } else {
          ast_value *fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
  
 -        if (fun->expression.flags & AST_FLAG_DEPRECATED) {
 +        if (fun->flags & AST_FLAG_DEPRECATED) {
              if (!fval) {
                  return !parsewarning(parser, WARN_DEPRECATED,
                          "call to function (which is marked deprecated)\n",
                      ast_ctx(fun).line);
          }
  
 -        if (vec_size(fun->expression.params) != paramcount &&
 -            !((fun->expression.flags & AST_FLAG_VARIADIC) &&
 -              vec_size(fun->expression.params) < paramcount))
 +        if (vec_size(fun->params) != paramcount &&
 +            !((fun->flags & AST_FLAG_VARIADIC) &&
 +              vec_size(fun->params) < paramcount))
          {
 -            const char *fewmany = (vec_size(fun->expression.params) > paramcount) ? "few" : "many";
 +            const char *fewmany = (vec_size(fun->params) > paramcount) ? "few" : "many";
              if (fval)
                  return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
                                       "too %s parameters for call to %s: expected %i, got %i\n"
                                       " -> `%s` has been declared here: %s:%i",
 -                                     fewmany, fval->name, (int)vec_size(fun->expression.params), (int)paramcount,
 +                                     fewmany, fval->name, (int)vec_size(fun->params), (int)paramcount,
                                       fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
              else
                  return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
                                       "too %s parameters for function call: expected %i, got %i\n"
                                       " -> it has been declared here: %s:%i",
 -                                     fewmany, (int)vec_size(fun->expression.params), (int)paramcount,
 +                                     fewmany, (int)vec_size(fun->params), (int)paramcount,
                                       ast_ctx(fun).file, (int)ast_ctx(fun).line);
          }
      }
@@@ -1883,7 -1883,7 +1883,7 @@@ static bool parse_sya_operand(parser_t 
              /* When adding more intrinsics, fix the above condition */
              prev = NULL;
          }
 -        if (prev && prev->expression.vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
 +        if (prev && prev->vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
          {
              var = (ast_expression*)parser->const_vec[ctoken[0]-'x'];
          } else {
@@@ -2229,8 -2229,8 +2229,8 @@@ static ast_expression* parse_expression
      }
  
      parser->lex->flags.noops = true;
 -    if (!vec_size(sy.out)) {
 -        parseerror(parser, "empty expression");
 +    if (vec_size(sy.out) != 1) {
 +        parseerror(parser, "expression with not 1 but %lu output values...", (unsigned long) vec_size(sy.out));
          expr = NULL;
      } else
          expr = sy.out[0].out;
@@@ -2365,13 -2365,13 +2365,13 @@@ static ast_expression* process_conditio
      ast_unary *unary;
      ast_expression *prev;
  
 -    if (cond->expression.vtype == TYPE_VOID || cond->expression.vtype >= TYPE_VARIANT) {
 +    if (cond->vtype == TYPE_VOID || cond->vtype >= TYPE_VARIANT) {
          char ty[1024];
          ast_type_to_string(cond, ty, sizeof(ty));
          compile_error(ast_ctx(cond), "invalid type for if() condition: %s", ty);
      }
  
 -    if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING)
 +    if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->vtype == TYPE_STRING)
      {
          prev = cond;
          cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
          }
          ifnot = !ifnot;
      }
 -    else if (OPTS_FLAG(CORRECT_LOGIC) && cond->expression.vtype == TYPE_VECTOR)
 +    else if (OPTS_FLAG(CORRECT_LOGIC) && cond->vtype == TYPE_VECTOR)
      {
          /* vector types need to be cast to true booleans */
          ast_binary *bin = (ast_binary*)cond;
@@@ -2455,17 -2455,17 +2455,17 @@@ static bool parse_if(parser_t *parser, 
      /* closing paren */
      if (parser->tok != ')') {
          parseerror(parser, "expected closing paren after 'if' condition");
 -        ast_delete(cond);
 +        ast_unref(cond);
          return false;
      }
      /* parse into the 'then' branch */
      if (!parser_next(parser)) {
          parseerror(parser, "expected statement for on-true branch of 'if'");
 -        ast_delete(cond);
 +        ast_unref(cond);
          return false;
      }
      if (!parse_statement_or_block(parser, &ontrue)) {
 -        ast_delete(cond);
 +        ast_unref(cond);
          return false;
      }
      if (!ontrue)
          if (!parser_next(parser)) {
              parseerror(parser, "expected on-false branch after 'else'");
              ast_delete(ontrue);
 -            ast_delete(cond);
 +            ast_unref(cond);
              return false;
          }
          if (!parse_statement_or_block(parser, &onfalse)) {
              ast_delete(ontrue);
 -            ast_delete(cond);
 +            ast_unref(cond);
              return false;
          }
      }
@@@ -2578,23 -2578,23 +2578,23 @@@ static bool parse_while_go(parser_t *pa
      /* closing paren */
      if (parser->tok != ')') {
          parseerror(parser, "expected closing paren after 'while' condition");
 -        ast_delete(cond);
 +        ast_unref(cond);
          return false;
      }
      /* parse into the 'then' branch */
      if (!parser_next(parser)) {
          parseerror(parser, "expected while-loop body");
 -        ast_delete(cond);
 +        ast_unref(cond);
          return false;
      }
      if (!parse_statement_or_block(parser, &ontrue)) {
 -        ast_delete(cond);
 +        ast_unref(cond);
          return false;
      }
  
      cond = process_condition(parser, cond, &ifnot);
      if (!cond) {
 -        ast_delete(ontrue);
 +        ast_unref(ontrue);
          return false;
      }
      aloop = ast_loop_new(ctx, NULL, cond, ifnot, NULL, false, NULL, ontrue);
@@@ -2694,21 -2694,21 +2694,21 @@@ static bool parse_dowhile_go(parser_t *
      if (parser->tok != ')') {
          parseerror(parser, "expected closing paren after 'while' condition");
          ast_delete(ontrue);
 -        ast_delete(cond);
 +        ast_unref(cond);
          return false;
      }
      /* parse on */
      if (!parser_next(parser) || parser->tok != ';') {
          parseerror(parser, "expected semicolon after condition");
          ast_delete(ontrue);
 -        ast_delete(cond);
 +        ast_unref(cond);
          return false;
      }
  
      if (!parser_next(parser)) {
          parseerror(parser, "parse error");
          ast_delete(ontrue);
 -        ast_delete(cond);
 +        ast_unref(cond);
          return false;
      }
  
@@@ -2781,6 -2781,7 +2781,6 @@@ static bool parse_for_go(parser_t *pars
      ast_expression *initexpr, *cond, *increment, *ontrue;
      ast_value      *typevar;
  
 -    bool retval = true;
      bool ifnot  = false;
  
      lex_ctx ctx = parser_ctx(parser);
      aloop = ast_loop_new(ctx, initexpr, cond, ifnot, NULL, false, increment, ontrue);
      *out = (ast_expression*)aloop;
  
 -    if (!parser_leaveblock(parser))
 -        retval = false;
 -    return retval;
 +    if (!parser_leaveblock(parser)) {
 +        ast_delete(aloop);
 +        return false;
 +    }
 +    return true;
  onerr:
 -    if (initexpr)  ast_delete(initexpr);
 -    if (cond)      ast_delete(cond);
 -    if (increment) ast_delete(increment);
 +    if (initexpr)  ast_unref(initexpr);
 +    if (cond)      ast_unref(cond);
 +    if (increment) ast_unref(increment);
      (void)!parser_leaveblock(parser);
      return false;
  }
  
  static bool parse_return(parser_t *parser, ast_block *block, ast_expression **out)
  {
 -    ast_expression *exp = NULL;
 -    ast_return     *ret = NULL;
 +    ast_expression *exp      = NULL;
 +    ast_expression *var      = NULL;
 +    ast_return     *ret      = NULL;
 +    ast_value      *retval   = parser->function->return_value;
      ast_value      *expected = parser->function->vtype;
  
      lex_ctx ctx = parser_ctx(parser);
          return false;
      }
  
 +    /* return assignments */
 +    if (parser->tok == '=') {
 +        if (!OPTS_FLAG(RETURN_ASSIGNMENTS)) {
 +            parseerror(parser, "return assignments not activated, try using -freturn-assigments");
 +            return false;
 +        }
 +
 +        if (type_store_instr[expected->expression.next->vtype] == VINSTR_END) {
 +            char ty1[1024];
 +            ast_type_to_string(expected->expression.next, ty1, sizeof(ty1));
 +            parseerror(parser, "invalid return type: `%s'", ty1);
 +            return false;
 +        }
 +
 +        if (!parser_next(parser)) {
 +            parseerror(parser, "expected return assignment expression");
 +            return false;
 +        }
 +
 +        if (!(exp = parse_expression_leave(parser, false, false, false)))
 +            return false;
 +
 +        /* prepare the return value */
 +        if (!retval) {
 +            retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID);
 +            ast_type_adopt(retval, expected->expression.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));
 +            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],
 +            (ast_expression*)retval, exp);
 +
 +        if (!var) {
 +            ast_unref(exp);
 +            return false;
 +        }
 +
 +        if (parser->tok != ';')
 +            parseerror(parser, "missing semicolon after return assignment");
 +        else if (!parser_next(parser))
 +            parseerror(parser, "parse error after return assignment");
 +
 +        *out = var;
 +        return true;
 +    }
 +
      if (parser->tok != ';') {
          exp = parse_expression(parser, false, false);
          if (!exp)
              return false;
  
 -        if (exp->expression.vtype != TYPE_NIL &&
 -            exp->expression.vtype != expected->expression.next->expression.vtype)
 +        if (exp->vtype != TYPE_NIL &&
 +            exp->vtype != ((ast_expression*)expected)->next->vtype)
          {
              parseerror(parser, "return with invalid expression");
          }
  
          ret = ast_return_new(ctx, exp);
          if (!ret) {
 -            ast_delete(exp);
 +            ast_unref(exp);
              return false;
          }
      } else {
          if (!parser_next(parser))
              parseerror(parser, "parse error");
 -        if (expected->expression.next->expression.vtype != TYPE_VOID) {
 +
 +        if (!retval && expected->expression.next->vtype != TYPE_VOID)
 +        {
              (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
          }
 -        ret = ast_return_new(ctx, NULL);
 +        ret = ast_return_new(ctx, (ast_expression*)retval);
      }
      *out = (ast_expression*)ret;
      return true;
@@@ -3738,7 -3677,7 +3738,7 @@@ static bool parse_statement(parser_t *p
              }
              return parse_typedef(parser);
          }
 -        parseerror(parser, "Unexpected keyword");
 +        parseerror(parser, "Unexpected keyword: `%s'", parser_tokval(parser));
          return false;
      }
      else if (parser->tok == '{')
@@@ -4129,9 -4068,9 +4129,9 @@@ static bool parse_function_body(parser_
              /* qc allows the use of not-yet-declared functions here
               * - this automatically creates a prototype */
              ast_value      *thinkfunc;
 -            ast_expression *functype = fld_think->expression.next;
 +            ast_expression *functype = fld_think->next;
  
 -            thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->expression.vtype);
 +            thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->vtype);
              if (!thinkfunc) { /* || !ast_type_adopt(thinkfunc, functype)*/
                  ast_unref(framenum);
                  parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
  
          if (param->expression.vtype != TYPE_VECTOR &&
              (param->expression.vtype != TYPE_FIELD ||
 -             param->expression.next->expression.vtype != TYPE_VECTOR))
 +             param->expression.next->vtype != TYPE_VECTOR))
          {
              continue;
          }
      }
  
      vec_push(func->blocks, block);
 +    
  
      parser->function = old;
      if (!parser_leaveblock(parser))
@@@ -4417,7 -4355,7 +4417,7 @@@ static ast_expression *array_setter_nod
          ast_store       *st;
          int assignop = type_store_instr[value->expression.vtype];
  
 -        if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
 +        if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
              assignop = INSTR_STORE_V;
  
          subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
@@@ -4483,7 -4421,7 +4483,7 @@@ static ast_expression *array_field_sett
          ast_store       *st;
          int assignop = type_storep_instr[value->expression.vtype];
  
 -        if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
 +        if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
              assignop = INSTR_STOREP_V;
  
          subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
@@@ -5334,7 -5272,7 +5334,7 @@@ static bool parse_variable(parser_t *pa
              {
                  /* deal with other globals */
                  old = parser_find_global(parser, var->name);
 -                if (old && var->expression.vtype == TYPE_FUNCTION && old->expression.vtype == TYPE_FUNCTION)
 +                if (old && var->expression.vtype == TYPE_FUNCTION && old->vtype == TYPE_FUNCTION)
                  {
                      /* This is a function which had a prototype */
                      if (!ast_istype(old, ast_value)) {
              if (var->expression.vtype == TYPE_VECTOR)
                  isvector = true;
              else if (var->expression.vtype == TYPE_FIELD &&
 -                     var->expression.next->expression.vtype == TYPE_VECTOR)
 +                     var->expression.next->vtype == TYPE_VECTOR)
                  isvector = true;
  
              if (isvector) {
                              return false;
                          }
  
 -                        if (var->expression.vtype != find->expression.vtype) {
 +                        if (var->expression.vtype != find->vtype) {
                              char ty1[1024];
                              char ty2[1024];
  
          }
          else if (!localblock && !nofields &&
                   var->expression.vtype == TYPE_FIELD &&
 -                 var->expression.next->expression.vtype == TYPE_ARRAY)
 +                 var->expression.next->vtype == TYPE_ARRAY)
          {
              char name[1024];
              ast_expression *telem;
@@@ -5687,7 -5625,7 +5687,7 @@@ skipvar
              }
          }
  
 -        if (parser->tok != '{') {
 +        if (parser->tok != '{' || var->expression.vtype != TYPE_FUNCTION) {
              if (parser->tok != '=') {
                  parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser));
                  break;
                  break;
              }
          }
 -        else if (parser->tok == '{' || parser->tok == '[')
 +        else if (var->expression.vtype == TYPE_ARRAY && parser->tok == '{')
 +        {
 +            if (localblock) {
 +                /* Note that fteqcc and most others don't even *have*
 +                 * local arrays, so this is not a high priority.
 +                 */
 +                parseerror(parser, "TODO: initializers for local arrays");
 +                break;
 +            }
 +            /*
 +static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels);
 +*/
 +            parseerror(parser, "TODO: initializing global arrays is not supported yet!");
 +            break;
 +        }
 +        else if (var->expression.vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '['))
          {
              if (localblock) {
                  parseerror(parser, "cannot declare functions within functions");
                  }
                  vec_free(sy.out);
                  vec_free(sy.ops);
 +                vec_free(sy.argc);
                  var->cvq = cvq;
              }
          }
@@@ -6048,7 -5970,7 +6048,7 @@@ static void generate_checksum(parser_t 
          if (!ast_istype(parser->fields[i], ast_value))
              continue;
          value = (ast_value*)(parser->fields[i]);
 -        switch (value->expression.next->expression.vtype) {
 +        switch (value->expression.next->vtype) {
              case TYPE_FLOAT:    crc = progdefs_crc_both(crc, "\tfloat\t"); break;
              case TYPE_VECTOR:   crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
              case TYPE_STRING:   crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
@@@ -6081,6 -6003,7 +6081,6 @@@ parser_t *parser_create(
          mem_d(parser);
          return NULL;
      }
 -    
  
      for (i = 0; i < operator_count; ++i) {
          if (operators[i].id == opid1('=')) {
      return parser;
  }
  
 -bool parser_compile(parser_t *parser)
 +static bool parser_compile(parser_t *parser)
  {
      /* initial lexer/parser state */
      parser->lex->flags.noops = true;
@@@ -6259,8 -6182,6 +6259,8 @@@ void parser_cleanup(parser_t *parser
  
      intrin_intrinsics_destroy(parser);
  
 +    code_cleanup(parser->code);
 +
      mem_d(parser);
  }
  
@@@ -6299,11 -6220,11 +6299,11 @@@ bool parser_finish(parser_t *parser, co
              ast_expression *subtype;
              field->hasvalue = true;
              subtype = field->expression.next;
 -            ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
 -            if (subtype->expression.vtype == TYPE_FIELD)
 -                ifld->fieldtype = subtype->expression.next->expression.vtype;
 -            else if (subtype->expression.vtype == TYPE_FUNCTION)
 -                ifld->outtype = subtype->expression.next->expression.vtype;
 +            ifld = ir_builder_create_field(ir, field->name, subtype->vtype);
 +            if (subtype->vtype == TYPE_FIELD)
 +                ifld->fieldtype = subtype->next->vtype;
 +            else if (subtype->vtype == TYPE_FUNCTION)
 +                ifld->outtype = subtype->next->vtype;
              (void)!ir_value_set_field(field->ir_v, ifld);
          }
      }
      }
      for (i = 0; i < vec_size(parser->fields); ++i) {
          ast_value *asvalue;
 -        asvalue = (ast_value*)(parser->fields[i]->expression.next);
 +        asvalue = (ast_value*)(parser->fields[i]->next);
  
          if (!ast_istype((ast_expression*)asvalue, ast_value))
              continue;