]> de.git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
qcvm -trace now shows the current function name and nest-depth
[xonotic/gmqcc.git] / parser.c
index 076d9df791ac06467b7ee661f6e50550b1fc1020..7b7805f4f439e6c5709c42bb924f17616be193c8 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -463,6 +463,20 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
             }
             break;
 
+        case opid1('['):
+            if (exprs[0]->expression.vtype != TYPE_ARRAY) {
+                ast_type_to_string(exprs[0], ty1, sizeof(ty1));
+                parseerror(parser, "cannot index value of type %s", ty1);
+                return false;
+            }
+            if (exprs[1]->expression.vtype != TYPE_FLOAT) {
+                ast_type_to_string(exprs[0], ty1, sizeof(ty1));
+                parseerror(parser, "index must be of type float, not %s", ty1);
+                return false;
+            }
+            out = (ast_expression*)ast_array_index_new(ctx, exprs[0], exprs[1]);
+            break;
+
         case opid1(','):
             if (blocks[0]) {
                 if (!ast_block_exprs_add(blocks[0], exprs[1]))
@@ -999,6 +1013,16 @@ static bool parser_close_paren(parser_t *parser, shunt *sy, bool functions_only)
             sy->ops_count--;
             return !functions_only;
         }
+        if (sy->ops[sy->ops_count-1].paren == SY_PAREN_INDEX) {
+            if (functions_only)
+                return false;
+            /* pop off the parenthesis */
+            sy->ops_count--;
+            /* then apply the index operator */
+            if (!parser_sy_pop(parser, sy))
+                return false;
+            return true;
+        }
         if (!parser_sy_pop(parser, sy))
             return false;
     }
@@ -1183,6 +1207,16 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
             }
             wantop = true;
         }
+        else if (parser->tok == ']') {
+            if (!wantop)
+                parseerror(parser, "operand expected");
+            --parens;
+            if (parens < 0)
+                break;
+            if (!parser_close_paren(parser, &sy, false))
+                goto onerr;
+            wantop = true;
+        }
         else if (parser->tok != TOKEN_OPERATOR) {
             if (wantop) {
                 parseerror(parser, "expected operator or end of statement");
@@ -1270,6 +1304,18 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                     DEBUGSHUNTDO(printf("push [nop] (\n"));
                 }
                 wantop = false;
+            } else if (op->id == opid1('[')) {
+                if (!wantop) {
+                    parseerror(parser, "unexpected array subscript");
+                    goto onerr;
+                }
+                ++parens;
+                /* push both the operator and the paren, this makes life easier */
+                if (!shunt_ops_add(&sy, syop(parser_ctx(parser), op)))
+                    goto onerr;
+                if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), SY_PAREN_INDEX, 0)))
+                    goto onerr;
+                wantop = false;
             } else {
                 DEBUGSHUNTDO(printf("push operator %s\n", op->op));
                 if (!shunt_ops_add(&sy, syop(parser_ctx(parser), op)))
@@ -1280,7 +1326,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
         if (!parser_next(parser)) {
             goto onerr;
         }
-        if (parser->tok == ';' || parser->tok == ']') {
+        if (parser->tok == ';' || (!parens && parser->tok == ']')) {
             break;
         }
     }
@@ -3540,7 +3586,8 @@ bool parser_finish(const char *output)
             asvalue = (ast_value*)(parser->globals[i].var);
             if (asvalue->setter) {
                 if (!ast_global_codegen(asvalue->setter, ir, false) ||
-                    !ast_function_codegen(asvalue->setter->constval.vfunc, ir))
+                    !ast_function_codegen(asvalue->setter->constval.vfunc, ir) ||
+                    !ir_function_finalize(asvalue->setter->constval.vfunc->ir_func))
                 {
                     printf("failed to generate setter for %s\n", parser->globals[i].name);
                     ir_builder_delete(ir);
@@ -3549,7 +3596,8 @@ bool parser_finish(const char *output)
             }
             if (asvalue->getter) {
                 if (!ast_global_codegen(asvalue->getter, ir, false) ||
-                    !ast_function_codegen(asvalue->getter->constval.vfunc, ir))
+                    !ast_function_codegen(asvalue->getter->constval.vfunc, ir) ||
+                    !ir_function_finalize(asvalue->getter->constval.vfunc->ir_func))
                 {
                     printf("failed to generate getter for %s\n", parser->globals[i].name);
                     ir_builder_delete(ir);