]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ast.c
finish parsing of labeled loops; ast support added
[xonotic/gmqcc.git] / ast.c
diff --git a/ast.c b/ast.c
index 5dc131ea38bc617289aac9a5dae09d91985502d0..3bb5bf8b8367be6f8ed6ca981f017c13da20f71d 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;
@@ -756,12 +764,13 @@ void ast_loop_delete(ast_loop *self)
     mem_d(self);
 }
 
-ast_breakcont* ast_breakcont_new(lex_ctx ctx, bool iscont)
+ast_breakcont* ast_breakcont_new(lex_ctx ctx, bool iscont, unsigned int levels)
 {
     ast_instantiate(ast_breakcont, ctx, ast_breakcont_delete);
     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_breakcont_codegen);
 
     self->is_continue = iscont;
+    self->levels      = levels;
 
     return self;
 }
@@ -1017,8 +1026,8 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
     self->ir_func = NULL;
     self->curblock = NULL;
 
-    self->breakblock    = NULL;
-    self->continueblock = NULL;
+    self->breakblocks    = NULL;
+    self->continueblocks = NULL;
 
     vtype->hasvalue = true;
     vtype->constval.vfunc = self;
@@ -1043,6 +1052,8 @@ void ast_function_delete(ast_function *self)
     for (i = 0; i < vec_size(self->blocks); ++i)
         ast_delete(self->blocks[i]);
     vec_free(self->blocks);
+    vec_free(self->breakblocks);
+    vec_free(self->continueblocks);
     mem_d(self);
 }
 
@@ -1098,9 +1109,9 @@ bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_valu
      * on all the globals.
      */
     if (!self->ir_v) {
-        char typename[1024];
-        ast_type_to_string((ast_expression*)self, typename, sizeof(typename));
-        compile_error(ast_ctx(self), "ast_value used before generated %s %s", typename, self->name);
+        char tname[1024]; /* typename is reserved in C++ */
+        ast_type_to_string((ast_expression*)self, tname, sizeof(tname));
+        compile_error(ast_ctx(self), "ast_value used before generated %s %s", tname, self->name);
         return false;
     }
     *out = self->ir_v;
@@ -1161,6 +1172,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             }
             v->context = ast_ctx(self);
             v->unique_life = true;
+            v->locked      = true;
             array->ir_v = self->ir_v = v;
 
             namelen = strlen(self->name);
@@ -1179,6 +1191,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
                 }
                 array->ir_values[ai]->context = ast_ctx(self);
                 array->ir_values[ai]->unique_life = true;
+                array->ir_values[ai]->locked      = true;
             }
             mem_d(name);
         }
@@ -1212,6 +1225,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
         }
         v->context = ast_ctx(self);
         v->unique_life = true;
+        v->locked      = true;
 
         namelen = strlen(self->name);
         name    = (char*)mem_a(namelen + 16);
@@ -1229,6 +1243,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             }
             self->ir_values[ai]->context = ast_ctx(self);
             self->ir_values[ai]->unique_life = true;
+            self->ir_values[ai]->locked      = true;
         }
         mem_d(name);
     }
@@ -1317,6 +1332,8 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
         ast_expression_common *elemtype = &self->expression.next->expression;
         int vtype = elemtype->vtype;
 
+        func->flags |= IR_FLAG_HAS_ARRAYS;
+
         if (param) {
             compile_error(ast_ctx(self), "array-parameters are not supported");
             return false;
@@ -1340,6 +1357,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
         }
         v->context = ast_ctx(self);
         v->unique_life = true;
+        v->locked      = true;
 
         namelen = strlen(self->name);
         name    = (char*)mem_a(namelen + 16);
@@ -1355,6 +1373,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
             }
             self->ir_values[ai]->context = ast_ctx(self);
             self->ir_values[ai]->unique_life = true;
+            self->ir_values[ai]->locked      = true;
         }
     }
     else
@@ -2390,9 +2409,6 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
     ir_block *bcontinue     = NULL;
     ir_block *bbreak        = NULL;
 
-    ir_block *old_bcontinue = NULL;
-    ir_block *old_bbreak    = NULL;
-
     ir_block *tmpblock      = NULL;
 
     (void)lvalue;
@@ -2485,12 +2501,11 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         /* enter */
         func->curblock = bbody;
 
-        old_bbreak          = func->breakblock;
-        old_bcontinue       = func->continueblock;
-        func->breakblock    = bbreak;
-        func->continueblock = bcontinue;
-        if (!func->continueblock)
-            func->continueblock = bbody;
+        vec_push(func->breakblocks,    bbreak);
+        if (bcontinue)
+            vec_push(func->continueblocks, bcontinue);
+        else
+            vec_push(func->continueblocks, bbody);
 
         /* generate */
         if (self->body) {
@@ -2500,8 +2515,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         }
 
         end_bbody = func->curblock;
-        func->breakblock    = old_bbreak;
-        func->continueblock = old_bcontinue;
+        vec_pop(func->breakblocks);
+        vec_pop(func->continueblocks);
     }
 
     /* post-loop-condition */
@@ -2627,9 +2642,9 @@ bool ast_breakcont_codegen(ast_breakcont *self, ast_function *func, bool lvalue,
     self->expression.outr = (ir_value*)1;
 
     if (self->is_continue)
-        target = func->continueblock;
+        target = func->continueblocks[vec_size(func->continueblocks)-1-self->levels];
     else
-        target = func->breakblock;
+        target = func->breakblocks[vec_size(func->breakblocks)-1-self->levels];
 
     if (!target) {
         compile_error(ast_ctx(self), "%s is lacking a target block", (self->is_continue ? "continue" : "break"));
@@ -2652,7 +2667,6 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
 
     ir_value *dummy     = NULL;
     ir_value *irop      = NULL;
-    ir_block *old_break = NULL;
     ir_block *bout      = NULL;
     ir_block *bfall     = NULL;
     size_t    bout_id;
@@ -2695,8 +2709,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
         return false;
 
     /* setup the break block */
-    old_break        = func->breakblock;
-    func->breakblock = bout;
+    vec_push(func->breakblocks, bout);
 
     /* Now create all cases */
     for (c = 0; c < vec_size(self->cases); ++c) {
@@ -2801,7 +2814,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
     func->curblock = bout;
 
     /* restore the break block */
-    func->breakblock = old_break;
+    vec_pop(func->breakblocks);
 
     /* Move 'bout' to the end, it's nicer */
     vec_remove(func->ir_func->blocks, bout_id, 1);
@@ -2856,14 +2869,14 @@ bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value
         if (self->irblock_from) {
             /* we already tried once, this is the callback */
             self->irblock_from->final = false;
-            if (!ir_block_create_jump(self->irblock_from, ast_ctx(self), self->target->irblock)) {
+            if (!ir_block_create_goto(self->irblock_from, ast_ctx(self), self->target->irblock)) {
                 compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
                 return false;
             }
         }
         else
         {
-            if (!ir_block_create_jump(func->curblock, ast_ctx(self), self->target->irblock)) {
+            if (!ir_block_create_goto(func->curblock, ast_ctx(self), self->target->irblock)) {
                 compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
                 return false;
             }