-/*\r
- * Mesa 3-D graphics library\r
- * Version: 6.5\r
- *\r
- * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included\r
- * in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\r
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- */\r
-\r
-/**\r
- * \file slang_assemble_typeinfo.c\r
- * slang type info\r
- * \author Michal Krol\r
- */\r
-\r
-#include "imports.h"\r
-#include "slang_utility.h"\r
-#include "slang_assemble_typeinfo.h"\r
-\r
-/* slang_assembly_typeinfo */\r
-\r
-GLboolean slang_assembly_typeinfo_construct (slang_assembly_typeinfo *ti)\r
-{\r
- if (!slang_type_specifier_construct (&ti->spec))\r
- return GL_FALSE;\r
- ti->array_len = 0;\r
- return GL_TRUE;\r
-}\r
-\r
-GLvoid slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *ti)\r
-{\r
- slang_type_specifier_destruct (&ti->spec);\r
-}\r
-\r
-/* _slang_typeof_operation() */\r
-\r
-static GLboolean typeof_existing_function (const char *name, slang_operation *params,\r
- GLuint num_params, slang_assembly_name_space *space, slang_type_specifier *spec,\r
- slang_atom_pool *atoms)\r
-{\r
- slang_atom atom;\r
- GLboolean exists;\r
-\r
- atom = slang_atom_pool_atom (atoms, name);\r
- if (!_slang_typeof_function (atom, params, num_params, space, spec, &exists, atoms))\r
- return GL_FALSE;\r
- return exists;\r
-}\r
-\r
-GLboolean _slang_typeof_operation (slang_assemble_ctx *A, slang_operation *op,\r
- slang_assembly_typeinfo *ti)\r
-{\r
- return _slang_typeof_operation_ (op, &A->space, ti, A->atoms);\r
-}\r
-\r
-GLboolean _slang_typeof_operation_ (slang_operation *op, slang_assembly_name_space *space,\r
- slang_assembly_typeinfo *ti, slang_atom_pool *atoms)\r
-{\r
- ti->can_be_referenced = GL_FALSE;\r
- ti->is_swizzled = GL_FALSE;\r
-\r
- switch (op->type)\r
- {\r
- case slang_oper_block_no_new_scope:\r
- case slang_oper_block_new_scope:\r
- case slang_oper_variable_decl:\r
- case slang_oper_asm:\r
- case slang_oper_break:\r
- case slang_oper_continue:\r
- case slang_oper_discard:\r
- case slang_oper_return:\r
- case slang_oper_if:\r
- case slang_oper_while:\r
- case slang_oper_do:\r
- case slang_oper_for:\r
- case slang_oper_void:\r
- ti->spec.type = slang_spec_void;\r
- break;\r
- case slang_oper_expression:\r
- case slang_oper_assign:\r
- case slang_oper_addassign:\r
- case slang_oper_subassign:\r
- case slang_oper_mulassign:\r
- case slang_oper_divassign:\r
- case slang_oper_preincrement:\r
- case slang_oper_predecrement:\r
- if (!_slang_typeof_operation_ (op->children, space, ti, atoms))\r
- return 0;\r
- break;\r
- case slang_oper_literal_bool:\r
- case slang_oper_logicalor:\r
- case slang_oper_logicalxor:\r
- case slang_oper_logicaland:\r
- case slang_oper_equal:\r
- case slang_oper_notequal:\r
- case slang_oper_less:\r
- case slang_oper_greater:\r
- case slang_oper_lessequal:\r
- case slang_oper_greaterequal:\r
- case slang_oper_not:\r
- ti->spec.type = slang_spec_bool;\r
- break;\r
- case slang_oper_literal_int:\r
- ti->spec.type = slang_spec_int;\r
- break;\r
- case slang_oper_literal_float:\r
- ti->spec.type = slang_spec_float;\r
- break;\r
- case slang_oper_identifier:\r
- {\r
- slang_variable *var;\r
-\r
- var = _slang_locate_variable (op->locals, op->a_id, GL_TRUE);\r
- if (var == NULL)\r
- return GL_FALSE;\r
- if (!slang_type_specifier_copy (&ti->spec, &var->type.specifier))\r
- return GL_FALSE;\r
- ti->can_be_referenced = GL_TRUE;\r
- ti->array_len = var->array_len;\r
- }\r
- break;\r
- case slang_oper_sequence:\r
- /* TODO: check [0] and [1] if they match */\r
- if (!_slang_typeof_operation_ (&op->children[1], space, ti, atoms))\r
- return GL_FALSE;\r
- ti->can_be_referenced = GL_FALSE;\r
- ti->is_swizzled = GL_FALSE;\r
- break;\r
- /*case slang_oper_modassign:*/\r
- /*case slang_oper_lshassign:*/\r
- /*case slang_oper_rshassign:*/\r
- /*case slang_oper_orassign:*/\r
- /*case slang_oper_xorassign:*/\r
- /*case slang_oper_andassign:*/\r
- case slang_oper_select:\r
- /* TODO: check [1] and [2] if they match */\r
- if (!_slang_typeof_operation_ (&op->children[1], space, ti, atoms))\r
- return GL_FALSE;\r
- ti->can_be_referenced = GL_FALSE;\r
- ti->is_swizzled = GL_FALSE;\r
- break;\r
- /*case slang_oper_bitor:*/\r
- /*case slang_oper_bitxor:*/\r
- /*case slang_oper_bitand:*/\r
- /*case slang_oper_lshift:*/\r
- /*case slang_oper_rshift:*/\r
- case slang_oper_add:\r
- if (!typeof_existing_function ("+", op->children, 2, space, &ti->spec, atoms))\r
- return GL_FALSE;\r
- break;\r
- case slang_oper_subtract:\r
- if (!typeof_existing_function ("-", op->children, 2, space, &ti->spec, atoms))\r
- return GL_FALSE;\r
- break;\r
- case slang_oper_multiply:\r
- if (!typeof_existing_function ("*", op->children, 2, space, &ti->spec, atoms))\r
- return GL_FALSE;\r
- break;\r
- case slang_oper_divide:\r
- if (!typeof_existing_function ("/", op->children, 2, space, &ti->spec, atoms))\r
- return GL_FALSE;\r
- break;\r
- /*case slang_oper_modulus:*/\r
- case slang_oper_plus:\r
- if (!_slang_typeof_operation_ (op->children, space, ti, atoms))\r
- return GL_FALSE;\r
- ti->can_be_referenced = GL_FALSE;\r
- ti->is_swizzled = GL_FALSE;\r
- break;\r
- case slang_oper_minus:\r
- if (!typeof_existing_function ("-", op->children, 1, space, &ti->spec, atoms))\r
- return GL_FALSE;\r
- break;\r
- /*case slang_oper_complement:*/\r
- case slang_oper_subscript:\r
- {\r
- slang_assembly_typeinfo _ti;\r
-\r
- if (!slang_assembly_typeinfo_construct (&_ti))\r
- return GL_FALSE;\r
- if (!_slang_typeof_operation_ (op->children, space, &_ti, atoms))\r
- {\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- return GL_FALSE;\r
- }\r
- ti->can_be_referenced = _ti.can_be_referenced;\r
- if (_ti.spec.type == slang_spec_array)\r
- {\r
- if (!slang_type_specifier_copy (&ti->spec, _ti.spec._array))\r
- {\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- return GL_FALSE;\r
- }\r
- }\r
- else\r
- {\r
- if (!_slang_type_is_vector (_ti.spec.type) && !_slang_type_is_matrix (_ti.spec.type))\r
- {\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- return GL_FALSE;\r
- }\r
- ti->spec.type = _slang_type_base (_ti.spec.type);\r
- }\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- }\r
- break;\r
- case slang_oper_call:\r
- {\r
- GLboolean exists;\r
-\r
- if (!_slang_typeof_function (op->a_id, op->children, op->num_children, space, &ti->spec,\r
- &exists, atoms))\r
- return GL_FALSE;\r
- if (!exists)\r
- {\r
- slang_struct *s = slang_struct_scope_find (space->structs, op->a_id, GL_TRUE);\r
- if (s != NULL)\r
- {\r
- ti->spec.type = slang_spec_struct;\r
- ti->spec._struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));\r
- if (ti->spec._struct == NULL)\r
- return GL_FALSE;\r
- if (!slang_struct_construct (ti->spec._struct))\r
- {\r
- slang_alloc_free (ti->spec._struct);\r
- ti->spec._struct = NULL;\r
- return GL_FALSE;\r
- }\r
- if (!slang_struct_copy (ti->spec._struct, s))\r
- return GL_FALSE;\r
- }\r
- else\r
- {\r
- const char *name;\r
- slang_type_specifier_type type;\r
-\r
- name = slang_atom_pool_id (atoms, op->a_id);\r
- type = slang_type_specifier_type_from_string (name);\r
- if (type == slang_spec_void)\r
- return GL_FALSE;\r
- ti->spec.type = type;\r
- }\r
- }\r
- }\r
- break;\r
- case slang_oper_field:\r
- {\r
- slang_assembly_typeinfo _ti;\r
-\r
- if (!slang_assembly_typeinfo_construct (&_ti))\r
- return GL_FALSE;\r
- if (!_slang_typeof_operation_ (op->children, space, &_ti, atoms))\r
- {\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- return GL_FALSE;\r
- }\r
- if (_ti.spec.type == slang_spec_struct)\r
- {\r
- slang_variable *field;\r
- \r
- field = _slang_locate_variable (_ti.spec._struct->fields, op->a_id, GL_FALSE);\r
- if (field == NULL)\r
- {\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- return GL_FALSE;\r
- }\r
- if (!slang_type_specifier_copy (&ti->spec, &field->type.specifier))\r
- {\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- return GL_FALSE;\r
- }\r
- ti->can_be_referenced = _ti.can_be_referenced;\r
- }\r
- else\r
- {\r
- GLuint rows;\r
- const char *swizzle;\r
- slang_type_specifier_type base;\r
-\r
- /* determine the swizzle of the field expression */\r
- if (!_slang_type_is_vector (_ti.spec.type))\r
- {\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- return GL_FALSE;\r
- }\r
- rows = _slang_type_dim (_ti.spec.type);\r
- swizzle = slang_atom_pool_id (atoms, op->a_id);\r
- if (!_slang_is_swizzle (swizzle, rows, &ti->swz))\r
- {\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- return GL_FALSE;\r
- }\r
- ti->is_swizzled = GL_TRUE;\r
- ti->can_be_referenced = _ti.can_be_referenced && _slang_is_swizzle_mask (&ti->swz,\r
- rows);\r
- if (_ti.is_swizzled)\r
- {\r
- slang_swizzle swz;\r
-\r
- /* swizzle the swizzle */\r
- _slang_multiply_swizzles (&swz, &_ti.swz, &ti->swz);\r
- ti->swz = swz;\r
- }\r
- base = _slang_type_base (_ti.spec.type);\r
- switch (ti->swz.num_components)\r
- {\r
- case 1:\r
- ti->spec.type = base;\r
- break;\r
- case 2:\r
- switch (base)\r
- {\r
- case slang_spec_float:\r
- ti->spec.type = slang_spec_vec2;\r
- break;\r
- case slang_spec_int:\r
- ti->spec.type = slang_spec_ivec2;\r
- break;\r
- case slang_spec_bool:\r
- ti->spec.type = slang_spec_bvec2;\r
- break;\r
- default:\r
- break;\r
- }\r
- break;\r
- case 3:\r
- switch (base)\r
- {\r
- case slang_spec_float:\r
- ti->spec.type = slang_spec_vec3;\r
- break;\r
- case slang_spec_int:\r
- ti->spec.type = slang_spec_ivec3;\r
- break;\r
- case slang_spec_bool:\r
- ti->spec.type = slang_spec_bvec3;\r
- break;\r
- default:\r
- break;\r
- }\r
- break;\r
- case 4:\r
- switch (base)\r
- {\r
- case slang_spec_float:\r
- ti->spec.type = slang_spec_vec4;\r
- break;\r
- case slang_spec_int:\r
- ti->spec.type = slang_spec_ivec4;\r
- break;\r
- case slang_spec_bool:\r
- ti->spec.type = slang_spec_bvec4;\r
- break;\r
- default:\r
- break;\r
- }\r
- break;\r
- default:\r
- break;\r
- }\r
- }\r
- slang_assembly_typeinfo_destruct (&_ti);\r
- }\r
- break;\r
- case slang_oper_postincrement:\r
- case slang_oper_postdecrement:\r
- if (!_slang_typeof_operation_ (op->children, space, ti, atoms))\r
- return GL_FALSE;\r
- ti->can_be_referenced = GL_FALSE;\r
- ti->is_swizzled = GL_FALSE;\r
- break;\r
- default:\r
- return GL_FALSE;\r
- }\r
-\r
- return GL_TRUE;\r
-}\r
-\r
-/* _slang_typeof_function() */\r
-\r
-GLboolean _slang_typeof_function (slang_atom a_name, slang_operation *params, GLuint num_params,\r
- slang_assembly_name_space *space, slang_type_specifier *spec, GLboolean *exists,\r
- slang_atom_pool *atoms)\r
-{\r
- slang_function *fun;\r
- \r
- fun = _slang_locate_function (space->funcs, a_name, params, num_params, space, atoms);\r
- *exists = fun != NULL;\r
- if (fun == NULL)\r
- return GL_TRUE;\r
- return slang_type_specifier_copy (spec, &fun->header.type.specifier);\r
-}\r
-\r
-/* _slang_type_is_matrix() */\r
-\r
-GLboolean _slang_type_is_matrix (slang_type_specifier_type ty)\r
-{\r
- switch (ty)\r
- {\r
- case slang_spec_mat2:\r
- case slang_spec_mat3:\r
- case slang_spec_mat4:\r
- return GL_TRUE;\r
- default:\r
- return GL_FALSE;\r
- }\r
-}\r
-\r
-/* _slang_type_is_vector() */\r
-\r
-GLboolean _slang_type_is_vector (slang_type_specifier_type ty)\r
-{\r
- switch (ty)\r
- {\r
- case slang_spec_vec2:\r
- case slang_spec_vec3:\r
- case slang_spec_vec4:\r
- case slang_spec_ivec2:\r
- case slang_spec_ivec3:\r
- case slang_spec_ivec4:\r
- case slang_spec_bvec2:\r
- case slang_spec_bvec3:\r
- case slang_spec_bvec4:\r
- return GL_TRUE;\r
- default:\r
- return GL_FALSE;\r
- }\r
-}\r
-\r
-/* _slang_type_base_of_vector() */\r
-\r
-slang_type_specifier_type _slang_type_base (slang_type_specifier_type ty)\r
-{\r
- switch (ty)\r
- {\r
- case slang_spec_float:\r
- case slang_spec_vec2:\r
- case slang_spec_vec3:\r
- case slang_spec_vec4:\r
- return slang_spec_float;\r
- case slang_spec_int:\r
- case slang_spec_ivec2:\r
- case slang_spec_ivec3:\r
- case slang_spec_ivec4:\r
- return slang_spec_int;\r
- case slang_spec_bool:\r
- case slang_spec_bvec2:\r
- case slang_spec_bvec3:\r
- case slang_spec_bvec4:\r
- return slang_spec_bool;\r
- case slang_spec_mat2:\r
- return slang_spec_vec2;\r
- case slang_spec_mat3:\r
- return slang_spec_vec3;\r
- case slang_spec_mat4:\r
- return slang_spec_vec4;\r
- default:\r
- return slang_spec_void;\r
- }\r
-}\r
-\r
-/* _slang_type_dim */\r
-\r
-GLuint _slang_type_dim (slang_type_specifier_type ty)\r
-{\r
- switch (ty)\r
- {\r
- case slang_spec_float:\r
- case slang_spec_int:\r
- case slang_spec_bool:\r
- return 1;\r
- case slang_spec_vec2:\r
- case slang_spec_ivec2:\r
- case slang_spec_bvec2:\r
- case slang_spec_mat2:\r
- return 2;\r
- case slang_spec_vec3:\r
- case slang_spec_ivec3:\r
- case slang_spec_bvec3:\r
- case slang_spec_mat3:\r
- return 3;\r
- case slang_spec_vec4:\r
- case slang_spec_ivec4:\r
- case slang_spec_bvec4:\r
- case slang_spec_mat4:\r
- return 4;\r
- default:\r
- return 0;\r
- }\r
-}\r
-\r
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_assemble_typeinfo.c
+ * slang type info
+ * \author Michal Krol
+ */
+
+#include "imports.h"
+#include "slang_assemble.h"
+#include "slang_compile.h"
+#include "slang_error.h"
+
+
+GLvoid
+slang_type_specifier_ctr(slang_type_specifier * self)
+{
+ self->type = slang_spec_void;
+ self->_struct = NULL;
+ self->_array = NULL;
+}
+
+GLvoid
+slang_type_specifier_dtr(slang_type_specifier * self)
+{
+ if (self->_struct != NULL) {
+ slang_struct_destruct(self->_struct);
+ slang_alloc_free(self->_struct);
+ }
+ if (self->_array != NULL) {
+ slang_type_specifier_dtr(self->_array);
+ slang_alloc_free(self->_array);
+ }
+}
+
+GLboolean
+slang_type_specifier_copy(slang_type_specifier * x,
+ const slang_type_specifier * y)
+{
+ slang_type_specifier z;
+
+ slang_type_specifier_ctr(&z);
+ z.type = y->type;
+ if (z.type == slang_spec_struct) {
+ z._struct = (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
+ if (z._struct == NULL) {
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ if (!slang_struct_construct(z._struct)) {
+ slang_alloc_free(z._struct);
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ if (!slang_struct_copy(z._struct, y->_struct)) {
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ }
+ else if (z.type == slang_spec_array) {
+ z._array =
+ (slang_type_specifier *)
+ slang_alloc_malloc(sizeof(slang_type_specifier));
+ if (z._array == NULL) {
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ slang_type_specifier_ctr(z._array);
+ if (!slang_type_specifier_copy(z._array, y->_array)) {
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ }
+ slang_type_specifier_dtr(x);
+ *x = z;
+ return GL_TRUE;
+}
+
+GLboolean
+slang_type_specifier_equal(const slang_type_specifier * x,
+ const slang_type_specifier * y)
+{
+ if (x->type != y->type)
+ return 0;
+ if (x->type == slang_spec_struct)
+ return slang_struct_equal(x->_struct, y->_struct);
+ if (x->type == slang_spec_array)
+ return slang_type_specifier_equal(x->_array, y->_array);
+ return 1;
+}
+
+
+GLboolean
+slang_assembly_typeinfo_construct(slang_assembly_typeinfo * ti)
+{
+ slang_type_specifier_ctr(&ti->spec);
+ ti->array_len = 0;
+ return GL_TRUE;
+}
+
+GLvoid
+slang_assembly_typeinfo_destruct(slang_assembly_typeinfo * ti)
+{
+ slang_type_specifier_dtr(&ti->spec);
+}
+
+
+/**
+ * Determine the return type of a function.
+ * \param name name of the function
+ * \param params array of function parameters
+ * \param num_params number of parameters
+ * \param space namespace to use
+ * \param spec returns the function's type
+ * \param atoms atom pool
+ * \return GL_TRUE for success, GL_FALSE if failure
+ */
+static GLboolean
+typeof_existing_function(const char *name, const slang_operation * params,
+ GLuint num_params,
+ const slang_assembly_name_space * space,
+ slang_type_specifier * spec,
+ slang_atom_pool * atoms)
+{
+ slang_atom atom;
+ GLboolean exists;
+
+ atom = slang_atom_pool_atom(atoms, name);
+ if (!_slang_typeof_function(atom, params, num_params, space, spec,
+ &exists, atoms))
+ return GL_FALSE;
+ return exists;
+}
+
+GLboolean
+_slang_typeof_operation(const slang_assemble_ctx * A,
+ const slang_operation * op,
+ slang_assembly_typeinfo * ti)
+{
+ return _slang_typeof_operation_(op, &A->space, ti, A->atoms);
+}
+
+
+/**
+ * Determine the return type of an operation.
+ * \param op the operation node
+ * \param space the namespace to use
+ * \param ti the returned type
+ * \param atoms atom pool
+ * \return GL_TRUE for success, GL_FALSE if failure
+ */
+GLboolean
+_slang_typeof_operation_(const slang_operation * op,
+ const slang_assembly_name_space * space,
+ slang_assembly_typeinfo * ti,
+ slang_atom_pool * atoms)
+{
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+
+ switch (op->type) {
+ case slang_oper_block_no_new_scope:
+ case slang_oper_block_new_scope:
+ case slang_oper_variable_decl:
+ case slang_oper_asm:
+ case slang_oper_break:
+ case slang_oper_continue:
+ case slang_oper_discard:
+ case slang_oper_return:
+ case slang_oper_if:
+ case slang_oper_while:
+ case slang_oper_do:
+ case slang_oper_for:
+ case slang_oper_void:
+ ti->spec.type = slang_spec_void;
+ break;
+ case slang_oper_expression:
+ case slang_oper_assign:
+ case slang_oper_addassign:
+ case slang_oper_subassign:
+ case slang_oper_mulassign:
+ case slang_oper_divassign:
+ case slang_oper_preincrement:
+ case slang_oper_predecrement:
+ if (!_slang_typeof_operation_(op->children, space, ti, atoms))
+ return GL_FALSE;
+ break;
+ case slang_oper_literal_bool:
+ case slang_oper_logicalor:
+ case slang_oper_logicalxor:
+ case slang_oper_logicaland:
+ case slang_oper_equal:
+ case slang_oper_notequal:
+ case slang_oper_less:
+ case slang_oper_greater:
+ case slang_oper_lessequal:
+ case slang_oper_greaterequal:
+ case slang_oper_not:
+ ti->spec.type = slang_spec_bool;
+ break;
+ case slang_oper_literal_int:
+ ti->spec.type = slang_spec_int;
+ break;
+ case slang_oper_literal_float:
+ ti->spec.type = slang_spec_float;
+ break;
+ case slang_oper_identifier:
+ {
+ slang_variable *var;
+ var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
+ if (var == NULL)
+ RETURN_ERROR2("undefined variable", (char *) op->a_id, 0);
+ if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier))
+ RETURN_OUT_OF_MEMORY();
+ ti->can_be_referenced = GL_TRUE;
+ ti->array_len = var->array_len;
+ }
+ break;
+ case slang_oper_sequence:
+ /* TODO: check [0] and [1] if they match */
+ if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
+ RETURN_NIL();
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+ break;
+ /*case slang_oper_modassign: */
+ /*case slang_oper_lshassign: */
+ /*case slang_oper_rshassign: */
+ /*case slang_oper_orassign: */
+ /*case slang_oper_xorassign: */
+ /*case slang_oper_andassign: */
+ case slang_oper_select:
+ /* TODO: check [1] and [2] if they match */
+ if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
+ RETURN_NIL();
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+ break;
+ /*case slang_oper_bitor: */
+ /*case slang_oper_bitxor: */
+ /*case slang_oper_bitand: */
+ /*case slang_oper_lshift: */
+ /*case slang_oper_rshift: */
+ case slang_oper_add:
+ if (!typeof_existing_function("+", op->children, 2, space,
+ &ti->spec, atoms))
+ RETURN_NIL();
+ break;
+ case slang_oper_subtract:
+ if (!typeof_existing_function("-", op->children, 2, space,
+ &ti->spec, atoms))
+ RETURN_NIL();
+ break;
+ case slang_oper_multiply:
+ if (!typeof_existing_function("*", op->children, 2, space,
+ &ti->spec, atoms))
+ RETURN_NIL();
+ break;
+ case slang_oper_divide:
+ if (!typeof_existing_function("/", op->children, 2, space,
+ &ti->spec, atoms))
+ RETURN_NIL();
+ break;
+ /*case slang_oper_modulus: */
+ case slang_oper_plus:
+ if (!_slang_typeof_operation_(op->children, space, ti, atoms))
+ RETURN_NIL();
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+ break;
+ case slang_oper_minus:
+ if (!typeof_existing_function("-", op->children, 1, space,
+ &ti->spec, atoms))
+ RETURN_NIL();
+ break;
+ /*case slang_oper_complement: */
+ case slang_oper_subscript:
+ {
+ slang_assembly_typeinfo _ti;
+
+ if (!slang_assembly_typeinfo_construct(&_ti))
+ RETURN_NIL();
+ if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
+ slang_assembly_typeinfo_destruct(&_ti);
+ RETURN_NIL();
+ }
+ ti->can_be_referenced = _ti.can_be_referenced;
+ if (_ti.spec.type == slang_spec_array) {
+ if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
+ slang_assembly_typeinfo_destruct(&_ti);
+ RETURN_NIL();
+ }
+ }
+ else {
+ if (!_slang_type_is_vector(_ti.spec.type)
+ && !_slang_type_is_matrix(_ti.spec.type)) {
+ slang_assembly_typeinfo_destruct(&_ti);
+ RETURN_ERROR("cannot index a non-array type", 0);
+ }
+ ti->spec.type = _slang_type_base(_ti.spec.type);
+ }
+ slang_assembly_typeinfo_destruct(&_ti);
+ }
+ break;
+ case slang_oper_call:
+ {
+ GLboolean exists;
+
+ if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
+ space, &ti->spec, &exists, atoms))
+ RETURN_NIL();
+ if (!exists) {
+ slang_struct *s =
+ slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
+ if (s != NULL) {
+ ti->spec.type = slang_spec_struct;
+ ti->spec._struct =
+ (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
+ if (ti->spec._struct == NULL)
+ RETURN_NIL();
+ if (!slang_struct_construct(ti->spec._struct)) {
+ slang_alloc_free(ti->spec._struct);
+ ti->spec._struct = NULL;
+ RETURN_NIL();
+ }
+ if (!slang_struct_copy(ti->spec._struct, s))
+ RETURN_NIL();
+ }
+ else {
+ const char *name;
+ slang_type_specifier_type type;
+
+ name = slang_atom_pool_id(atoms, op->a_id);
+ type = slang_type_specifier_type_from_string(name);
+ if (type == slang_spec_void)
+ RETURN_ERROR2("function not found", name, 0);
+ ti->spec.type = type;
+ }
+ }
+ }
+ break;
+ case slang_oper_field:
+ {
+ slang_assembly_typeinfo _ti;
+
+ if (!slang_assembly_typeinfo_construct(&_ti))
+ RETURN_NIL();
+ if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
+ slang_assembly_typeinfo_destruct(&_ti);
+ RETURN_NIL();
+ }
+ if (_ti.spec.type == slang_spec_struct) {
+ slang_variable *field;
+
+ field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
+ GL_FALSE);
+ if (field == NULL) {
+ slang_assembly_typeinfo_destruct(&_ti);
+ RETURN_NIL();
+ }
+ if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
+ slang_assembly_typeinfo_destruct(&_ti);
+ RETURN_NIL();
+ }
+ ti->can_be_referenced = _ti.can_be_referenced;
+ }
+ else {
+ GLuint rows;
+ const char *swizzle;
+ slang_type_specifier_type base;
+
+ /* determine the swizzle of the field expression */
+#if 000
+ if (!_slang_type_is_vector(_ti.spec.type)) {
+ slang_assembly_typeinfo_destruct(&_ti);
+ RETURN_ERROR("Can't swizzle scalar expression", 0);
+ }
+#endif
+ rows = _slang_type_dim(_ti.spec.type);
+ swizzle = slang_atom_pool_id(atoms, op->a_id);
+ if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
+ slang_assembly_typeinfo_destruct(&_ti);
+ RETURN_ERROR("Bad swizzle", 0);
+ }
+ ti->is_swizzled = GL_TRUE;
+ ti->can_be_referenced = _ti.can_be_referenced
+ && _slang_is_swizzle_mask(&ti->swz, rows);
+ if (_ti.is_swizzled) {
+ slang_swizzle swz;
+
+ /* swizzle the swizzle */
+ _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
+ ti->swz = swz;
+ }
+ base = _slang_type_base(_ti.spec.type);
+ switch (ti->swz.num_components) {
+ case 1:
+ ti->spec.type = base;
+ break;
+ case 2:
+ switch (base) {
+ case slang_spec_float:
+ ti->spec.type = slang_spec_vec2;
+ break;
+ case slang_spec_int:
+ ti->spec.type = slang_spec_ivec2;
+ break;
+ case slang_spec_bool:
+ ti->spec.type = slang_spec_bvec2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 3:
+ switch (base) {
+ case slang_spec_float:
+ ti->spec.type = slang_spec_vec3;
+ break;
+ case slang_spec_int:
+ ti->spec.type = slang_spec_ivec3;
+ break;
+ case slang_spec_bool:
+ ti->spec.type = slang_spec_bvec3;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 4:
+ switch (base) {
+ case slang_spec_float:
+ ti->spec.type = slang_spec_vec4;
+ break;
+ case slang_spec_int:
+ ti->spec.type = slang_spec_ivec4;
+ break;
+ case slang_spec_bool:
+ ti->spec.type = slang_spec_bvec4;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ slang_assembly_typeinfo_destruct(&_ti);
+ }
+ break;
+ case slang_oper_postincrement:
+ case slang_oper_postdecrement:
+ if (!_slang_typeof_operation_(op->children, space, ti, atoms))
+ RETURN_NIL();
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+ break;
+ default:
+ RETURN_NIL();
+ }
+
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Determine the return type of a function.
+ * \param a_name the function name
+ * \param param function parameters (overloading)
+ * \param num_params number of parameters to function
+ * \param space namespace to search
+ * \param exists returns GL_TRUE or GL_FALSE to indicate existance of function
+ * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
+ */
+GLboolean
+_slang_typeof_function(slang_atom a_name, const slang_operation * params,
+ GLuint num_params,
+ const slang_assembly_name_space * space,
+ slang_type_specifier * spec, GLboolean * exists,
+ slang_atom_pool * atoms)
+{
+ slang_function *fun = _slang_locate_function(space->funcs, a_name, params,
+ num_params, space, atoms);
+ *exists = fun != NULL;
+ if (!fun)
+ return GL_TRUE; /* yes, not false */
+ return slang_type_specifier_copy(spec, &fun->header.type.specifier);
+}
+
+
+
+/**
+ * Determine if a type is a matrix.
+ * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
+ */
+GLboolean
+_slang_type_is_matrix(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case slang_spec_mat2:
+ case slang_spec_mat3:
+ case slang_spec_mat4:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Determine if a type is a vector.
+ * \return GL_TRUE if is a vector, GL_FALSE otherwise.
+ */
+GLboolean
+_slang_type_is_vector(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case slang_spec_vec2:
+ case slang_spec_vec3:
+ case slang_spec_vec4:
+ case slang_spec_ivec2:
+ case slang_spec_ivec3:
+ case slang_spec_ivec4:
+ case slang_spec_bvec2:
+ case slang_spec_bvec3:
+ case slang_spec_bvec4:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Given a vector type, return the type of the vector's elements
+ */
+slang_type_specifier_type
+_slang_type_base(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case slang_spec_float:
+ case slang_spec_vec2:
+ case slang_spec_vec3:
+ case slang_spec_vec4:
+ return slang_spec_float;
+ case slang_spec_int:
+ case slang_spec_ivec2:
+ case slang_spec_ivec3:
+ case slang_spec_ivec4:
+ return slang_spec_int;
+ case slang_spec_bool:
+ case slang_spec_bvec2:
+ case slang_spec_bvec3:
+ case slang_spec_bvec4:
+ return slang_spec_bool;
+ case slang_spec_mat2:
+ return slang_spec_vec2;
+ case slang_spec_mat3:
+ return slang_spec_vec3;
+ case slang_spec_mat4:
+ return slang_spec_vec4;
+ default:
+ return slang_spec_void;
+ }
+}
+
+
+/**
+ * Return the dimensionality of a vector or matrix type.
+ */
+GLuint
+_slang_type_dim(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case slang_spec_float:
+ case slang_spec_int:
+ case slang_spec_bool:
+ return 1;
+ case slang_spec_vec2:
+ case slang_spec_ivec2:
+ case slang_spec_bvec2:
+ case slang_spec_mat2:
+ return 2;
+ case slang_spec_vec3:
+ case slang_spec_ivec3:
+ case slang_spec_bvec3:
+ case slang_spec_mat3:
+ return 3;
+ case slang_spec_vec4:
+ case slang_spec_ivec4:
+ case slang_spec_bvec4:
+ case slang_spec_mat4:
+ return 4;
+ default:
+ return 0;
+ }
+}