]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
initialize max_param_count to 1 so vararg functions don't try to create an accessor...
[xonotic/gmqcc.git] / parser.c
index b8e5a484214be6c042a99df425199856f576a882..10ddbdcb606c4b96b54ff32733f420b2a26317ba 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -31,7 +31,7 @@
 /* beginning of locals */
 #define PARSER_HT_LOCALS  2
 
-#define PARSER_HT_SIZE    1024
+#define PARSER_HT_SIZE    128
 #define TYPEDEF_HT_SIZE   16
 
 enum parser_pot { POT_PAREN, POT_TERNARY1, POT_TERNARY2 };
@@ -937,9 +937,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 if (CanConstFold(exprs[0], exprs[1]))
                     out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), 1.0/ConstF(1)));
                 else {
-                    out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
-                                                          (ast_expression*)parser_const_float_1(parser),
-                                                          exprs[1]);
+                    if (CanConstFold1(exprs[1])) {
+                        out = (ast_expression*)parser_const_float(parser, 1.0 / ConstF(1));
+                    } else {
+                        out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
+                                                              (ast_expression*)parser_const_float_1(parser),
+                                                              exprs[1]);
+                    }
                     if (!out) {
                         compile_error(ctx, "internal error: failed to generate division");
                         return false;
@@ -1288,11 +1292,17 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                                                                 exprs[0], exprs[1]);
                     } else {
                         /* there's no DIV_VF */
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
-                                                              (ast_expression*)parser_const_float_1(parser),
-                                                              exprs[1]);
-                        if (!out)
+                        if (CanConstFold1(exprs[1])) {
+                            out = (ast_expression*)parser_const_float(parser, 1.0 / ConstF(1));
+                        } else {
+                            out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
+                                                                  (ast_expression*)parser_const_float_1(parser),
+                                                                  exprs[1]);
+                        }
+                        if (!out) {
+                            compile_error(ctx, "internal error: failed to generate division");
                             return false;
+                        }
                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
                                                                 exprs[0], out);
                     }
@@ -1521,16 +1531,21 @@ static bool parser_close_paren(parser_t *parser, shunt *sy, bool functions_only)
     }
     */
     while (vec_size(sy->ops)) {
-        if (sy->ops[vec_size(sy->ops)-1].paren == SY_PAREN_FUNC) {
+        if (vec_last(sy->ops).paren == SY_PAREN_FUNC) {
             if (!parser_close_call(parser, sy))
                 return false;
             break;
         }
-        if (sy->ops[vec_size(sy->ops)-1].paren == SY_PAREN_EXPR) {
+        if (vec_last(sy->ops).paren == SY_PAREN_EXPR) {
+            if (!vec_size(sy->out)) {
+                compile_error(vec_last(sy->ops).ctx, "empty paren expression");
+                vec_shrinkby(sy->ops, 1);
+                return false;
+            }
             vec_shrinkby(sy->ops, 1);
             return !functions_only;
         }
-        if (sy->ops[vec_size(sy->ops)-1].paren == SY_PAREN_INDEX) {
+        if (vec_last(sy->ops).paren == SY_PAREN_INDEX) {
             if (functions_only)
                 return false;
             /* pop off the parenthesis */
@@ -1540,7 +1555,7 @@ static bool parser_close_paren(parser_t *parser, shunt *sy, bool functions_only)
                 return false;
             return true;
         }
-        if (sy->ops[vec_size(sy->ops)-1].paren == SY_PAREN_TERNARY) {
+        if (vec_last(sy->ops).paren == SY_PAREN_TERNARY) {
             if (functions_only)
                 return false;
             if (vec_last(parser->pot) != POT_TERNARY1) {
@@ -1669,6 +1684,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
 {
     ast_expression *expr = NULL;
     shunt sy;
+    size_t i;
     bool wantop = false;
     /* only warn once about an assignment in a truth value because the current code
      * would trigger twice on: if(a = b && ...), once for the if-truth-value, once for the && part
@@ -2126,6 +2142,10 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
 
 onerr:
     parser->lex->flags.noops = true;
+    for (i = 0; i < vec_size(sy.out); ++i) {
+        if (sy.out[i].out)
+            ast_unref(sy.out[i].out);
+    }
     vec_free(sy.out);
     vec_free(sy.ops);
     return NULL;
@@ -3795,7 +3815,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
 
     if (!OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
         if (parsewarning(parser, WARN_VARIADIC_FUNCTION,
-                         "variadic function with implementation will not be able to access additional parameters"))
+                         "variadic function with implementation will not be able to access additional parameters (try -fvariadic-args)"))
         {
             return false;
         }
@@ -3990,6 +4010,14 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         }
     }
 
+    func = ast_function_new(ast_ctx(var), var->name, var);
+    if (!func) {
+        parseerror(parser, "failed to allocate function for `%s`", var->name);
+        ast_block_delete(block);
+        goto enderr;
+    }
+    vec_push(parser->functions, func);
+
     parser_enterblock(parser);
 
     for (parami = 0; parami < vec_size(var->expression.params); ++parami) {
@@ -4006,7 +4034,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
 
         if (!create_vector_members(param, me)) {
             ast_block_delete(block);
-            return false;
+            goto enderrfn;
         }
 
         for (e = 0; e < 3; ++e) {
@@ -4015,14 +4043,6 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         }
     }
 
-    func = ast_function_new(ast_ctx(var), var->name, var);
-    if (!func) {
-        parseerror(parser, "failed to allocate function for `%s`", var->name);
-        ast_block_delete(block);
-        goto enderr;
-    }
-    vec_push(parser->functions, func);
-
     if (var->argcounter) {
         ast_value *argc = ast_value_new(ast_ctx(var), var->argcounter, TYPE_FLOAT);
         parser_addlocal(parser, argc->name, (ast_expression*)argc);
@@ -4039,13 +4059,13 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         if (!parser_create_array_setter_proto(parser, varargs, name)) {
             ast_delete(varargs);
             ast_block_delete(block);
-            goto enderr;
+            goto enderrfn;
         }
         snprintf(name, sizeof(name), "%s##va##GET", var->name);
         if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) {
             ast_delete(varargs);
             ast_block_delete(block);
-            goto enderr;
+            goto enderrfn;
         }
         func->varargs = varargs;
     }
@@ -4073,12 +4093,12 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
     return retval;
 
 enderrfn:
+    (void)!parser_leaveblock(parser);
     vec_pop(parser->functions);
     ast_function_delete(func);
     var->constval.vfunc = NULL;
 
 enderr:
-    (void)!parser_leaveblock(parser);
     parser->function = old;
     return false;
 }
@@ -4807,7 +4827,6 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
         if (!var) {
             if (name)
                 mem_d((void*)name);
-            ast_delete(var);
             return NULL;
         }
     }
@@ -5689,6 +5708,8 @@ bool parser_init()
     if (OPTS_FLAG(UNTYPED_NIL))
         util_htset(parser->htglobals, "nil", (void*)parser->nil);
 
+    parser->max_param_count = 1;
+
     parser->const_vec[0] = ast_value_new(empty_ctx, "<vector.x>", TYPE_NOEXPR);
     parser->const_vec[1] = ast_value_new(empty_ctx, "<vector.y>", TYPE_NOEXPR);
     parser->const_vec[2] = ast_value_new(empty_ctx, "<vector.z>", TYPE_NOEXPR);