summaryrefslogtreecommitdiff
path: root/src/runtime/value/small.c
blob: f07e40511b0d2e05346228e7a7f20ce2d581893b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <lcq/pit/runtime/value/small.h>

#ifndef PIT_NO_DOUBLE
double pit_value_as_double(pit_runtime *rt, pit_value v) {
    if (pit_value_sort(v) != PIT_VALUE_SORT_DOUBLE) {
        pit_error(rt, "invalid use of value as double");
        return 0.0;
    }
    union { double dval; u64 ival; } x;
    x.ival = v;
    return x.dval;
}
bool pit_value_is_double(pit_runtime *rt, pit_value a) {
    (void) rt;
    return pit_value_sort(a) == PIT_VALUE_SORT_DOUBLE;
}
pit_value pit_value_double_new(pit_runtime *rt, double d) {
    union { double dval; u64 ival; } x;
    x.dval = d;
    return pit_value_new(rt, PIT_VALUE_SORT_DOUBLE, x.ival);
}
#endif

i64 pit_value_as_integer(pit_runtime *rt, pit_value v) {
    if (pit_value_sort(v) != PIT_VALUE_SORT_INTEGER) {
        pit_error(rt, "invalid use of value as integer");
        return -1;
    }
    u64 lo = pit_value_data(v);
    return ((i64) (lo << 15)) >> 15; /* sign-extend low 49 bits */

}
bool pit_value_is_integer(pit_runtime *rt, pit_value a) {
    (void) rt;
    return pit_value_sort(a) == PIT_VALUE_SORT_INTEGER;
}
pit_value pit_value_integer_new(pit_runtime *rt, i64 i) {
    return pit_value_new(rt, PIT_VALUE_SORT_INTEGER, 0x1ffffffffffff & (u64) i);
}
pit_value pit_value_bool_new(pit_runtime *rt, bool i) {
    (void) rt;
    return i ? PIT_T : PIT_NIL;
}

pit_symbol pit_value_as_symbol(pit_runtime *rt, pit_value v) {
    if (pit_value_sort(v) != PIT_VALUE_SORT_SYMBOL) {
        pit_error(rt, "invalid use of value as symbol");
        return -1;
    }
    return (pit_symbol) (pit_value_data(v) & 0xffffffff);
}
bool pit_value_is_symbol(pit_runtime *rt, pit_value a) {
    (void) rt;
    return pit_value_sort(a) == PIT_VALUE_SORT_SYMBOL;
}
pit_value pit_value_symbol_new(pit_runtime *rt, pit_symbol s) {
    return pit_value_new(rt, PIT_VALUE_SORT_SYMBOL, (u64) s);
}

pit_ref pit_value_as_ref(pit_runtime *rt, pit_value v) {
    if (pit_value_sort(v) != PIT_VALUE_SORT_REF) {
        pit_error(rt, "invalid use of value as ref");
        return -1;
    }
    return (pit_ref) (pit_value_data(v) & 0xffffffff);
}
bool pit_value_is_ref(pit_runtime *rt, pit_value a) {
    (void) rt;
    return pit_value_sort(a) == PIT_VALUE_SORT_REF;
}
pit_value pit_value_ref_new(pit_runtime *rt, pit_ref r) {
    return pit_value_new(rt, PIT_VALUE_SORT_REF, (u64) r);
}
pit_value pit_value_ref_heavy_new(pit_runtime *rt) {
    pit_arena_index idx = pit_arena_alloc_index(rt->heap);
    if (idx < 0) {
        pit_error(rt, "failed to allocate space for heavy value");
        return PIT_NIL;
    }
    return pit_value_ref_new(rt, idx);
}
pit_value_heavy *pit_value_ref_deref(pit_runtime *rt, pit_ref p) {
    return pit_arena_get(rt->heap, p);
}
bool pit_value_is_ref_heavy_sort(pit_runtime *rt, pit_value a, enum pit_value_heavy_sort e) {
    switch (pit_value_sort(a)) {
    case PIT_VALUE_SORT_REF: {
        pit_value_heavy *ha = pit_value_ref_deref(rt, pit_value_as_ref(rt, a));
        if (!ha) { pit_error(rt, "bad ref"); return false; }
        return ha->hsort == e;
    }
    default:
        break;
    }
    return false;
}