]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
reduce the hashtable size a bit
[xonotic/gmqcc.git] / parser.c
index 05fa142a55e693c0159c6f9f894abe4f4a36eef9..3bd1073382a5fd006f83c825dfa5dd16c7a9eff2 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 };
@@ -921,16 +921,43 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             };
             break;
         case opid1('/'):
-            if (NotSameType(TYPE_FLOAT)) {
-                compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s",
-                              type_name[exprs[0]->expression.vtype],
-                              type_name[exprs[1]->expression.vtype]);
+            if (exprs[1]->expression.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 (CanConstFold(exprs[0], exprs[1]))
-                out = (ast_expression*)parser_const_float(parser, ConstF(0) / ConstF(1));
+            if (exprs[0]->expression.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) {
+                if (CanConstFold(exprs[0], exprs[1]))
+                    out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), 1.0/ConstF(1)));
+                else {
+                    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_binary_new(ctx, INSTR_MUL_VF, exprs[0], out);
+                }
+            }
             else
-                out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
+            {
+                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;
+            }
             break;
         case opid1('%'):
         case opid2('%','='):
@@ -1096,8 +1123,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                         field->expression.next->expression.vtype == TYPE_FUNCTION &&
                         exprs[1]->expression.vtype == TYPE_FUNCTION)
                     {
-                        (void)!parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
-                                            "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
+                        (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
+                                               "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
                     }
                     else
                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
@@ -1128,8 +1155,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                         exprs[0]->expression.vtype == TYPE_FUNCTION &&
                         exprs[1]->expression.vtype == TYPE_FUNCTION)
                     {
-                        (void)!parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
-                                            "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
+                        (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
+                                               "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
                     }
                     else
                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
@@ -1265,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);
                     }
@@ -1498,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 */
@@ -1517,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) {
@@ -1646,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
@@ -2103,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;
@@ -3772,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;
         }
@@ -3967,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) {
@@ -3983,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) {
@@ -3992,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);
@@ -4016,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;
     }
@@ -4050,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;
 }
@@ -4784,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;
         }
     }