]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ast.c
Experimental ast_member to access vector members
[xonotic/gmqcc.git] / ast.c
diff --git a/ast.c b/ast.c
index e153a5a7f57ef47b60d5a0f62b7f98e7da68b409..c19fad2656ba70d43a2d3d3b242c512548bc9ce4 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -32,7 +32,7 @@
     if (!self) {                                                    \
         return NULL;                                                \
     }                                                               \
-    ast_node_init((ast_node*)self, ctx);                            \
+    ast_node_init((ast_node*)self, ctx, TYPE_##T);                  \
     ( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn
 
 /* It must not be possible to get here. */
@@ -43,11 +43,12 @@ static GMQCC_NORETURN void _ast_node_destroy(ast_node *self)
 }
 
 /* Initialize main ast node aprts */
-static void ast_node_init(ast_node *self, lex_ctx ctx)
+static void ast_node_init(ast_node *self, lex_ctx ctx, int nodetype)
 {
     self->node.context = ctx;
     self->node.destroy = &_ast_node_destroy;
     self->node.keep    = false;
+    self->node.nodetype = nodetype;
 }
 
 /* General expression initialization */
@@ -285,6 +286,32 @@ void ast_entfield_delete(ast_entfield *self)
     mem_d(self);
 }
 
+ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int field)
+{
+    ast_instantiate(ast_member, ctx, ast_member_delete);
+    if (field >= 3) {
+        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;
+
+    self->owner = owner;
+    self->field = field;
+
+    return self;
+}
+
+void ast_member_delete(ast_member *self)
+{
+    ast_unref(self->owner);
+    ast_expression_delete((ast_expression*)self);
+    mem_d(self);
+}
+
 ast_ifthen* ast_ifthen_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
 {
     ast_instantiate(ast_ifthen, ctx, ast_ifthen_delete);
@@ -910,6 +937,23 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i
     return true;
 }
 
+bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_value **out)
+{
+    ast_expression_codegen *cgen;
+    ir_value *vec, *field;
+
+    cgen = self->owner->expression.codegen;
+    if (!(*cgen)((ast_expression*)(self->owner), func, true, &vec))
+        return false;
+
+    if (vec->vtype != TYPE_VECTOR)
+        return false;
+
+    *out = ir_value_vector_member(vec, self->field);
+
+    return (*out != NULL);
+}
+
 bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_value **out)
 {
     ast_expression_codegen *cgen;