2 * Mesa 3-D graphics library
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * \file slang_compile_function.c
27 * slang front-end compiler
31 #include "main/imports.h"
32 #include "slang_compile.h"
33 #include "slang_mem.h"
37 slang_function_construct(slang_function
* func
)
39 func
->kind
= SLANG_FUNC_ORDINARY
;
40 if (!slang_variable_construct(&func
->header
))
43 func
->parameters
= (slang_variable_scope
*)
44 _slang_alloc(sizeof(slang_variable_scope
));
45 if (func
->parameters
== NULL
) {
46 slang_variable_destruct(&func
->header
);
50 _slang_variable_scope_ctr(func
->parameters
);
51 func
->param_count
= 0;
57 slang_function_destruct(slang_function
* func
)
59 slang_variable_destruct(&func
->header
);
60 slang_variable_scope_destruct(func
->parameters
);
61 _slang_free(func
->parameters
);
62 if (func
->body
!= NULL
) {
63 slang_operation_destruct(func
->body
);
64 _slang_free(func
->body
);
70 slang_function_new(slang_function_kind kind
)
72 slang_function
*fun
= (slang_function
*)
73 _slang_alloc(sizeof(slang_function
));
75 slang_function_construct(fun
);
83 * slang_function_scope
87 _slang_function_scope_ctr(slang_function_scope
* self
)
89 self
->functions
= NULL
;
90 self
->num_functions
= 0;
91 self
->outer_scope
= NULL
;
95 slang_function_scope_destruct(slang_function_scope
* scope
)
99 for (i
= 0; i
< scope
->num_functions
; i
++)
100 slang_function_destruct(scope
->functions
+ i
);
101 _slang_free(scope
->functions
);
106 * Does this function have a non-void return value?
109 _slang_function_has_return_value(const slang_function
*fun
)
111 return fun
->header
.type
.specifier
.type
!= SLANG_SPEC_VOID
;
116 * Search a list of functions for a particular function by name.
117 * \param funcs the list of functions to search
118 * \param a_name the name to search for
119 * \param all_scopes if non-zero, search containing scopes too.
120 * \return pointer to found function, or NULL.
123 slang_function_scope_find_by_name(slang_function_scope
* funcs
,
124 slang_atom a_name
, int all_scopes
)
128 for (i
= 0; i
< funcs
->num_functions
; i
++)
129 if (a_name
== funcs
->functions
[i
].header
.a_name
)
131 if (all_scopes
&& funcs
->outer_scope
!= NULL
)
132 return slang_function_scope_find_by_name(funcs
->outer_scope
, a_name
, 1);
138 * Search a list of functions for a particular function (for implementing
139 * function calls. Matching is done by first comparing the function's name,
140 * then the function's parameter list.
142 * \param funcs the list of functions to search
143 * \param fun the function to search for
144 * \param all_scopes if non-zero, search containing scopes too.
145 * \return pointer to found function, or NULL.
148 slang_function_scope_find(slang_function_scope
* funcs
, slang_function
* fun
,
153 for (i
= 0; i
< funcs
->num_functions
; i
++) {
154 slang_function
*f
= &funcs
->functions
[i
];
155 const GLuint haveRetValue
= 0;
157 = (f
->header
.type
.specifier
.type
!= SLANG_SPEC_VOID
);
162 printf("Compare name %s to %s (ret %u, %d, %d)\n",
163 (char *) fun->header.a_name, (char *) f->header.a_name,
165 fun->param_count, f->param_count);
168 if (fun
->header
.a_name
!= f
->header
.a_name
)
170 if (fun
->param_count
!= f
->param_count
)
172 for (j
= haveRetValue
; j
< fun
->param_count
; j
++) {
173 if (!slang_type_specifier_equal
174 (&fun
->parameters
->variables
[j
]->type
.specifier
,
175 &f
->parameters
->variables
[j
]->type
.specifier
))
178 if (j
== fun
->param_count
) {
180 printf("Found match\n");
186 printf("Not found\n");
188 if (all_scopes
&& funcs
->outer_scope
!= NULL
)
189 return slang_function_scope_find(funcs
->outer_scope
, fun
, 1);
195 * Lookup a function according to name and parameter count/types.
198 _slang_function_locate(const slang_function_scope
* funcs
, slang_atom a_name
,
199 slang_operation
* args
, GLuint num_args
,
200 const slang_name_space
* space
, slang_atom_pool
* atoms
,
201 slang_info_log
*log
, GLboolean
*error
)
203 slang_typeinfo arg_ti
[100];
208 /* determine type of each argument */
209 assert(num_args
< 100);
210 for (i
= 0; i
< num_args
; i
++) {
211 if (!slang_typeinfo_construct(&arg_ti
[i
]))
213 if (!_slang_typeof_operation(&args
[i
], space
, &arg_ti
[i
], atoms
, log
)) {
218 /* loop over function scopes */
221 /* look for function with matching name and argument/param types */
222 for (i
= 0; i
< funcs
->num_functions
; i
++) {
223 slang_function
*f
= &funcs
->functions
[i
];
224 const GLuint haveRetValue
= _slang_function_has_return_value(f
);
227 if (a_name
!= f
->header
.a_name
)
229 if (f
->param_count
- haveRetValue
!= num_args
)
232 /* compare parameter / argument types */
233 for (j
= 0; j
< num_args
; j
++) {
234 if (!slang_type_specifier_compatible(&arg_ti
[j
].spec
,
235 &f
->parameters
->variables
[j
]->type
.specifier
)) {
236 /* param/arg types don't match */
240 /* "out" and "inout" formal parameter requires the actual
241 * argument to be an l-value.
243 if (!arg_ti
[j
].can_be_referenced
&&
244 (f
->parameters
->variables
[j
]->type
.qualifier
== SLANG_QUAL_OUT
||
245 f
->parameters
->variables
[j
]->type
.qualifier
== SLANG_QUAL_INOUT
)) {
246 /* param is not an lvalue! */
253 /* name and args match! */
258 funcs
= funcs
->outer_scope
;