]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
strictness sweep: (void)-ing all vec_ macros which don't evaluate to a sensible value
[xonotic/gmqcc.git] / parser.c
index aa3c38e5ae6d7eb434b6b6b591d2adef9832a814..9912f564d8f6ee638b2caf515e85963b336e87c0 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -109,6 +109,7 @@ static const ast_expression *intrinsic_debug_typestring = (ast_expression*)0x10;
 static void parser_enterblock(parser_t *parser);
 static bool parser_leaveblock(parser_t *parser);
 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e);
+static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e);
 static bool parse_typedef(parser_t *parser);
 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring);
 static ast_block* parse_block(parser_t *parser);
@@ -928,14 +929,21 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     exprs[0], exprs[1]);
             break;
         case opid1('^'):
-            parseerror(parser, "TODO: bitxor");
+            compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor via ^");
             return false;
 
         case opid2('<','<'):
         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))));
+                else
+                    out = (ast_expression*)parser_const_float(parser, (double)((int)(ConstF(0)) >> (int)(ConstF(1))));
+                break;
+            }
         case opid3('<','<','='):
         case opid3('>','>','='):
-            parseerror(parser, "TODO: shifts");
+            compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-shifts");
             return false;
 
         case opid2('|','|'):
@@ -1643,14 +1651,19 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                      * other things as well.
                      */
                     if (OPTS_FLAG(ENHANCED_DIAGNOSTICS)) {
+                        correction_t corr;
+                        correct_init(&corr);
+
                         for (i = 0; i < vec_size(parser->correct_variables); i++) {
-                            correct = correct_str(parser->correct_variables[i], parser_tokval(parser));
+                            correct = correct_str(&corr, parser->correct_variables[i], parser_tokval(parser));
                             if (strcmp(correct, parser_tokval(parser))) {
                                 break;
                             } else if (correct) {
                                 mem_d(correct);
+                                correct = NULL;
                             }
                         }
+                        correct_free(&corr);
 
                         if (correct) {
                             parseerror(parser, "unexpected ident: %s (did you mean %s?)", parser_tokval(parser), correct);
@@ -1944,7 +1957,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
             goto onerr;
         }
         if (parser->tok == ';' ||
-            (!parens && parser->tok == ']'))
+            (!parens && (parser->tok == ']' || parser->tok == ')')))
         {
             break;
         }
@@ -1983,8 +1996,13 @@ static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool
     ast_expression *e = parse_expression_leave(parser, stopatcomma, false, with_labels);
     if (!e)
         return NULL;
+    if (parser->tok != ';') {
+        parseerror(parser, "semicolon expected after expression");
+        ast_unref(e);
+        return NULL;
+    }
     if (!parser_next(parser)) {
-        ast_delete(e);
+        ast_unref(e);
         return NULL;
     }
     return e;
@@ -2062,6 +2080,19 @@ static void parser_addlocal(parser_t *parser, const char *name, ast_expression *
     );
 }
 
+static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e)
+{
+    vec_push(parser->globals, e);
+    util_htset(parser->htglobals, name, e);
+
+    /* corrector */
+    correct_add (
+         parser->correct_variables[0],
+        &parser->correct_variables_score[0],
+        name
+    );
+}
+
 static ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot)
 {
     bool       ifnot = false;
@@ -2165,6 +2196,8 @@ static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out)
         ast_delete(cond);
         return false;
     }
+    if (!ontrue)
+        ontrue = (ast_expression*)ast_block_new(parser_ctx(parser));
     /* check for an else */
     if (!strcmp(parser_tokval(parser), "else")) {
         /* parse into the 'else' branch */
@@ -2642,6 +2675,13 @@ static bool parse_break_continue(parser_t *parser, ast_block *block, ast_express
         return false;
     }
 
+    if (!vec_size(loops)) {
+        if (is_continue)
+            parseerror(parser, "`continue` can only be used inside loops");
+        else
+            parseerror(parser, "`break` can only be used inside loops or switches");
+    }
+
     if (parser->tok == TOKEN_IDENT) {
         if (!OPTS_FLAG(LOOP_LABELS))
             parseerror(parser, "labeled loops not activated, try using -floop-labels");
@@ -3592,8 +3632,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
                 return false;
             }
 
-            vec_push(parser->globals, (ast_expression*)thinkfunc);
-            util_htset(parser->htglobals, thinkfunc->name, thinkfunc);
+            parser_addglobal(parser, thinkfunc->name, (ast_expression*)thinkfunc);
 
             nextthink = (ast_expression*)thinkfunc;
 
@@ -4810,12 +4849,10 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                     }
                 }
                 else {
-                    vec_push(parser->globals, (ast_expression*)var);
-                    util_htset(parser->htglobals, var->name, var);
+                    parser_addglobal(parser, var->name, (ast_expression*)var);
                     if (isvector) {
                         for (i = 0; i < 3; ++i) {
-                            vec_push(parser->globals, (ast_expression*)me[i]);
-                            util_htset(parser->htglobals, me[i]->name, me[i]);
+                            parser_addglobal(parser, me[i]->name, (ast_expression*)me[i]);
                         }
                     }
                 }
@@ -5309,6 +5346,10 @@ bool parser_init()
     vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
     vec_push(parser->_blocktypedefs, 0);
 
+    /* corrector */
+    vec_push(parser->correct_variables, correct_trie_new());
+    vec_push(parser->correct_variables_score, NULL);
+
     empty_ctx.file = "<internal>";
     empty_ctx.line = 0;
     parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL);
@@ -5414,9 +5455,6 @@ void parser_cleanup()
     for (i = 0; i < vec_size(parser->correct_variables); ++i) {
         correct_del(parser->correct_variables[i], parser->correct_variables_score[i]);
     }
-    for (i = 0; i < vec_size(parser->correct_variables_score); ++i) {
-        vec_free(parser->correct_variables_score[i]);
-    }
     vec_free(parser->correct_variables);
     vec_free(parser->correct_variables_score);