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

Changeset f85ca3f in mainline


Ignore:
Timestamp:
2012-07-28T21:25:49Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
84e8a70
Parents:
32eb01b
Message:

Bithenge: add expressions that use the current node being created

Location:
uspace/app/bithenge
Files:
5 edited

Legend:

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

    r32eb01b rf85ca3f  
    5858}
    5959
     60static void expression_indestructible(bithenge_expression_t *self)
     61{
     62        assert(false);
     63}
     64
     65static int current_node_evaluate(bithenge_expression_t *self,
     66    bithenge_scope_t *scope, bithenge_node_t **out)
     67{
     68        *out = bithenge_scope_get_current_node(scope);
     69        if (!*out)
     70                return EINVAL;
     71        return EOK;
     72}
     73
     74static const bithenge_expression_ops_t current_node_ops = {
     75        .evaluate = current_node_evaluate,
     76        .destroy = expression_indestructible,
     77};
     78
     79static bithenge_expression_t current_node_expression = {
     80        &current_node_ops, 1
     81};
     82
     83/** Create an expression that gets the current node being created.
     84 * @param[out] out Holds the new expression.
     85 * @return EOK on success or an error code from errno.h. */
     86int bithenge_current_node_expression(bithenge_expression_t **out)
     87{
     88        bithenge_expression_inc_ref(&current_node_expression);
     89        *out = &current_node_expression;
     90        return EOK;
     91}
     92
    6093typedef struct {
    6194        bithenge_expression_t base;
     
    176209        *out = const_as_expression(self);
    177210        return EOK;
     211}
     212
     213typedef struct {
     214        bithenge_expression_t base;
     215        bithenge_expression_t *expr;
     216        bithenge_node_t *key;
     217} member_expression_t;
     218
     219static member_expression_t *expression_as_member(bithenge_expression_t *base)
     220{
     221        return (member_expression_t *)base;
     222}
     223
     224static bithenge_expression_t *member_as_expression(member_expression_t *expr)
     225{
     226        return &expr->base;
     227}
     228
     229static int member_expression_evaluate(bithenge_expression_t *base,
     230    bithenge_scope_t *scope, bithenge_node_t **out)
     231{
     232        member_expression_t *self = expression_as_member(base);
     233        bithenge_node_t *node;
     234        int rc = bithenge_expression_evaluate(self->expr, scope, &node);
     235        if (rc != EOK)
     236                return rc;
     237        bithenge_node_inc_ref(self->key);
     238        rc = bithenge_node_get(node, self->key, out);
     239        bithenge_node_dec_ref(node);
     240        return rc;
     241}
     242
     243static void member_expression_destroy(bithenge_expression_t *base)
     244{
     245        member_expression_t *self = expression_as_member(base);
     246        bithenge_expression_dec_ref(self->expr);
     247        bithenge_node_dec_ref(self->key);
     248        free(self);
     249}
     250
     251static const bithenge_expression_ops_t member_expression_ops = {
     252        .evaluate = member_expression_evaluate,
     253        .destroy = member_expression_destroy,
     254};
     255
     256/** Create an expression that gets a member from a node. Takes references to
     257 * @a expr and @a key.
     258 * @param[out] out Holds the new expression.
     259 * @param expr Calculates the node to get the member of.
     260 * @param key The member to get.
     261 * @return EOK on success or an error code from errno.h. */
     262int bithenge_member_expression(bithenge_expression_t **out,
     263    bithenge_expression_t *expr, bithenge_node_t *key)
     264{
     265        int rc;
     266        member_expression_t *self = malloc(sizeof(*self));
     267        if (!self) {
     268                rc = ENOMEM;
     269                goto error;
     270        }
     271
     272        rc = bithenge_init_expression(member_as_expression(self),
     273            &member_expression_ops);
     274        if (rc != EOK)
     275                goto error;
     276
     277        self->expr = expr;
     278        self->key = key;
     279        *out = member_as_expression(self);
     280        return EOK;
     281
     282error:
     283        bithenge_expression_dec_ref(expr);
     284        bithenge_node_dec_ref(key);
     285        free(self);
     286        return rc;
    178287}
    179288
  • uspace/app/bithenge/expression.h

    r32eb01b rf85ca3f  
    9393int bithenge_init_expression(bithenge_expression_t *,
    9494    const bithenge_expression_ops_t *);
     95int bithenge_current_node_expression(bithenge_expression_t **);
    9596int bithenge_param_expression(bithenge_expression_t **, int);
    9697int bithenge_const_expression(bithenge_expression_t **, bithenge_node_t *);
     98int bithenge_member_expression(bithenge_expression_t **,
     99    bithenge_expression_t *, bithenge_node_t *);
    97100int bithenge_param_wrapper(bithenge_transform_t **, bithenge_transform_t *,
    98101    bithenge_expression_t **);
  • uspace/app/bithenge/script.c

    r32eb01b rf85ca3f  
    119119}
    120120
    121 /** Note that an error has occurred. */
     121/** Note that an error has occurred if error is not EOK. */
    122122static void error_errno(state_t *state, int error)
    123123{
    124124        // Don't overwrite a previous error.
    125         if (state->error == EOK) {
     125        if (state->error == EOK && error != EOK) {
    126126                done_with_token(state);
    127127                state->token = TOKEN_ERROR;
     
    220220                int rc = bithenge_parse_int(state->buffer +
    221221                    state->old_buffer_pos, &state->token_int);
    222                 if (rc != EOK)
    223                         error_errno(state, rc);
     222                error_errno(state, rc);
    224223        } else if (ch == '<') {
    225224                state->token = ch;
     
    368367
    369368                next_token(state);
     369
     370                return expr;
     371        } else if (state->token == '.') {
     372                next_token(state);
     373
     374                const char *id = expect_identifier(state);
     375                bithenge_node_t *key = NULL;
     376                bithenge_expression_t *expr = NULL;
     377                int rc = bithenge_current_node_expression(&expr);
     378                error_errno(state, rc);
     379
     380                if (state->error == EOK) {
     381                        rc = bithenge_new_string_node(&key, id, true);
     382                        id = NULL;
     383                        error_errno(state, rc);
     384                }
     385
     386                if (state->error == EOK) {
     387                        rc = bithenge_member_expression(&expr, expr, key);
     388                        key = NULL;
     389                        if (rc != EOK)
     390                                expr = NULL;
     391                        error_errno(state, rc);
     392                }
     393
     394                if (state->error != EOK) {
     395                        free((char *)id);
     396                        bithenge_node_dec_ref(key);
     397                        bithenge_expression_dec_ref(expr);
     398                        return NULL;
     399                }
    370400
    371401                return expr;
     
    588618        done_with_token(state);
    589619        state->token = TOKEN_ERROR;
    590         fclose(state->file);
     620        if (state->file)
     621                fclose(state->file);
    591622        transform_list_t *entry = state->transform_list;
    592623        while (entry) {
  • uspace/app/bithenge/transform.c

    r32eb01b rf85ca3f  
    552552        node->blob = bithenge_node_as_blob(in);
    553553        *out = struct_as_node(node);
     554        bithenge_node_inc_ref(*out);
     555        bithenge_scope_set_current_node(&node->scope, *out);
    554556        return EOK;
    555557}
  • uspace/app/bithenge/transform.h

    r32eb01b rf85ca3f  
    5252typedef struct {
    5353        /** @privatesection */
     54        int num_params;
    5455        bithenge_node_t **params;
    55         int num_params;
     56        bithenge_node_t *current_node;
    5657} bithenge_scope_t;
    5758
     
    7475static inline void bithenge_scope_init(bithenge_scope_t *scope)
    7576{
     77        scope->num_params = 0;
    7678        scope->params = NULL;
    77         scope->num_params = 0;
     79        scope->current_node = NULL;
    7880}
    7981
     
    8385static inline void bithenge_scope_destroy(bithenge_scope_t *scope)
    8486{
     87        bithenge_node_dec_ref(scope->current_node);
    8588        for (int i = 0; i < scope->num_params; i++)
    8689                bithenge_node_dec_ref(scope->params[i]);
     
    104107        for (int i = 0; i < out->num_params; i++)
    105108                bithenge_node_inc_ref(out->params[i]);
    106         return EOK;
     109        out->current_node = scope->current_node;
     110        if (out->current_node)
     111                bithenge_node_inc_ref(out->current_node);
     112        return EOK;
     113}
     114
     115/** Set the current node being created. Takes a reference to @a node.
     116 * @param scope The scope to set the current node in.
     117 * @param node The current node being created.
     118 * @return EOK on success or an error code from errno.h. */
     119static inline void bithenge_scope_set_current_node(bithenge_scope_t *scope,
     120    bithenge_node_t *node)
     121{
     122        bithenge_node_dec_ref(scope->current_node);
     123        scope->current_node = node;
     124}
     125
     126/** Get the current node being created, which may be NULL.
     127 * @param scope The scope to get the current node from.
     128 * @return The node being created, or NULL. */
     129static inline bithenge_node_t *bithenge_scope_get_current_node(
     130    bithenge_scope_t *scope)
     131{
     132        if (scope->current_node)
     133                bithenge_node_inc_ref(scope->current_node);
     134        return scope->current_node;
    107135}
    108136
    109137/** Allocate parameters. The parameters must then be set with @a
    110  * bithenge_scope_set_param.
     138 * bithenge_scope_set_param. This must not be called on a scope that already
     139 * has parameters.
    111140 * @param scope The scope in which to allocate parameters.
    112141 * @param num_params The number of parameters to allocate.
Note: See TracChangeset for help on using the changeset viewer.