diff options
author | Ian Romanick <[email protected]> | 2010-03-11 14:50:30 -0800 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2010-03-11 14:57:26 -0800 |
commit | 471471f83471481db0445e73f8c89e6a9149838e (patch) | |
tree | 29aed0e3d5964c57264ca66ca67a258d53b516fa /ast_to_hir.cpp | |
parent | cdb8d54b6808b13092cb85e44cf02e4e91c3a669 (diff) |
Initial pass at resolving function calls
The code is still really rough and *REALLY* incomplete. This at least
passes the first few trivially simple test cases.
Diffstat (limited to 'ast_to_hir.cpp')
-rw-r--r-- | ast_to_hir.cpp | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp index c791aec3e24..d24dc159f21 100644 --- a/ast_to_hir.cpp +++ b/ast_to_hir.cpp @@ -720,11 +720,74 @@ ast_function_expression::hir(exec_list *instructions, * 2. methods - Only the .length() method of array types. * 3. functions - Calls to regular old functions. * + * There are two kinds of constructor call. Constructors for built-in + * language types, such as mat4 and vec2, are free form. The only + * requirement is that the parameters must provide enough values of the + * correct scalar type. Constructors for arrays and structures must have + * the exact number of parameters with matching types in the correct order. + * These constructors follow essentially the same type matching rules as + * functions. + * * Method calls are actually detected when the ast_field_selection * expression is handled. */ - (void) instructions; - (void) state; + if (is_constructor()) { + return ir_call::get_error_instruction(); + } else { + const ast_expression *id = subexpressions[0]; + + ir_function *f = (ir_function *) + _mesa_symbol_table_find_symbol(state->symbols, 0, + id->primary_expression.identifier); + + if (f == NULL) { + YYLTYPE loc = id->get_location(); + + _mesa_glsl_error(& loc, state, "function `%s' undeclared", + id->primary_expression.identifier); + return ir_call::get_error_instruction(); + } + + /* Once we've determined that the function being called might exist, + * process the parameters. + */ + exec_list actual_parameters; + simple_node *const first = subexpressions[1]; + if (first != NULL) { + simple_node *ptr = first; + do { + ir_instruction *const result = + ((ast_node *) ptr)->hir(instructions, state); + ptr = ptr->next; + + actual_parameters.push_tail(result); + } while (ptr != first); + } + + /* After processing the function's actual parameters, try to find an + * overload of the function that matches. + */ + const ir_function_signature *sig = + f->matching_signature(& actual_parameters); + if (sig != NULL) { + /* FINISHME: The list of actual parameters needs to be modified to + * FINISHME: include any necessary conversions. + */ + return new ir_call(sig, & actual_parameters); + } else { + YYLTYPE loc = id->get_location(); + + /* FINISHME: Log a better error message here. G++ will show the types + * FINISHME: of the actual parameters and the set of candidate + * FINISHME: functions. A different error should also be logged when + * FINISHME: multiple functions match. + */ + _mesa_glsl_error(& loc, state, "no matching function for call to `%s'", + id->primary_expression.identifier); + return ir_call::get_error_instruction(); + } + } + return ir_call::get_error_instruction(); } |