types refactoring
[m6w6/ext-psi] / src / types / let_val.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #else
29 # include "php_config.h"
30 #endif
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <assert.h>
35
36 #include "data.h"
37
38 let_val *init_let_val(enum let_val_kind kind, void *data) {
39 let_val *let = calloc(1, sizeof(*let));
40 switch (let->kind = kind) {
41 case PSI_LET_NULL:
42 break;
43 case PSI_LET_NUMEXP:
44 let->data.num = data;
45 break;
46 case PSI_LET_CALLOC:
47 let->data.alloc = data;
48 break;
49 case PSI_LET_CALLBACK:
50 let->data.callback = data;
51 break;
52 case PSI_LET_FUNC:
53 let->data.func = data;
54 break;
55 case PSI_LET_TMP:
56 let->data.var = data;
57 break;
58 default:
59 assert(0);
60 }
61 return let;
62 }
63
64 void free_let_val(let_val *let) {
65 switch (let->kind) {
66 case PSI_LET_NULL:
67 break;
68 case PSI_LET_NUMEXP:
69 free_num_exp(let->data.num);
70 break;
71 case PSI_LET_CALLOC:
72 free_let_calloc(let->data.alloc);
73 break;
74 case PSI_LET_CALLBACK:
75 free_let_callback(let->data.callback);
76 break;
77 case PSI_LET_FUNC:
78 free_let_func(let->data.func);
79 break;
80 case PSI_LET_TMP:
81 free_decl_var(let->data.var);
82 break;
83 default:
84 assert(0);
85 }
86 free(let);
87 }
88
89 void dump_let_val(int fd, let_val *val, unsigned level, int last) {
90 if (level > 1) {
91 /* only if not directly after `set ...` */
92 dprintf(fd, "%s", psi_t_indent(level));
93 }
94
95 dprintf(fd, "%s", val->flags.one.is_reference ? "&" : "");
96
97 switch (val->kind) {
98 case PSI_LET_NULL:
99 dprintf(fd, "NULL");
100 break;
101 case PSI_LET_TMP:
102 dump_decl_var(fd, val->data.var);
103 break;
104 case PSI_LET_CALLOC:
105 dprintf(fd, "calloc(");
106 dump_num_exp(fd, val->data.alloc->nmemb);
107 dprintf(fd, ", ");
108 dump_num_exp(fd, val->data.alloc->size);
109 dprintf(fd, ")");
110 break;
111 case PSI_LET_CALLBACK:
112 dprintf(fd, "callback %s(%s(", val->data.callback->func->name,
113 val->data.callback->func->var->name);
114 if (val->data.callback->args) {
115 size_t i, c = val->data.callback->args->count;
116
117 dprintf(fd, "\n");
118 for (i = 0; i < c; ++i) {
119 set_value *set = val->data.callback->args->vals[i];
120 ++level;
121 dump_set_value(fd, set, level, i + 1 == c);
122 --level;
123 }
124 dprintf(fd, "%s", psi_t_indent(level));
125 }
126 dprintf(fd, "))");
127 break;
128 case PSI_LET_FUNC:
129 dump_let_func(fd, val->data.func, level);
130 break;
131 case PSI_LET_NUMEXP:
132 dump_num_exp(fd, val->data.num);
133 break;
134
135 default:
136 assert(0);
137 }
138
139 if (level > 1) {
140 if (!last) {
141 dprintf(fd, ",");
142 }
143 } else {
144 dprintf(fd, ";");
145 }
146 }
147
148 int validate_let_val(struct psi_data *data, let_val *val, decl_var *let_var, impl *impl) {
149 switch (val->kind) {
150 case PSI_LET_NULL:
151 break;
152 case PSI_LET_TMP:
153 if (!let_var) {
154 data->error(data, NULL, PSI_WARNING,
155 "Ivalid let statement value of implementation '%s'",
156 impl->func->name);
157 return 0;
158 }
159 /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
160 /* e.g. let foo = *bar; */
161 let_var->pointer_level = val->data.var->pointer_level;
162 let_var->arg = init_decl_arg(
163 init_decl_type(
164 real_decl_type(val->data.var->arg->type)->type,
165 real_decl_type(val->data.var->arg->type)->name),
166 init_decl_var(
167 let_var->name,
168 let_var->pointer_level,
169 let_var->array_size));
170 break;
171 case PSI_LET_NUMEXP:
172 if (!validate_num_exp(data, val->data.num, impl->decl->args, impl->decl->func, NULL)) {
173 return 0;
174 }
175 break;
176 case PSI_LET_CALLOC:
177 if (!validate_num_exp(data, val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
178 return 0;
179 }
180 if (!validate_num_exp(data, val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
181 return 0;
182 }
183 break;
184 case PSI_LET_CALLBACK:
185 if (!let_var) {
186 data->error(data, NULL, PSI_WARNING,
187 "Ivalid let statement value of implementation '%s'",
188 impl->func->name);
189 return 0;
190 }
191 if (val->data.callback->func->inner) {
192 size_t i;
193 decl_type *var_typ = real_decl_type(let_var->arg->type);
194 decl_args *sub_args;
195
196 switch (var_typ->type) {
197 case PSI_T_STRUCT:
198 sub_args = var_typ->real.strct->args;
199 break;
200 case PSI_T_UNION:
201 sub_args = var_typ->real.unn->args;
202 break;
203 default:
204 data->error(data, let_var->token, PSI_WARNING,
205 "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
206 real_decl_type(let_var->arg->type)->name, let_var->name);
207 return 0;
208 }
209 for (i = 0; i < val->data.callback->func->inner->count; ++i) {
210 let_val *inner = val->data.callback->func->inner->vals[i];
211 switch (inner->kind) {
212 case PSI_LET_FUNC:
213 inner->data.func->outer = val;
214 inner->data.func->ref = locate_decl_arg(sub_args,
215 &inner->data.func->var->name[1]);
216 break;
217
218 break;
219 case PSI_LET_CALLBACK:
220 inner->data.callback->func->outer = val;
221 inner->data.callback->func->ref = locate_decl_arg(sub_args,
222 &inner->data.callback->func->var->name[1]);
223 break;
224 }
225 }
226 }
227 if (!validate_let_callback(data, let_var, val->data.callback, impl)) {
228 return 0;
229 }
230 break;
231 case PSI_LET_FUNC:
232 if (val->data.func->inner) {
233 size_t i;
234 decl_type *var_typ = real_decl_type(let_var->arg->type);
235 decl_args *sub_args;
236
237 switch (var_typ->type) {
238 case PSI_T_STRUCT:
239 sub_args = var_typ->real.strct->args;
240 break;
241 case PSI_T_UNION:
242 sub_args = var_typ->real.unn->args;
243 break;
244 default:
245 data->error(data, let_var->token, PSI_WARNING,
246 "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
247 real_decl_type(let_var->arg->type)->name, let_var->name);
248 return 0;
249 }
250 for (i = 0; i < val->data.func->inner->count; ++i) {
251 let_val *inner = val->data.func->inner->vals[i];
252 switch (inner->kind) {
253 case PSI_LET_FUNC:
254 inner->data.func->outer = val;
255 inner->data.func->ref = locate_decl_arg(sub_args,
256 &inner->data.func->var->name[1]);
257 break;
258 case PSI_LET_CALLBACK:
259 inner->data.callback->func->outer = val;
260 inner->data.callback->func->ref = locate_decl_arg(sub_args,
261 &inner->data.callback->func->var->name[1]);
262 break;
263 }
264 }
265 }
266
267 val->data.func->var;
268
269 if (!validate_let_func(data, val->data.func, let_var, impl)) {
270 return 0;
271 }
272 break;
273 }
274
275 return 1;
276 }