]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Added the 'static' keyword.
authorWolfgang Bumiller <blub@speed.at>
Mon, 24 Dec 2012 10:30:58 +0000 (11:30 +0100)
committerWolfgang Bumiller <blub@speed.at>
Mon, 24 Dec 2012 10:30:58 +0000 (11:30 +0100)
Implements #71

ast.c
ast.h
parser.c

diff --git a/ast.c b/ast.c
index 3894cdefaad6e8fe4fb5ff6a38154e320fee2784..1a686de3824c2663f9b816889e7c1a02561efa82 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -596,6 +596,14 @@ void ast_member_delete(ast_member *self)
     mem_d(self);
 }
 
+bool ast_member_set_name(ast_member *self, const char *name)
+{
+    if (self->name)
+        mem_d((void*)self->name);
+    self->name = util_strdup(name);
+    return !!self->name;
+}
+
 ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_expression *index)
 {
     ast_expression *outtype;
diff --git a/ast.h b/ast.h
index 8b8afd10eb04c3bdf8e052dfad82279695827432..bc37eea72888fb3800028997f1f9b4559567224c 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -326,6 +326,7 @@ struct ast_member_s
 };
 ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int field, const char *name);
 void ast_member_delete(ast_member*);
+bool ast_member_set_name(ast_member*, const char *name);
 
 bool ast_member_codegen(ast_member*, ast_function*, bool lvalue, ir_value**);
 
index bfa6d6a284d7e7cbcc7b713a4183637e7d54b22f..c8c6fb33beb067050b77ac6365d44d90c2a3830e 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -103,7 +103,7 @@ 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 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 noreturn);
+static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool noreturn, bool is_static);
 static ast_block* parse_block(parser_t *parser);
 static bool parse_block_into(parser_t *parser, ast_block *block);
 static bool parse_statement_or_block(parser_t *parser, ast_expression **out);
@@ -2199,7 +2199,7 @@ static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
                              "current standard does not allow variable declarations in for-loop initializers"))
                 goto onerr;
         }
-        if (!parse_variable(parser, block, true, CV_VAR, typevar, false, false))
+        if (!parse_variable(parser, block, true, CV_VAR, typevar, false, false, false))
             goto onerr;
     }
     else if (parser->tok != ';')
@@ -2344,13 +2344,14 @@ static bool parse_break_continue(parser_t *parser, ast_block *block, ast_express
 /* returns true when it was a variable qualifier, false otherwise!
  * on error, cvq is set to CV_WRONG
  */
-static bool parse_var_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *noref, bool *noreturn)
+static bool parse_var_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *noref, bool *noreturn, bool *is_static)
 {
-    bool had_const = false;
-    bool had_var   = false;
-    bool had_noref = false;
+    bool had_const    = false;
+    bool had_var      = false;
+    bool had_noref    = false;
     bool had_noreturn = false;
-    bool had_attrib = false;
+    bool had_attrib   = false;
+    bool had_static   = false;
 
     *cvq = CV_NONE;
     for (;;) {
@@ -2391,6 +2392,8 @@ static bool parse_var_qualifiers(parser_t *parser, bool with_local, int *cvq, bo
                 }
             }
         }
+        else if (!strcmp(parser_tokval(parser), "static"))
+            had_static = true;
         else if (!strcmp(parser_tokval(parser), "const"))
             had_const = true;
         else if (!strcmp(parser_tokval(parser), "var"))
@@ -2399,7 +2402,7 @@ static bool parse_var_qualifiers(parser_t *parser, bool with_local, int *cvq, bo
             had_var = true;
         else if (!strcmp(parser_tokval(parser), "noref"))
             had_noref = true;
-        else if (!had_const && !had_var && !had_noref && !had_noreturn && !had_attrib) {
+        else if (!had_const && !had_var && !had_noref && !had_noreturn && !had_attrib && !had_static) {
             return false;
         }
         else
@@ -2413,8 +2416,9 @@ static bool parse_var_qualifiers(parser_t *parser, bool with_local, int *cvq, bo
         *cvq = CV_VAR;
     else
         *cvq = CV_NONE;
-    *noref    = had_noref;
-    *noreturn = had_noreturn;
+    *noref     = had_noref;
+    *noreturn  = had_noreturn;
+    *is_static = had_static;
     return true;
 onerr:
     parseerror(parser, "parse error after variable qualifier");
@@ -2431,7 +2435,7 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou
     ast_switch_case swcase;
 
     int  cvq;
-    bool noref, noreturn;
+    bool noref, noreturn, is_static;
 
     lex_ctx ctx = parser_ctx(parser);
 
@@ -2483,19 +2487,19 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou
         if (parser->tok == TOKEN_IDENT)
             typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
         if (typevar || parser->tok == TOKEN_TYPENAME) {
-            if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false)) {
+            if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, false)) {
                 ast_delete(switchnode);
                 return false;
             }
             continue;
         }
-        if (parse_var_qualifiers(parser, true, &cvq, &noref, &noreturn))
+        if (parse_var_qualifiers(parser, true, &cvq, &noref, &noreturn, &is_static))
         {
             if (cvq == CV_WRONG) {
                 ast_delete(switchnode);
                 return false;
             }
-            if (!parse_variable(parser, block, false, cvq, NULL, noref, noreturn)) {
+            if (!parse_variable(parser, block, false, cvq, NULL, noref, noreturn, is_static)) {
                 ast_delete(switchnode);
                 return false;
             }
@@ -2710,7 +2714,7 @@ static bool parse_pragma(parser_t *parser)
 
 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases)
 {
-    bool       noref, noreturn;
+    bool       noref, noreturn, is_static;
     int        cvq = CV_NONE;
     ast_value *typevar = NULL;
 
@@ -2730,15 +2734,15 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
             if (parsewarning(parser, WARN_EXTENSIONS, "missing 'local' keyword when declaring a local variable"))
                 return false;
         }
-        if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false))
+        if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, false))
             return false;
         return true;
     }
-    else if (parse_var_qualifiers(parser, !!block, &cvq, &noref, &noreturn))
+    else if (parse_var_qualifiers(parser, !!block, &cvq, &noref, &noreturn, &is_static))
     {
         if (cvq == CV_WRONG)
             return false;
-        return parse_variable(parser, block, true, cvq, NULL, noref, noreturn);
+        return parse_variable(parser, block, true, cvq, NULL, noref, noreturn, is_static);
     }
     else if (parser->tok == TOKEN_KEYWORD)
     {
@@ -3994,7 +3998,7 @@ static bool parse_typedef(parser_t *parser)
     return true;
 }
 
-static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool noreturn)
+static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool noreturn, bool is_static)
 {
     ast_value *var;
     ast_value *proto;
@@ -4257,16 +4261,55 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                     }
                 }
             } else {
-                vec_push(localblock->locals, var);
-                parser_addlocal(parser, var->name, (ast_expression*)var);
-                if (isvector) {
-                    for (i = 0; i < 3; ++i) {
-                        parser_addlocal(parser, me[i]->name, (ast_expression*)me[i]);
-                        ast_block_collect(localblock, (ast_expression*)me[i]);
+                if (is_static) {
+                    /* a static adds itself to be generated like any other global
+                     * but is added to the local namespace instead
+                     */
+                    char   *defname = NULL;
+                    size_t  prefix_len, ln;
+
+                    ln = strlen(parser->function->name);
+                    vec_append(defname, ln, parser->function->name);
+
+                    vec_append(defname, 2, "::");
+                    /* remember the length up to here */
+                    prefix_len = vec_size(defname);
+
+                    /* Add it to the local scope */
+                    util_htset(vec_last(parser->variables), var->name, (void*)var);
+                    /* now rename the global */
+                    ln = strlen(var->name);
+                    vec_append(defname, ln, var->name);
+                    ast_value_set_name(var, defname);
+
+                    /* push it to the to-be-generated globals */
+                    vec_push(parser->globals, (ast_expression*)var);
+
+                    /* same game for the vector members */
+                    if (isvector) {
+                        for (i = 0; i < 3; ++i) {
+                            util_htset(vec_last(parser->variables), me[i]->name, (void*)(me[i]));
+
+                            vec_shrinkto(defname, prefix_len);
+                            ln = strlen(me[i]->name);
+                            vec_append(defname, ln, me[i]->name);
+                            ast_member_set_name(me[i], defname);
+
+                            vec_push(parser->globals, (ast_expression*)me[i]);
+                        }
+                    }
+                    vec_free(defname);
+                } else {
+                    vec_push(localblock->locals, var);
+                    parser_addlocal(parser, var->name, (ast_expression*)var);
+                    if (isvector) {
+                        for (i = 0; i < 3; ++i) {
+                            parser_addlocal(parser, me[i]->name, (ast_expression*)me[i]);
+                            ast_block_collect(localblock, (ast_expression*)me[i]);
+                        }
                     }
                 }
             }
-
         }
         me[0] = me[1] = me[2] = NULL;
         cleanvar = false;
@@ -4527,23 +4570,24 @@ cleanup:
 
 static bool parser_global_statement(parser_t *parser)
 {
-    int        cvq      = CV_WRONG;
-    bool       noref    = false;
-    bool       noreturn = false;
-    ast_value *istype   = NULL;
+    int        cvq       = CV_WRONG;
+    bool       noref     = false;
+    bool       noreturn  = false;
+    bool       is_static = false;
+    ast_value *istype    = NULL;
 
     if (parser->tok == TOKEN_IDENT)
         istype = parser_find_typedef(parser, parser_tokval(parser), 0);
 
     if (istype || parser->tok == TOKEN_TYPENAME || parser->tok == '.')
     {
-        return parse_variable(parser, NULL, false, CV_NONE, istype, false, false);
+        return parse_variable(parser, NULL, false, CV_NONE, istype, false, false, false);
     }
-    else if (parse_var_qualifiers(parser, false, &cvq, &noref, &noreturn))
+    else if (parse_var_qualifiers(parser, false, &cvq, &noref, &noreturn, &is_static))
     {
         if (cvq == CV_WRONG)
             return false;
-        return parse_variable(parser, NULL, true, cvq, NULL, noref, noreturn);
+        return parse_variable(parser, NULL, true, cvq, NULL, noref, noreturn, is_static);
     }
     else if (parser->tok == TOKEN_KEYWORD)
     {