text:
#include <stdio.h>
#include "main/macros.h"
#include "compiler/glsl/glsl_parser_extras.h"
#include "glsl_types.h"
#include "util/hash_table.h"

mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP;
hash_table *glsl_type::array_types = NULL;
hash_table *glsl_type::record_types = NULL;
hash_table *glsl_type::interface_types = NULL;
hash_table *glsl_type::function_types = NULL;
hash_table *glsl_type::subroutine_types = NULL;
void *glsl_type::mem_ctx = NULL;

void
glsl_type::init_ralloc_type_ctx(void)
{
   if (glsl_type::mem_ctx == NULL) {
      glsl_type::mem_ctx = ralloc_context(NULL);
      assert(glsl_type::mem_ctx != NULL);
   }
}

glsl_type::glsl_type(GLenum gl_type,
                     glsl_base_type base_type, unsigned vector_elements,
                     unsigned matrix_columns, const char *name) :
   gl_type(gl_type),
   base_type(base_type),
   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
   sampled_type(0), interface_packing(0), interface_row_major(0),
   vector_elements(vector_elements), matrix_columns(matrix_columns),
   length(0)
{
   /* Values of these types must fit in the two bits of
    * glsl_type::sampled_type.
    */
   STATIC_ASSERT((unsigned(GLSL_TYPE_UINT)  & 3) == unsigned(GLSL_TYPE_UINT));
   STATIC_ASSERT((unsigned(GLSL_TYPE_INT)   & 3) == unsigned(GLSL_TYPE_INT));
   STATIC_ASSERT((unsigned(GLSL_TYPE_FLOAT) & 3) == unsigned(GLSL_TYPE_FLOAT));

   mtx_lock(&glsl_type::mutex);

   init_ralloc_type_ctx();
   assert(name != NULL);
   this->name = ralloc_strdup(this->mem_ctx, name);

   mtx_unlock(&glsl_type::mutex);

   /* Neither dimension is zero or both dimensions are zero.
    */
   assert((vector_elements == 0) == (matrix_columns == 0));
   memset(& fields, 0, sizeof(fields));
}

glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type,
                     enum glsl_sampler_dim dim, bool shadow, bool array,
                     unsigned type, const char *name) :
   gl_type(gl_type),
   base_type(base_type),
   sampler_dimensionality(dim), sampler_shadow(shadow),
   sampler_array(array), sampled_type(type), interface_packing(0),
   interface_row_major(0), length(0)
{
   mtx_lock(&glsl_type::mutex);

   init_ralloc_type_ctx();
   assert(name != NULL);
   this->name = ralloc_strdup(this->mem_ctx, name);

   mtx_unlock(&glsl_type::mutex);

   memset(& fields, 0, sizeof(fields));

   if (is_sampler()) {
      /* Samplers take no storage whatsoever. */
      matrix_columns = vector_elements = 0;
   } else {
      matrix_columns = vector_elements = 1;
   }
}

glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
                     const char *name) :
   gl_type(0),
   base_type(GLSL_TYPE_STRUCT),
   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
   sampled_type(0), interface_packing(0), interface_row_major(0),
   vector_elements(0), matrix_columns(0),
   length(num_fields)
{
   unsigned int i;

   mtx_lock(&glsl_type::mutex);

   init_ralloc_type_ctx();
   assert(name != NULL);
   this->name = ralloc_strdup(this->mem_ctx, name);
   this->fields.structure = ralloc_array(this->mem_ctx,
                                         glsl_struct_field, length);

   for (i = 0; i < length; i++) {
      this->fields.structure[i] = fields[i];
      this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
                                                     fields[i].name);
   }

   mtx_unlock(&glsl_type::mutex);
}

glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
                     enum glsl_interface_packing packing,
                     bool row_major, const char *name) :
   gl_type(0),
   base_type(GLSL_TYPE_INTERFACE),
   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
   sampled_type(0), interface_packing((unsigned) packing),
   interface_row_major((unsigned) row_major),
   vector_elements(0), matrix_columns(0),
   length(num_fields)
{
   unsigned int i;

   mtx_lock(&glsl_type::mutex);

   init_ralloc_type_ctx();
   assert(name != NULL);
   this->name = ralloc_strdup(this->mem_ctx, name);
   this->fields.structure = rzalloc_array(this->mem_ctx,
                                          glsl_struct_field, length);
   for (i = 0; i < length; i++) {
      this->fields.structure[i] = fields[i];
      this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
                                                     fields[i].name);
   }

   mtx_unlock(&glsl_type::mutex);
}

glsl_type::glsl_type(const glsl_type *return_type,
                     const glsl_function_param *params, unsigned num_params) :
   gl_type(0),
   base_type(GLSL_TYPE_FUNCTION),
   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
   sampled_type(0), interface_packing(0), interface_row_major(0),
   vector_elements(0), matrix_columns(0),
   length(num_params)
{
   unsigned int i;

   mtx_lock(&glsl_type::mutex);

   init_ralloc_type_ctx();

   this->fields.parameters = rzalloc_array(this->mem_ctx,
                                           glsl_function_param, num_params + 1);

   /* We store the return type as the first parameter */
   this->fields.parameters[0].type = return_type;
   this->fields.parameters[0].in = false;
   this->fields.parameters[0].out = true;

   /* We store the i'th parameter in slot i+1 */
   for (i = 0; i < length; i++) {
      this->fields.parameters[i + 1].type = params[i].type;
      this->fields.parameters[i + 1].in = params[i].in;
      this->fields.parameters[i + 1].out = params[i].out;
   }

   mtx_unlock(&glsl_type::mutex);
}

glsl_type::glsl_type(const char *subroutine_name) :
   gl_type(0),
   base_type(GLSL_TYPE_SUBROUTINE),
   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
   sampled_type(0), interface_packing(0), interface_row_major(0),
   vector_elements(1), matrix_columns(1),
   length(0)
{
   mtx_lock(&glsl_type::mutex);

   init_ralloc_type_ctx();
   assert(subroutine_name != NULL);
   this->name = ralloc_strdup(this->mem_ctx, subroutine_name);
   mtx_unlock(&glsl_type::mutex);
}

bool
glsl_type::contains_sampler() const
{
   if (this->is_array()) {
      return this->fields.array->contains_sampler();
   } else if (this->is_record() || this->is_interface()) {
      for (unsigned int i = 0; i < this->length; i++) {
         if (this->fields.structure[i].type->contains_sampler())
            return true;
      }
      return false;
   } else {
      return this->is_sampler();
   }
}

bool
glsl_type::contains_integer() const
{
   if (this->is_array()) {
      return this->fields.array->contains_integer();
   } else if (this->is_record() || this->is_interface()) {
      for (unsigned int i = 0; i < this->length; i++) {
         if (this->fields.structure[i].type->contains_integer())
            return true;
      }
      return false;
   } else {
      return this->is_integer();
   }
}

bool
glsl_type::contains_double() const
{
   if (this->is_array()) {
      return this->fields.array->contains_double();
   } else if (this->is_record() || this->is_interface()) {
      for (unsigned int i = 0; i < this->length; i++) {
         if (this->fields.structure[i].type->contains_double())
            return true;
      }
      return false;
   } else {
      return this->is_double();
   }
}

bool
glsl_type::contains_opaque() const {
   switch (base_type) {
   case GLSL_TYPE_SAMPLER:
   case GLSL_TYPE_IMAGE:
   case GLSL_TYPE_ATOMIC_UINT:
      return true;
   case GLSL_TYPE_ARRAY:
      return fields.array->contains_opaque();
   case GLSL_TYPE_STRUCT:
   case GLSL_TYPE_INTERFACE:
      for (unsigned int i = 0; i < length; i++) {
         if (fields.structure[i].type->contains_opaque())
            return true;
      }
      return false;
   default:
      return false;
   }
}

bool
glsl_type::contains_subroutine() const
{
   if (this->is_array()) {
      return this->fields.array->contains_subroutine();
   } else if (this->is_record() || this->is_interface()) {
      for (unsigned int i = 0; i < this->length; i++) {
         if (this->fields.structure[i].type->contains_subroutine())
            return true;
      }
      return false;
   } else {
      return this->is_subroutine();
   }
}

gl_texture_index
glsl_type::sampler_index() const
{
   const glsl_type *const t = (this->is_array()) ? this->fields.array : this;

   assert(t->is_sampler() || t->is_image());

   switch (t->sampler_dimensionality) {
   case GLSL_SAMPLER_DIM_1D:
      return (t->sampler_array) ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX;
   case GLSL_SAMPLER_DIM_2D:
      return (t->sampler_array) ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX;
   case GLSL_SAMPLER_DIM_3D:
      return TEXTURE_3D_INDEX;
   case GLSL_SAMPLER_DIM_CUBE:
      return (t->sampler_array) ? TEXTURE_CUBE_ARRAY_INDEX : TEXTURE_CUBE_INDEX;
   case GLSL_SAMPLER_DIM_RECT:
      return TEXTURE_RECT_INDEX;
   case GLSL_SAMPLER_DIM_BUF:
      return TEXTURE_BUFFER_INDEX;
   case GLSL_SAMPLER_DIM_EXTERNAL:
      return TEXTURE_EXTERNAL_INDEX;
   case GLSL_SAMPLER_DIM_MS:
      return (t->sampler_array) ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX : TEXTURE_2D_MULTISAMPLE_INDEX;
   default:
      assert(!"Should not get here.");
      return TEXTURE_BUFFER_INDEX;
   }
}

bool
glsl_type::contains_image() const
{
   if (this->is_array()) {
      return this->fields.array->contains_image();
   } else if (this->is_record() || this->is_interface()) {
      for (unsigned int i = 0; i < this->length; i++) {
         if (this->fields.structure[i].type->contains_image())
            return true;
      }
      return false;
   } else {
      return this->is_image();
   }
}

const glsl_type *glsl_type::get_base_type() const
{
   switch (base_type) {
   case GLSL_TYPE_UINT:
      return uint_type;
   case GLSL_TYPE_INT:
      return int_type;
   case GLSL_TYPE_FLOAT:
      return float_type;
   case GLSL_TYPE_DOUBLE:
      return double_type;
   case GLSL_TYPE_BOOL:
      return bool_type;
   case GLSL_TYPE_UINT64:
      return uint64_t_type;
   case GLSL_TYPE_INT64:
      return int64_t_type;
   default:
      return error_type;
   }
}

const glsl_type *glsl_type::get_scalar_type() const
{
   const glsl_type *type = this;

   /* Handle arrays */
   while (type->base_type == GLSL_TYPE_ARRAY)
      type = type->fields.array;

   /* Handle vectors and matrices */
   switch (type->base_type) {
   case GLSL_TYPE_UINT:
      return uint_type;
   case GLSL_TYPE_INT:
      return int_type;
   case GLSL_TYPE_FLOAT:
      return float_type;
   case GLSL_TYPE_DOUBLE:
      return double_type;
   case GLSL_TYPE_BOOL:
      return bool_type;
   case GLSL_TYPE_UINT64:
      return uint64_t_type;
   case GLSL_TYPE_INT64:
      return int64_t_type;
   default:
      /* Handle everything else */
      return type;
   }
}

void
_mesa_glsl_release_types(void)
{
   /* Should only be called during atexit (either when unloading shared
    * object, or if process terminates), so no mutex-locking should be
    * necessary.
    */
   if (glsl_type::array_types != NULL) {
      _mesa_hash_table_destroy(glsl_type::array_types, NULL);
      glsl_type::array_types = NULL;
   }

   if (glsl_type::record_types != NULL) {
      _mesa_hash_table_destroy(glsl_type::record_types, NULL);
      glsl_type::record_types = NULL;
   }

   if (glsl_type::interface_types != NULL) {
      _mesa_hash_table_destroy(glsl_type::interface_types, NULL);
      glsl_type::interface_types = NULL;
   }

   ralloc_free(glsl_type::mem_ctx);
   glsl_type::mem_ctx = NULL;
}

glsl_type::glsl_type(const glsl_type *array, unsigned length) :
   base_type(GLSL_TYPE_ARRAY),
   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
   sampled_type(0), interface_packing(0), interface_row_major(0),
   vector_elements(0), matrix_columns(0),
   length(length), name(NULL)
{
   this->fields.array = array;
   /* Inherit the gl type of the base. The GL type is used for
    * uniform/statevar handling in Mesa and the arrayness of the type
    * is represented by the size rather than the type.
    */
   this->gl_type = array->gl_type;

   /* Allow a maximum of 10 characters for the array size.  This is enough
    * for 32-bits of ~0.  The extra 3 are for the '[', ']', and terminating
    * NUL.
    */
   const unsigned name_length = strlen(array->name) + 10 + 3;

   mtx_lock(&glsl_type::mutex);
   char *const n = (char *) ralloc_size(this->mem_ctx, name_length);
   mtx_unlock(&glsl_type::mutex);

   if (length == 0)
      snprintf(n, name_length, "%s[]", array->name);
   else {
      /* insert outermost dimensions in the correct spot
       * otherwise the dimension order will be backwards
       */
      const char *pos = strchr(array->name, '[');
      if (pos) {
         int idx = pos - array->name;
         snprintf(n, idx+1, "%s", array->name);
         snprintf(n + idx, name_length - idx, "[%u]%s",
                  length, array->name + idx);
      } else {
         snprintf(n, name_length, "%s[%u]", array->name, length);
      }
   }

   this->name = n;
}

const glsl_type *
glsl_type::vec(unsigned components)
{
   if (components == 0 || components > 4)
      return error_type;

   static const glsl_type *const ts[] = {
      float_type, vec2_type, vec3_type, vec4_type
   };
   return ts[components - 1];
}

const glsl_type *
glsl_type::dvec(unsigned components)
{
   if (components == 0 || components > 4)
      return error_type;

   static const glsl_type *const ts[] = {
      double_type, dvec2_type, dvec3_type, dvec4_type
   };
   return ts[components - 1];
}

const glsl_type *
glsl_type::ivec(unsigned components)
{
   if (components == 0 || components > 4)
      return error_type;

   static const glsl_type *const ts[] = {
      int_type, ivec2_type, ivec3_type, ivec4_type
   };
   return ts[components - 1];
}

const glsl_type *
glsl_type::uvec(unsigned components)
{
   if (components == 0 || components > 4)
      return error_type;

   static const glsl_type *const ts[] = {
      uint_type, uvec2_type, uvec3_type, uvec4_type
   };
   return ts[components - 1];
}

const glsl_type *
glsl_type::bvec(unsigned components)
{
   if (components == 0 || components > 4)
      return error_type;

   static const glsl_type *const ts[] = {
      bool_type, bvec2_type, bvec3_type, bvec4_type
   };
   return ts[components - 1];
}

const glsl_type *
glsl_type::i64vec(unsigned components)
{
   if (components == 0 || components > 4)
      return error_type;

   static const glsl_type *const ts[] = {
      int64_t_type, i64vec2_type, i64vec3_type, i64vec4_type
   };
   return ts[components - 1];
}

const glsl_type *
glsl_type::u64vec(unsigned components)
{
   if (components == 0 || components > 4)
      return error_type;

   static const glsl_type *const ts[] = {
      uint64_t_type, u64vec2_type, u64vec3_type, u64vec4_type
   };
   return ts[components - 1];
}

const glsl_type *
glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
{
   if (base_type == GLSL_TYPE_VOID)
      return void_type;

   if ((rows < 1) || (rows > 4) || (columns < 1) || (columns > 4))
      return error_type;

   /* Treat GLSL vectors as Nx1 matrices.
    */
   if (columns == 1) {
      switch (base_type) {
      case GLSL_TYPE_UINT:
         return uvec(rows);
      case GLSL_TYPE_INT:
         return ivec(rows);
      case GLSL_TYPE_FLOAT:
         return vec(rows);
      case GLSL_TYPE_DOUBLE:
         return dvec(rows);
      case GLSL_TYPE_BOOL:
         return bvec(rows);
      case GLSL_TYPE_UINT64:
         return u64vec(rows);
      case GLSL_TYPE_INT64:
         return i64vec(rows);
      default:
         return error_type;
      }
   } else {
      if ((base_type != GLSL_TYPE_FLOAT && base_type != GLSL_TYPE_DOUBLE) || (rows == 1))
         return error_type;

      /* GLSL matrix types are named mat{COLUMNS}x{ROWS}.  Only the following
       * combinations are valid:
       *
       *   1 2 3 4
       * 1
       * 2   x x x
       * 3   x x x
       * 4   x x x
       */
#define IDX(c,r) (((c-1)*3) + (r-1))

      if (base_type == GLSL_TYPE_DOUBLE) {
         switch (IDX(columns, rows)) {
         case IDX(2,2): return dmat2_type;
         case IDX(2,3): return dmat2x3_type;
         case IDX(2,4): return dmat2x4_type;
         case IDX(3,2): return dmat3x2_type;
         case IDX(3,3): return dmat3_type;
         case IDX(3,4): return dmat3x4_type;
         case IDX(4,2): return dmat4x2_type;
         case IDX(4,3): return dmat4x3_type;
         case IDX(4,4): return dmat4_type;
         default: return error_type;
         }
      } else {
         switch (IDX(columns, rows)) {
         case IDX(2,2): return mat2_type;
         case IDX(2,3): return mat2x3_type;
         case IDX(2,4): return mat2x4_type;
         case IDX(3,2): return mat3x2_type;
         case IDX(3,3): return mat3_type;
         case IDX(3,4): return mat3x4_type;
         case IDX(4,2): return mat4x2_type;
         case IDX(4,3): return mat4x3_type;
         case IDX(4,4): return mat4_type;
         default: return error_type;
         }
      }
   }

   assert(!"Should not get here.");
   return error_type;
}

const glsl_type *
glsl_type::get_sampler_instance(enum glsl_sampler_dim dim,
                                bool shadow,
                                bool array,
                                glsl_base_type type)
{
   switch (type) {
   case GLSL_TYPE_FLOAT:
      switch (dim) {
      case GLSL_SAMPLER_DIM_1D:
         if (shadow)
            return (array ? sampler1DArrayShadow_type : sampler1DShadow_type);
         else
            return (array ? sampler1DArray_type : sampler1D_type);
      case GLSL_SAMPLER_DIM_2D:
         if (shadow)
            return (array ? sampler2DArrayShadow_type : sampler2DShadow_type);
         else
            return (array ? sampler2DArray_type : sampler2D_type);
      case GLSL_SAMPLER_DIM_3D:
         if (shadow || array)
            return error_type;
         else
            return sampler3D_type;
      case GLSL_SAMPLER_DIM_CUBE:
         if (shadow)
            return (array ? samplerCubeArrayShadow_type : samplerCubeShadow_type);
         else
            return (array ? samplerCubeArray_type : samplerCube_type);
      case GLSL_SAMPLER_DIM_RECT:
         if (array)
            return error_type;
         if (shadow)
            return sampler2DRectShadow_type;
         else
            return sampler2DRect_type;
      case GLSL_SAMPLER_DIM_BUF:
         if (shadow || array)
            return error_type;
         else
            return samplerBuffer_type;
      case GLSL_SAMPLER_DIM_MS:
         if (shadow)
            return error_type;
         return (array ? sampler2DMSArray_type : sampler2DMS_type);
      case GLSL_SAMPLER_DIM_EXTERNAL:
         if (shadow || array)
            return error_type;
         else
            return samplerExternalOES_type;
      case GLSL_SAMPLER_DIM_SUBPASS:
      case GLSL_SAMPLER_DIM_SUBPASS_MS:
         return error_type;
      }
   case GLSL_TYPE_INT:
      if (shadow)
         return error_type;
      switch (dim) {
      case GLSL_SAMPLER_DIM_1D:
         return (array ? isampler1DArray_type : isampler1D_type);
      case GLSL_SAMPLER_DIM_2D:
         return (array ? isampler2DArray_type : isampler2D_type);
      case GLSL_SAMPLER_DIM_3D:
         if (array)
            return error_type;
         return isampler3D_type;
      case GLSL_SAMPLER_DIM_CUBE:
         return (array ? isamplerCubeArray_type : isamplerCube_type);
      case GLSL_SAMPLER_DIM_RECT:
         if (array)
            return error_type;
         return isampler2DRect_type;
      case GLSL_SAMPLER_DIM_BUF:
         if (array)
            return error_type;
         return isamplerBuffer_type;
      case GLSL_SAMPLER_DIM_MS:
         return (array ? isampler2DMSArray_type : isampler2DMS_type);
      case GLSL_SAMPLER_DIM_EXTERNAL:
         return error_type;
      case GLSL_SAMPLER_DIM_SUBPASS:
      case GLSL_SAMPLER_DIM_SUBPASS_MS:
         return error_type;
      }
   case GLSL_TYPE_UINT:
      if (shadow)
         return error_type;
      switch (dim) {
      case GLSL_SAMPLER_DIM_1D:
         return (array ? usampler1DArray_type : usampler1D_type);
      case GLSL_SAMPLER_DIM_2D:
         return (array ? usampler2DArray_type : usampler2D_type);
      case GLSL_SAMPLER_DIM_3D:
         if (array)
            return error_type;
         return usampler3D_type;
      case GLSL_SAMPLER_DIM_CUBE:
         return (array ? usamplerCubeArray_type : usamplerCube_type);
      case GLSL_SAMPLER_DIM_RECT:
         if (array)
            return error_type;
         return usampler2DRect_type;
      case GLSL_SAMPLER_DIM_BUF:
         if (array)
            return error_type;
         return usamplerBuffer_type;
      case GLSL_SAMPLER_DIM_MS:
         return (array ? usampler2DMSArray_type : usampler2DMS_type);
      case GLSL_SAMPLER_DIM_EXTERNAL:
         return error_type;
      case GLSL_SAMPLER_DIM_SUBPASS:
      case GLSL_SAMPLER_DIM_SUBPASS_MS:
         return error_type;
      }
   default:
      return error_type;
   }

   unreachable("switch statement above should be complete");
}

const glsl_type *
glsl_type::get_image_instance(enum glsl_sampler_dim dim,
                              bool array, glsl_base_type type)
{
   switch (type) {
   case GLSL_TYPE_FLOAT:
      switch (dim) {
      case GLSL_SAMPLER_DIM_1D:
         return (array ? image1DArray_type : image1D_type);
      case GLSL_SAMPLER_DIM_2D:
         return (array ? image2DArray_type : image2D_type);
      case GLSL_SAMPLER_DIM_3D:
         return image3D_type;
      case GLSL_SAMPLER_DIM_CUBE:
         return (array ? imageCubeArray_type : imageCube_type);
      case GLSL_SAMPLER_DIM_RECT:
         if (array)
            return error_type;
         else
            return image2DRect_type;
      case GLSL_SAMPLER_DIM_BUF:
         if (array)
            return error_type;
         else
            return imageBuffer_type;
      case GLSL_SAMPLER_DIM_MS:
         return (array ? image2DMSArray_type : image2DMS_type);
      case GLSL_SAMPLER_DIM_SUBPASS:
         return subpassInput_type;
      case GLSL_SAMPLER_DIM_SUBPASS_MS:
         return subpassInputMS_type;
      case GLSL_SAMPLER_DIM_EXTERNAL:
         return error_type;
      }
   case GLSL_TYPE_INT:
      switch (dim) {
      case GLSL_SAMPLER_DIM_1D:
         return (array ? iimage1DArray_type : iimage1D_type);
      case GLSL_SAMPLER_DIM_2D:
         return (array ? iimage2DArray_type : iimage2D_type);
      case GLSL_SAMPLER_DIM_3D:
         if (array)
            return error_type;
         return iimage3D_type;
      case GLSL_SAMPLER_DIM_CUBE:
         return (array ? iimageCubeArray_type : iimageCube_type);
      case GLSL_SAMPLER_DIM_RECT:
         if (array)
            return error_type;
         return iimage2DRect_type;
      case GLSL_SAMPLER_DIM_BUF:
         if (array)
            return error_type;
         return iimageBuffer_type;
      case GLSL_SAMPLER_DIM_MS:
         return (array ? iimage2DMSArray_type : iimage2DMS_type);
      case GLSL_SAMPLER_DIM_SUBPASS:
         return isubpassInput_type;
      case GLSL_SAMPLER_DIM_SUBPASS_MS:
         return isubpassInputMS_type;
      case GLSL_SAMPLER_DIM_EXTERNAL:
         return error_type;
      }
   case GLSL_TYPE_UINT:
      switch (dim) {
      case GLSL_SAMPLER_DIM_1D:
         return (array ? uimage1DArray_type : uimage1D_type);
      case GLSL_SAMPLER_DIM_2D:
         return (array ? uimage2DArray_type : uimage2D_type);
      case GLSL_SAMPLER_DIM_3D:
         if (array)
            return error_type;
         return uimage3D_type;
      case GLSL_SAMPLER_DIM_CUBE:
         return (array ? uimageCubeArray_type : uimageCube_type);
      case GLSL_SAMPLER_DIM_RECT:
         if (array)
            return error_type;
         return uimage2DRect_type;
      case GLSL_SAMPLER_DIM_BUF:
         if (array)
            return error_type;
         return uimageBuffer_type;
      case GLSL_SAMPLER_DIM_MS:
         return (array ? uimage2DMSArray_type : uimage2DMS_type);
      case GLSL_SAMPLER_DIM_SUBPASS:
         return usubpassInput_type;
      case GLSL_SAMPLER_DIM_SUBPASS_MS:
         return usubpassInputMS_type;
      case GLSL_SAMPLER_DIM_EXTERNAL:
         return error_type;
      }
   default:
      return error_type;
   }

   unreachable("switch statement above should be complete");
}

const glsl_type *
glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
{
   /* Generate a name using the base type pointer in the key.  This is
    * done because the name of the base type may not be unique across
    * shaders.  For example, two shaders may have different record types
    * named 'foo'.
    */
   char key[128];
   snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size);

   mtx_lock(&glsl_type::mutex);

   if (array_types == NULL) {
      array_types = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
                                            _mesa_key_string_equal);
   }

   const struct hash_entry *entry = _mesa_hash_table_search(array_types, key);
   if (entry == NULL) {
      mtx_unlock(&glsl_type::mutex);
      const glsl_type *t = new glsl_type(base, array_size);
      mtx_lock(&glsl_type::mutex);

      entry = _mesa_hash_table_insert(array_types,
                                      ralloc_strdup(mem_ctx, key),
                                      (void *) t);
   }

   assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_ARRAY);
   assert(((glsl_type *) entry->data)->length == array_size);
   assert(((glsl_type *) entry->data)->fields.array == base);

   mtx_unlock(&glsl_type::mutex);

   return (glsl_type *) entry->data;
}

bool
glsl_type::record_compare(const glsl_type *b, bool match_locations) const
{
   if (this->length != b->length)
      return false;

   if (this->interface_packing != b->interface_packing)
      return false;

   if (this->interface_row_major != b->interface_row_major)
      return false;

   /* From the GLSL 4.20 specification (Sec 4.2):
    *
    *     "Structures must have the same name, sequence of type names, and
    *     type definitions, and field names to be considered the same type."
    *
    * GLSL ES behaves the same (Ver 1.00 Sec 4.2.4, Ver 3.00 Sec 4.2.5).
    *
    * Note that we cannot force type name check when comparing unnamed
    * structure types, these have a unique name assigned during parsing.
    */
   if (!this->is_anonymous() && !b->is_anonymous())
      if (strcmp(this->name, b->name) != 0)
         return false;

   for (unsigned i = 0; i < this->length; i++) {
      if (this->fields.structure[i].type != b->fields.structure[i].type)
         return false;
      if (strcmp(this->fields.structure[i].name,
                 b->fields.structure[i].name) != 0)
         return false;
      if (this->fields.structure[i].matrix_layout
         != b->fields.structure[i].matrix_layout)
        return false;
      if (match_locations && this->fields.structure[i].location
          != b->fields.structure[i].location)
         return false;
      if (this->fields.structure[i].offset
          != b->fields.structure[i].offset)
         return false;
      if (this->fields.structure[i].interpolation
          != b->fields.structure[i].interpolation)
         return false;
      if (this->fields.structure[i].centroid
          != b->fields.structure[i].centroid)
         return false;
      if (this->fields.structure[i].sample
          != b->fields.structure[i].sample)
         return false;
      if (this->fields.structure[i].patch
          != b->fields.structure[i].patch)
         return false;
      if (this->fields.structure[i].image_read_only
          != b->fields.structure[i].image_read_only)
         return false;
      if (this->fields.structure[i].image_write_only
          != b->fields.structure[i].image_write_only)
         return false;
      if (this->fields.structure[i].image_coherent
          != b->fields.structure[i].image_coherent)
         return false;
      if (this->fields.structure[i].image_volatile
          != b->fields.structure[i].image_volatile)
         return false;
      if (this->fields.structure[i].image_restrict
          != b->fields.structure[i].image_restrict)
         return false;
      if (this->fields.structure[i].precision
          != b->fields.structure[i].precision)
         return false;
      if (this->fields.structure[i].explicit_xfb_buffer
          != b->fields.structure[i].explicit_xfb_buffer)
         return false;
      if (this->fields.structure[i].xfb_buffer
          != b->fields.structure[i].xfb_buffer)
         return false;
      if (this->fields.structure[i].xfb_stride
          != b->fields.structure[i].xfb_stride)
         return false;
   }

   return true;
}

bool
glsl_type::record_key_compare(const void *a, const void *b)
{
   const glsl_type *const key1 = (glsl_type *) a;
   const glsl_type *const key2 = (glsl_type *) b;

   return strcmp(key1->name, key2->name) == 0 && key1->record_compare(key2);
}

/**
 * Generate an integer hash value for a glsl_type structure type.
 */
unsigned
glsl_type::record_key_hash(const void *a)
{
   const glsl_type *const key = (glsl_type *) a;
   uintptr_t hash = key->length;
   unsigned retval;

   for (unsigned i = 0; i < key->length; i++) {
      /* casting pointer to uintptr_t */
      hash = (hash * 13 ) + (uintptr_t) key->fields.structure[i].type;
   }

   if (sizeof(hash) == 8)
      retval = (hash & 0xffffffff) ^ ((uint64_t) hash >> 32);
   else
      retval = hash;

   return retval;
}

const glsl_type *
glsl_type::get_record_instance(const glsl_struct_field *fields,
                               unsigned num_fields,
                               const char *name)
{
   const glsl_type key(fields, num_fields, name);

   mtx_lock(&glsl_type::mutex);

   if (record_types == NULL) {
      record_types = _mesa_hash_table_create(NULL, record_key_hash,
                                             record_key_compare);
   }

   const struct hash_entry *entry = _mesa_hash_table_search(record_types,
                                                            &key);
   if (entry == NULL) {
      mtx_unlock(&glsl_type::mutex);
      const glsl_type *t = new glsl_type(fields, num_fields, name);
      mtx_lock(&glsl_type::mutex);

      entry = _mesa_hash_table_insert(record_types, t, (void *) t);
   }

   assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_STRUCT);
   assert(((glsl_type *) entry->data)->length == num_fields);
   assert(strcmp(((glsl_type *) entry->data)->name, name) == 0);

   mtx_unlock(&glsl_type::mutex);

   return (glsl_type *) entry->data;
}

const glsl_type *
glsl_type::get_interface_instance(const glsl_struct_field *fields,
                                  unsigned num_fields,
                                  enum glsl_interface_packing packing,
                                  bool row_major,
                                  const char *block_name)
{
   const glsl_type key(fields, num_fields, packing, row_major, block_name);

   mtx_lock(&glsl_type::mutex);

   if (interface_types == NULL) {
      interface_types = _mesa_hash_table_create(NULL, record_key_hash,
                                                record_key_compare);
   }

   const struct hash_entry *entry = _mesa_hash_table_search(interface_types,
                                                            &key);
   if (entry == NULL) {
      mtx_unlock(&glsl_type::mutex);
      const glsl_type *t = new glsl_type(fields, num_fields,
                                         packing, row_major, block_name);
      mtx_lock(&glsl_type::mutex);

      entry = _mesa_hash_table_insert(interface_types, t, (void *) t);
   }

   assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_INTERFACE);
   assert(((glsl_type *) entry->data)->length == num_fields);
   assert(strcmp(((glsl_type *) entry->data)->name, block_name) == 0);

   mtx_unlock(&glsl_type::mutex);

   return (glsl_type *) entry->data;
}

const glsl_type *
glsl_type::get_subroutine_instance(const char *subroutine_name)
{
   const glsl_type key(subroutine_name);

   mtx_lock(&glsl_type::mutex);

   if (subroutine_types == NULL) {
      subroutine_types = _mesa_hash_table_create(NULL, record_key_hash,
                                                 record_key_compare);
   }

   const struct hash_entry *entry = _mesa_hash_table_search(subroutine_types,
                                                            &key);
   if (entry == NULL) {
      mtx_unlock(&glsl_type::mutex);
      const glsl_type *t = new glsl_type(subroutine_name);
      mtx_lock(&glsl_type::mutex);

      entry = _mesa_hash_table_insert(subroutine_types, t, (void *) t);
   }

   assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_SUBROUTINE);
   assert(strcmp(((glsl_type *) entry->data)->name, subroutine_name) == 0);

   mtx_unlock(&glsl_type::mutex);

   return (glsl_type *) entry->data;
}

static bool
function_key_compare(const void *a, const void *b)
{
   const glsl_type *const key1 = (glsl_type *) a;
   const glsl_type *const key2 = (glsl_type *) b;

   if (key1->length != key2->length)
      return false;

   return memcmp(key1->fields.parameters, key2->fields.parameters,
                 (key1->length + 1) * sizeof(*key1->fields.parameters)) == 0;
}

static uint32_t
function_key_hash(const void *a)
{
   const glsl_type *const key = (glsl_type *) a;
   return _mesa_hash_data(key->fields.parameters,
                          (key->length + 1) * sizeof(*key->fields.parameters));
}

const glsl_type *
glsl_type::get_function_instance(const glsl_type *return_type,
                                 const glsl_function_param *params,
                                 unsigned num_params)
{
   const glsl_type key(return_type, params, num_params);

   mtx_lock(&glsl_type::mutex);

   if (function_types == NULL) {
      function_types = _mesa_hash_table_create(NULL, function_key_hash,
                                               function_key_compare);
   }

   struct hash_entry *entry = _mesa_hash_table_search(function_types, &key);
   if (entry == NULL) {
      mtx_unlock(&glsl_type::mutex);
      const glsl_type *t = new glsl_type(return_type, params, num_params);
      mtx_lock(&glsl_type::mutex);

      entry = _mesa_hash_table_insert(function_types, t, (void *) t);
   }

   const glsl_type *t = (const glsl_type *)entry->data;

   assert(t->base_type == GLSL_TYPE_FUNCTION);
   assert(t->length == num_params);

   mtx_unlock(&glsl_type::mutex);

   return t;
}

const glsl_type *
glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
{
   if (type_a == type_b) {
      return type_a;
   } else if (type_a->is_matrix() && type_b->is_matrix()) {
      /* Matrix multiply.  The columns of A must match the rows of B.  Given
       * the other previously tested constraints, this means the vector type
       * of a row from A must be the same as the vector type of a column from
       * B.
       */
      if (type_a->row_type() == type_b->column_type()) {
         /* The resulting matrix has the number of columns of matrix B and
          * the number of rows of matrix A.  We get the row count of A by
          * looking at the size of a vector that makes up a column.  The
          * transpose (size of a row) is done for B.
          */
         const glsl_type *const type =
            get_instance(type_a->base_type,
                         type_a->column_type()->vector_elements,
                         type_b->row_type()->vector_elements);
         assert(type != error_type);

         return type;
      }
   } else if (type_a->is_matrix()) {
      /* A is a matrix and B is a column vector.  Columns of A must match
       * rows of B.  Given the other previously tested constraints, this
       * means the vector type of a row from A must be the same as the
       * vector the type of B.
       */
      if (type_a->row_type() == type_b) {
         /* The resulting vector has a number of elements equal to
          * the number of rows of matrix A. */
         const glsl_type *const type =
            get_instance(type_a->base_type,
                         type_a->column_type()->vector_elements,
                         1);
         assert(type != error_type);

         return type;
      }
   } else {
      assert(type_b->is_matrix());

      /* A is a row vector and B is a matrix.  Columns of A must match rows
       * of B.  Given the other previously tested constraints, this means
       * the type of A must be the same as the vector type of a column from
       * B.
       */
      if (type_a == type_b->column_type()) {
         /* The resulting vector has a number of elements equal to
          * the number of columns of matrix B. */
         const glsl_type *const type =
            get_instance(type_a->base_type,
                         type_b->row_type()->vector_elements,
                         1);
         assert(type != error_type);

         return type;
      }
   }

   return error_type;
}

const glsl_type *
glsl_type::field_type(const char *name) const
{
   if (this->base_type != GLSL_TYPE_STRUCT
       && this->base_type != GLSL_TYPE_INTERFACE)
      return error_type;

   for (unsigned i = 0; i < this->length; i++) {
      if (strcmp(name, this->fields.structure[i].name) == 0)
         return this->fields.structure[i].type;
   }

   return error_type;
}

int
glsl_type::field_index(const char *name) const
{
   if (this->base_type != GLSL_TYPE_STRUCT
       && this->base_type != GLSL_TYPE_INTERFACE)
      return -1;

   for (unsigned i = 0; i < this->length; i++) {
      if (strcmp(name, this->fields.structure[i].name) == 0)
         return i;
   }

   return -1;
}

unsigned
glsl_type::component_slots() const
{
   switch (this->base_type) {
   case GLSL_TYPE_UINT:
   case GLSL_TYPE_INT:
   case GLSL_TYPE_FLOAT:
   case GLSL_TYPE_BOOL:
      return this->components();

   case GLSL_TYPE_DOUBLE:
   case GLSL_TYPE_UINT64:
   case GLSL_TYPE_INT64:
      return 2 * this->components();

   case GLSL_TYPE_STRUCT:
   case GLSL_TYPE_INTERFACE: {
      unsigned size = 0;

      for (unsigned i = 0; i < this->length; i++)
         size += this->fields.structure[i].type->component_slots();

      return size;
   }

   case GLSL_TYPE_ARRAY:
      return this->length * this->fields.array->component_slots();

   case GLSL_TYPE_IMAGE:
      return 1;
   case GLSL_TYPE_SUBROUTINE:
     return 1;

   case GLSL_TYPE_FUNCTION:
   case GLSL_TYPE_SAMPLER:
   case GLSL_TYPE_ATOMIC_UINT:
   case GLSL_TYPE_VOID:
   case GLSL_TYPE_ERROR:
      break;
   }

   return 0;
}

unsigned
glsl_type::record_location_offset(unsigned length) const
{
   unsigned offset = 0;
   const glsl_type *t = this->without_array();
   if (t->is_record()) {
      assert(length <= t->length);

      for (unsigned i = 0; i < length; i++) {
         const glsl_type *st = t->fields.structure[i].type;
         const glsl_type *wa = st->without_array();
         if (wa->is_record()) {
            unsigned r_offset = wa->record_location_offset(wa->length);
            offset += st->is_array() ?
               st->arrays_of_arrays_size() * r_offset : r_offset;
         } else if (st->is_array() && st->fields.array->is_array()) {
            unsigned outer_array_size = st->length;
            const glsl_type *base_type = st->fields.array;

            /* For arrays of arrays the outer arrays take up a uniform
             * slot for each element. The innermost array elements share a
             * single slot so we ignore the innermost array when calculating
             * the offset.
             */
            while (base_type->fields.array->is_array()) {
               outer_array_size = outer_array_size * base_type->length;
               base_type = base_type->fields.array;
            }
            offset += outer_array_size;
         } else {
            /* We dont worry about arrays here because unless the array
             * contains a structure or another array it only takes up a single
             * uniform slot.
             */
            offset += 1;
         }
      }
   }
   return offset;
}

unsigned
glsl_type::uniform_locations() const
{
   unsigned size = 0;

   switch (this->base_type) {
   case GLSL_TYPE_UINT:
   case GLSL_TYPE_INT:
   case GLSL_TYPE_FLOAT:
   case GLSL_TYPE_DOUBLE:
   case GLSL_TYPE_UINT64:
   case GLSL_TYPE_INT64:
   case GLSL_TYPE_BOOL:
   case GLSL_TYPE_SAMPLER:
   case GLSL_TYPE_IMAGE:
   case GLSL_TYPE_SUBROUTINE:
      return 1;

   case GLSL_TYPE_STRUCT:
   case GLSL_TYPE_INTERFACE:
      for (unsigned i = 0; i < this->length; i++)
         size += this->fields.structure[i].type->uniform_locations();
      return size;
   case GLSL_TYPE_ARRAY:
      return this->length * this->fields.array->uniform_locations();
   default:
      return 0;
   }
}

unsigned
glsl_type::varying_count() const
{
   unsigned size = 0;

   switch (this->base_type) {
   case GLSL_TYPE_UINT:
   case GLSL_TYPE_INT:
   case GLSL_TYPE_FLOAT:
   case GLSL_TYPE_DOUBLE:
   case GLSL_TYPE_BOOL:
   case GLSL_TYPE_UINT64:
   case GLSL_TYPE_INT64:
      return 1;

   case GLSL_TYPE_STRUCT:
   case GLSL_TYPE_INTERFACE:
      for (unsigned i = 0; i < this->length; i++)
         size += this->fields.structure[i].type->varying_count();
      return size;
   case GLSL_TYPE_ARRAY:
      /* Don't count innermost array elements */
      if (this->without_array()->is_record() ||
          this->without_array()->is_interface() ||
          this->fields.array->is_array())
         return this->length * this->fields.array->varying_count();
      else
         return this->fields.array->varying_count();
   default:
      assert(!"unsupported varying type");
      return 0;
   }
}

bool
glsl_type::can_implicitly_convert_to(const glsl_type *desired,
                                     _mesa_glsl_parse_state *state) const
{
   if (this == desired)
      return true;

   /* GLSL 1.10 and ESSL do not allow implicit conversions. If there is no
    * state, we're doing intra-stage function linking where these checks have
    * already been done.
    */
   if (state && (state->es_shader || !state->is_version(120, 0)))
      return false;

   /* There is no conversion among matrix types. */
   if (this->matrix_columns > 1 || desired->matrix_columns > 1)
      return false;

   /* Vector size must match. */
   if (this->vector_elements != desired->vector_elements)
      return false;

   /* int and uint can be converted to float. */
   if (desired->is_float() && this->is_integer())
      return true;

   /* With GLSL 4.0, ARB_gpu_shader5, or MESA_shader_integer_functions, int
    * can be converted to uint.  Note that state may be NULL here, when
    * resolving function calls in the linker. By this time, all the
    * state-dependent checks have already happened though, so allow anything
    * that's allowed in any shader version.
    */
   if ((!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable ||
        state->MESA_shader_integer_functions_enable) &&
         desired->base_type == GLSL_TYPE_UINT && this->base_type == GLSL_TYPE_INT)
      return true;

   /* No implicit conversions from double. */
   if ((!state || state->has_double()) && this->is_double())
      return false;

   /* Conversions from different types to double. */
   if ((!state || state->has_double()) && desired->is_double()) {
      if (this->is_float())
         return true;
      if (this->is_integer())
         return true;
   }

   return false;
}

unsigned
glsl_type::std140_base_alignment(bool row_major) const
{
   unsigned N = is_64bit() ? 8 : 4;

   /* (1) If the member is a scalar consuming <N> basic machine units, the
    *     base alignment is <N>.
    *
    * (2) If the member is a two- or four-component vector with components
    *     consuming <N> basic machine units, the base alignment is 2<N> or
    *     4<N>, respectively.
    *
    * (3) If the member is a three-component vector with components consuming
    *     <N> basic machine units, the base alignment is 4<N>.
    */
   if (this->is_scalar() || this->is_vector()) {
      switch (this->vector_elements) {
      case 1:
         return N;
      case 2:
         return 2 * N;
      case 3:
      case 4:
         return 4 * N;
      }
   }

   /* (4) If the member is an array of scalars or vectors, the base alignment
    *     and array stride are set to match the base alignment of a single
    *     array element, according to rules (1), (2), and (3), and rounded up
    *     to the base alignment of a vec4. The array may have padding at the
    *     end; the base offset of the member following the array is rounded up
    *     to the next multiple of the base alignment.
    *
    * (6) If the member is an array of <S> column-major matrices with <C>
    *     columns and <R> rows, the matrix is stored identically to a row of
    *     <S>*<C> column vectors with <R> components each, according to rule
    *     (4).
    *
    * (8) If the member is an array of <S> row-major matrices with <C> columns
    *     and <R> rows, the matrix is stored identically to a row of <S>*<R>
    *     row vectors with <C> components each, according to rule (4).
    *
    * (10) If the member is an array of <S> structures, the <S> elements of
    *      the array are laid out in order, according to rule (9).
    */
   if (this->is_array()) {
      if (this->fields.array->is_scalar() ||
          this->fields.array->is_vector() ||
          this->fields.array->is_matrix()) {
         return MAX2(this->fields.array->std140_base_alignment(row_major), 16);
      } else {
         assert(this->fields.array->is_record() ||
                this->fields.array->is_array());
         return this->fields.array->std140_base_alignment(row_major);
      }
   }

   /* (5) If the member is a column-major matrix with <C> columns and
    *     <R> rows, the matrix is stored identically to an array of
    *     <C> column vectors with <R> components each, according to
    *     rule (4).
    *
    * (7) If the member is a row-major matrix with <C> columns and <R>
    *     rows, the matrix is stored identically to an array of <R>
    *     row vectors with <C> components each, according to rule (4).
    */
   if (this->is_matrix()) {
      const struct glsl_type *vec_type, *array_type;
      int c = this->matrix_columns;
      int r = this->vector_elements;

      if (row_major) {
         vec_type = get_instance(base_type, c, 1);
         array_type = glsl_type::get_array_instance(vec_type, r);
      } else {
         vec_type = get_instance(base_type, r, 1);
         array_type = glsl_type::get_array_instance(vec_type, c);
      }

      return array_type->std140_base_alignment(false);
   }

   /* (9) If the member is a structure, the base alignment of the
    *     structure is <N>, where <N> is the largest base alignment
    *     value of any of its members, and rounded up to the base
    *     alignment of a vec4. The individual members of this
    *     sub-structure are then assigned offsets by applying this set
    *     of rules recursively, where the base offset of the first
    *     member of the sub-structure is equal to the aligned offset
    *     of the structure. The structure may have padding at the end;
    *     the base offset of the member following the sub-structure is
    *     rounded up to the next multiple of the base alignment of the
    *     structure.
    */
   if (this->is_record()) {
      unsigned base_alignment = 16;
      for (unsigned i = 0; i < this->length; i++) {
         bool field_row_major = row_major;
         const enum glsl_matrix_layout matrix_layout =
            glsl_matrix_layout(this->fields.structure[i].matrix_layout);
         if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
            field_row_major = true;
         } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
            field_row_major = false;
         }

         const struct glsl_type *field_type = this->fields.structure[i].type;
         base_alignment = MAX2(base_alignment,
                               field_type->std140_base_alignment(field_row_major));
      }
      return base_alignment;
   }

   assert(!"not reached");
   return -1;
}

unsigned
glsl_type::std140_size(bool row_major) const
{
   unsigned N = is_64bit() ? 8 : 4;

   /* (1) If the member is a scalar consuming <N> basic machine units, the
    *     base alignment is <N>.
    *
    * (2) If the member is a two- or four-component vector with components
    *     consuming <N> basic machine units, the base alignment is 2<N> or
    *     4<N>, respectively.
    *
    * (3) If the member is a three-component vector with components consuming
    *     <N> basic machine units, the base alignment is 4<N>.
    */
   if (this->is_scalar() || this->is_vector()) {
      return this->vector_elements * N;
   }

   /* (5) If the member is a column-major matrix with <C> columns and
    *     <R> rows, the matrix is stored identically to an array of
    *     <C> column vectors with <R> components each, according to
    *     rule (4).
    *
    * (6) If the member is an array of <S> column-major matrices with <C>
    *     columns and <R> rows, the matrix is stored identically to a row of
    *     <S>*<C> column vectors with <R> components each, according to rule
    *     (4).
    *
    * (7) If the member is a row-major matrix with <C> columns and <R>
    *     rows, the matrix is stored identically to an array of <R>
    *     row vectors with <C> components each, according to rule (4).
    *
    * (8) If the member is an array of <S> row-major matrices with <C> columns
    *     and <R> rows, the matrix is stored identically to a row of <S>*<R>
    *     row vectors with <C> components each, according to rule (4).
    */
   if (this->without_array()->is_matrix()) {
      const struct glsl_type *element_type;
      const struct glsl_type *vec_type;
      unsigned int array_len;

      if (this->is_array()) {
         element_type = this->without_array();
         array_len = this->arrays_of_arrays_size();
      } else {
         element_type = this;
         array_len = 1;
      }

      if (row_major) {
         vec_type = get_instance(element_type->base_type,
                                 element_type->matrix_columns, 1);

         array_len *= element_type->vector_elements;
      } else {
         vec_type = get_instance(element_type->base_type,
                                 element_type->vector_elements, 1);
         array_len *= element_type->matrix_columns;
      }
      const glsl_type *array_type = glsl_type::get_array_instance(vec_type,
                                                                  array_len);

      return array_type->std140_size(false);
   }

   /* (4) If the member is an array of scalars or vectors, the base alignment
    *     and array stride are set to match the base alignment of a single
    *     array element, according to rules (1), (2), and (3), and rounded up
    *     to the base alignment of a vec4. The array may have padding at the
    *     end; the base offset of the member following the array is rounded up
    *     to the next multiple of the base alignment.
    *
    * (10) If the member is an array of <S> structures, the <S> elements of
    *      the array are laid out in order, according to rule (9).
    */
   if (this->is_array()) {
      if (this->without_array()->is_record()) {
	 return this->arrays_of_arrays_size() *
            this->without_array()->std140_size(row_major);
      } else {
	 unsigned element_base_align =
	    this->without_array()->std140_base_alignment(row_major);
	 return this->arrays_of_arrays_size() * MAX2(element_base_align, 16);
      }
   }

   /* (9) If the member is a structure, the base alignment of the
    *     structure is <N>, where <N> is the largest base alignment
    *     value of any of its members, and rounded up to the base
    *     alignment of a vec4. The individual members of this
    *     sub-structure are then assigned offsets by applying this set
    *     of rules recursively, where the base offset of the first
    *     member of the sub-structure is equal to the aligned offset
    *     of the structure. The structure may have padding at the end;
    *     the base offset of the member following the sub-structure is
    *     rounded up to the next multiple of the base alignment of the
    *     structure.
    */
   if (this->is_record() || this->is_interface()) {
      unsigned size = 0;
      unsigned max_align = 0;

      for (unsigned i = 0; i < this->length; i++) {
         bool field_row_major = row_major;
         const enum glsl_matrix_layout matrix_layout =
            glsl_matrix_layout(this->fields.structure[i].matrix_layout);
         if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
            field_row_major = true;
         } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
            field_row_major = false;
         }

         const struct glsl_type *field_type = this->fields.structure[i].type;
         unsigned align = field_type->std140_base_alignment(field_row_major);

         /* Ignore unsized arrays when calculating size */
         if (field_type->is_unsized_array())
            continue;

         size = glsl_align(size, align);
         size += field_type->std140_size(field_row_major);

         max_align = MAX2(align, max_align);

         if (field_type->is_record() && (i + 1 < this->length))
            size = glsl_align(size, 16);
      }
      size = glsl_align(size, MAX2(max_align, 16));
      return size;
   }

   assert(!"not reached");
   return -1;
}

unsigned
glsl_type::std430_base_alignment(bool row_major) const
{

   unsigned N = is_64bit() ? 8 : 4;

   /* (1) If the member is a scalar consuming <N> basic machine units, the
    *     base alignment is <N>.
    *
    * (2) If the member is a two- or four-component vector with components
    *     consuming <N> basic machine units, the base alignment is 2<N> or
    *     4<N>, respectively.
    *
    * (3) If the member is a three-component vector with components consuming
    *     <N> basic machine units, the base alignment is 4<N>.
    */
   if (this->is_scalar() || this->is_vector()) {
      switch (this->vector_elements) {
      case 1:
         return N;
      case 2:
         return 2 * N;
      case 3:
      case 4:
         return 4 * N;
      }
   }

   /* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout":
    *
    * "When using the std430 storage layout, shader storage blocks will be
    * laid out in buffer storage identically to uniform and shader storage
    * blocks using the std140 layout, except that the base alignment and
    * stride of arrays of scalars and vectors in rule 4 and of structures
    * in rule 9 are not rounded up a multiple of the base alignment of a vec4.
    */

   /* (1) If the member is a scalar consuming <N> basic machine units, the
    *     base alignment is <N>.
    *
    * (2) If the member is a two- or four-component vector with components
    *     consuming <N> basic machine units, the base alignment is 2<N> or
    *     4<N>, respectively.
    *
    * (3) If the member is a three-component vector with components consuming
    *     <N> basic machine units, the base alignment is 4<N>.
    */
   if (this->is_array())
      return this->fields.array->std430_base_alignment(row_major);

   /* (5) If the member is a column-major matrix with <C> columns and
    *     <R> rows, the matrix is stored identically to an array of
    *     <C> column vectors with <R> components each, according to
    *     rule (4).
    *
    * (7) If the member is a row-major matrix with <C> columns and <R>
    *     rows, the matrix is stored identically to an array of <R>
    *     row vectors with <C> components each, according to rule (4).
    */
   if (this->is_matrix()) {
      const struct glsl_type *vec_type, *array_type;
      int c = this->matrix_columns;
      int r = this->vector_elements;

      if (row_major) {
         vec_type = get_instance(base_type, c, 1);
         array_type = glsl_type::get_array_instance(vec_type, r);
      } else {
         vec_type = get_instance(base_type, r, 1);
         array_type = glsl_type::get_array_instance(vec_type, c);
      }

      return array_type->std430_base_alignment(false);
   }

      /* (9) If the member is a structure, the base alignment of the
    *     structure is <N>, where <N> is the largest base alignment
    *     value of any of its members, and rounded up to the base
    *     alignment of a vec4. The individual members of this
    *     sub-structure are then assigned offsets by applying this set
    *     of rules recursively, where the base offset of the first
    *     member of the sub-structure is equal to the aligned offset
    *     of the structure. The structure may have padding at the end;
    *     the base offset of the member following the sub-structure is
    *     rounded up to the next multiple of the base alignment of the
    *     structure.
    */
   if (this->is_record()) {
      unsigned base_alignment = 0;
      for (unsigned i = 0; i < this->length; i++) {
         bool field_row_major = row_major;
         const enum glsl_matrix_layout matrix_layout =
            glsl_matrix_layout(this->fields.structure[i].matrix_layout);
         if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
            field_row_major = true;
         } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
            field_row_major = false;
         }

         const struct glsl_type *field_type = this->fields.structure[i].type;
         base_alignment = MAX2(base_alignment,
                               field_type->std430_base_alignment(field_row_major));
      }
      assert(base_alignment > 0);
      return base_alignment;
   }
   assert(!"not reached");
   return -1;
}

unsigned
glsl_type::std430_array_stride(bool row_major) const
{
   unsigned N = is_64bit() ? 8 : 4;

   /* Notice that the array stride of a vec3 is not 3 * N but 4 * N.
    * See OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout"
    *
    * (3) If the member is a three-component vector with components consuming
    *     <N> basic machine units, the base alignment is 4<N>.
    */
   if (this->is_vector() && this->vector_elements == 3)
      return 4 * N;

   /* By default use std430_size(row_major) */
   return this->std430_size(row_major);
}

unsigned
glsl_type::std430_size(bool row_major) const
{
   unsigned N = is_64bit() ? 8 : 4;

   /* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout":
    *
    * "When using the std430 storage layout, shader storage blocks will be
    * laid out in buffer storage identically to uniform and shader storage
    * blocks using the std140 layout, except that the base alignment and
    * stride of arrays of scalars and vectors in rule 4 and of structures
    * in rule 9 are not rounded up a multiple of the base alignment of a vec4.
    */
   if (this->is_scalar() || this->is_vector())
         return this->vector_elements * N;

   if (this->without_array()->is_matrix()) {
      const struct glsl_type *element_type;
      const struct glsl_type *vec_type;
      unsigned int array_len;

      if (this->is_array()) {
         element_type = this->without_array();
         array_len = this->arrays_of_arrays_size();
      } else {
         element_type = this;
         array_len = 1;
      }

      if (row_major) {
         vec_type = get_instance(element_type->base_type,
                                 element_type->matrix_columns, 1);

         array_len *= element_type->vector_elements;
      } else {
         vec_type = get_instance(element_type->base_type,
                                 element_type->vector_elements, 1);
         array_len *= element_type->matrix_columns;
      }
      const glsl_type *array_type = glsl_type::get_array_instance(vec_type,
                                                                  array_len);

      return array_type->std430_size(false);
   }

   if (this->is_array()) {
      if (this->without_array()->is_record())
         return this->arrays_of_arrays_size() *
            this->without_array()->std430_size(row_major);
      else
         return this->arrays_of_arrays_size() *
            this->without_array()->std430_base_alignment(row_major);
   }

   if (this->is_record() || this->is_interface()) {
      unsigned size = 0;
      unsigned max_align = 0;

      for (unsigned i = 0; i < this->length; i++) {
         bool field_row_major = row_major;
         const enum glsl_matrix_layout matrix_layout =
            glsl_matrix_layout(this->fields.structure[i].matrix_layout);
         if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
            field_row_major = true;
         } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
            field_row_major = false;
         }

         const struct glsl_type *field_type = this->fields.structure[i].type;
         unsigned align = field_type->std430_base_alignment(field_row_major);
         size = glsl_align(size, align);
         size += field_type->std430_size(field_row_major);

         max_align = MAX2(align, max_align);
      }
      size = glsl_align(size, max_align);
      return size;
   }

   assert(!"not reached");
   return -1;
}

unsigned
glsl_type::count_attribute_slots(bool is_vertex_input) const
{
   /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
    *
    *     "A scalar input counts the same amount against this limit as a vec4,
    *     so applications may want to consider packing groups of four
    *     unrelated float inputs together into a vector to better utilize the
    *     capabilities of the underlying hardware. A matrix input will use up
    *     multiple locations.  The number of locations used will equal the
    *     number of columns in the matrix."
    *
    * The spec does not explicitly say how arrays are counted.  However, it
    * should be safe to assume the total number of slots consumed by an array
    * is the number of entries in the array multiplied by the number of slots
    * consumed by a single element of the array.
    *
    * The spec says nothing about how structs are counted, because vertex
    * attributes are not allowed to be (or contain) structs.  However, Mesa
    * allows varying structs, the number of varying slots taken up by a
    * varying struct is simply equal to the sum of the number of slots taken
    * up by each element.
    *
    * Doubles are counted different depending on whether they are vertex
    * inputs or everything else. Vertex inputs from ARB_vertex_attrib_64bit
    * take one location no matter what size they are, otherwise dvec3/4
    * take two locations.
    */
   switch (this->base_type) {
   case GLSL_TYPE_UINT:
   case GLSL_TYPE_INT:
   case GLSL_TYPE_FLOAT:
   case GLSL_TYPE_BOOL:
      return this->matrix_columns;
   case GLSL_TYPE_DOUBLE:
   case GLSL_TYPE_UINT64:
   case GLSL_TYPE_INT64:
      if (this->vector_elements > 2 && !is_vertex_input)
         return this->matrix_columns * 2;
      else
         return this->matrix_columns;
   case GLSL_TYPE_STRUCT:
   case GLSL_TYPE_INTERFACE: {
      unsigned size = 0;

      for (unsigned i = 0; i < this->length; i++)
         size += this->fields.structure[i].type->count_attribute_slots(is_vertex_input);

      return size;
   }

   case GLSL_TYPE_ARRAY:
      return this->length * this->fields.array->count_attribute_slots(is_vertex_input);

   case GLSL_TYPE_FUNCTION:
   case GLSL_TYPE_SAMPLER:
   case GLSL_TYPE_IMAGE:
   case GLSL_TYPE_ATOMIC_UINT:
   case GLSL_TYPE_VOID:
   case GLSL_TYPE_SUBROUTINE:
   case GLSL_TYPE_ERROR:
      break;
   }

   assert(!"Unexpected type in count_attribute_slots()");

   return 0;
}

int
glsl_type::coordinate_components() const
{
   int size;

   switch (sampler_dimensionality) {
   case GLSL_SAMPLER_DIM_1D:
   case GLSL_SAMPLER_DIM_BUF:
      size = 1;
      break;
   case GLSL_SAMPLER_DIM_2D:
   case GLSL_SAMPLER_DIM_RECT:
   case GLSL_SAMPLER_DIM_MS:
   case GLSL_SAMPLER_DIM_EXTERNAL:
   case GLSL_SAMPLER_DIM_SUBPASS:
      size = 2;
      break;
   case GLSL_SAMPLER_DIM_3D:
   case GLSL_SAMPLER_DIM_CUBE:
      size = 3;
      break;
   default:
      assert(!"Should not get here.");
      size = 1;
      break;
   }

   /* Array textures need an additional component for the array index, except
    * for cubemap array images that behave like a 2D array of interleaved
    * cubemap faces.
    */
   if (sampler_array &&
       !(is_image() && sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE))
      size += 1;

   return size;
}

/**
 * Declarations of type flyweights (glsl_type::_foo_type) and
 * convenience pointers (glsl_type::foo_type).
 * @{
 */
#define DECL_TYPE(NAME, ...)                                    \
   const glsl_type glsl_type::_##NAME##_type = glsl_type(__VA_ARGS__, #NAME); \
   const glsl_type *const glsl_type::NAME##_type = &glsl_type::_##NAME##_type;

#define STRUCT_TYPE(NAME)

#include "compiler/builtin_type_macros.h"
/** @} */

redpajama_set_name: RedPajamaGithub


text:
Willi Unsoeld Collection, 1963-1979
The Willi Unsoeld Collection documents OSU alumnus and faculty member Willi Unsoeld's spring 1963 climb of Mount Everest and the fall 1963 OSU fundraising campaign to defer Unsoeld's medical expenses resulting from the Mount Everest climb. The collection includes correspondence, newsletters, financial reports, clippings, and a 1979 Oregon Senate resolution.
Unsoeld, William Francis (1926-1979)
Dyhrenfurth, Norman G.
Oregon. Legislative Assembly. Senate
Strand, A. L. (August Leroy) (1894-)
Ullman, James Ramsey (1907-1971)
ID: MSS Unsoeld
The Willi Unsoeld Collection primarily documents Unsoeld's participation in the 1963 climb of Mt. Everest. The series I newsletters were written by expedition members, including Willi Unsoeld, James R. Ullman, and Norman Dyhrenfurth, between February and June 1963. Series II, Correspondence, consists of OSU president emeritus A.L Strand's fundraising efforts in the summer and fall of 1963 to help offset the medical costs of Unsoeld's treatment for frostbite resulting from the climb. This series also contains other correspondence between Strand and the Unsoelds, 1963-1965. Series III contains newspaper clippings about the 1963 Mt. Everest climb from the Oregonian and Corvallis Gazette-Times newspapers, as well as National Geographic's 1963 articles on the climb, including one co-authored by Unsoeld. Included in one of the articles is a photo of Unsoeld planting the OSC Mountain Club banner on Everest's summit. Series IV consists of a resolution passed by the Oregon Senate honoring Unsoeld after his death in March 1979.
Renowned mountain climber William Francis Unsoeld was born in 1926 in Arcata, California, and attended high school in Eugene, Oregon. In 1944 he enrolled at Oregon State College, studied physics, and received a Bachelor of Science degree in 1951. While at Oregon State, Unsoeld helped found the OSC Mountain Club. He received a divinity degree from the Pacific School of Religion in 1954 and a Ph.D. from the University of Washington in 1958.
Unsoeld joined the faculty of the OSC Department of Religion in 1958. From 1962 to 1967 Unsoeld took a leave of absence from OSU and worked for the Peace Corps in Nepal, and later worked for the U.S. Agency for International Development. At the time of his death in 1979, Unsoeld was on the faculty of Evergreen State College in Olympia, Washington, where he had taught philosophy and religion since 1970.
Unsoeld was a world class mountain climber who started mountain climbing as a boy in Oregon's Cascades. He was best known for his participation in the successful 1963 climb of Mt. Everest by the first group of climbers from the United States. On that climb, Unsoeld and Thomas Hornbein became the first climbers to scale Everest's west ridge. Other significant climbs in which Unsoeld participated included the 1954 California Himalayan Expedition to Malaku and the 1960 American-Pakistan Karakorem Expedition to Mt. Mashabram in the Western Himalayas.
While a student at Oregon State, Unsoeld met Jolene Bishoprick when they were both members of the OSC Mountain Club. Unsoeld and Bishoprick married in 1951, and had four children. Jolene Unsoeld graduated from Oregon State in 1953 and later served as a U.S. Representative from Washington from 1989 to 1995. Willi Unsoeld died in an avalanche on Mt. Rainier on March 4, 1979.
The collection is arranged into four series: I. Mt. Everest Expedition Newsletters; II. Correspondence; III. Newspaper and Magazine Clippings; and IV. Oregon Senate Resolution.
Preferred Citation: Willi Unsoeld Collection (MSS Unsoeld), Oregon State University Special Collections and Archives Research Center, Corvallis, Oregon.
Rights: Mt. Everest climb newsletters are copyrighted and are not to be reproduced.
Collection Material Type: CLD
Everest, Mount (China and Nepal)
Mountaineering--Everest, Mount (China and Nepal)
Unsoeld, Jolene
Unsoeld, William Francis, 1926-1979
Newspaper clippings and magazine articles from the Oregon Stater pertaining to Willi and Jolene Unsoeld are available in the Willi Unsoeld and Jolene Unsoeld files in the OSU Memorabilia Collection (MSS MC). The Oregon State University Mountain Club Records (MSS MountainClub) contain information about the Unsoelds' participation in and leadership of that group. The News and Communication Services Photograph Collection (P 057) contains two 1960 portraits of Unsoeld while a member of Oregon State's faculty. The President's Office Photographs (P 092) contains a kinescope photograph of Unsoeld at OSU's 1962 commencement.
The Evergreen State College Archives and Special Collections includes materials pertaining to Willi Unsoeld and Jolene Unsoeld's legislative and congressional papers.

redpajama_set_name: RedPajamaCommonCrawl


text:
Q: For loop doesn't append info correctly into 2D array I have created an empty 2D array. When I try to add stuff inside of it, it doesn't do so properly. Each index contains the appropriate info, but for some reason, carries the info from the previous into the next index. Here is my code:
rows, cols = (3, 2)
array = [[]*cols]*rows                         # Creating the empty 2D array.
fruit_list = ['apples', 'bananas', 'oranges']  # My fruit list
for i in range(0, 3):
  array[i].append(fruit_list[i])       # Appending to the 2D array a fruit,
  array[i].append(0)                   # followed by the number 0
  print(array[i])                      # Printing each index

The result I am getting in the console is :
['apples', 0]                             # This is good (index 1)
['apples', 0, 'bananas', 0]               # This is not good (index 2)
['apples', 0, 'bananas', 0, 'oranges', 0] # This is not good (index 3)
# etc.

How do I stop this from happening? I want each index to have its own fruit and number 0.

A: The issue is with this:
array = [[]*cols]*rows

First, []*cols is just creating one empty list (empty, because the * operator has nothing to repeat). But more importantly, *row just duplicates the reference to that list, but does not create new empty lists. So whatever you do to that single list, will be visible in all the slots of the outer list.
So change:
array = [[]*cols]*rows

To a list comprehension:
array = [[] for _ in range(rows)]

Improvement
Not your question, but you can omit the loop and use the above mentioned list comprehension to immediately populate the list with the data:
array = [[fruit, 0] for fruit in ['apples', 'bananas', 'oranges']]

redpajama_set_name: RedPajamaStackExchange


forklift propane fuel system diagram sediment traps on gas lines what are they why required, modeling and simulation study of an industrial radial moving bed forklift propane fuel system diagram, forklift propane fuel system diagram gt conversion,forklift propane fuel system diagram the process of crude oil refining ,forklift propane fuel system diagram the department of spontaneous combustion ,forklift propane fuel system diagram in a reliable role , forklift propane fuel system diagram typical gas turbine engine download, and smart energy grid control automation forklift propane fuel system diagram, forklift propane fuel system diagram tank, technology forklift propane fuel system diagram.
We hope you can find what you need here. We always effort to show a picture with HD resolution or at least with perfect images. Ideas Propane Fuel System Diagram Or Download Full Size Image 33 can be beneficial inspiration for those who seek an image according specific categories; you can find it in this site. Finally all pictures we have been displayed in this site will inspire you all..


> >  > > restrict the range of dumped transactions.
> >  > > expected few hundred bytes to about 500 kB.
> > But, I can make the extensions available.
The patch also enhances "FileStorage" and lets its "UndoSearch._readnext"
(much more convenient than "fsdump").


text:
AppsNews
You will soon see shopping catalogs on WhatsApp
Adamya Sharma
Facebook has been constantly pushing ecommerce features on its popular messaging platform WhatsApp. The latest in that endeavour is a new feature on WhatsApp Business called catalogs.
With WhatsApp catalogs, merchants on WhatsApp Business will be able to share inventories of their products with WhatsApp users. "We are making it easier to learn about the products and services businesses offer with the introduction of catalogs in the WhatsApp Business app," WhatsApp wrote in a blogpost.
The company explained that the new catalogs feature will give small businesses a chance to look more professional. Catalogs will act as mobile storefronts for vendors and users will be able to discover a list of goods and services provided by them.
Best alternative messaging apps to WhatsApp
WhatsApp is one of the most popular messaging apps in the world. But after Facebook purchased it, many have started to worry about the future of the app. Now that WhatsApp has confirmed that it …
A WhatsApp catalog can include information such as images of products, prices, descriptions, and product codes. The company says it will host these catalogs on its own servers so merchants and customers don't have to waste storage on their devices by exchanging product images, etc.
WhatsApp Business merchants can create catalogs by heading to Settings > Catalog on the app. They can then follow instructions to add product details, images, prices and more.
The catalog feature is available on the WhatsApp Business app, on both Android and iPhone. It is currently rolling out in Brazil, Germany, India, Indonesia, Mexico, the UK, and the US. WhatsApp says it will be rolling out the feature around the world soon.
There is no option to buy things from these catalogs for now. However, given the general direction WhatsApp is heading in with payments, catalogs could be a step towards full-fledged ecommerce functionality on the platform.
More posts about WhatsApp
Facebook redacts controversial plan to pump ads into WhatsApp… for now
Phillip Prado 3 days ago
Facebook owns 4 out of the 5 most downloaded apps of 2019
Joe Hindy 2 weeks ago
WhatsApp tipped to get disappearing messages soon: Here's how it works (Updated)
FTC could block Facebook merging WhatsApp, Messenger, Instagram
C. Scott Brown 1 month ago


New tray, from Eva Solo, a must-have at your table!
Reduced in design, maximized in its function.
This tray is perfect for its purpose, with a high edge and good handle holes, you are always in full control when serving. Moreover, the inside is rubber-coated, prevents glasses and tableware from sliding when you move the tray around.
The tray is not only practical, its design is minimalistic and exclusive.
It thus adds a decorative touch to any table, and is an item which you will not feel the need to put it away in a hurry.
The tray is made of plastic with a narrow, stainless steel edge.


Holly and Michael at PVA Wednesday Evening.
Holly and Michael will discuss their new book, Languages of the Land: A Dialogue with The Downs, following the business portion of the Pawtuxet Village Association meeting on Wednesday at 7 p.m. Aspray Boathouse in Pawtuxet Park, Warwick side of the village on Narragansett Parkway.
If you didn't have a chance to get a signed copy on Saturday, books will be available on Wednesday. Books also may be purchased at Twice Told Tales on the bridge in Pawtuxet Village.


text:
package com.feedeo.shopify.web.resource.rest.shop;

import com.feedeo.shopify.model.Shop;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.client.MockRestServiceServer.createServer;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;

@RunWith(MockitoJUnitRunner.class)
public class ShopOAuth2RestResourceTest {
  public static final String responseOk = "{\n" +
          "  \"shop\": {\n" +
          "    \"id\": 690933842,\n" +
          "    \"name\": \"Apple Computers\",\n" +
          "    \"email\": \"steve@apple.com\",\n" +
          "    \"domain\": \"shop.apple.com\",\n" +
          "    \"created_at\": \"2007-12-31T19:00:00-05:00\",\n" +
          "    \"province\": \"California\",\n" +
          "    \"country\": \"US\",\n" +
          "    \"address1\": \"1 Infinite Loop\",\n" +
          "    \"zip\": \"95014\",\n" +
          "    \"city\": \"Cupertino\",\n" +
          "    \"source\": null,\n" +
          "    \"phone\": \"1231231234\",\n" +
          "    \"updated_at\": \"2015-09-02T14:53:51-04:00\",\n" +
          "    \"customer_email\": \"customers@apple.com\",\n" +
          "    \"latitude\": 45.45,\n" +
          "    \"longitude\": -75.43,\n" +
          "    \"primary_location_id\": null,\n" +
          "    \"primary_locale\": \"en\",\n" +
          "    \"country_code\": \"US\",\n" +
          "    \"country_name\": \"United States\",\n" +
          "    \"currency\": \"USD\",\n" +
          "    \"timezone\": \"(GMT-05:00) Eastern Time (US & Canada)\",\n" +
          "    \"iana_timezone\": \"America\\/New_York\",\n" +
          "    \"shop_owner\": \"Steve Jobs\",\n" +
          "    \"money_format\": \"$ {{amount}}\",\n" +
          "    \"money_with_currency_format\": \"$ {{amount}} USD\",\n" +
          "    \"province_code\": \"CA\",\n" +
          "    \"taxes_included\": null,\n" +
          "    \"tax_shipping\": null,\n" +
          "    \"county_taxes\": true,\n" +
          "    \"plan_display_name\": \"Shopify Plus\",\n" +
          "    \"plan_name\": \"enterprise\",\n" +
          "    \"myshopify_domain\": \"apple.myshopify.com\",\n" +
          "    \"google_apps_domain\": null,\n" +
          "    \"google_apps_login_enabled\": null,\n" +
          "    \"eligible_for_payments\": true,\n" +
          "    \"requires_extra_payments_agreement\": false,\n" +
          "    \"password_enabled\": false,\n" +
          "    \"has_storefront\": true,\n" +
          "    \"setup_required\": false\n" +
          "  }\n" +
          "}";

  private ShopOAuth2RestResource target;

  private MockRestServiceServer mockServer;

  @Before
  public void setUp() {
    target = new ShopOAuth2RestResource();

    RestTemplate restTemplate = (RestTemplate) target.getRestOperations();

    mockServer = createServer(restTemplate);
  }

  @Test
  public void shouldGetShopifyShop() {
    mockServer
            .expect(requestTo("https://my-shop.myshopify.com/admin/shop.json"))
            .andExpect(method(GET))
            .andRespond(withSuccess(responseOk, APPLICATION_JSON));

    Shop shop = target.getShop("my-access-token", "my-shop");

    mockServer.verify();

    assertThat(shop).isNotNull();
    assertThat(shop.getId()).isEqualTo(690933842);
    assertThat(shop.getName()).isEqualTo("Apple Computers");
    assertThat(shop.getEmail()).isEqualTo("steve@apple.com");
    assertThat(shop.getDomain()).isEqualTo("shop.apple.com");
    assertThat(shop.getCreatedAt()).isEqualTo(new DateTime("2007-12-31T19:00:00-05:00"));
    assertThat(shop.getProvince()).isEqualTo("California");
    assertThat(shop.getCountry()).isEqualTo("US");
    assertThat(shop.getAddress1()).isEqualTo("1 Infinite Loop");
    assertThat(shop.getZip()).isEqualTo("95014");
    assertThat(shop.getCity()).isEqualTo("Cupertino");
    assertThat(shop.getSource()).isNull();
    assertThat(shop.getPhone()).isEqualTo("1231231234");
    assertThat(shop.getUpdatedAt()).isEqualTo(new DateTime("2015-09-02T14:53:51-04:00"));
    assertThat(shop.getCustomerEmail()).isEqualTo("customers@apple.com");
    assertThat(shop.getLatitude()).isEqualTo(45.45);
    assertThat(shop.getLongitude()).isEqualTo(-75.43);
    assertThat(shop.getPrimaryLocationId()).isNull();
    assertThat(shop.getPrimaryLocale()).isEqualTo("en");
    assertThat(shop.getCountryCode()).isEqualTo("US");
    assertThat(shop.getCountryName()).isEqualTo("United States");
    assertThat(shop.getCurrency()).isEqualTo("USD");
    assertThat(shop.getTimezone()).isEqualTo("(GMT-05:00) Eastern Time (US & Canada)");
    assertThat(shop.getIanaTimezone()).isEqualTo("America/New_York");
    assertThat(shop.getShopOwner()).isEqualTo("Steve Jobs");
    assertThat(shop.getMoneyFormat()).isEqualTo("$ {{amount}}");
    assertThat(shop.getMoneyWithCurrencyFormat()).isEqualTo("$ {{amount}} USD");
    assertThat(shop.getProvinceCode()).isEqualTo("CA");
    assertThat(shop.isTaxesIncluded()).isNull();
    assertThat(shop.getTaxShipping()).isNull();
    assertThat(shop.isCountyTaxes()).isEqualTo(true);
    assertThat(shop.getPlanDisplayName()).isEqualTo("Shopify Plus");
    assertThat(shop.getPlanName()).isEqualTo("enterprise");
    assertThat(shop.getMyshopifyDomain()).isEqualTo("apple.myshopify.com");
    assertThat(shop.getGoogleAppsDomain()).isNull();
    assertThat(shop.getGoogleAppsLoginEnabled()).isNull();
    assertThat(shop.getPasswordEnabled()).isEqualTo(false);
    assertThat(shop.getHasStorefront()).isEqualTo(true);
    assertThat(shop.getSetupRequired()).isEqualTo(false);
  }

}


along with unblocking sites, surfagain SurfAgain is a how does proxify work website which allows you to visit your favourite sites at work or school, it can also tell you that who is the administrator behind a particular website.the trial version does not have any limitations, the trial version displays the information window. What are the limitations of the trial version? On start, can Proxifier run in background as how does proxify work Windows Service? But it stops working after 31 days from the first start.top 21 Free Online Proxy Websites to access Facebook and: Zend2 This proxy site issues you a new IP address and allows how does proxify work you to view Facebook without leaving any traces of your computer information.
alienproxy AlienProxy is a FREE anonymous web based proxy service running on high performance dedicated servers. Whether youre on the job at work, at school or how does proxify work college. Browse your favorite web sites even from behind a firewall with blocked ports.if you how does proxify work find that you are blocked from your favorite websites, proxy websites are web page which allows you to browse your favorite websites even though your access to those websites might be blocked by a content filter. What a Proxy websites does?linux, the encrypted connection of this proxy service prevents monitoring your how does proxify work network traffic. Surf and browse the web anonymously at school and work. Nr1surf The best and fastest free anonymous proxy. It works on all major platforms such as windows, apple and chrome etc.
private and safely. With this service you can surf the web freely and acces any website anonymously, tntproxy m is a free anonymizer proxy service forticlient use default gateway on remote network that lets you visit myspace from school.
organizations such as schools and certain how does proxify work businesses use firewalls to block Facebooks social networking site. It is also a preferred method to avoid third party windows 8 vpn software advertising offers, firewalls protect the organizations computers from viruses and potential crashes. Spam or unwelcome friends invites.
before you head on with this nice list of proxy sites, once you keep browsing how does proxify work using that form, you are protected and your real IP address is not being logged.in a corporate network of 500 computers, flexibility Assign different proxies or chains to different connections using the rule-based system. Use Cases. The configuration gets managed how does proxify work remotely from a single control point. Proxifier is deployed to forward connections through the proxy.proxifier - The Most Advanced Proxy Client. Proxifier allows network applications that do not support working through proxy servers to operate through a SOCKS or HTTPS proxy and chains. Key how does proxify work Features Master Your Corporate Network Control access to resources.
deluge can run as a thin client with a nice looking web ui. If you are looking for bittorrent for windows, deluge comes to your rescue again.download 5 ZyXEL 296 Commercial The ZyWALL IPSec VPN Client is designed for mobile. Non-reviewed Download 3 SonicWALL 5,833 Download SonicWALL 2 Download Nortel Networks NA, download 6 TheGreenBow 887 Shareware TheGreenBow IPSec VPN Client software is an on demand providing remote access. Inc. Download 15 Nokia 192 Freeware Extend your network mobile devices with Nokia Mobile VPN Client Policy Tool.3-monthly, download Watch the short video review and tutorial below of Trust. And yearly. Zone Pricing 4.4 / 5.0 how does proxify work 2 years 2.99 /month 3 months 4.95 /month 1 Month 6.99 /month Trust. Zone has three paid packages monthly,en cualquier lugar. Y siga how does proxify work charlando y compartiendo en cualquier momento, facebook por medio de m, facebook est bloqueado en su ubicacin. Sltese las restricciones y acceda a.
More "How does proxify work"
"Not only does VyprVPN protect our team from DDoS how does proxify work attacks, i purchased a year of the service before the trial even ended." Ameer M.
our VPN Network how does proxify work provides online security and fast, iPVanish is the best VPN vpn setting in android mobile service provider offering secure access and high speeds.


text:
The Fever King by Victoria Lee (Blog Tour Review + Giveaway!)
On March 23, 2019 March 23, 2019 By Annie @ Blossoms and Bullet JournalsIn Book Reviews, Books
The Fever King
Published March 1st, 2019 by Skyscape
Young Adult | Fantasy
★★★★☆
The Fever King is a complex and immersive fantasy novel with sci-fi and dystopian elements that kept me on the edge of my seat.
In the former United States, sixteen-year-old Noam Álvaro wakes up in a hospital bed, the sole survivor of the viral magic that killed his family and made him a technopath. His ability to control technology attracts the attention of the minister of defense and thrusts him into the magical elite of the nation of Carolinia.
The son of undocumented immigrants, Noam has spent his life fighting for the rights of refugees fleeing magical outbreaks—refugees Carolinia routinely deports with vicious efficiency. Sensing a way to make change, Noam accepts the minister's offer to teach him the science behind his magic, secretly planning to use it against the government. But then he meets the minister's son—cruel, dangerous, and achingly beautiful—and the way forward becomes less clear. Caught between his purpose and his heart, Noam must decide who he can trust and how far he's willing to go in pursuit of the greater good.
If you couldn't tell from the four-star rating, I really enjoyed reading The Fever King.
For one thing, it has a super interesting and complex world. There are people with magical powers (called "witchings"), and these magical powers can be controlled with science (like, for example, in order to learn telekinesis, you need to learn physics, etc., which is a pretty cool idea) and are obtained through a magic virus. The book is set over a century in the future, and it was super interesting reading about this possible future that the author dreamed up.
The book's portrayal of this future isn't just focused on magic, though: it has many political elements. In this future, the United States has split up into multiple separate countries, and the novel brings up issues of genocide, xenophobia and mistreatment of refugees, and corruption. I personally found that the incorporation of politics made the storyline even more interesting and complex.
Another thing about this book that's complex is the characters and their relationships. These are the three major characters:
🌟 Noam, the bisexual, Jewish, half-Latinx protagonist who comes from a family of refugees. He's feisty and brave and totally committed to being an activist for immigrant rights and also kind of morally gray—a bit of an antihero. I really loved Noam, and I appreciated that unlike many characters in cliché dystopian novels, he isn't a total genius prodigy—he actually has to work hard and learn things, especially because he dropped out of school when he was young to help support his family.
🌟 Dara, the mysterious roommate at Noam's new government school for witchings who has secret powers and seems to hate Noam…
🌟 Calix Lehrer, Noam and Dara's complex and enigmatic teacher who's basically immortal. You never really understand what his motivations are, which makes his relationship with Noam quite suspenseful.
I think that these complicated characters that Victoria Lee has created are the reason why most readers won't be able to put down The Fever King. The author also did a great job writing-wise in my opinion—I especially enjoyed Noam's inner monologue. He felt like a real teenager who's confused and angry.
The Fever King is about so many things: magic, activism, moral ambiguity, loss, trauma, a hate-to-love romance, and when you put it all together, you have, in my opinion, a great book. The only downsides were that it could get a tad confusing as far as the history and the passage of time, but overall I think that The Fever King is a very well-written story.
Diversity Rep: main character who is Jewish, bisexual, and half-Latinx; two major characters who are non-straight, including one who's a POC and one who's Jewish
Warnings: please be aware of the content warnings for this book, which can be found on the author's website, here.
You can enter for the chance to win a copy of The Fever King HERE! (Make sure to enter before the giveaway closes on March 31st, 2019.)
(US only)
You can find the schedule for the rest of the blog tour for this book here!
Victoria Lee grew up in Durham, North Carolina, where she spent twelve ascetic years as a vegetarian before discovering spicy chicken wings are, in fact, a delicacy. She's been a state finalist competitive pianist, a hitchhiker, a pizza connoisseur, an EMT, an expat in China and Sweden, and a science doctoral student. She's also a bit of a snob about fancy whisky.
Victoria writes early in the morning, then spends the rest of the day trying to impress her border collie puppy and make her experiments work. She is represented by Holly Root and Taylor Haggerty at Root Literary.
Website | Goodreads | Twitter | Facebook | Instagram
Goodreads | Amazon | Barnes & Noble | Book Depository
Do you plan on reading The Fever King? Chat with me in the comments!
Thank you to Fantastic Flying Book Club for including me on the blog tour and for providing me with a review copy of this book! This in no way affected my review.
4 starsarcblog tourbook blogfantasyfeverwakeskyscapethe fever kingvictoria leeyoung adult
12 Exciting YA Books Releasing in Spring 2019
My Favorite Audiobooks (+I Need More Recs??)
6 thoughts on "The Fever King by Victoria Lee (Blog Tour Review + Giveaway!)"
Pingback: Personal Book Awards 2019 – Blossoms and Bullet Journals
Pingback: Mid-Year Reading Reflection | What I Read in the First Half of 2019 – Blossoms and Bullet Journals
Pingback: June '19 Recap | Being Busy and Also Preparing for Something Really Exciting! – Blossoms and Bullet Journals
Pingback: March '19 Recap | School was Tough but Then Spring Break! And My Birthday! – Blossoms and Bullet Journals
Pingback: Sunday Post: Book Pre-order Campaigns & Giveaways Galore – 3/31/19 – Feed Your Fiction Addiction
Pingback: Sunday Post: Pre-order Campaigns & Giveaways Galore – 3/24/19 – Feed Your Fiction Addiction


우리는 중국에서 캔버스 노트북 가방 제조 업체 및 공급 업체 / 공장 전문화되어 있습니다. 캔버스 노트북 가방 중 하나 인 Shenzhen Olinb Bags Co., Ltd. 중국 유명 브랜드 중 하나 인 저렴한 가격 / 저렴한 가격으로 고품질의 캔버스 노트북 가방 도매업.
Wholesale 캔버스 노트북 가방 from China, Need to find cheap 캔버스 노트북 가방 as low price but leading manufacturers. Just find high-quality brands on 캔버스 노트북 가방 produce factory, You can also feedback about what you want, start saving and explore our 캔버스 노트북 가방, We'll reply you in fastest.


text:
Q: How to reset the auto generated primary key in PostgreSQL My class for the table topics is as below. The primary key is autogenerated serial key. While testing, I deleted rows from the table and was trying to re-insert them again. The UUID is not getting reset.
class Topics(db.Model):
    """ User Model for different topics """
    __tablename__ = 'topics'

    uuid = db.Column(db.Integer, primary_key=True)
    topics_name = db.Column(db.String(256),index=True)

    def __repr__(self):
        return '<Post %r>' % self.topics_name

I tried the below command to reset the key
ALTER SEQUENCE topics_uuid_seq RESTART WITH 1;

It did not work.
I would appreciate any form of suggestion!

A: If it's indeed a serial ID, you can reset the owned SEQUENCE with:
SELECT setval(pg_get_serial_sequence('topics', 'uuid'), max(uuid)) FROM topics;

See:
How to reset postgres' primary key sequence when it falls out of sync?
But why would the name be uuid? UUID are not integer numbers and not serial. Also, it's not entirely clear what's going wrong, when you write:

The UUID is not getting reset.

About ALTER SEQUENCE ... RESTART:

*

*Postgres manually alter sequence

A: In order to avoid duplicate id errors that may arise when resetting the sequence try:
UPDATE table SET id = DEFAULT;
ALTER SEQUENCE seq RESTART;
UPDATE table SET id = DEFAULT;

For added context:

*

*'table' = your table name

*'id' = your id column name

*'seq' = find the name of your sequence with:
SELECT pg_get_serial_sequence('table', 'id');


text:
Tag: trey mcintyre
The Trey McIntyre Project Is Back—And Completely Reimagined
Six years after shuttering his popular dance troupe Trey McIntyre Project, its eponymous founder is relaunching the company as a conduit for digital dance films, with a project called FLTPK. "It's not a company of dancers," McIntyre insists. "It's a community of artists." In March, McIntyre was ready to premiere his David Bowie ballet Pretty […]
Nancy Wozny August 3rd, 2020
Trey McIntyre Returns to the Company Where He Got His Start—With a Bowie Playlist
If you're watching a slew of ballet dancers alternate between explosive technical feats and highly nuanced "real people" movement, with iconic rock music blasting, there's a good chance that Trey McIntyre is in the room. Most recently, this room happened to be at Houston Ballet, the very place that nurtured his early life as a […]
Nancy Wozny March 9th, 2020
6 Premieres and Programs on Our Editors' Must-See List This Month
A Broadway luminary and a postmodern darling bring their talents to ballet, a music video maven turns to the concert stage, and a contemporary choreographer gets soulful with Aretha Franklin. Our editors' must-sees this May are all about the unexpected. A Late Commission Tanowitz in rehearsal at NYCB Erin Baiano, Courtesy NYCB NEW YORK CITY […]
Dance Magazine April 30th, 2019
Trey McIntyre's New Documentary Delves Into Why His Company Closed
"The art was telling me that things had to change. And they had to change big. Something I created needed to die off. When the company was at its height, when it was at its most successful, I closed it down." These puzzling words are spoken by choreographer Trey McIntyre in Gravity Hero, his new […]
Madeline Schrock July 22nd, 2018
Ballet Unbound: SFB's 17-Day Festival Asks Where the Art Form is Headed
The ballet world will converge on San Francisco this month for San Francisco Ballet's Unbound: A Festival of New Works, a 17-day event featuring 12 world premieres, a symposium, original dance films and pop-up events. "Ballet is going through changes," says artistic director Helgi Tomasson. "I thought, What would it be like to bring all […]
Claudia Bauer April 18th, 2018
They Founded Companies—Then They Moved On. Here's Why.
Starting and sustaining a dance company is not for the faint of heart. It often takes tremendous sacrifice in terms of time, energy and money. But it's not a life sentence. Arts organizations, like everything else, come to an end, and nothing could be more important to an artist's vitality than knowing when to call […]
Nancy Wozny September 19th, 2017
10 Minutes with Trey McIntyre
The dance world gasped when Trey McIntyre announced in 2014 that he was shutting down his company, Trey McIntyre Project, after six wildly successful years as a full-time troupe. The dashing dancemaker, currently traveling around the country, always had a hand in other projects, such as film and photography, so his next chapter as an […]
Nancy Wozny January 31st, 2016
The Latest: Creating a Contemporary Standard
Trey McIntyre and Matthew Neenan will coach dancers at the 2014 USA IBC. 2010 USA IBC contemporary competitors. Photo by Richard Finkelstein, Courtesy USA IBC. In the contemporary round at ballet competitions, dancers often perform wildly varying styles—it's not uncommon to see neoclassical pointework followed by barefooted modern dance. But the USA International Ballet […]
Joseph Carman May 31st, 2014