Vectors and matrices can be dereferenced like arrays.
authorRyan C. Gordon <icculus@icculus.org>
Wed, 19 Jan 2011 01:24:08 -0800
changeset 985 bea4dafa2782
parent 984 b75637d50945
child 986 805aa6eb75af
Vectors and matrices can be dereferenced like arrays.
mojoshader_compiler.c
--- a/mojoshader_compiler.c	Wed Jan 19 01:04:40 2011 -0800
+++ b/mojoshader_compiler.c	Wed Jan 19 01:24:08 2011 -0800
@@ -2293,6 +2293,33 @@
 } // match_func_to_call
 
 
+static const MOJOSHADER_astDataType *vectype_from_base(Context *ctx,
+                                            const MOJOSHADER_astDataTypeType base,
+                                            const int len)
+{
+    assert(len > 0);
+    assert(len <= 4);
+
+    const char *typestr = NULL;
+    switch (base)
+    {
+        case MOJOSHADER_AST_DATATYPE_BOOL: typestr = "bool"; break;
+        case MOJOSHADER_AST_DATATYPE_INT: typestr = "int"; break;
+        case MOJOSHADER_AST_DATATYPE_UINT: typestr = "uint"; break;
+        case MOJOSHADER_AST_DATATYPE_HALF: typestr = "half"; break;
+        case MOJOSHADER_AST_DATATYPE_FLOAT: typestr = "float"; break;
+        case MOJOSHADER_AST_DATATYPE_DOUBLE: typestr = "double"; break;
+        default: assert(0 && "This shouldn't happen"); break;
+    } // switch
+
+    char buf[32];
+    snprintf(buf, sizeof (buf), "%s%d", typestr, len);
+    const MOJOSHADER_astDataType *datatype = get_usertype(ctx, buf);
+    assert(datatype != NULL);
+    return datatype;
+} // vectype_from_base
+
+
 // Go through the AST and make sure all datatypes check out okay. For datatypes
 //  that are compatible but are relying on an implicit cast, we add explicit
 //  casts to the AST here, so further processing doesn't have to worry about
@@ -2336,10 +2363,20 @@
         case MOJOSHADER_AST_OP_DEREF_ARRAY:
             datatype = type_check_ast(ctx, ast->binary.left);
             datatype2 = type_check_ast(ctx, ast->binary.right);
-            require_array_datatype(ctx, datatype);
             require_integer_datatype(ctx, datatype2);
             add_type_coercion(ctx, NULL, &ctx->dt_int, &ast->binary.right, datatype2);
-            ast->binary.datatype = array_element_datatype(ctx, datatype);
+
+            datatype = reduce_datatype(ctx, datatype);
+            if (datatype->type == MOJOSHADER_AST_DATATYPE_VECTOR)
+                ast->binary.datatype = datatype->vector.base;
+            else if (datatype->type == MOJOSHADER_AST_DATATYPE_MATRIX)
+                ast->binary.datatype = vectype_from_base(ctx, datatype->matrix.base->type, datatype->matrix.columns);  // !!! FIXME: rows?
+            else
+            {
+                require_array_datatype(ctx, datatype);
+                ast->binary.datatype = array_element_datatype(ctx, datatype);
+            } // else
+
             return ast->binary.datatype;
 
         case MOJOSHADER_AST_OP_DEREF_STRUCT:
@@ -2363,24 +2400,7 @@
 
                 const int swizlen = (int) strlen(member);
                 if (swizlen != veclen)
-                {
-                    const char *typestr = NULL;
-                    switch (reduced->vector.base->type)
-                    {
-                        case MOJOSHADER_AST_DATATYPE_BOOL: typestr = "bool"; break;
-                        case MOJOSHADER_AST_DATATYPE_INT: typestr = "int"; break;
-                        case MOJOSHADER_AST_DATATYPE_UINT: typestr = "uint"; break;
-                        case MOJOSHADER_AST_DATATYPE_HALF: typestr = "half"; break;
-                        case MOJOSHADER_AST_DATATYPE_FLOAT: typestr = "float"; break;
-                        case MOJOSHADER_AST_DATATYPE_DOUBLE: typestr = "double"; break;
-                        default: assert(0 && "This shouldn't happen"); break;
-                    } // switch
-
-                    char buf[32];
-                    snprintf(buf, sizeof (buf), "%s%d", typestr, swizlen);
-                    datatype = get_usertype(ctx, buf);
-                    assert(datatype != NULL);
-                } // if
+                    datatype = vectype_from_base(ctx, reduced->vector.base->type, swizlen);
 
                 ast->derefstruct.datatype = datatype;
                 return ast->derefstruct.datatype;