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

Changeset 20ac1a4 in mainline


Ignore:
Timestamp:
2012-07-30T02:07:10Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
78d3a00
Parents:
10334c2e
Message:

Bithenge: add syntactic sugar for if in struct

Location:
uspace/app/bithenge
Files:
3 edited

Legend:

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

    r10334c2e r20ac1a4  
    420420        bithenge_transform_t base;
    421421        bithenge_expression_t *expr;
     422} expression_transform_t;
     423
     424static inline bithenge_transform_t *expression_as_transform(
     425    expression_transform_t *self)
     426{
     427        return &self->base;
     428}
     429
     430static inline expression_transform_t *transform_as_expression(
     431    bithenge_transform_t *base)
     432{
     433        return (expression_transform_t *)base;
     434}
     435
     436static int expression_transform_apply(bithenge_transform_t *base,
     437    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
     438{
     439        expression_transform_t *self = transform_as_expression(base);
     440        if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
     441                return EINVAL;
     442        aoff64_t len;
     443        int rc = bithenge_blob_size(bithenge_node_as_blob(in), &len);
     444        if (rc != EOK)
     445                return rc;
     446        if (len != 0)
     447                return EINVAL;
     448        return bithenge_expression_evaluate(self->expr, scope, out);
     449}
     450
     451static int expression_transform_prefix_length(bithenge_transform_t *base,
     452    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
     453{
     454        *out = 0;
     455        return EOK;
     456}
     457
     458static void expression_transform_destroy(bithenge_transform_t *base)
     459{
     460        expression_transform_t *self = transform_as_expression(base);
     461        bithenge_expression_dec_ref(self->expr);
     462        free(self);
     463}
     464
     465static const bithenge_transform_ops_t expression_transform_ops = {
     466        .apply = expression_transform_apply,
     467        .prefix_length = expression_transform_prefix_length,
     468        .destroy = expression_transform_destroy,
     469};
     470
     471/** Create a transform that takes an empty blob and produces the result of an
     472 * expression. Takes a reference to the expression.
     473 * @param[out] out Holds the new transform.
     474 * @param expr The expression to evaluate.
     475 * @return EOK on success or an error code from errno.h. */
     476int bithenge_expression_transform(bithenge_transform_t ** out,
     477    bithenge_expression_t *expr)
     478{
     479        int rc;
     480        expression_transform_t *self = malloc(sizeof(*self));
     481        if (!self) {
     482                rc = ENOMEM;
     483                goto error;
     484        }
     485
     486        rc = bithenge_init_transform(expression_as_transform(self),
     487            &expression_transform_ops, 0);
     488        if (rc != EOK)
     489                goto error;
     490
     491        self->expr = expr;
     492        *out = expression_as_transform(self);
     493        return EOK;
     494
     495error:
     496        free(self);
     497        bithenge_expression_dec_ref(expr);
     498        return rc;
     499}
     500
     501typedef struct {
     502        bithenge_transform_t base;
     503        bithenge_expression_t *expr;
    422504        bithenge_transform_t *true_xform, *false_xform;
    423505} if_transform_t;
  • uspace/app/bithenge/expression.h

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

    r10334c2e r20ac1a4  
    342342
    343343static bithenge_transform_t *parse_transform(state_t *state);
     344static bithenge_transform_t *parse_struct(state_t *state);
    344345
    345346static bithenge_expression_t *parse_expression(state_t *state)
     
    490491}
    491492
    492 static bithenge_transform_t *parse_if(state_t *state)
     493static bithenge_transform_t *parse_if(state_t *state, bool in_struct)
    493494{
    494495        expect(state, TOKEN_IF);
     
    497498        expect(state, ')');
    498499        expect(state, '{');
    499         bithenge_transform_t *true_xform = parse_transform(state);
     500        bithenge_transform_t *true_xform =
     501            in_struct ? parse_struct(state) : parse_transform(state);
    500502        expect(state, '}');
    501         expect(state, TOKEN_ELSE);
    502         expect(state, '{');
    503         bithenge_transform_t *false_xform = parse_transform(state);
    504         expect(state, '}');
     503        bithenge_transform_t *false_xform = NULL;
     504        if (state->token == TOKEN_ELSE) {
     505                next_token(state);
     506                expect(state, '{');
     507                false_xform =
     508                    in_struct ? parse_struct(state) : parse_transform(state);
     509                expect(state, '}');
     510        } else {
     511                if (in_struct) {
     512                        bithenge_node_t *node;
     513                        int rc = bithenge_new_empty_internal_node(&node);
     514                        if (rc != EOK) {
     515                                error_errno(state, rc);
     516                                goto error;
     517                        }
     518                        bithenge_expression_t *expr;
     519                        rc = bithenge_const_expression(&expr, node);
     520                        if (rc != EOK) {
     521                                error_errno(state, rc);
     522                                goto error;
     523                        }
     524                        rc = bithenge_expression_transform(&false_xform, expr);
     525                        if (rc != EOK) {
     526                                error_errno(state, rc);
     527                                false_xform = NULL;
     528                                goto error;
     529                        }
     530                } else
     531                        syntax_error(state, "else expected");
     532        }
    505533        if (state->error != EOK) {
     534error:
    506535                bithenge_expression_dec_ref(expr);
    507536                bithenge_transform_dec_ref(true_xform);
     
    519548}
    520549
     550/* The TOKEN_STRUCT and '{' must already have been skipped. */
    521551static bithenge_transform_t *parse_struct(state_t *state)
    522552{
     
    525555        /* We keep an extra space for the {NULL, NULL} terminator. */
    526556        subxforms = state_malloc(state, sizeof(*subxforms));
    527         expect(state, TOKEN_STRUCT);
    528         expect(state, '{');
    529557        while (state->error == EOK && state->token != '}') {
    530                 if (state->token == '.') {
    531                         expect(state, '.');
    532                         subxforms[num].name = expect_identifier(state);
     558                if (state->token == TOKEN_IF) {
     559                        subxforms[num].transform = parse_if(state, true);
     560                        subxforms[num].name = NULL;
     561                } else {
     562                        if (state->token == '.') {
     563                                next_token(state);
     564                                subxforms[num].name = expect_identifier(state);
     565                        } else {
     566                                subxforms[num].name = NULL;
     567                        }
    533568                        expect(state, TOKEN_LEFT_ARROW);
    534                 } else {
    535                         subxforms[num].name = NULL;
    536                         expect(state, TOKEN_LEFT_ARROW);
    537                 }
    538                 subxforms[num].transform = parse_transform(state);
    539                 expect(state, ';');
     569                        subxforms[num].transform = parse_transform(state);
     570                        expect(state, ';');
     571                }
    540572                num++;
    541573                subxforms = state_realloc(state, subxforms,
    542574                    (num + 1)*sizeof(*subxforms));
    543575        }
    544         expect(state, '}');
    545576
    546577        if (state->error != EOK) {
     
    571602                return parse_invocation(state);
    572603        } else if (state->token == TOKEN_IF) {
    573                 return parse_if(state);
     604                return parse_if(state, false);
    574605        } else if (state->token == TOKEN_STRUCT) {
    575                 return parse_struct(state);
     606                next_token(state);
     607                expect(state, '{');
     608                bithenge_transform_t *xform = parse_struct(state);
     609                expect(state, '}');
     610                return xform;
    576611        } else {
    577612                syntax_error(state, "unexpected (transform expected)");
Note: See TracChangeset for help on using the changeset viewer.