#include "imports.h"
#include "slang_assemble.h"
#include "slang_compile.h"
+#include "slang_error.h"
-/*
- * slang_type_specifier
- */
GLvoid
slang_type_specifier_ctr(slang_type_specifier * self)
return 1;
}
-/* slang_assembly_typeinfo */
GLboolean
slang_assembly_typeinfo_construct(slang_assembly_typeinfo * ti)
slang_type_specifier_dtr(&ti->spec);
}
-/* _slang_typeof_operation() */
+/**
+ * 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, slang_operation * params,
- GLuint num_params, slang_assembly_name_space * space,
- slang_type_specifier * spec, slang_atom_pool * atoms)
+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))
+ if (!_slang_typeof_function(atom, params, num_params, space, spec,
+ &exists, atoms))
return GL_FALSE;
return exists;
}
GLboolean
-_slang_typeof_operation(slang_assemble_ctx * A, slang_operation * op,
+_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_(slang_operation * op,
- slang_assembly_name_space * space,
+_slang_typeof_operation_(const slang_operation * op,
+ const slang_assembly_name_space * space,
slang_assembly_typeinfo * ti,
slang_atom_pool * atoms)
{
case slang_oper_preincrement:
case slang_oper_predecrement:
if (!_slang_typeof_operation_(op->children, space, ti, atoms))
- return 0;
+ return GL_FALSE;
break;
case slang_oper_literal_bool:
case slang_oper_logicalor:
case slang_oper_identifier:
{
slang_variable *var;
-
var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
if (var == NULL)
- return GL_FALSE;
+ RETURN_ERROR2("undefined variable", (char *) op->a_id, 0);
if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
ti->can_be_referenced = GL_TRUE;
ti->array_len = var->array_len;
}
case slang_oper_sequence:
/* TODO: check [0] and [1] if they match */
if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
- return GL_FALSE;
+ RETURN_NIL();
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
case slang_oper_select:
/* TODO: check [1] and [2] if they match */
if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
- return GL_FALSE;
+ RETURN_NIL();
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
/*case slang_oper_lshift: */
/*case slang_oper_rshift: */
case slang_oper_add:
- if (!typeof_existing_function
- ("+", op->children, 2, space, &ti->spec, atoms))
- return GL_FALSE;
+ 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 GL_FALSE;
+ 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 GL_FALSE;
+ 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 GL_FALSE;
+ 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 GL_FALSE;
+ 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 GL_FALSE;
+ 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 GL_FALSE;
+ RETURN_NIL();
if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ 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 GL_FALSE;
+ RETURN_NIL();
}
}
else {
if (!_slang_type_is_vector(_ti.spec.type)
&& !_slang_type_is_matrix(_ti.spec.type)) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ RETURN_ERROR("cannot index a non-array type", 0);
}
ti->spec.type = _slang_type_base(_ti.spec.type);
}
{
GLboolean exists;
- if (!_slang_typeof_function
- (op->a_id, op->children, op->num_children, space, &ti->spec,
- &exists, atoms))
- return GL_FALSE;
+ 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);
ti->spec._struct =
(slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
if (ti->spec._struct == NULL)
- return GL_FALSE;
+ RETURN_NIL();
if (!slang_struct_construct(ti->spec._struct)) {
slang_alloc_free(ti->spec._struct);
ti->spec._struct = NULL;
- return GL_FALSE;
+ RETURN_NIL();
}
if (!slang_struct_copy(ti->spec._struct, s))
- return GL_FALSE;
+ RETURN_NIL();
}
else {
const char *name;
name = slang_atom_pool_id(atoms, op->a_id);
type = slang_type_specifier_type_from_string(name);
if (type == slang_spec_void)
- return GL_FALSE;
+ RETURN_ERROR2("function not found", name, 0);
ti->spec.type = type;
}
}
slang_assembly_typeinfo _ti;
if (!slang_assembly_typeinfo_construct(&_ti))
- return GL_FALSE;
+ RETURN_NIL();
if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ 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);
+ field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
+ GL_FALSE);
if (field == NULL) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ RETURN_NIL();
}
if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ RETURN_NIL();
}
ti->can_be_referenced = _ti.can_be_referenced;
}
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 GL_FALSE;
+ 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 GL_FALSE;
+ RETURN_ERROR("Bad swizzle", 0);
}
ti->is_swizzled = GL_TRUE;
ti->can_be_referenced = _ti.can_be_referenced
case slang_oper_postincrement:
case slang_oper_postdecrement:
if (!_slang_typeof_operation_(op->children, space, ti, atoms))
- return GL_FALSE;
+ RETURN_NIL();
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
default:
- return GL_FALSE;
+ RETURN_NIL();
}
return GL_TRUE;
}
-/* _slang_typeof_function() */
+
+/**
+ * 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, slang_operation * params,
- GLuint num_params, slang_assembly_name_space * space,
+_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;
-
- fun =
- _slang_locate_function(space->funcs, a_name, params, num_params, space,
- atoms);
+ slang_function *fun = _slang_locate_function(space->funcs, a_name, params,
+ num_params, space, atoms);
*exists = fun != NULL;
- if (fun == NULL)
- return GL_TRUE;
+ if (!fun)
+ return GL_TRUE; /* yes, not false */
return slang_type_specifier_copy(spec, &fun->header.type.specifier);
}
-/* _slang_type_is_matrix() */
+
+/**
+ * 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)
{
}
}
-/* _slang_type_is_vector() */
+/**
+ * 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)
{
}
}
-/* _slang_type_base_of_vector() */
+/**
+ * Given a vector type, return the type of the vector's elements
+ */
slang_type_specifier_type
_slang_type_base(slang_type_specifier_type ty)
{
}
}
-/* _slang_type_dim */
+/**
+ * Return the dimensionality of a vector or matrix type.
+ */
GLuint
_slang_type_dim(slang_type_specifier_type ty)
{