Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 10334c2e in mainline


Ignore:
Timestamp:
2012-07-30T01:40:55Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
20ac1a4
Parents:
d1e580a
Message:

Bithenge: add if_transform

Location:
uspace/app/bithenge
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/expression.c

    rd1e580a r10334c2e  
    417417}
    418418
     419typedef struct {
     420        bithenge_transform_t base;
     421        bithenge_expression_t *expr;
     422        bithenge_transform_t *true_xform, *false_xform;
     423} if_transform_t;
     424
     425static inline bithenge_transform_t *if_as_transform(if_transform_t *self)
     426{
     427        return &self->base;
     428}
     429
     430static inline if_transform_t *transform_as_if(bithenge_transform_t *base)
     431{
     432        return (if_transform_t *)base;
     433}
     434
     435static int if_transform_choose(if_transform_t *self, bithenge_scope_t *scope,
     436    bool *out)
     437{
     438        bithenge_node_t *cond_node;
     439        int rc = bithenge_expression_evaluate(self->expr, scope, &cond_node);
     440        if (rc != EOK)
     441                return rc;
     442        if (bithenge_node_type(cond_node) != BITHENGE_NODE_BOOLEAN) {
     443                bithenge_node_dec_ref(cond_node);
     444                return EINVAL;
     445        }
     446        *out = bithenge_boolean_node_value(cond_node);
     447        bithenge_node_dec_ref(cond_node);
     448        return EOK;
     449}
     450
     451static int if_transform_apply(bithenge_transform_t *base,
     452    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
     453{
     454        if_transform_t *self = transform_as_if(base);
     455        bool cond;
     456        int rc = if_transform_choose(self, scope, &cond);
     457        if (rc != EOK)
     458                return rc;
     459        return bithenge_transform_apply(
     460            cond ? self->true_xform : self->false_xform, scope, in, out);
     461}
     462
     463static int if_transform_prefix_length(bithenge_transform_t *base,
     464    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
     465{
     466        if_transform_t *self = transform_as_if(base);
     467        bool cond;
     468        int rc = if_transform_choose(self, scope, &cond);
     469        if (rc != EOK)
     470                return rc;
     471        return bithenge_transform_prefix_length(
     472            cond ? self->true_xform : self->false_xform, scope, in, out);
     473}
     474
     475static void if_transform_destroy(bithenge_transform_t *base)
     476{
     477        if_transform_t *self = transform_as_if(base);
     478        bithenge_expression_dec_ref(self->expr);
     479        bithenge_transform_dec_ref(self->true_xform);
     480        bithenge_transform_dec_ref(self->false_xform);
     481        free(self);
     482}
     483
     484static const bithenge_transform_ops_t if_transform_ops = {
     485        .apply = if_transform_apply,
     486        .prefix_length = if_transform_prefix_length,
     487        .destroy = if_transform_destroy,
     488};
     489
     490/** Create a transform that applies either of two transforms depending on a
     491 * boolean expression. Takes references to @a expr, @a true_xform, and
     492 * @a false_xform.
     493 * @param[out] out Holds the new transform.
     494 * @param expr The boolean expression to evaluate.
     495 * @param true_xform The transform to apply if the expression is true.
     496 * @param false_xform The transform to apply if the expression is false. */
     497int bithenge_if_transform(bithenge_transform_t **out,
     498    bithenge_expression_t *expr, bithenge_transform_t *true_xform,
     499    bithenge_transform_t *false_xform)
     500{
     501        int rc;
     502        if_transform_t *self = malloc(sizeof(*self));
     503        if (!self) {
     504                rc = ENOMEM;
     505                goto error;
     506        }
     507
     508        rc = bithenge_init_transform(if_as_transform(self), &if_transform_ops,
     509            0);
     510        if (rc != EOK)
     511                goto error;
     512
     513        self->expr = expr;
     514        self->true_xform = true_xform;
     515        self->false_xform = false_xform;
     516        *out = if_as_transform(self);
     517        return EOK;
     518
     519error:
     520        free(self);
     521        bithenge_expression_dec_ref(expr);
     522        bithenge_transform_dec_ref(true_xform);
     523        bithenge_transform_dec_ref(false_xform);
     524        return rc;
     525}
     526
    419527/** @}
    420528 */
  • uspace/app/bithenge/expression.h

    rd1e580a r10334c2e  
    100100int bithenge_param_wrapper(bithenge_transform_t **, bithenge_transform_t *,
    101101    bithenge_expression_t **);
     102int bithenge_if_transform(bithenge_transform_t **, bithenge_expression_t *,
     103    bithenge_transform_t *, bithenge_transform_t *);
    102104
    103105#endif
  • uspace/app/bithenge/script.c

    rd1e580a r10334c2e  
    5858
    5959        /* Keywords */
     60        TOKEN_ELSE,
     61        TOKEN_FALSE,
     62        TOKEN_IF,
    6063        TOKEN_STRUCT,
    6164        TOKEN_TRANSFORM,
     65        TOKEN_TRUE,
    6266} token_type_t;
    6367
     
    204208                if (!value) {
    205209                        error_errno(state, ENOMEM);
     210                } else if (!str_cmp(value, "else")) {
     211                        state->token = TOKEN_ELSE;
     212                        free(value);
     213                } else if (!str_cmp(value, "false")) {
     214                        state->token = TOKEN_FALSE;
     215                        free(value);
     216                } else if (!str_cmp(value, "if")) {
     217                        state->token = TOKEN_IF;
     218                        free(value);
    206219                } else if (!str_cmp(value, "struct")) {
    207220                        state->token = TOKEN_STRUCT;
     
    209222                } else if (!str_cmp(value, "transform")) {
    210223                        state->token = TOKEN_TRANSFORM;
     224                        free(value);
     225                } else if (!str_cmp(value, "true")) {
     226                        state->token = TOKEN_TRUE;
    211227                        free(value);
    212228                } else {
     
    329345static bithenge_expression_t *parse_expression(state_t *state)
    330346{
    331         if (state->token == TOKEN_INTEGER) {
     347        if (state->token == TOKEN_TRUE || state->token == TOKEN_FALSE) {
     348                bool val = state->token == TOKEN_TRUE;
     349                next_token(state);
     350                bithenge_node_t *node;
     351                int rc = bithenge_new_boolean_node(&node, val);
     352                if (rc != EOK) {
     353                        error_errno(state, rc);
     354                        return NULL;
     355                }
     356
     357                bithenge_expression_t *expr;
     358                rc = bithenge_const_expression(&expr, node);
     359                if (rc != EOK) {
     360                        error_errno(state, rc);
     361                        return NULL;
     362                }
     363
     364                return expr;
     365        } else if (state->token == TOKEN_INTEGER) {
    332366                bithenge_int_t val = state->token_int;
    333367                next_token(state);
     
    454488
    455489        return result;
     490}
     491
     492static bithenge_transform_t *parse_if(state_t *state)
     493{
     494        expect(state, TOKEN_IF);
     495        expect(state, '(');
     496        bithenge_expression_t *expr = parse_expression(state);
     497        expect(state, ')');
     498        expect(state, '{');
     499        bithenge_transform_t *true_xform = parse_transform(state);
     500        expect(state, '}');
     501        expect(state, TOKEN_ELSE);
     502        expect(state, '{');
     503        bithenge_transform_t *false_xform = parse_transform(state);
     504        expect(state, '}');
     505        if (state->error != EOK) {
     506                bithenge_expression_dec_ref(expr);
     507                bithenge_transform_dec_ref(true_xform);
     508                bithenge_transform_dec_ref(false_xform);
     509                return NULL;
     510        }
     511        bithenge_transform_t *if_xform;
     512        int rc = bithenge_if_transform(&if_xform, expr, true_xform,
     513            false_xform);
     514        if (rc != EOK) {
     515                error_errno(state, rc);
     516                return NULL;
     517        }
     518        return if_xform;
    456519}
    457520
     
    507570        if (state->token == TOKEN_IDENTIFIER) {
    508571                return parse_invocation(state);
     572        } else if (state->token == TOKEN_IF) {
     573                return parse_if(state);
    509574        } else if (state->token == TOKEN_STRUCT) {
    510575                return parse_struct(state);
  • uspace/app/bithenge/tree.c

    rd1e580a r10334c2e  
    126126}
    127127
     128/** Initialize an internal node.
     129 * @memberof bithenge_node_t
     130 * @param[out] self The node.
     131 * @param[in] ops The operations provided.
     132 * @return EOK on success or an error code from errno.h. */
     133int bithenge_init_internal_node(bithenge_node_t *self,
     134    const bithenge_internal_node_ops_t *ops)
     135{
     136        self->type = BITHENGE_NODE_INTERNAL;
     137        self->refs = 1;
     138        self->internal_ops = ops;
     139        return EOK;
     140}
     141
     142static void internal_node_indestructible(bithenge_node_t *self)
     143{
     144        assert(false);
     145}
     146
     147static int empty_internal_node_for_each(bithenge_node_t *base,
     148    bithenge_for_each_func_t func, void *data)
     149{
     150        return EOK;
     151}
     152
     153static int empty_internal_node_get(bithenge_node_t *self, bithenge_node_t *key,
     154    bithenge_node_t **out)
     155{
     156        return ENOENT;
     157}
     158
     159static const bithenge_internal_node_ops_t empty_internal_node_ops = {
     160        .for_each = empty_internal_node_for_each,
     161        .get = empty_internal_node_get,
     162        .destroy = internal_node_indestructible,
     163};
     164
     165static bithenge_node_t empty_internal_node = {
     166        BITHENGE_NODE_INTERNAL,
     167        1,
     168        { .internal_ops = &empty_internal_node_ops },
     169};
     170
     171/** Create an empty internal node.
     172 * @param[out] out Holds the created node.
     173 * @return EOK on success or an error code from errno.h. */
     174int bithenge_new_empty_internal_node(bithenge_node_t **out)
     175{
     176        bithenge_node_inc_ref(&empty_internal_node);
     177        *out = &empty_internal_node;
     178        return EOK;
     179}
     180
    128181typedef struct
    129182{
     
    173226        .destroy = simple_internal_node_destroy,
    174227};
    175 
    176 /** Initialize an internal node.
    177  * @memberof bithenge_node_t
    178  * @param[out] self The node.
    179  * @param[in] ops The operations provided.
    180  * @return EOK on success or an error code from errno.h. */
    181 int bithenge_init_internal_node(bithenge_node_t *self,
    182     const bithenge_internal_node_ops_t *ops)
    183 {
    184         self->type = BITHENGE_NODE_INTERNAL;
    185         self->refs = 1;
    186         self->internal_ops = ops;
    187         return EOK;
    188 }
    189228
    190229/** Create an internal node from a set of keys and values. This function takes
  • uspace/app/bithenge/tree.h

    rd1e580a r10334c2e  
    161161int bithenge_init_internal_node(bithenge_node_t *,
    162162    const bithenge_internal_node_ops_t *);
     163int bithenge_new_empty_internal_node(bithenge_node_t **);
    163164int bithenge_new_simple_internal_node(bithenge_node_t **, bithenge_node_t **,
    164165    bithenge_int_t, bool needs_free);
Note: See TracChangeset for help on using the changeset viewer.