Add some matrix math tests
[mesa.git] / ast_function.cpp
index 2e0cbe9e132100a28d3f9bf8a697dfd47b1fce55..7082ed3c1402f92e35dd674943fb8ff5d1494114 100644 (file)
  */
 
 #include <cstdio>
-#include "symbol_table.h"
+#include "glsl_symbol_table.h"
 #include "ast.h"
 #include "glsl_types.h"
 #include "ir.h"
 
+static ir_instruction *
+match_function_by_name(exec_list *instructions, const char *name,
+                      YYLTYPE *loc, simple_node *parameters,
+                      struct _mesa_glsl_parse_state *state)
+{
+   ir_function *f = state->symbols->get_function(name);
+
+   if (f == NULL) {
+      _mesa_glsl_error(loc, state, "function `%s' undeclared", name);
+      return ir_call::get_error_instruction();
+   }
+
+   /* Once we've determined that the function being called might exist,
+    * process the parameters.
+    */
+   exec_list actual_parameters;
+   simple_node *const first = parameters;
+   if (first != NULL) {
+      simple_node *ptr = first;
+      do {
+        ir_instruction *const result =
+           ((ast_node *) ptr)->hir(instructions, state);
+        ptr = ptr->next;
+
+        actual_parameters.push_tail(result);
+      } while (ptr != first);
+   }
+
+   /* After processing the function's actual parameters, try to find an
+    * overload of the function that matches.
+    */
+   const ir_function_signature *sig =
+      f->matching_signature(& actual_parameters);
+   if (sig != NULL) {
+      /* FINISHME: The list of actual parameters needs to be modified to
+       * FINISHME: include any necessary conversions.
+       */
+      return new ir_call(sig, & actual_parameters);
+   } else {
+      /* FINISHME: Log a better error message here.  G++ will show the types
+       * FINISHME: of the actual parameters and the set of candidate
+       * FINISHME: functions.  A different error should also be logged when
+       * FINISHME: multiple functions match.
+       */
+      _mesa_glsl_error(loc, state, "no matching function for call to `%s'",
+                      name);
+      return ir_call::get_error_instruction();
+   }
+}
+
+
 ir_instruction *
 ast_function_expression::hir(exec_list *instructions,
                             struct _mesa_glsl_parse_state *state)
@@ -37,72 +88,43 @@ ast_function_expression::hir(exec_list *instructions,
     * 2. methods - Only the .length() method of array types.
     * 3. functions - Calls to regular old functions.
     *
-    * There are two kinds of constructor call.  Constructors for built-in
-    * language types, such as mat4 and vec2, are free form.  The only
-    * requirement is that the parameters must provide enough values of the
-    * correct scalar type.  Constructors for arrays and structures must have
-    * the exact number of parameters with matching types in the correct order.
-    * These constructors follow essentially the same type matching rules as
-    * functions.
-    *
     * Method calls are actually detected when the ast_field_selection
     * expression is handled.
     */
    if (is_constructor()) {
-      return ir_call::get_error_instruction();
-   } else {
-      const ast_expression *id = subexpressions[0];
+      const ast_type_specifier *type = (ast_type_specifier *) subexpressions[0];
+      YYLTYPE loc = type->get_location();
 
-      ir_function *f = (ir_function *)
-        _mesa_symbol_table_find_symbol(state->symbols, 0,
-                                       id->primary_expression.identifier);
+      const glsl_type *const constructor_type =
+        state->symbols->get_type(type->type_name);
 
-      if (f == NULL) {
-        YYLTYPE loc = id->get_location();
 
-        _mesa_glsl_error(& loc, state, "function `%s' undeclared",
-                         id->primary_expression.identifier);
+      /* Constructors for samplers are illegal.
+       */
+      if (constructor_type->is_sampler()) {
+        _mesa_glsl_error(& loc, state, "cannot construct sampler type `%s'",
+                         constructor_type->name);
         return ir_call::get_error_instruction();
       }
 
-      /* Once we've determined that the function being called might exist,
-       * process the parameters.
-       */
-      exec_list actual_parameters;
-      simple_node *const first = subexpressions[1];
-      if (first != NULL) {
-        simple_node *ptr = first;
-        do {
-           ir_instruction *const result =
-              ((ast_node *) ptr)->hir(instructions, state);
-           ptr = ptr->next;
-
-           actual_parameters.push_tail(result);
-        } while (ptr != first);
-      }
 
-      /* After processing the function's actual parameters, try to find an
-       * overload of the function that matches.
+      /* There are two kinds of constructor call.  Constructors for built-in
+       * language types, such as mat4 and vec2, are free form.  The only
+       * requirement is that the parameters must provide enough values of the
+       * correct scalar type.  Constructors for arrays and structures must
+       * have the exact number of parameters with matching types in the
+       * correct order.  These constructors follow essentially the same type
+       * matching rules as functions.
        */
-      const ir_function_signature *sig =
-        f->matching_signature(& actual_parameters);
-      if (sig != NULL) {
-        /* FINISHME: The list of actual parameters needs to be modified to
-         * FINISHME: include any necessary conversions.
-         */
-        return new ir_call(sig, & actual_parameters);
-      } else {
-        YYLTYPE loc = id->get_location();
-
-        /* FINISHME: Log a better error message here.  G++ will show the types
-         * FINISHME: of the actual parameters and the set of candidate
-         * FINISHME: functions.  A different error should also be logged when
-         * FINISHME: multiple functions match.
-         */
-        _mesa_glsl_error(& loc, state, "no matching function for call to `%s'",
-                         id->primary_expression.identifier);
-        return ir_call::get_error_instruction();
-      }
+
+      return ir_call::get_error_instruction();
+   } else {
+      const ast_expression *id = subexpressions[0];
+      YYLTYPE loc = id->get_location();
+
+      return match_function_by_name(instructions, 
+                                   id->primary_expression.identifier, & loc,
+                                   subexpressions[1], state);
    }
 
    return ir_call::get_error_instruction();