]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
ast referencing
[xonotic/gmqcc.git] / parser.c
index aa536c50ac8161f4cba91617781cfb2603c4aa7e..f589d63629361ddc6b48edd09d20299bb93227ef 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -671,8 +671,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     return false;
                 }
             }
-            if (!ast_block_set_type(blocks[0], exprs[1]))
-                return false;
+            ast_block_set_type(blocks[0], exprs[1]);
 
             vec_push(sy->out, syblock(ctx, blocks[0]));
             return true;
@@ -1068,6 +1067,49 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]);
             break;
 
+        case opid3('<', '=', '>'): /* -1, 0, or 1 */
+            if (NotSameType(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 comparision: %s and %s",
+                    ty1, ty2);
+
+                return false;
+            }
+
+            if (CanConstFold(exprs[0], exprs[1])) {
+                if (ConstF(0) < ConstF(1))
+                    out = (ast_expression*)parser_const_float_neg1(parser);
+                else if (ConstF(0) == ConstF(1))
+                    out = (ast_expression*)parser_const_float_0(parser);
+                else if (ConstF(0) > ConstF(1))
+                    out = (ast_expression*)parser_const_float_1(parser);
+            } else {
+                ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]);
+
+                eq->refs = false; /* references nothing */
+
+                    /* if (lt) { */
+                out = (ast_expression*)ast_ternary_new(ctx,
+                        (ast_expression*)ast_binary_new(ctx, INSTR_LT, exprs[0], exprs[1]),
+                        /* out = -1 */
+                        (ast_expression*)parser_const_float_neg1(parser),
+                    /* } else { */
+                        /* if (eq) { */
+                        (ast_expression*)ast_ternary_new(ctx, (ast_expression*)eq,
+                            /* out = 0 */
+                            (ast_expression*)parser_const_float_0(parser),
+                        /* } else { */
+                            /* out = 1 */
+                            (ast_expression*)parser_const_float_1(parser)
+                        /* } */
+                        )
+                    /* } */
+                    );
+
+            }
+            break;
+
         case opid1('>'):
             generated_op += 1; /* INSTR_GT */
         case opid1('<'):
@@ -1372,7 +1414,6 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             else
                 out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser_const_float_neg1(parser), exprs[0]);
             break;
-            
     }
 #undef NotSameType
 
@@ -1898,8 +1939,8 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 }
             }
             if (o == operator_count) {
-                /* no operator found... must be the end of the statement */
-                break;
+                compile_error(parser_ctx(parser), "unknown operator: %s", parser_tokval(parser));
+                goto onerr;
             }
             /* found an operator */
             op = &operators[o];
@@ -3851,11 +3892,12 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
             ast_expression *functype = fld_think->expression.next;
 
             thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->expression.vtype);
-            if (!thinkfunc || !ast_type_adopt(thinkfunc, functype)) {
+            if (!thinkfunc) { /* || !ast_type_adopt(thinkfunc, functype)*/
                 ast_unref(framenum);
                 parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
                 return false;
             }
+            ast_type_adopt(thinkfunc, functype);
 
             if (!parser_next(parser)) {
                 ast_unref(framenum);
@@ -3981,6 +4023,12 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         }
     }
 
+    if (var->hasvalue) {
+        parseerror(parser, "function `%s` declared with multiple bodies", var->name);
+        ast_block_delete(block);
+        goto enderr;
+    }
+
     func = ast_function_new(ast_ctx(var), var->name, var);
     if (!func) {
         parseerror(parser, "failed to allocate function for `%s`", var->name);