Initial implementation of constructor handling code

All of the scalar, vector, and matrix constructors *except* "from
bool" constructors should be handled.  Array and structure
constructors are also not yet handled.
diff --git a/ast_function.cpp b/ast_function.cpp
index f774a2f..6470057 100644
--- a/ast_function.cpp
+++ b/ast_function.cpp
@@ -78,6 +78,89 @@
 }
 
 
+/**
+ * Perform automatic type conversion of constructor parameters
+ */
+static ir_rvalue *
+convert_component(ir_rvalue *src, const glsl_type *desired_type)
+{
+   const unsigned a = desired_type->base_type;
+   const unsigned b = src->type->base_type;
+
+   if (src->type->is_error())
+      return src;
+
+   assert(a <= GLSL_TYPE_BOOL);
+   assert(b <= GLSL_TYPE_BOOL);
+
+   if ((a == b) || (src->type->is_integer() && desired_type->is_integer()))
+      return src;
+
+   switch (a) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+      if (b == GLSL_TYPE_FLOAT)
+	 return new ir_expression(ir_unop_f2i, desired_type, src, NULL);
+      else {
+	 assert(b == GLSL_TYPE_BOOL);
+	 assert(!"FINISHME: Convert bool to int / uint.");
+      }
+   case GLSL_TYPE_FLOAT:
+      switch (b) {
+      case GLSL_TYPE_UINT:
+	 return new ir_expression(ir_unop_u2f, desired_type, src, NULL);
+      case GLSL_TYPE_INT:
+	 return new ir_expression(ir_unop_i2f, desired_type, src, NULL);
+      case GLSL_TYPE_BOOL:
+	 assert(!"FINISHME: Convert bool to float.");
+      }
+      break;
+   case GLSL_TYPE_BOOL: {
+      int z = 0;
+      ir_constant *const zero = new ir_constant(src->type, &z);
+
+      return new ir_expression(ir_binop_nequal, desired_type, src, zero);
+   }
+   }
+
+   assert(!"Should not get here.");
+   return NULL;
+}
+
+
+/**
+ * Dereference a specific component from a scalar, vector, or matrix
+ */
+static ir_rvalue *
+dereference_component(ir_rvalue *src, unsigned component)
+{
+   assert(component < src->type->components());
+
+   if (src->type->is_scalar()) {
+      return src;
+   } else if (src->type->is_vector()) {
+      return new ir_swizzle(src, component, 0, 0, 0, 1);
+   } else {
+      assert(src->type->is_matrix());
+
+      /* Dereference a row of the matrix, then call this function again to get
+       * a specific element from that row.
+       */
+      const int c = component / src->type->column_type()->vector_elements;
+      const int r = component % src->type->column_type()->vector_elements;
+      ir_constant *const col_index = new ir_constant(glsl_type::int_type, &c);
+      ir_dereference *const col = new ir_dereference(src, col_index);
+
+      col->type = src->type->column_type();
+
+      return dereference_component(col, r);
+   }
+
+   assert(!"Should not get here.");
+   return NULL;
+}
+
+
 ir_rvalue *
 ast_function_expression::hir(exec_list *instructions,
 			     struct _mesa_glsl_parse_state *state)
@@ -116,6 +199,163 @@
        * correct order.  These constructors follow essentially the same type
        * matching rules as functions.
        */
+      if (constructor_type->is_numeric() || constructor_type->is_boolean()) {
+	 /* Constructing a numeric type has a couple steps.  First all values
+	  * passed to the constructor are broken into individual parameters
+	  * and type converted to the base type of the thing being constructed.
+	  *
+	  * At that point we have some number of values that match the base
+	  * type of the thing being constructed.  Now the constructor can be
+	  * treated like a function call.  Each numeric type has a small set
+	  * of constructor functions.  The set of new parameters will either
+	  * match one of those functions or the original constructor is
+	  * invalid.
+	  */
+	 const glsl_type *const base_type = constructor_type->get_base_type();
+
+	 /* Total number of components of the type being constructed.
+	  */
+	 const unsigned type_components = constructor_type->components();
+
+	 /* Number of components from parameters that have actually been
+	  * consumed.  This is used to perform several kinds of error checking.
+	  */
+	 unsigned components_used = 0;
+
+	 unsigned matrix_parameters = 0;
+	 unsigned nonmatrix_parameters = 0;
+	 exec_list actual_parameters;
+	 simple_node *const first = subexpressions[1];
+
+	 assert(first != NULL);
+
+	 if (first != NULL) {
+	    simple_node *ptr = first;
+	    do {
+	       ir_rvalue *const result =
+		  ((ast_node *) ptr)->hir(instructions, state)->as_rvalue();
+	       ptr = ptr->next;
+
+	       /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
+		*
+		*    "It is an error to provide extra arguments beyond this
+		*    last used argument."
+		*/
+	       if (components_used >= type_components) {
+		  _mesa_glsl_error(& loc, state, "too many parameters to `%s' "
+				   "constructor",
+				   constructor_type->name);
+		  return ir_call::get_error_instruction();
+	       }
+
+	       if (!result->type->is_numeric() && !result->type->is_boolean()) {
+		  _mesa_glsl_error(& loc, state, "cannot construct `%s' from a "
+				   "non-numeric data type",
+				   constructor_type->name);
+		  return ir_call::get_error_instruction();
+	       }
+
+	       /* Count the number of matrix and nonmatrix parameters.  This
+		* is used below to enforce some of the constructor rules.
+		*/
+	       if (result->type->is_matrix())
+		  matrix_parameters++;
+	       else
+		  nonmatrix_parameters++;
+
+
+	       /* Process each of the components of the parameter.  Dereference
+		* each component individually, perform any type conversions, and
+		* add it to the parameter list for the constructor.
+		*/
+	       for (unsigned i = 0; i < result->type->components(); i++) {
+		  if (components_used >= type_components)
+		     break;
+
+		  ir_rvalue *const component =
+		     convert_component(dereference_component(result, i),
+				       base_type);
+
+		  /* All cases that could result in component->type being the
+		   * error type should have already been caught above.
+		   */
+		  assert(component->type == base_type);
+
+		  /* Don't actually generate constructor calls for scalars.
+		   * Instead, do the usual component selection and conversion,
+		   * and return the single component.
+		   */
+		  if (constructor_type->is_scalar())
+		     return component;
+
+		  actual_parameters.push_tail(component);
+		  components_used++;
+	       }
+	    } while (ptr != first);
+	 }
+
+	 /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
+	  *
+	  *    "It is an error to construct matrices from other matrices. This
+	  *    is reserved for future use."
+	  */
+	 if ((state->language_version <= 110) && (matrix_parameters > 0)
+	     && constructor_type->is_matrix()) {
+	    _mesa_glsl_error(& loc, state, "cannot construct `%s' from a "
+			     "matrix in GLSL 1.10",
+			     constructor_type->name);
+	    return ir_call::get_error_instruction();
+	 }
+
+	 /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
+	  *
+	  *    "If a matrix argument is given to a matrix constructor, it is
+	  *    an error to have any other arguments."
+	  */
+	 if ((matrix_parameters > 0)
+	     && ((matrix_parameters + nonmatrix_parameters) > 1)
+	     && constructor_type->is_matrix()) {
+	    _mesa_glsl_error(& loc, state, "for matrix `%s' constructor, "
+			     "matrix must be only parameter",
+			     constructor_type->name);
+	    return ir_call::get_error_instruction();
+	 }
+
+	 /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
+	  *
+	  *    "In these cases, there must be enough components provided in the
+	  *    arguments to provide an initializer for every component in the
+	  *    constructed value."
+	  */
+	 if (components_used < type_components) {
+	    _mesa_glsl_error(& loc, state, "too few components to construct "
+			     "`%s'",
+			     constructor_type->name);
+	    return ir_call::get_error_instruction();
+	 }
+
+	 ir_function *f = state->symbols->get_function(constructor_type->name);
+	 if (f == NULL) {
+	    _mesa_glsl_error(& loc, state, "no constructor for type `%s'",
+			     constructor_type->name);
+	    return ir_call::get_error_instruction();
+	 }
+
+	 const ir_function_signature *sig =
+	    f->matching_signature(& actual_parameters);
+	 if (sig != NULL) {
+	    return new ir_call(sig, & actual_parameters);
+	 } else {
+	    /* FINISHME: Log a better error message here.  G++ will show the
+	     * FINSIHME: types of the actual parameters and the set of
+	     * FINSIHME: candidate functions.  A different error should also be
+	     * FINSIHME: logged when multiple functions match.
+	     */
+	    _mesa_glsl_error(& loc, state, "no matching constructor for `%s'",
+			     constructor_type->name);
+	    return ir_call::get_error_instruction();
+	 }
+      }
 
       return ir_call::get_error_instruction();
    } else {