slang_operation_copy(inlined, fun->body);
/*** XXX review this */
- assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE);
+ assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
+ inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE);
inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE;
#if 0
* all of them...
*/
static slang_function *
-_slang_find_function_by_argc(struct slang_function_scope_ *scope,
+_slang_find_function_by_argc(slang_function_scope *scope,
const char *name, int numArgs)
{
- GLuint i;
- for (i = 0; i < scope->num_functions; i++) {
- slang_function *f = &scope->functions[i];
- if (strcmp(name, (char*) f->header.a_name) == 0
- /*&& numArgs == f->param_count*/)
- return f;
+ while (scope) {
+ GLuint i;
+ for (i = 0; i < scope->num_functions; i++) {
+ slang_function *f = &scope->functions[i];
+ if (strcmp(name, (char*) f->header.a_name) == 0) {
+ int haveRetValue = _slang_function_has_return_value(f);
+ if (numArgs == f->param_count - haveRetValue)
+ return f;
+ }
+ }
+ scope = scope->outer_scope;
}
- if (scope->outer_scope)
- return _slang_find_function_by_argc(scope->outer_scope, name, numArgs);
+
return NULL;
}
+static slang_function *
+_slang_find_function_by_max_argc(slang_function_scope *scope,
+ const char *name)
+{
+ slang_function *maxFunc = NULL;
+ GLuint maxArgs = 0;
+
+ while (scope) {
+ GLuint i;
+ for (i = 0; i < scope->num_functions; i++) {
+ slang_function *f = &scope->functions[i];
+ if (strcmp(name, (char*) f->header.a_name) == 0) {
+ if (f->param_count > maxArgs) {
+ maxArgs = f->param_count;
+ maxFunc = f;
+ }
+ }
+ }
+ scope = scope->outer_scope;
+ }
+
+ return maxFunc;
+}
+
+
/**
* Generate a new slang_function which is a constructor for a user-defined
* struct type.
* return T;
*/
{
+ slang_variable_scope *scope;
slang_variable *var;
GLint i;
fun->body = slang_operation_new(1);
- fun->body->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+ fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
fun->body->num_children = numFields + 2;
fun->body->children = slang_operation_new(numFields + 2);
+ scope = fun->body->locals;
+ scope->outer_scope = fun->parameters;
+
/* create local var 't' */
- var = slang_variable_scope_grow(fun->parameters);
+ var = slang_variable_scope_grow(scope);
var->a_name = slang_atom_pool_atom(A->atoms, "t");
var->type = fun->header.type;
decl = &fun->body->children[0];
decl->type = SLANG_OPER_VARIABLE_DECL;
- decl->locals = _slang_variable_scope_new(fun->parameters);
+ decl->locals = _slang_variable_scope_new(scope);
decl->a_id = var->a_name;
}
slang_operation *assign = &fun->body->children[1 + i];
assign->type = SLANG_OPER_ASSIGN;
- assign->locals = _slang_variable_scope_new(fun->parameters);
+ assign->locals = _slang_variable_scope_new(scope);
assign->num_children = 2;
assign->children = slang_operation_new(2);
slang_operation *lhs = &assign->children[0];
lhs->type = SLANG_OPER_FIELD;
- lhs->locals = _slang_variable_scope_new(fun->parameters);
+ lhs->locals = _slang_variable_scope_new(scope);
lhs->num_children = 1;
lhs->children = slang_operation_new(1);
lhs->a_id = str->fields->variables[i]->a_name;
lhs->children[0].type = SLANG_OPER_IDENTIFIER;
lhs->children[0].a_id = var->a_name;
- lhs->children[0].locals = _slang_variable_scope_new(fun->parameters);
+ lhs->children[0].locals = _slang_variable_scope_new(scope);
#if 0
lhs->children[1].num_children = 1;
lhs->children[1].children = slang_operation_new(1);
lhs->children[1].children[0].type = SLANG_OPER_IDENTIFIER;
lhs->children[1].children[0].a_id = str->fields->variables[i]->a_name;
- lhs->children[1].children->locals = _slang_variable_scope_new(fun->parameters);
+ lhs->children[1].children->locals = _slang_variable_scope_new(scope);
#endif
}
slang_operation *rhs = &assign->children[1];
rhs->type = SLANG_OPER_IDENTIFIER;
- rhs->locals = _slang_variable_scope_new(fun->parameters);
+ rhs->locals = _slang_variable_scope_new(scope);
rhs->a_id = str->fields->variables[i]->a_name;
}
}
slang_operation *ret = &fun->body->children[numFields + 1];
ret->type = SLANG_OPER_RETURN;
- ret->locals = _slang_variable_scope_new(fun->parameters);
+ ret->locals = _slang_variable_scope_new(scope);
ret->num_children = 1;
ret->children = slang_operation_new(1);
ret->children[0].type = SLANG_OPER_IDENTIFIER;
ret->children[0].a_id = var->a_name;
- ret->children[0].locals = _slang_variable_scope_new(fun->parameters);
+ ret->children[0].locals = _slang_variable_scope_new(scope);
}
}
}
+
+static GLboolean
+_slang_is_vec_mat_type(const char *name)
+{
+ static const char *vecmat_types[] = {
+ "float", "int", "bool",
+ "vec2", "vec3", "vec4",
+ "ivec2", "ivec3", "ivec4",
+ "bvec2", "bvec3", "bvec4",
+ "mat2", "mat3", "mat4",
+ "mat2x3", "mat2x4", "mat3x2", "mat3x4", "mat4x2", "mat4x3",
+ NULL
+ };
+ int i;
+ for (i = 0; vecmat_types[i]; i++)
+ if (_mesa_strcmp(name, vecmat_types[i]) == 0)
+ return GL_TRUE;
+ return GL_FALSE;
+}
+
+
/**
* Assemble a function call, given a particular function name.
* \param name the function's name (operators like '*' are possible).
const GLuint param_count = oper->num_children;
slang_atom atom;
slang_function *fun;
+ GLboolean error;
atom = slang_atom_pool_atom(A->atoms, name);
if (atom == SLANG_ATOM_NULL)
return NULL;
/*
- * Use 'name' to find the function to call
+ * First, try to find function by name and exact argument type matching.
*/
fun = _slang_locate_function(A->space.funcs, atom, params, param_count,
- &A->space, A->atoms, A->log);
+ &A->space, A->atoms, A->log, &error);
+
+ if (error) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
+ return NULL;
+ }
if (!fun) {
+ /* Next, try locating a constructor function for a user-defined type */
fun = _slang_locate_struct_constructor(A, name);
}
- if (!fun) {
- /* A function with exactly the right parameters/types was not found.
- * Try adapting the parameters.
+ if (!fun && _slang_is_vec_mat_type(name)) {
+ /* Next, if this call looks like a vec() or mat() constructor call,
+ * try "unwinding" the args to satisfy a constructor.
*/
+ fun = _slang_find_function_by_max_argc(A->space.funcs, name);
+ if (fun) {
+ if (!_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
+ return NULL;
+ }
+ }
+ }
+
+ if (!fun) {
+ /* Next, try casting args to the types of the formal parameters */
int numArgs = oper->num_children;
fun = _slang_find_function_by_argc(A->space.funcs, name, numArgs);
- if (!fun || !_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
- slang_info_log_error(A->log, "Function '%s' not found (check argument types)", name);
+ if (!fun || !_slang_cast_func_params(oper, fun, &A->space, A->atoms, A->log)) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
return NULL;
}
assert(fun);
/*n->Store = _slang_clone_ir_storage_swz(n->Store, */
n->Writemask = WRITEMASK_X << index;
}
+ assert(n->Store);
return n;
}
else {
}
}
+ if (!array->Store) {
+ slang_info_log_error(A->log, "Invalid array");
+ return NULL;
+ }
+
elem = new_node2(IR_ELEMENT, array, index);
elem->Store = _slang_new_ir_storage_relative(constIndex,
elemSize,
array->Store);
+ assert(elem->Store->Parent);
/* XXX try to do some array bounds checking here */
return elem;
}
#endif
+#if 0
+static void
+_slang_undeclare_vars(slang_variable_scope *locals)
+{
+ if (locals->num_variables > 0) {
+ int i;
+ for (i = 0; i < locals->num_variables; i++) {
+ slang_variable *v = locals->variables[i];
+ printf("undeclare %s at %p\n", (char*) v->a_name, v);
+ v->declared = GL_FALSE;
+ }
+ }
+}
+#endif
+
+
/**
* Generate IR tree for a slang_operation (AST node)
*/
_slang_pop_var_table(A->vartable);
+ /*_slang_undeclare_vars(oper->locals);*/
/*print_vars(oper->locals);*/
if (n)
tree = new_seq(tree, n);
}
-#if 00
- if (oper->locals->num_variables > 0) {
- int i;
- /*
- printf("\n****** Deallocate vars in scope!\n");
- */
- for (i = 0; i < oper->locals->num_variables; i++) {
- slang_variable *v = oper->locals->variables + i;
- if (v->aux) {
- slang_ir_storage *store = (slang_ir_storage *) v->aux;
- /*
- printf(" Deallocate var %s\n", (char*) v->a_name);
- */
- assert(store->File == PROGRAM_TEMPORARY);
- assert(store->Index >= 0);
- _slang_free_temp(A->vartable, store->Index, store->Size);
- }
- }
- }
-#endif
- /*print_vars(oper->locals);*/
return tree;
}
else {
static GLboolean
parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O,
- slang_variable * var, const slang_type_specifier * sp)
+ slang_variable * var, slang_atom a_name,
+ const slang_type_specifier * sp)
{
- var->a_name = parse_identifier(C);
+ var->a_name = a_name;
if (var->a_name == SLANG_ATOM_NULL)
return GL_FALSE;
return 0;
do {
+ slang_atom a_name;
slang_variable *var = slang_variable_scope_grow(st->fields);
if (!var) {
slang_info_log_memory(C->L);
return 0;
}
- if (!parse_struct_field_var(C, &o, var, sp))
+ a_name = parse_identifier(C);
+ if (_slang_locate_variable(st->fields, a_name, GL_FALSE)) {
+ slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name);
+ return 0;
+ }
+
+ if (!parse_struct_field_var(C, &o, var, a_name, sp))
return 0;
}
while (*C->I++ != FIELD_NONE);
const slang_fully_specified_type * type)
{
slang_variable *var;
+ slang_atom a_name;
/* empty init declatator (without name, e.g. "float ;") */
if (*C->I++ == VARIABLE_NONE)
return 1;
+ a_name = parse_identifier(C);
+
+ /* check if name is already in this scope */
+ if (_slang_locate_variable(O->vars, a_name, GL_FALSE)) {
+ slang_info_log_error(C->L,
+ "declaration of '%s' conflicts with previous declaration",
+ (char *) a_name);
+ return 0;
+ }
+
/* make room for the new variable and initialize it */
var = slang_variable_scope_grow(O->vars);
if (!var) {
/* copy the declarator qualifier type, parse the identifier */
var->type.qualifier = type->qualifier;
- var->a_name = parse_identifier(C);
+ var->a_name = a_name;
if (var->a_name == SLANG_ATOM_NULL)
return 0;
A.space.vars = O->vars;
A.program = O->program;
A.vartable = O->vartable;
+ A.log = C->L;
A.curFuncEndLabel = NULL;
if (!_slang_codegen_global_variable(&A, var, C->type))
return 0;
GLboolean success;
grammar id = 0;
-#if 0 /* for debug */
+#if 1 /* for debug */
_mesa_printf("********* COMPILE SHADER ***********\n");
_mesa_printf("%s\n", shader->Source);
_mesa_printf("************************************\n");
var->size = 0;
var->isTemp = GL_FALSE;
var->aux = NULL;
+ var->declared = 0;
return 1;
}
}
+/**
+ * Search for named variable in given scope.
+ * \param all if true, search parent scopes too.
+ */
slang_variable *
_slang_locate_variable(const slang_variable_scope * scope,
const slang_atom a_name, GLboolean all)
{
- GLuint i;
-
- for (i = 0; i < scope->num_variables; i++)
- if (a_name == scope->variables[i]->a_name)
- return scope->variables[i];
- if (all && scope->outer_scope != NULL)
- return _slang_locate_variable(scope->outer_scope, a_name, 1);
+ while (scope) {
+ GLuint i;
+ for (i = 0; i < scope->num_variables; i++)
+ if (a_name == scope->variables[i]->a_name)
+ return scope->variables[i];
+ if (all)
+ scope = scope->outer_scope;
+ else
+ scope = NULL;
+ }
return NULL;
}
}
assert(st->File >= 0);
+#if 1 /* XXX temporary */
+ if (st->File == PROGRAM_UNDEFINED) {
+ slang_ir_storage *st0 = (slang_ir_storage *) st;
+ st0->File = PROGRAM_TEMPORARY;
+ }
+#endif
assert(st->File < PROGRAM_UNDEFINED);
src->File = st->File;
/*
* Mesa 3-D graphics library
- * Version: 6.5.2
+ * Version: 7.1
*
- * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 2005-2008 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"),
*/
/**
- * \file slang_assemble_typeinfo.c
- * slang type info
- * \author Michal Krol
+ * Functions for constant folding, built-in constant lookup, and function
+ * call casting.
*/
+
#include "main/imports.h"
#include "main/macros.h"
#include "main/get.h"
/**
- * Adapt the arguments for a function call to match the parameters of
- * the given function.
- * This is for:
- * 1. converting/casting argument types to match parameters
- * 2. breaking up vector/matrix types into individual components to
- * satisfy constructors.
+ * Insert casts to try to adapt actual parameters to formal parameters for a
+ * function call when an exact match for the parameter types is not found.
+ * Example:
+ * void foo(int i, bool b) {}
+ * x = foo(3.15, 9);
+ * Gets translated into:
+ * x = foo(int(3.15), bool(9))
*/
GLboolean
-_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
- const slang_name_space * space,
- slang_atom_pool * atoms, slang_info_log *log)
+_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
+ const slang_name_space * space,
+ slang_atom_pool * atoms, slang_info_log *log)
{
const GLboolean haveRetValue = _slang_function_has_return_value(fun);
const int numParams = fun->param_count - haveRetValue;
int dbg = 0;
if (dbg)
- printf("Adapt %d args to %d parameters for %s\n",
- callOper->num_children, numParams, (char *) fun->header.a_name);
+ printf("Adapt call of %d args to func %s (%d params)\n",
+ callOper->num_children, (char*) fun->header.a_name, numParams);
- /* Only try adapting for constructors */
- if (fun->kind != SLANG_FUNC_CONSTRUCTOR)
- return GL_FALSE;
-
- if (callOper->num_children != numParams) {
- /* number of arguments doesn't match number of parameters */
-
- if (fun->kind == SLANG_FUNC_CONSTRUCTOR) {
- /* For constructor calls, we can try to unroll vector/matrix args
- * into individual floats/ints and try to match the function params.
- */
- for (i = 0; i < numParams; i++) {
- slang_typeinfo argType;
- GLint argSz, j;
-
- /* Get type of arg[i] */
- if (!slang_typeinfo_construct(&argType))
- return GL_FALSE;
- if (!_slang_typeof_operation_(&callOper->children[i], space,
- &argType, atoms, log)) {
- slang_typeinfo_destruct(&argType);
- return GL_FALSE;
- }
-
- /*
- paramSz = _slang_sizeof_type_specifier(¶mVar->type.specifier);
- assert(paramSz == 1);
- */
- argSz = _slang_sizeof_type_specifier(&argType.spec);
- if (argSz > 1) {
- slang_operation origArg;
- /* break up arg[i] into components */
- if (dbg)
- printf("Break up arg %d from 1 to %d elements\n", i, argSz);
-
- slang_operation_construct(&origArg);
- slang_operation_copy(&origArg,
- &callOper->children[i]);
-
- /* insert argSz-1 new children/args */
- for (j = 0; j < argSz - 1; j++) {
- (void) slang_operation_insert(&callOper->num_children,
- &callOper->children, i);
- }
-
- /* replace arg[i+j] with subscript/index oper */
- for (j = 0; j < argSz; j++) {
- callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT;
- callOper->children[i + j].num_children = 2;
- callOper->children[i + j].children = slang_operation_new(2);
- slang_operation_copy(&callOper->children[i + j].children[0],
- &origArg);
- callOper->children[i + j].children[1].type
- = SLANG_OPER_LITERAL_INT;
- callOper->children[i + j].children[1].literal[0] = (GLfloat) j;
- }
-
- }
- } /* for i */
- }
- else {
- /* non-constructor function: number of args must match number
- * of function params.
- */
- return GL_FALSE; /* caller will record an error msg */
- }
- }
-
- if (callOper->num_children < (GLuint) numParams) {
- /* still not enough args for all params */
- return GL_FALSE;
- }
- else if (callOper->num_children > (GLuint) numParams) {
- /* now too many arguments */
- /* XXX this isn't always an error, see spec */
- return GL_FALSE;
- }
-
- /*
- * Second phase, argument casting.
- * Example:
- * void foo(int i, bool b) {}
- * x = foo(3.15, 9);
- * Gets translated into:
- * x = foo(int(3.15), bool(9))
- */
for (i = 0; i < numParams; i++) {
slang_typeinfo argType;
slang_variable *paramVar = fun->parameters->variables[i];
slang_operation_copy(child, &callOper->children[i]);
child->locals->outer_scope = callOper->children[i].locals;
+#if 0
+ if (_slang_sizeof_type_specifier(&argType.spec) >
+ _slang_sizeof_type_specifier(¶mVar->type.specifier)) {
+ }
+#endif
+
callOper->children[i].type = SLANG_OPER_CALL;
callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName);
callOper->children[i].num_children = 1;
slang_typeinfo_destruct(&argType);
}
+ if (dbg) {
+ printf("===== New call to %s with cast arguments ===============\n",
+ (char*) fun->header.a_name);
+ slang_print_tree(callOper, 5);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Adapt the arguments for a function call to match the parameters of
+ * the given function.
+ * This is for:
+ * 1. converting/casting argument types to match parameters
+ * 2. breaking up vector/matrix types into individual components to
+ * satisfy constructors.
+ */
+GLboolean
+_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
+ const slang_name_space * space,
+ slang_atom_pool * atoms, slang_info_log *log)
+{
+ const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+ const int numParams = fun->param_count - haveRetValue;
+ int i;
+ int dbg = 0;
+
+ if (dbg)
+ printf("Adapt %d args to %d parameters for %s\n",
+ callOper->num_children, numParams, (char *) fun->header.a_name);
+
+ /* Only try adapting for constructors */
+ if (fun->kind != SLANG_FUNC_CONSTRUCTOR)
+ return GL_FALSE;
+
+ if (callOper->num_children != numParams) {
+ /* number of arguments doesn't match number of parameters */
+
+ /* For constructor calls, we can try to unroll vector/matrix args
+ * into individual floats/ints and try to match the function params.
+ */
+ for (i = 0; i < numParams; i++) {
+ slang_typeinfo argType;
+ GLint argSz, j;
+
+ /* Get type of arg[i] */
+ if (!slang_typeinfo_construct(&argType))
+ return GL_FALSE;
+ if (!_slang_typeof_operation_(&callOper->children[i], space,
+ &argType, atoms, log)) {
+ slang_typeinfo_destruct(&argType);
+ return GL_FALSE;
+ }
+
+ /*
+ paramSz = _slang_sizeof_type_specifier(¶mVar->type.specifier);
+ assert(paramSz == 1);
+ */
+ argSz = _slang_sizeof_type_specifier(&argType.spec);
+ if (argSz > 1) {
+ slang_operation origArg;
+ /* break up arg[i] into components */
+ if (dbg)
+ printf("Break up arg %d from 1 to %d elements\n", i, argSz);
+
+ slang_operation_construct(&origArg);
+ slang_operation_copy(&origArg, &callOper->children[i]);
+
+ /* insert argSz-1 new children/args */
+ for (j = 0; j < argSz - 1; j++) {
+ (void) slang_operation_insert(&callOper->num_children,
+ &callOper->children, i);
+ }
+
+ /* replace arg[i+j] with subscript/index oper */
+ for (j = 0; j < argSz; j++) {
+ callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT;
+ callOper->children[i + j].locals = _slang_variable_scope_new(callOper->locals);
+ callOper->children[i + j].num_children = 2;
+ callOper->children[i + j].children = slang_operation_new(2);
+ slang_operation_copy(&callOper->children[i + j].children[0],
+ &origArg);
+ callOper->children[i + j].children[1].type
+ = SLANG_OPER_LITERAL_INT;
+ callOper->children[i + j].children[1].literal[0] = (GLfloat) j;
+ }
+ }
+ }
+ }
+
+ if (callOper->num_children < (GLuint) numParams) {
+ /* still not enough args for all params */
+ return GL_FALSE;
+ }
+ else if (callOper->num_children > (GLuint) numParams) {
+ /* now too many arguments */
+ /* just truncate */
+ callOper->num_children = (GLuint) numParams;
+ }
+
if (dbg) {
printf("===== New call to %s with adapted arguments ===============\n",
(char*) fun->header.a_name);
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 2005-2008 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.
+ */
#ifndef SLANG_SIMPLIFY_H
#define SLANG_SIMPLIFY_H
slang_atom_pool * atoms);
+extern GLboolean
+_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
+ const slang_name_space * space,
+ slang_atom_pool * atoms, slang_info_log *log);
+
extern GLboolean
_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
const slang_name_space * space,
GLboolean
slang_typeinfo_construct(slang_typeinfo * ti)
{
+ /*_mesa_bzero(ti, sizeof(*ti));*/
slang_type_specifier_ctr(&ti->spec);
ti->array_len = 0;
return GL_TRUE;
slang_function **funFound,
slang_atom_pool *atoms, slang_info_log *log)
{
+ GLboolean error;
+
*funFound = _slang_locate_function(space->funcs, a_name, params,
- num_params, space, atoms, log);
+ num_params, space, atoms, log, &error);
+ if (error)
+ return GL_FALSE;
+
if (!*funFound)
return GL_TRUE; /* yes, not false */
+
return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
}
_slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
slang_operation * args, GLuint num_args,
const slang_name_space * space, slang_atom_pool * atoms,
- slang_info_log *log)
+ slang_info_log *log, GLboolean *error)
{
+ slang_typeinfo arg_ti[100];
GLuint i;
- for (i = 0; i < funcs->num_functions; i++) {
- slang_function *f = &funcs->functions[i];
- const GLuint haveRetValue = _slang_function_has_return_value(f);
- GLuint j;
-
- if (a_name != f->header.a_name)
- continue;
- if (f->param_count - haveRetValue != num_args)
- continue;
-
- /* compare parameter / argument types */
- for (j = 0; j < num_args; j++) {
- slang_typeinfo ti;
-
- if (!slang_typeinfo_construct(&ti))
- return NULL;
- if (!_slang_typeof_operation_(&args[j], space, &ti, atoms, log)) {
- slang_typeinfo_destruct(&ti);
- return NULL;
+ *error = GL_FALSE;
+
+ /* determine type of each argument */
+ assert(num_args < 100);
+ for (i = 0; i < num_args; i++) {
+ if (!slang_typeinfo_construct(&arg_ti[i]))
+ return NULL;
+ if (!_slang_typeof_operation_(&args[i], space, &arg_ti[i], atoms, log)) {
+ return NULL;
+ }
+ }
+
+ /* loop over function scopes */
+ while (funcs) {
+
+ /* look for function with matching name and argument/param types */
+ for (i = 0; i < funcs->num_functions; i++) {
+ slang_function *f = &funcs->functions[i];
+ const GLuint haveRetValue = _slang_function_has_return_value(f);
+ GLuint j;
+
+ if (a_name != f->header.a_name)
+ continue;
+ if (f->param_count - haveRetValue != num_args)
+ continue;
+
+ /* compare parameter / argument types */
+ for (j = 0; j < num_args; j++) {
+ if (!slang_type_specifier_compatible(&arg_ti[j].spec,
+ &f->parameters->variables[j]->type.specifier)) {
+ /* param/arg types don't match */
+ break;
+ }
+
+ /* "out" and "inout" formal parameter requires the actual
+ * argument to be an l-value.
+ */
+ if (!arg_ti[j].can_be_referenced &&
+ (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
+ f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) {
+ /* param is not an lvalue! */
+ *error = GL_TRUE;
+ return NULL;
+ }
}
- if (!slang_type_specifier_compatible(&ti.spec,
- &f->parameters->variables[j]->type.specifier)) {
- slang_typeinfo_destruct(&ti);
- break;
+
+ if (j == num_args) {
+ /* name and args match! */
+ return f;
}
- slang_typeinfo_destruct(&ti);
-
- /* "out" and "inout" formal parameter requires the actual
- * parameter to be l-value.
- */
- if (!ti.can_be_referenced &&
- (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
- f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT))
- break;
}
- if (j == num_args)
- return f;
+
+ funcs = funcs->outer_scope;
}
- if (funcs->outer_scope != NULL)
- return _slang_locate_function(funcs->outer_scope, a_name, args,
- num_args, space, atoms, log);
+
return NULL;
}
slang_atom name, struct slang_operation_ *params,
GLuint num_params,
const slang_name_space *space,
- slang_atom_pool *atoms, slang_info_log *log);
+ slang_atom_pool *atoms, slang_info_log *log,
+ GLboolean *error);
extern GLboolean