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

Changeset 78d3a00 in mainline


Ignore:
Timestamp:
2012-07-31T21:07:26Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
3f2ea63
Parents:
20ac1a4
Message:

Bithenge: add switch transforms and sugar

Location:
uspace
Files:
8 edited

Legend:

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

    r20ac1a4 r78d3a00  
    6363}
    6464
     65typedef struct {
     66        bithenge_expression_t base;
     67        bithenge_binary_op_t op;
     68        bithenge_expression_t *a, *b;
     69} binary_expression_t;
     70
     71static inline binary_expression_t *expression_as_binary(
     72    bithenge_expression_t *base)
     73{
     74        return (binary_expression_t *)base;
     75}
     76
     77static inline bithenge_expression_t *binary_as_expression(
     78    binary_expression_t *self)
     79{
     80        return &self->base;
     81}
     82
     83static int binary_expression_evaluate(bithenge_expression_t *base,
     84    bithenge_scope_t *scope, bithenge_node_t **out)
     85{
     86        binary_expression_t *self = expression_as_binary(base);
     87        bithenge_node_t *a, *b;
     88        int rc = bithenge_expression_evaluate(self->a, scope, &a);
     89        if (rc != EOK)
     90                return rc;
     91        rc = bithenge_expression_evaluate(self->b, scope, &b);
     92        if (rc != EOK) {
     93                bithenge_node_dec_ref(a);
     94                return rc;
     95        }
     96        switch (self->op) {
     97        case BITHENGE_EXPRESSION_EQUALS:
     98                rc = bithenge_new_boolean_node(out, bithenge_node_equal(a, b));
     99                break;
     100        }
     101        bithenge_node_dec_ref(a);
     102        bithenge_node_dec_ref(b);
     103        return rc;
     104}
     105
     106static void binary_expression_destroy(bithenge_expression_t *base)
     107{
     108        binary_expression_t *self = expression_as_binary(base);
     109        bithenge_expression_dec_ref(self->a);
     110        bithenge_expression_dec_ref(self->b);
     111        free(self);
     112}
     113
     114static const bithenge_expression_ops_t binary_expression_ops = {
     115        .evaluate = binary_expression_evaluate,
     116        .destroy = binary_expression_destroy,
     117};
     118
     119/** Create a binary expression. Takes ownership of @a a and @a b.
     120 * @param[out] out Holds the new expression.
     121 * @param op The operator to apply.
     122 * @param a The first operand.
     123 * @param b The second operand.
     124 * @return EOK on success or an error code from errno.h. */
     125int bithenge_binary_expression(bithenge_expression_t **out,
     126    bithenge_binary_op_t op, bithenge_expression_t *a,
     127    bithenge_expression_t *b)
     128{
     129        int rc;
     130        binary_expression_t *self = malloc(sizeof(*self));
     131        if (!self) {
     132                rc = ENOMEM;
     133                goto error;
     134        }
     135
     136        rc = bithenge_init_expression(binary_as_expression(self),
     137            &binary_expression_ops);
     138        if (rc != EOK)
     139                goto error;
     140
     141        self->op = op;
     142        self->a = a;
     143        self->b = b;
     144        *out = binary_as_expression(self);
     145        return EOK;
     146
     147error:
     148        bithenge_expression_dec_ref(a);
     149        bithenge_expression_dec_ref(b);
     150        free(self);
     151        return rc;
     152}
     153
    65154static int current_node_evaluate(bithenge_expression_t *self,
    66155    bithenge_scope_t *scope, bithenge_node_t **out)
  • uspace/app/bithenge/expression.h

    r20ac1a4 r78d3a00  
    9191}
    9292
     93typedef enum {
     94        BITHENGE_EXPRESSION_EQUALS,
     95} bithenge_binary_op_t;
     96
    9397int bithenge_init_expression(bithenge_expression_t *,
    9498    const bithenge_expression_ops_t *);
     99int bithenge_binary_expression(bithenge_expression_t **, bithenge_binary_op_t,
     100    bithenge_expression_t *, bithenge_expression_t *);
    95101int bithenge_current_node_expression(bithenge_expression_t **);
    96102int bithenge_param_expression(bithenge_expression_t **, int);
  • uspace/app/bithenge/script.c

    r20ac1a4 r78d3a00  
    6262        TOKEN_IF,
    6363        TOKEN_STRUCT,
     64        TOKEN_SWITCH,
    6465        TOKEN_TRANSFORM,
    6566        TOKEN_TRUE,
     
    219220                } else if (!str_cmp(value, "struct")) {
    220221                        state->token = TOKEN_STRUCT;
     222                        free(value);
     223                } else if (!str_cmp(value, "switch")) {
     224                        state->token = TOKEN_SWITCH;
    221225                        free(value);
    222226                } else if (!str_cmp(value, "transform")) {
     
    548552}
    549553
     554static bithenge_transform_t *parse_switch(state_t *state, bool in_struct)
     555{
     556        expect(state, TOKEN_SWITCH);
     557        expect(state, '(');
     558        bithenge_expression_t *ref_expr = parse_expression(state);
     559        expect(state, ')');
     560        expect(state, '{');
     561        int num = 0;
     562        bithenge_expression_t **exprs = NULL;
     563        bithenge_transform_t **xforms = NULL;
     564        while (state->error == EOK && state->token != '}') {
     565                bithenge_expression_t *expr;
     566                if (state->token == TOKEN_ELSE) {
     567                        next_token(state);
     568                        bithenge_node_t *node;
     569                        int rc = bithenge_new_boolean_node(&node, true);
     570                        if (rc != EOK) {
     571                                error_errno(state, rc);
     572                                break;
     573                        }
     574                        rc = bithenge_const_expression(&expr, node);
     575                        if (rc != EOK) {
     576                                error_errno(state, rc);
     577                                break;
     578                        }
     579                } else {
     580                        expr = parse_expression(state);
     581                        if (state->error == EOK) {
     582                                bithenge_expression_inc_ref(ref_expr);
     583                                int rc = bithenge_binary_expression(&expr,
     584                                    BITHENGE_EXPRESSION_EQUALS, ref_expr,
     585                                    expr);
     586                                if (rc != EOK) {
     587                                        error_errno(state, rc);
     588                                        break;
     589                                }
     590                        }
     591                }
     592
     593                expect(state, ':');
     594                bithenge_transform_t *xform;
     595                if (in_struct) {
     596                        expect(state, '{');
     597                        xform = parse_struct(state);
     598                        expect(state, '}');
     599                } else
     600                        xform = parse_transform(state);
     601                expect(state, ';');
     602
     603                exprs = state_realloc(state, exprs,
     604                    sizeof(*exprs) * (num + 1));
     605                xforms = state_realloc(state, xforms,
     606                    sizeof(*xforms) * (num + 1));
     607                if (state->error != EOK) {
     608                        bithenge_expression_dec_ref(expr);
     609                        bithenge_transform_dec_ref(xform);
     610                        break;
     611                }
     612
     613                exprs[num] = expr;
     614                xforms[num] = xform;
     615                num++;
     616        }
     617        bithenge_expression_dec_ref(ref_expr);
     618
     619        bithenge_transform_t *switch_xform = &bithenge_invalid_transform;
     620        bithenge_transform_inc_ref(switch_xform);
     621        while (state->error == EOK && num >= 1) {
     622                num--;
     623                int rc = bithenge_if_transform(&switch_xform, exprs[num],
     624                    xforms[num], switch_xform);
     625                if (rc != EOK)
     626                        error_errno(state, rc);
     627        }
     628
     629        while (num >= 1) {
     630                num--;
     631                bithenge_expression_dec_ref(exprs[num]);
     632                bithenge_transform_dec_ref(xforms[num]);
     633        }
     634        free(exprs);
     635        free(xforms);
     636
     637        expect(state, '}');
     638        return switch_xform;
     639}
     640
    550641/* The TOKEN_STRUCT and '{' must already have been skipped. */
    551642static bithenge_transform_t *parse_struct(state_t *state)
     
    558649                if (state->token == TOKEN_IF) {
    559650                        subxforms[num].transform = parse_if(state, true);
     651                        subxforms[num].name = NULL;
     652                } else if (state->token == TOKEN_SWITCH) {
     653                        subxforms[num].transform = parse_switch(state, true);
    560654                        subxforms[num].name = NULL;
    561655                } else {
     
    609703                expect(state, '}');
    610704                return xform;
     705        } else if (state->token == TOKEN_SWITCH) {
     706                return parse_switch(state, false);
    611707        } else {
    612708                syntax_error(state, "unexpected (transform expected)");
  • uspace/app/bithenge/transform.c

    r20ac1a4 r78d3a00  
    183183bithenge_transform_t bithenge_ascii_transform = {
    184184        &ascii_ops, 1, 0
     185};
     186
     187static int invalid_apply(bithenge_transform_t *self, bithenge_scope_t *scope,
     188    bithenge_node_t *in, bithenge_node_t **out)
     189{
     190        return EINVAL;
     191}
     192
     193static const bithenge_transform_ops_t invalid_ops = {
     194        .apply = invalid_apply,
     195        .destroy = transform_indestructible,
     196};
     197
     198/** A transform that always raises an error. */
     199bithenge_transform_t bithenge_invalid_transform = {
     200        &invalid_ops, 1, 0
    185201};
    186202
  • uspace/app/bithenge/transform.h

    r20ac1a4 r78d3a00  
    256256extern bithenge_transform_t bithenge_ascii_transform;
    257257extern bithenge_transform_t bithenge_known_length_transform;
     258extern bithenge_transform_t bithenge_invalid_transform;
    258259extern bithenge_transform_t bithenge_uint8_transform;
    259260extern bithenge_transform_t bithenge_uint16le_transform;
  • uspace/app/bithenge/tree.c

    r20ac1a4 r78d3a00  
    325325
    326326/** Check whether the contents of two nodes are equal. Does not yet work for
    327  * internal nodes.
     327 * internal nodes. Takes ownership of nothing.
    328328 * @memberof bithenge_node_t
    329329 * @param a, b Nodes to compare.
  • uspace/dist/src/bithenge/test.bh

    r20ac1a4 r78d3a00  
    88};
    99
    10 transform item(first_len, second_len) = struct {
    11         .id <- uint32le <- known_length(4); # the known_length is unnecessary
     10transform u32(little_endian) =
     11        if (little_endian) {
     12                uint32le
     13        } else {
     14                uint32be
     15        };
     16
     17transform item(little_endian, len) = struct {
     18        .type <- u32(little_endian);
    1219        .name <- pascal_string;
    13         .first <- known_length(first_len);
    14         .second <- known_length(second_len);
     20        switch (.type) {
     21                3: {
     22                        .val <- u32(little_endian);
     23                };
     24                14: {
     25                        .text <- ascii <- known_length(len);
     26                };
     27                else: {
     28                        .unknown <- known_length(len);
     29                };
     30        }
    1531};
    1632
    17 transform main() = item(3, 0);
     33transform main() = struct {
     34        .first_item <- item(true, 3);
     35        .second_item <- item(false, 4);
     36};
Note: See TracChangeset for help on using the changeset viewer.