source: mainline/uspace/app/bithenge/expression.c@ 32eb01b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 32eb01b was 4056ad0, checked in by Sean Bartell <wingedtachikoma@…>, 13 years ago

Bithenge: basic parameter passing (integer literals only)

  • Property mode set to 100644
File size: 8.4 KB
RevLine 
[6e34bd0]1/*
2 * Copyright (c) 2012 Sean Bartell
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
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup bithenge
30 * @{
31 */
32/**
33 * @file
34 * Expressions.
35 */
36
37#include <assert.h>
38#include <errno.h>
39#include <stdlib.h>
40#include "blob.h"
41#include "expression.h"
42#include "transform.h"
43#include "tree.h"
44
45/** Initialize a new expression.
46 * @param[out] self Expression to initialize.
47 * @param[in] ops Operations provided by the expression.
48 * @return EOK or an error code from errno.h. */
49int bithenge_init_expression(bithenge_expression_t *self,
50 const bithenge_expression_ops_t *ops)
51{
52 assert(ops);
53 assert(ops->evaluate);
54 assert(ops->destroy);
55 self->ops = ops;
56 self->refs = 1;
57 return EOK;
58}
59
60typedef struct {
61 bithenge_expression_t base;
62 int index;
63} param_expression_t;
64
65static inline param_expression_t *expression_as_param(
66 bithenge_expression_t *base)
67{
68 return (param_expression_t *)base;
69}
70
71static inline bithenge_expression_t *param_as_expression(
72 param_expression_t *self)
73{
74 return &self->base;
75}
76
77static int param_expression_evaluate(bithenge_expression_t *base,
78 bithenge_scope_t *scope, bithenge_node_t **out)
79{
80 param_expression_t *self = expression_as_param(base);
81 return bithenge_scope_get_param(scope, self->index, out);
82}
83
84static void param_expression_destroy(bithenge_expression_t *base)
85{
86 param_expression_t *self = expression_as_param(base);
87 free(self);
88}
89
90static const bithenge_expression_ops_t param_expression_ops = {
91 .evaluate = param_expression_evaluate,
92 .destroy = param_expression_destroy,
93};
94
95/** Create an expression that returns a parameter.
96 * @param[out] out Holds the created expression.
97 * @param index The index of the parameter to get.
98 * @return EOK on success or an error code from errno.h. */
99int bithenge_param_expression(bithenge_expression_t **out, int index)
100{
101 int rc;
102 param_expression_t *self = malloc(sizeof(*self));
103 if (!self)
104 return ENOMEM;
105
106 rc = bithenge_init_expression(param_as_expression(self),
107 &param_expression_ops);
108 if (rc != EOK) {
109 free(self);
110 return rc;
111 }
112
113 self->index = index;
114 *out = param_as_expression(self);
115 return EOK;
116}
117
118typedef struct {
119 bithenge_expression_t base;
120 bithenge_node_t *node;
121} const_expression_t;
122
123static inline const_expression_t *expression_as_const(
124 bithenge_expression_t *base)
125{
126 return (const_expression_t *)base;
127}
128
129static inline bithenge_expression_t *const_as_expression(
130 const_expression_t *self)
131{
132 return &self->base;
133}
134
135static int const_expression_evaluate(bithenge_expression_t *base,
136 bithenge_scope_t *scope, bithenge_node_t **out)
137{
138 const_expression_t *self = expression_as_const(base);
139 bithenge_node_inc_ref(self->node);
140 *out = self->node;
141 return EOK;
142}
143
144static void const_expression_destroy(bithenge_expression_t *base)
145{
146 const_expression_t *self = expression_as_const(base);
147 bithenge_node_dec_ref(self->node);
148 free(self);
149}
150
151static const bithenge_expression_ops_t const_expression_ops = {
152 .evaluate = const_expression_evaluate,
153 .destroy = const_expression_destroy,
154};
155
156/** Create an expression that returns a constant. Takes a reference to @a node.
157 * @param[out] out Holds the created expression.
158 * @param node The constant.
159 * @return EOK on success or an error code from errno.h. */
160int bithenge_const_expression(bithenge_expression_t **out,
161 bithenge_node_t *node)
162{
163 int rc;
164 const_expression_t *self = malloc(sizeof(*self));
165 if (!self)
166 return ENOMEM;
167
168 rc = bithenge_init_expression(const_as_expression(self),
169 &const_expression_ops);
170 if (rc != EOK) {
171 free(self);
172 return rc;
173 }
174
175 self->node = node;
176 *out = const_as_expression(self);
177 return EOK;
178}
179
180typedef struct {
181 bithenge_transform_t base;
182 bithenge_transform_t *transform;
183 bithenge_expression_t **params;
184} param_wrapper_t;
185
186static inline bithenge_transform_t *param_wrapper_as_transform(
187 param_wrapper_t *self)
188{
189 return &self->base;
190}
191
192static inline param_wrapper_t *transform_as_param_wrapper(
193 bithenge_transform_t *base)
194{
195 return (param_wrapper_t *)base;
196}
197
198static int param_wrapper_fill_scope(param_wrapper_t *self, bithenge_scope_t
199 *inner, bithenge_scope_t *outer)
200{
201 int rc;
202 int num_params = bithenge_transform_num_params(self->transform);
203 rc = bithenge_scope_alloc_params(inner, num_params);
204 if (rc != EOK)
205 return rc;
206 for (int i = 0; i < num_params; i++) {
207 bithenge_node_t *node;
208 rc = bithenge_expression_evaluate(self->params[i], outer,
209 &node);
210 if (rc != EOK)
211 return rc;
212 rc = bithenge_scope_set_param(inner, i, node);
213 if (rc != EOK)
214 return rc;
215 }
216 return EOK;
217}
218
219static int param_wrapper_apply(bithenge_transform_t *base,
220 bithenge_scope_t *outer, bithenge_node_t *in, bithenge_node_t **out)
221{
222 param_wrapper_t *self = transform_as_param_wrapper(base);
223 bithenge_scope_t inner;
224 bithenge_scope_init(&inner);
225 int rc = param_wrapper_fill_scope(self, &inner, outer);
226 if (rc != EOK)
227 goto error;
228
229 rc = bithenge_transform_apply(self->transform, &inner, in, out);
230 in = NULL;
231
232error:
233 bithenge_scope_destroy(&inner);
234 return rc;
235}
236
237static int param_wrapper_prefix_length(bithenge_transform_t *base,
238 bithenge_scope_t *outer, bithenge_blob_t *in, aoff64_t *out)
239{
240 param_wrapper_t *self = transform_as_param_wrapper(base);
241 bithenge_scope_t inner;
242 bithenge_scope_init(&inner);
243 int rc = param_wrapper_fill_scope(self, &inner, outer);
244 if (rc != EOK)
245 goto error;
246
247 rc = bithenge_transform_prefix_length(self->transform, &inner, in,
248 out);
249 in = NULL;
250
251error:
252 bithenge_scope_destroy(&inner);
253 return rc;
254}
[4056ad0]255
[6e34bd0]256static void param_wrapper_destroy(bithenge_transform_t *base)
257{
258 param_wrapper_t *self = transform_as_param_wrapper(base);
259 int num_params = bithenge_transform_num_params(self->transform);
260 bithenge_transform_dec_ref(self->transform);
261 for (int i = 0; i < num_params; i++)
262 bithenge_expression_dec_ref(self->params[i]);
263 free(self->params);
264 free(self);
265}
266
267static const bithenge_transform_ops_t param_wrapper_ops = {
268 .apply = param_wrapper_apply,
269 .prefix_length = param_wrapper_prefix_length,
270 .destroy = param_wrapper_destroy,
271};
272
273/** Create a transform that calculates parameters for another transform. Takes
274 * ownership of @a transform, @a params, and each element of @a params. The
275 * number of parameters must be correct.
276 * @param[out] out Holds the new transform.
277 * @param transform The transform for which parameters are calculated.
278 * @param params The expressions used to calculate the parameters.
279 * @return EOK on success or an error code from errno.h. */
280int bithenge_param_wrapper(bithenge_transform_t **out,
281 bithenge_transform_t *transform, bithenge_expression_t **params)
282{
283 int rc;
284 int num_params = bithenge_transform_num_params(transform);
285 param_wrapper_t *self = malloc(sizeof(*self));
286 if (!self) {
287 rc = ENOMEM;
288 goto error;
289 }
290
291 rc = bithenge_init_transform(param_wrapper_as_transform(self),
[03cad47]292 &param_wrapper_ops, 0);
[6e34bd0]293 if (rc != EOK)
294 goto error;
295
296 self->transform = transform;
297 self->params = params;
298 *out = param_wrapper_as_transform(self);
299 return EOK;
300
301error:
302 free(self);
303 for (int i = 0; i < num_params; i++)
304 bithenge_expression_dec_ref(params[i]);
305 free(params);
306 bithenge_transform_dec_ref(transform);
307 return rc;
308}
309
310/** @}
311 */
Note: See TracBrowser for help on using the repository browser.