]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ast.c
Merge branch 'master' into blub/parser
[xonotic/gmqcc.git] / ast.c
diff --git a/ast.c b/ast.c
index d7684090887af261cb8869c0c23caa5a3374d8a3..5dfad22a408a57c84f939ab6c3d6e0022b3e318b 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -94,6 +94,15 @@ static ast_value* ast_value_copy(const ast_value *self)
     return cp;
 }
 
+static ast_expression* ast_shallow_type(lex_ctx ctx, int vtype)
+{
+    ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
+    self->expression.codegen = NULL;
+    self->expression.next    = NULL;
+    self->expression.vtype   = vtype;
+    return self;
+}
+
 static ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
 {
     size_t i;
@@ -202,6 +211,18 @@ ast_binary* ast_binary_new(lex_ctx ctx, int op,
     self->left = left;
     self->right = right;
 
+    if (op >= INSTR_EQ_F && op <= INSTR_GT)
+        self->expression.vtype = TYPE_FLOAT;
+    else if (op == INSTR_AND || op == INSTR_OR ||
+             op == INSTR_BITAND || op == INSTR_BITOR)
+        self->expression.vtype = TYPE_FLOAT;
+    else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV)
+        self->expression.vtype = TYPE_VECTOR;
+    else if (op == INSTR_MUL_V)
+        self->expression.vtype = TYPE_FLOAT;
+    else
+        self->expression.vtype = left->expression.vtype;
+
     return self;
 }
 
@@ -294,10 +315,22 @@ ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int fiel
         return NULL;
     }
 
+    if (owner->expression.vtype != TYPE_VECTOR &&
+        owner->expression.vtype != TYPE_FIELD) {
+        printf("ast_member on an invalid owner of type %i\n", (int)owner->expression.vtype);
+        mem_d(self);
+        return NULL;
+    }
+
     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
 
-    self->expression.vtype = TYPE_FLOAT;
-    self->expression.next  = NULL;
+    if (owner->expression.vtype == TYPE_VECTOR) {
+        self->expression.vtype = TYPE_FLOAT;
+        self->expression.next  = NULL;
+    } else {
+        self->expression.vtype = TYPE_FIELD;
+        self->expression.next = ast_shallow_type(ctx, TYPE_FLOAT);
+    }
 
     self->owner = owner;
     self->field = field;
@@ -629,8 +662,10 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir)
     }
 
     v = ir_builder_create_global(ir, self->name, self->expression.vtype);
-    if (!v)
+    if (!v) {
+        printf("ir_builder_create_global failed\n");
         return false;
+    }
 
     if (self->isconst) {
         switch (self->expression.vtype)
@@ -958,8 +993,11 @@ bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_va
     if (!(*cgen)((ast_expression*)(self->owner), func, true, &vec))
         return false;
 
-    if (vec->vtype != TYPE_VECTOR)
+    if (vec->vtype != TYPE_VECTOR &&
+        !(vec->vtype == TYPE_FIELD && self->owner->expression.next->expression.vtype == TYPE_VECTOR))
+    {
         return false;
+    }
 
     *out = ir_value_vector_member(vec, self->field);