view src/value_test.c @ 128:38714d118bbd

value: Implement stack-references for function calls
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 01 Sep 2019 19:22:12 +0200
parents 3b468dad363f
children a4a714456110
line wrap: on
line source

#include "value.h"

#include <assert.h>

void test_value_create_resolve(void) {
    ystr_t sym;
    ystr_init(&sym, "vcr_symbol");

    assert(YVALUE_INVALID_ID == yvalue_resolve_symbol(&sym));

    yvalue_id_t id = yvalue_resolve_or_create_symbol(&sym);
    assert(YVALUE_INVALID_ID != id);
    assert(id == yvalue_resolve_symbol(&sym));

    yvalue_id_t id2 = yvalue_create();
    assert(id2 != id);
    assert(id2 == id+1);

    ystr_destroy(&sym);
}

void test_ref_create_resolve(void) {
    ystr_t symbol = ystr_new("rcr_symbol_long_long");
    ystr_t symbol2 = ystr_new(NULL);
    ystr_copy(&symbol, &symbol2);
    yref_t ref = yref_new_str(&symbol);  // symbol is now owned by ref.

    yref_t cloned = yref_clone(&ref);
    assert(cloned.ref.sym.inner.big.base != ref.ref.sym.inner.big.base);

    yvalue_resolve_or_create_ref(&ref);
    assert(YVALUE_INVALID_ID != yvalue_resolve_symbol(&symbol2));
    assert(YREF_ID == yref_type(&ref));
    assert(ref.ref.id == yref_clone(&ref).ref.id);
    assert(YREF_SYM == yref_type(&cloned));
    assert(ref.ref.id == yvalue_resolve_symbol(&symbol2));

    ystr_destroy(&symbol2);
    yref_destroy(&ref);
    yref_destroy(&cloned);
}

void test_value_clone(void) {
    yvalue_t first_value = { .typ = YVALUE_EXPR, .value.expr = yexpr_new() };
    yexpr_set_str(&first_value.value.expr, ystr_new("a long external test string"));
    yref_t first = yvalue_set(YVALUE_INSERT, &first_value);
    yref_t second = yvalue_set(YVALUE_INSERT, &first_value);
    yref_t cloned = yvalue_clone(&first);
    assert(first.ref.id != cloned.ref.id);

    *ystr_at(&yvalue_get(first)->value.expr.value.str, 0) = 'A';
    assert('A' == *ystr_at(&yvalue_get(first)->value.expr.value.str, 0));
    assert('A' == *ystr_at(&yvalue_get(second)->value.expr.value.str, 0));
    assert('A' == *ystr_at(&yvalue_get(yref_clone(&first))->value.expr.value.str, 0));
    assert('a' == *ystr_at(&yvalue_get(cloned)->value.expr.value.str, 0));
}

void test_value_set(void) {
    yexpr_t expr;
    expr.typ = YEXPR_NUMBER;
    expr.value.n = 12345;
    yvalue_t val;
    val.typ = YVALUE_EXPR;
    val.value.expr = expr;

    // Allocate unnamed ref.
    yref_t ref = yvalue_set(YVALUE_INSERT, &val);
    assert(YREF_ID == yref_type(&ref));
    yvalue_t* got = yvalue_get(ref);
    assert(YVALUE_EXPR == got->typ);
    assert(YEXPR_NUMBER == got->value.expr.typ);
    assert(12345 == got->value.expr.value.n);

    // Use named refs.
    ystr_t symbol = ystr_new("vs_symbol");
    ystr_t symbol2 = ystr_new("vs_symbol");

    val.value.expr.value.n = 12346;
    yvalue_id_t id = yvalue_resolve_or_create_symbol(&symbol);
    yref_t ref2 = yref_new_id(id);
    yref_t ref2b = yvalue_set(ref2, &val);
    assert(ref2b.ref.id == ref2.ref.id);
    yvalue_t* got2 = yvalue_get(ref2);
    assert(12346 == got2->value.expr.value.n);

    // Get symbolically.
    yref_t ref3 = yref_new_str(&symbol2);
    yvalue_t* got3 = yvalue_get(ref3);
    assert(12346 == got3->value.expr.value.n);

    // Get invalid entry.
    yref_t ref_invalid = yref_new_c("invalid_entry");
    assert(NULL == yvalue_get(ref_invalid));
    assert(NULL != yvalue_get(ref3));

    yvalue_destroy(&val);
    yref_destroy(&ref);
    yref_destroy(&ref2);
    yref_destroy(&ref2b);
    yref_destroy(&ref3);
    yref_destroy(&ref_invalid);
}

void test_value_refs(void) {
    yref_t ref = yref_new_c("hello");
    assert(YREF_SYM == yref_type(&ref));
    yref_destroy(&ref);
    ref = yref_new();
    assert(YREF_ID == yref_type(&ref));
    yref_destroy(&ref);
    ref = yref_new_cix(2);
    assert(YREF_STACK == yref_type(&ref));
    assert(2 == yref_cix(&ref));
    ystr_t dbg = yref_debug(&ref);
    assert(0 == ystr_cmp_str(&dbg, "id:<stackrel:-2>"));
    ystr_destroy(&dbg);
    yref_destroy(&ref);
}

int main(void) {
    test_value_create_resolve();
    test_ref_create_resolve();
    test_value_clone();
    test_value_set();
    test_value_refs();
}