Serene Runtime 1.0.0
C runtime for the Serene programming language
Loading...
Searching...
No Matches
protocols.h File Reference
#include "serene/rt/engine.h"
Include dependency graph for protocols.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

srn_value_tsrn_value_eq (srn_context_t *ctx, const srn_value_t *a, const srn_value_t *b)
 Check to values for equality. Return a boolean.
 
srn_hash_t srn_value_hash (srn_context_t *ctx, const srn_value_t *v)
 Compute the xxHash32 of a value using the engine seed.
 

Function Documentation

◆ srn_value_eq()

srn_value_t * srn_value_eq ( srn_context_t * ctx,
const srn_value_t * a,
const srn_value_t * b )

Check to values for equality. Return a boolean.

Definition at line 38 of file protocols.c.

38 {
39 PANIC_IF_NULL(ctx);
40 if (a == nullptr || b == nullptr || (a->type != b->type)) {
41 return &false_v;
42 }
43
44 switch (a->type) {
45 case VNil:
46 case VTrue:
47 case VFalse:
48 // Tag-only values; matching tags means equal.
49 return &true_v;
50
51 case VI64:
52 return equality_to_value(AS_I64(a) == AS_I64(b));
53
54 case VF64:
55 // IEEE compare: NaN != NaN, +0.0 == -0.0. Hash normalizes -0.0 -> +0.0
56 // so the eq <=> hash invariant holds.
57 return equality_to_value(AS_F64(a) == AS_F64(b));
58
59 case VString:
61
62 case VSymbol:
63 // Symbols are interned per namespace; pointer identity is enough.
64 return equality_to_value(AS_SYMBOL(a) == AS_SYMBOL(b));
65
66 case VKeyword:
67 // Keywords are interned engine-wide; pointer identity is enough.
69
70 case VNamespace:
71 // Namespaces are unique per engine; pointer identity suffices.
72 return equality_to_value(AS_NS(a) == AS_NS(b));
73
74 case VList: {
75 srn_list_t *la = AS_LIST(a);
76 srn_list_t *lb = AS_LIST(b);
77 if (la->len != lb->len) {
78 return &false_v;
79 }
80 srn_list_node_t *na = la->head;
81 srn_list_node_t *nb = lb->head;
82 while (na != nullptr) {
83 if (srn_value_eq(ctx, na->value, nb->value) == &false_v) {
84 return &false_v;
85 }
86 na = na->next;
87 nb = nb->next;
88 }
89 return &true_v;
90 }
91
92 case VSeq: {
93 srn_seq_t *sa = AS_SEQ(a);
94 srn_seq_t *sb = AS_SEQ(b);
95
96 if (sa->inner.len != sb->inner.len) {
97 return &false_v;
98 }
99 for (size_t i = 0; i < sa->inner.len; i++) {
100 seq_lookup_result_t ra = seq_get(ctx, &sa->inner, i);
101 seq_lookup_result_t rb = seq_get(ctx, &sb->inner, i);
102 if (ra.maybe_error != nullptr || rb.maybe_error != nullptr) {
103 return &false_v;
104 }
105 if (srn_value_eq(ctx, (srn_value_t *)ra.data, (srn_value_t *)rb.data) == &false_v) {
106 return &false_v;
107 }
108 }
109 return &true_v;
110 }
111
112 case VMap:
113 // Identity equality for now. Two maps compare equal iff they share the
114 // same underlying CHAMT instance. Structural map equality is parked until
115 // there's a real need (and a corresponding hmap walker).
116 return equality_to_value(AS_MAP(a) == AS_MAP(b));
117
118 case VClosure:
119 return equality_to_value(AS_CLOSURE(a) == AS_CLOSURE(b));
120
121 case VError:
122 return equality_to_value(AS_ERROR(a) == AS_ERROR(b));
123
124 case VQuote:
125 TODO("VQuote payload is not defined yet");
126
127 default:
128 PANIC("Unknown value tag in srn_value_eq");
129 }
130}
#define AS_LIST(value_ref)
Definition core.h:174
#define AS_F64(value_ref)
Definition core.h:168
#define AS_SYMBOL(value_ref)
Definition core.h:172
static srn_value_t false_v
Definition core.h:158
@ VQuote
Definition core.h:120
@ VSeq
Definition core.h:119
@ VNamespace
Definition core.h:122
@ VClosure
Definition core.h:121
@ VNil
Definition core.h:113
@ VList
Definition core.h:118
@ VFalse
Definition core.h:115
@ VF64
Definition core.h:117
@ VSymbol
Definition core.h:124
@ VI64
Definition core.h:116
@ VMap
Definition core.h:126
@ VError
VError should be last.
Definition core.h:128
@ VKeyword
Definition core.h:125
@ VTrue
Definition core.h:114
@ VString
Definition core.h:123
#define AS_STRING(value_ref)
Definition core.h:171
#define AS_NS(value_ref)
Definition core.h:170
#define AS_I64(value_ref)
Definition core.h:167
#define AS_MAP(value_ref)
Definition core.h:177
#define AS_SEQ(value_ref)
Definition core.h:176
static srn_value_t true_v
Definition core.h:157
#define AS_ERROR(value_ref)
Definition core.h:173
#define AS_CLOSURE(value_ref)
Definition core.h:169
#define AS_KEYWORD(value_ref)
Definition core.h:175
srn_value_t * srn_value_eq(srn_context_t *ctx, const srn_value_t *a, const srn_value_t *b)
Check to values for equality. Return a boolean.
Definition protocols.c:38
static srn_value_t * equality_to_value(bool cond)
Definition protocols.c:36
seq_lookup_result_t seq_get(const srn_context_t *ctx, const seq_t *seq, size_t n)
Negative index is not supported.
Definition seq.c:173
bool srn_string_eq(const srn_string_t *a, const srn_string_t *b)
Definition strings.c:76
seq_elem_t data
Definition seq.h:135
size_t len
logical length.
Definition seq.h:161
A list is a singly linked sequence of values.
Definition lists.h:30
struct srn_list_node_t * next
Definition lists.h:32
srn_value_t * value
Definition lists.h:31
Since all the values are immutable and persistent.
Definition lists.h:36
srn_pair_t * head
Definition lists.h:38
size_t len
Definition lists.h:36
A persistent, immutable, indexed sequence.
Definition seqs.h:27
seq_t inner
Definition seqs.h:28
srn_value_tag_t type
Definition core.h:132
#define PANIC_IF_NULL(ptr)
Definition utils.h:64
#define TODO(msg)
Definition utils.h:52
#define PANIC(msg)
Definition utils.h:51
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_value_hash()

srn_hash_t srn_value_hash ( srn_context_t * ctx,
const srn_value_t * v )

Compute the xxHash32 of a value using the engine seed.

The invariant srn_value_eq(a, b) == true_v => srn_value_hash(a) == srn_value_hash(b) must hold for every tag.

Definition at line 138 of file protocols.c.

138 {
139 PANIC_IF_NULL(ctx);
140 PANIC_IF_NULL(v);
141
142 srn_engine_t *engine = ctx->engine;
143
144 switch (v->type) {
145 case VNil: {
146 return 0;
147 }
148 case VTrue: {
149 return 1;
150 }
151 case VFalse: {
152 return 2;
153 }
154
155 case VI64: {
156 int64_t n = AS_I64(v);
157 return srn_hash(engine, &n, sizeof(n));
158 }
159
160 case VF64: {
161 double d = AS_F64(v);
162 return srn_hash(engine, &d, sizeof(d));
163 }
164
165 case VString: {
166 srn_string_t *s = AS_STRING(v);
167 return srn_hash(engine, s->buffer, s->len);
168 }
169
170 case VSymbol: {
171 // Interned identity: hash the pointer bits.
172 srn_symbol_t *sym = AS_SYMBOL(v);
173 return srn_hash(engine, sym, sizeof(*sym));
174 }
175
176 case VKeyword: {
177 // Interned; hash the pointer-sized payload (the name pointer).
179 return srn_hash(engine, k, sizeof(*k));
180 }
181
182 case VNamespace: {
183 srn_namespace_t *ns = AS_NS(v);
184 return srn_hash(engine, ns->name->buffer, ns->name->len);
185 }
186
187 case VList:
188 // Lists are intentionally not hashable; they can't be used as map keys.
189 // Use a seq or other container if you need a hashable sequence.
190 PANIC("Lists are not hashable");
191
192 case VSeq: {
193 srn_seq_t *s = AS_SEQ(v);
194 srn_hash_t h = srn_hash(engine, &s->inner.len, sizeof(s->inner.len));
195
196 for (size_t i = 0; i < s->inner.len; i++) {
197 seq_lookup_result_t r = seq_get(ctx, &s->inner, i);
198 if (r.maybe_error != nullptr) {
199 PANIC("Corrupted seq during hash");
200 }
202 h = combine2(engine, h, hi);
203 }
204 return h;
205 }
206
207 case VMap: {
208 PANIC("Hashmaps are not hashable");
209 }
210
211 case VClosure: {
212 PANIC("Closures are not hashable");
213 }
214
215 case VError: {
216 srn_error_t *e = AS_ERROR(v);
217 return srn_hash(engine, e, sizeof(*e));
218 }
219
220 case VQuote:
221 TODO("VQuote payload is not defined yet");
222
223 default:
224 PANIC("Unknown value tag in srn_value_hash");
225 }
226}
int n
Definition acutest.h:538
SRN_HASH_TYPE srn_hash_t
Definition context.h:44
srn_hash_t srn_hash(const srn_engine_t *engine, const void *data, size_t len)
Definition engine.c:131
static srn_hash_t combine2(srn_engine_t *engine, srn_hash_t a, srn_hash_t b)
Definition protocols.c:133
srn_hash_t srn_value_hash(srn_context_t *ctx, const srn_value_t *v)
Compute the xxHash32 of a value using the engine seed.
Definition protocols.c:138
srn_engine_t * engine
Long term state of the compiler.
Definition context.h:49
Engine is a structure to own the long living and main pieces of the compiler.
Definition engine.h:49
A keyword: just a name.
Definition keywords.h:29
srn_string_t * name
Definition namespaces.h:49
uint8_t buffer[]
The buffer that holds the WTF8 sequence.
Definition strings.h:39
size_t len
length of the WTF-8 sequence in bytes
Definition strings.h:37
Here is the call graph for this function:
Here is the caller graph for this function: