view src/expr_test.c @ 151:fe5d01fa28ee

value, expr: Test "==" methods and enable freeing all symbols
author Lewin Bormann <lbo@spheniscida.de>
date Tue, 03 Sep 2019 12:57:53 +0200
parents 63650268d006
children 800a02381024
line wrap: on
line source

#include "expr.h"

#include "value.h"

void test_expr_ref_type(void) {
    ystr_t str = ystr_new("abc");
    yref_t ref0, ref = yref_new_c("abc");

    assert(YREF_SYM == yref_type(&ref));
    yref_destroy(&ref);

    ref = yref_new_str(&str);
    assert(YREF_SYM == yref_type(&ref));

    yexpr_t exprref = yexpr_new();
    yexpr_set_ref(&exprref, ref);
    assert(YEXPR_REF == exprref.typ);

    yexpr_destroy(&exprref);

    ystr_t str2 = ystr_new("abc");
    ref = yref_new_id(yvalue_resolve_or_create_symbol(&str2));
    assert(YREF_ID == yref_type(&ref));
    ystr_destroy(&str2);
    ref0 = ref;

    ref = yref_new();
    assert(YREF_ID == yref_type(&ref));
    assert(ref.ref.id == ref0.ref.id + 1);
}

void test_expr_copy(void) {
    yexpr_t expr = yexpr_new();
    yref_t ref = yref_new_c("a long external reference name");

    yexpr_set_ref(&expr, ref);
    yexpr_t copy = yexpr_copy(&expr);
    assert(ystr_at(&expr.value.ref.ref.sym, 0) !=
           ystr_at(&copy.value.ref.ref.sym, 0));

    yexpr_destroy(&expr);
    yexpr_destroy(&copy);

    yexpr_t ilist[] = {yexpr_new(), yexpr_new(), yexpr_new()};
    yexpr_set_number(&ilist[0], 22);
    yexpr_set_number(&ilist[1], 23);
    yexpr_set_number(&ilist[2], 24);
    yvec_t vec = YVEC_NEW(ilist, 4, yexpr_t);
    yexpr_set_list(&expr, vec);
    copy = yexpr_copy(&expr);
    (*YVEC_AT(&vec, 0, int))++;
    assert(23 == YVEC_AT(&expr.value.list, 0, yexpr_t)->value.n);
    assert(22 == YVEC_AT(&copy.value.list, 0, yexpr_t)->value.n);

    yexpr_destroy(&expr);
    yexpr_destroy(&copy);
}

void test_expr_set(void) {
    yexpr_t expr = yexpr_new();

    // Test undef.
    yexpr_debug(&expr);

    // Test atoms.
    yexpr_set_atom_name(&expr, "myatom");
    assert(0 == strcmp("myatom", yatom_name(expr.value.atom)));
    yexpr_set_atom(&expr, yatom_get_or_add("myatom2"));
    assert(0 == strcmp("myatom2", yatom_name(expr.value.atom)));
    yexpr_debug(&expr);
    yexpr_destroy(&expr);
    expr = yexpr_new();

    // Test builtins.
    yexpr_set_builtin(&expr, YBUILTIN_DEFN);
    assert(YEXPR_BUILTIN == expr.typ);
    assert(YBUILTIN_DEFN == expr.value.builtin);
    yexpr_debug(&expr);

    // Test number.
    yexpr_set_number(&expr, 12345);
    assert(12345 == expr.value.n);
    yexpr_debug(&expr);
    yexpr_destroy(&expr);
    expr = yexpr_new();

    // Test string.
    yexpr_set_str(&expr, ystr_new("hello"));
    assert(0 == ystr_cmp_str(&expr.value.str, "hello"));
    yexpr_debug(&expr);
    yexpr_destroy(&expr);
    expr = yexpr_new();

    // Test refs, symbolic and numeric.
    yexpr_set_ref(&expr, yref_new_c("my-ref"));
    yexpr_debug(&expr);
    yvalue_resolve_or_create_ref(&expr.value.ref);
    assert(YREF_ID == yref_type(&expr.value.ref));
    yexpr_debug(&expr);
    yexpr_destroy(&expr);
    expr = yexpr_new();

    // Test exception.
    ystr_t message = ystr_new("some error happened");
    yexpr_set_exception(&expr, message);
    yexpr_debug(&expr);
    yexpr_destroy(&expr);
    expr = yexpr_new();

    // Test list.
    yexpr_t src[3] = {yexpr_new(), yexpr_new(), yexpr_new()};
    yexpr_set_number(&src[0], 123);
    yexpr_set_number(&src[1], 124);
    yexpr_set_number(&src[2], 125);
    yvec_t vec = YVEC_NEW(src, 3, yexpr_t);
    yexpr_set_list(&expr, vec);
    assert(124 == (YVEC_AT(&expr.value.list, 1, yexpr_t))->value.n);

    // Test append (first value to end).
    yexpr_append_value(&expr, src[0]);
    yexpr_append_value(&expr, src[2]);
    assert(123 == (YVEC_AT(&expr.value.list, 3, yexpr_t))->value.n);
    assert(125 == (YVEC_AT(&expr.value.list, 4, yexpr_t))->value.n);

    yexpr_destroy(&expr);
    expr = yexpr_new();

    // Test init_or_extend.
    yexpr_set_builtin(&expr, YBUILTIN_MULT);
    yexpr_t tmp = yexpr_new();
    yexpr_set_number(&tmp, 12345);
    yexpr_init_or_extend(&expr, tmp);

    yexpr_t src2[3] = {yexpr_new(), yexpr_new(), yexpr_new()};
    yexpr_set_atom_name(&src2[0], "atom1");
    yexpr_set_atom_name(&src2[1], "atom2");
    yexpr_set_atom_name(&src2[2], "atom3");
    yexpr_init_or_extend(&expr, src2[0]);
    yexpr_init_or_extend(&expr, src2[2]);
    // Expr now contains list of exprs: 12345, atom1, atom3.
    yvec_t list = expr.value.list;
    assert(12345 == YVEC_AT(&list, 1, yexpr_t)->value.n);
    yatom_t got = YVEC_AT(&list, 2, yexpr_t)->value.atom;
    assert(yatom_get_or_add("atom1") == got);
    got = YVEC_AT(&list, 3, yexpr_t)->value.atom;
    assert(yatom_get_or_add("atom3") == got);

    yexpr_debug(&expr);

    yexpr_destroy(&expr);
}

int main(void) {
    test_expr_ref_type();
    test_expr_copy();
    test_expr_set();
    return 0;
}