better test coverage
[protos/libecoli.git] / lib / ecoli_node_expr.c
index cbc9441..2be8f55 100644 (file)
@@ -47,6 +47,8 @@
 #include <ecoli_node_weakref.h>
 #include <ecoli_node_expr.h>
 
+EC_LOG_TYPE_REGISTER(node_expr);
+
 struct ec_node_expr {
        struct ec_node gen;
 
@@ -72,16 +74,21 @@ static int ec_node_expr_parse(const struct ec_node *gen_node,
 {
        struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 
+       if (node->child == NULL)
+               return -ENOENT;
        return ec_node_parse_child(node->child, state, strvec);
 }
 
-static struct ec_completed *ec_node_expr_complete(const struct ec_node *gen_node,
-                                               struct ec_parsed *state,
-                                               const struct ec_strvec *strvec)
+static int
+ec_node_expr_complete(const struct ec_node *gen_node,
+               struct ec_completed *completed,
+               const struct ec_strvec *strvec)
 {
        struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 
-       return ec_node_complete_child(node->child, state, strvec);
+       if (node->child == NULL)
+               return -ENOENT;
+       return ec_node_complete_child(node->child, completed, strvec);
 }
 
 static void ec_node_expr_free_priv(struct ec_node *gen_node)
@@ -89,7 +96,7 @@ static void ec_node_expr_free_priv(struct ec_node *gen_node)
        struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
        unsigned int i;
 
-       ec_log(EC_LOG_DEBUG, "free %p %p %p\n", node, node->child, node->val_node);
+       EC_LOG(EC_LOG_DEBUG, "free %p %p %p\n", node, node->child, node->val_node);
        ec_node_free(node->val_node);
 
        for (i = 0; i < node->bin_ops_len; i++)
@@ -111,21 +118,37 @@ static void ec_node_expr_free_priv(struct ec_node *gen_node)
        ec_node_free(node->child);
 }
 
-static int ec_node_expr_build(struct ec_node *gen_node)
+static int ec_node_expr_build(struct ec_node_expr *node)
 {
-       struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
        struct ec_node *term = NULL, *expr = NULL, *next = NULL,
                *pre_op = NULL, *post_op = NULL,
                *post = NULL, *weak = NULL;
        unsigned int i;
        int ret;
 
+       ec_node_free(node->child);
+       node->child = NULL;
+
        if (node->val_node == NULL)
                return -EINVAL;
        if (node->bin_ops_len == 0 && node->pre_ops_len == 0 &&
                        node->post_ops_len == 0)
                return -EINVAL;
 
+       /*
+        * Example of created grammar:
+        *
+        * pre_op = "!"
+        * post_op = "^"
+        * post = val |
+        *        pre_op expr |
+        *        "(" expr ")"
+        * term = post post_op*
+        * prod = term ( "*" term )*
+        * sum = prod ( "+" prod )*
+        * expr = sum
+        */
+
        /* create the object, we will initialize it later: this is
         * needed because we have a circular dependency */
        ret = -ENOMEM;
@@ -157,12 +180,12 @@ static int ec_node_expr_build(struct ec_node *gen_node)
        if (ec_node_or_add(post, ec_node_clone(node->val_node)) < 0)
                goto fail;
        if (ec_node_or_add(post,
-               EC_NODE_SEQ(NULL,
+               EC_NODE_SEQ(EC_NO_ID,
                        ec_node_clone(pre_op),
                        ec_node_clone(weak))) < 0)
                goto fail;
        for (i = 0; i < node->paren_len; i++) {
-               if (ec_node_or_add(post, EC_NODE_SEQ(NULL,
+               if (ec_node_or_add(post, EC_NODE_SEQ(EC_NO_ID,
                                        ec_node_clone(node->open_ops[i]),
                                        ec_node_clone(weak),
                                        ec_node_clone(node->close_ops[i]))) < 0)
@@ -170,7 +193,7 @@ static int ec_node_expr_build(struct ec_node *gen_node)
        }
        term = EC_NODE_SEQ("term",
                ec_node_clone(post),
-               ec_node_many(NULL, ec_node_clone(post_op), 0, 0)
+               ec_node_many(EC_NO_ID, ec_node_clone(post_op), 0, 0)
        );
        if (term == NULL)
                goto fail;
@@ -178,8 +201,8 @@ static int ec_node_expr_build(struct ec_node *gen_node)
        for (i = 0; i < node->bin_ops_len; i++) {
                next = EC_NODE_SEQ("next",
                        ec_node_clone(term),
-                       ec_node_many(NULL,
-                               EC_NODE_SEQ(NULL,
+                       ec_node_many(EC_NO_ID,
+                               EC_NODE_SEQ(EC_NO_ID,
                                        ec_node_clone(node->bin_ops[i]),
                                        ec_node_clone(term)
                                ),
@@ -209,7 +232,6 @@ static int ec_node_expr_build(struct ec_node *gen_node)
        weak = NULL;
 
        node->child = expr;
-       ec_node_dump(stdout, node->child); //XXX
 
        return 0;
 
@@ -226,7 +248,6 @@ fail:
 
 static struct ec_node_type ec_node_expr_type = {
        .name = "expr",
-       .build = ec_node_expr_build,
        .parse = ec_node_expr_parse,
        .complete = ec_node_expr_complete,
        .size = sizeof(struct ec_node_expr),
@@ -240,18 +261,17 @@ int ec_node_expr_set_val_node(struct ec_node *gen_node, struct ec_node *val_node
        struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
        int ret;
 
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
+
        ret = -EINVAL;
        if (val_node == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;
-       ret = -EEXIST;
-       if (node->val_node != NULL)
-               goto fail;
 
+       ec_node_free(node->val_node);
        node->val_node = val_node;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -267,14 +287,13 @@ int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
        struct ec_node **bin_ops;
        int ret;
 
-       // XXX check node type
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
 
        ret = -EINVAL;
        if (node == NULL || op == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;
 
        ret = -ENOMEM;
        bin_ops = ec_realloc(node->bin_ops,
@@ -285,7 +304,7 @@ int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
        node->bin_ops = bin_ops;
        bin_ops[node->bin_ops_len] = op;
        node->bin_ops_len++;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -301,14 +320,13 @@ int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
        struct ec_node **pre_ops;
        int ret;
 
-       // XXX check node type
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
 
        ret = -EINVAL;
        if (node == NULL || op == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;
 
        ret = -ENOMEM;
        pre_ops = ec_realloc(node->pre_ops,
@@ -319,7 +337,7 @@ int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
        node->pre_ops = pre_ops;
        pre_ops[node->pre_ops_len] = op;
        node->pre_ops_len++;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -335,14 +353,13 @@ int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
        struct ec_node **post_ops;
        int ret;
 
-       // XXX check node type
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
 
        ret = -EINVAL;
        if (node == NULL || op == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;
 
        ret = -ENOMEM;
        post_ops = ec_realloc(node->post_ops,
@@ -353,7 +370,7 @@ int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
        node->post_ops = post_ops;
        post_ops[node->post_ops_len] = op;
        node->post_ops_len++;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -370,14 +387,13 @@ int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
        struct ec_node **open_ops, **close_ops;
        int ret;
 
-       // XXX check node type
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
 
        ret = -EINVAL;
        if (node == NULL || open == NULL || close == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;;
 
        ret = -ENOMEM;
        open_ops = ec_realloc(node->open_ops,
@@ -394,7 +410,7 @@ int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
        open_ops[node->paren_len] = open;
        close_ops[node->paren_len] = close;
        node->paren_len++;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -413,6 +429,7 @@ enum expr_node_type {
        PAREN_OPEN,
        PAREN_CLOSE,
 };
+
 static enum expr_node_type get_node_type(const struct ec_node *expr_gen_node,
        const struct ec_node *check)
 {
@@ -523,7 +540,7 @@ static int eval_expression(struct result *result,
        memset(result, 0, sizeof(*result));
        memset(&child_result, 0, sizeof(child_result));
 
-       type = get_node_type(expr_gen_node, parsed->node);
+       type = get_node_type(expr_gen_node, ec_parsed_get_node(parsed));
        if (type == VAL) {
                ret = ops->eval_var(&result->val, userctx, parsed);
                if (ret < 0)
@@ -534,9 +551,9 @@ static int eval_expression(struct result *result,
                result->op_type = type;
        }
 
-       TAILQ_FOREACH(child, &parsed->children, next) {
+       EC_PARSED_FOREACH_CHILD(child, parsed) {
 
-               type = get_node_type(expr_gen_node, child->node);
+               type = get_node_type(expr_gen_node, ec_parsed_get_node(child));
                if (type == PAREN_OPEN) {
                        open = child;
                        continue;
@@ -588,10 +605,13 @@ int ec_node_expr_eval(void **user_result, const struct ec_node *node,
                        ops->eval_parenthesis == NULL || ops->eval_free == NULL)
                return -EINVAL;
 
+       ret = ec_node_check_type(node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
+
        if (!ec_parsed_matches(parsed))
                return -EINVAL;
 
-       ec_parsed_dump(stdout, parsed); //XXX
        ret = eval_expression(&result, userctx, ops, node, parsed);
        if (ret < 0)
                return ret;