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_operation.c
27 * slang front-end compiler
31 #include "main/imports.h"
32 #include "slang_compile.h"
33 #include "slang_mem.h"
37 * Init a slang_operation object
40 slang_operation_construct(slang_operation
* oper
)
42 oper
->type
= SLANG_OPER_NONE
;
43 oper
->children
= NULL
;
44 oper
->num_children
= 0;
45 oper
->literal
[0] = 0.0;
46 oper
->literal_size
= 1;
47 oper
->array_constructor
= GL_FALSE
;
48 oper
->a_id
= SLANG_ATOM_NULL
;
49 oper
->a_obj
= SLANG_ATOM_NULL
;
50 oper
->locals
= _slang_variable_scope_new(NULL
);
51 if (oper
->locals
== NULL
)
53 _slang_variable_scope_ctr(oper
->locals
);
61 slang_operation_destruct(slang_operation
* oper
)
65 for (i
= 0; i
< oper
->num_children
; i
++)
66 slang_operation_destruct(oper
->children
+ i
);
67 _slang_free(oper
->children
);
68 slang_variable_scope_destruct(oper
->locals
);
69 _slang_free(oper
->locals
);
70 oper
->children
= NULL
;
71 oper
->num_children
= 0;
77 * Recursively traverse 'oper', replacing occurances of 'oldScope' with
78 * 'newScope' in the oper->locals->outer_scope field.
81 slang_replace_scope(slang_operation
*oper
,
82 slang_variable_scope
*oldScope
,
83 slang_variable_scope
*newScope
)
87 if (oper
->locals
!= newScope
&&
88 oper
->locals
->outer_scope
== oldScope
) {
89 /* found. replace old w/ new */
90 oper
->locals
->outer_scope
= newScope
;
93 if (oper
->type
== SLANG_OPER_VARIABLE_DECL
) {
94 /* search/replace in the initializer */
96 var
= _slang_variable_locate(oper
->locals
, oper
->a_id
, GL_TRUE
);
97 if (var
&& var
->initializer
) {
98 slang_replace_scope(var
->initializer
, oldScope
, newScope
);
102 /* search/replace in children */
103 for (i
= 0; i
< oper
->num_children
; i
++) {
104 slang_replace_scope(&oper
->children
[i
], oldScope
, newScope
);
110 * Recursively copy a slang_operation node.
111 * \param x copy target
112 * \param y copy source
113 * \return GL_TRUE for success, GL_FALSE if failure
116 slang_operation_copy(slang_operation
* x
, const slang_operation
* y
)
121 if (!slang_operation_construct(&z
))
124 if (y
->num_children
> 0) {
125 z
.children
= (slang_operation
*)
126 _slang_alloc(y
->num_children
* sizeof(slang_operation
));
127 if (z
.children
== NULL
) {
128 slang_operation_destruct(&z
);
132 for (z
.num_children
= 0; z
.num_children
< y
->num_children
;
134 if (!slang_operation_construct(&z
.children
[z
.num_children
])) {
135 slang_operation_destruct(&z
);
139 for (i
= 0; i
< z
.num_children
; i
++) {
140 if (!slang_operation_copy(&z
.children
[i
], &y
->children
[i
])) {
141 slang_operation_destruct(&z
);
145 z
.literal
[0] = y
->literal
[0];
146 z
.literal
[1] = y
->literal
[1];
147 z
.literal
[2] = y
->literal
[2];
148 z
.literal
[3] = y
->literal
[3];
149 z
.literal_size
= y
->literal_size
;
150 assert(y
->literal_size
>= 1);
151 assert(y
->literal_size
<= 4);
154 if (!slang_variable_scope_copy(z
.locals
, y
->locals
)) {
155 slang_operation_destruct(&z
);
160 /* update scoping for children */
161 for (i
= 0; i
< y
->num_children
; i
++) {
162 if (y
->children
[i
].locals
&&
163 y
->children
[i
].locals
->outer_scope
== y
->locals
) {
164 z
.children
[i
].locals
->outer_scope
= z
.locals
;
172 slang_operation_destruct(x
);
175 /* If this operation declares a new scope, we need to make sure
176 * all children point to it, not the original operation's scope!
178 if (x
->type
== SLANG_OPER_BLOCK_NEW_SCOPE
||
179 x
->type
== SLANG_OPER_WHILE
||
180 x
->type
== SLANG_OPER_FOR
) {
181 slang_replace_scope(x
, y
->locals
, x
->locals
);
189 slang_operation_new(GLuint count
)
192 = (slang_operation
*) _slang_alloc(count
* sizeof(slang_operation
));
196 for (i
= 0; i
< count
; i
++)
197 slang_operation_construct(ops
+ i
);
204 * Delete operation and all children
207 slang_operation_delete(slang_operation
*oper
)
209 slang_operation_destruct(oper
);
215 slang_operation_free_children(slang_operation
*oper
)
218 for (i
= 0; i
< slang_oper_num_children(oper
); i
++) {
219 slang_operation
*child
= slang_oper_child(oper
, i
);
220 slang_operation_destruct(child
);
222 _slang_free(oper
->children
);
223 oper
->children
= NULL
;
224 oper
->num_children
= 0;
229 slang_operation_grow(GLuint
*numChildren
, slang_operation
**children
)
231 slang_operation
*ops
;
233 ops
= (slang_operation
*)
234 _slang_realloc(*children
,
235 *numChildren
* sizeof(slang_operation
),
236 (*numChildren
+ 1) * sizeof(slang_operation
));
238 slang_operation
*newOp
= ops
+ *numChildren
;
239 if (!slang_operation_construct(newOp
)) {
252 * Insert a new slang_operation into an array.
253 * \param numElements pointer to current array size (in/out)
254 * \param array address of the array (in/out)
255 * \param pos position to insert new element
256 * \return pointer to the new operation/element
259 slang_operation_insert(GLuint
*numElements
, slang_operation
**array
,
262 slang_operation
*ops
;
264 assert(pos
<= *numElements
);
266 ops
= (slang_operation
*)
267 _slang_alloc((*numElements
+ 1) * sizeof(slang_operation
));
269 slang_operation
*newOp
;
272 _mesa_memcpy(ops
, *array
, pos
* sizeof(slang_operation
));
273 if (pos
< *numElements
)
274 _mesa_memcpy(newOp
+ 1, (*array
) + pos
,
275 (*numElements
- pos
) * sizeof(slang_operation
));
277 if (!slang_operation_construct(newOp
)) {
294 * Add/insert new child into given node at given position.
295 * \return pointer to the new child node
298 slang_operation_insert_child(slang_operation
*oper
, GLuint pos
)
300 slang_operation
*newOp
;
302 newOp
= slang_operation_insert(&oper
->num_children
,
306 newOp
->locals
->outer_scope
= oper
->locals
;
314 _slang_operation_swap(slang_operation
*oper0
, slang_operation
*oper1
)
316 slang_operation tmp
= *oper0
;
323 slang_operation_add_children(slang_operation
*oper
, GLuint num_children
)
326 assert(oper
->num_children
== 0);
327 assert(oper
->children
== NULL
);
328 oper
->num_children
= num_children
;
329 oper
->children
= slang_operation_new(num_children
);
330 for (i
= 0; i
< num_children
; i
++) {
331 oper
->children
[i
].locals
= _slang_variable_scope_new(oper
->locals
);