Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
maps.c
Go to the documentation of this file.
1/* -*- C -*-
2 * Serene programming language
3 * Copyright (C) 2019-2026 Sameer Rahmani <[email protected]>
4 *
5 * This library is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library. If not, see <https://www.gnu.org/licenses/>.
17 */
18#include "serene/rt/maps.h"
19
20#include "serene/rt/context.h"
21#include "serene/rt/core.h"
22#include "serene/rt/engine.h"
23#include "serene/rt/errors.h"
25#include "serene/rt/protocols.h"
26#include "serene/utils.h"
27
28static bool srn_vmap_cmp(const hmap_t *hmap, const hmap_key_t *a, const hmap_key_t *b) {
29 srn_value_t *va = (srn_value_t *)a->data;
30 srn_value_t *vb = (srn_value_t *)b->data;
31 srn_value_t *res = srn_value_eq(hmap->map_ctx, va, vb);
32 switch (TYPE(res)) {
33 case VFalse:
34 return false;
35 case VTrue:
36 return true;
37 default:
38 PANIC("Should never happen");
39 }
40}
41
42[[gnu::nonnull(1)]]
43static hmap_hash_t srn_vmap_hash(const hmap_t *hmap, const hmap_key_t *k) {
46 srn_value_t *v = (srn_value_t *)k->data;
47
49 return srn_value_hash(hmap->map_ctx, v);
50}
51
52static const hmap_control_t value_map = {
53 .cmp = &srn_vmap_cmp,
54 .hash = &srn_vmap_hash,
55 .insert = hmap_insert_ctl,
56 .lookup = hmap_lookup_ctl,
57 // The key bytes are a shallow srn_value_t struct; copying them into the
58 // map's pinned context keeps the retained key valid independently of the
59 // assoc'ing caller's context. Anything the value points at (its payload,
60 // metadata) is still the caller's to keep alive.
61 .copy_key = &hmap_copy_key,
62};
63
65 PANIC_IF_NULL(ctx);
66 srn_map_t *m = ALLOC(ctx, srn_map_t);
67 m->inner = hmap_empty(ctx);
68 return srn_value_make(ctx, VMap, metadata, (void *)m);
69}
70
72 srn_context_t *ctx, srn_metadata_t *metadata, srn_value_t *map, srn_value_t *key,
73 srn_value_t *value
74) {
75 PANIC_IF_NULL(ctx);
76 PANIC_IF_NULL(map);
77 PANIC_IF_NULL(key);
78 PANIC_IF_NULL(value);
79
80 if (!IS_A(map, VMap)) {
81 return srn_errors_make_error(ctx, metadata, ABSURD, "expected a map");
82 }
83
84 // Hashing panics on the unhashable tags, and a panic from a data driven
85 // value is wrong in an API that reports failures as values.
86 if (!srn_value_hashable(key)) {
87 return srn_errors_make_error(ctx, metadata, ABSURD, "map key is not hashable");
88 }
89
90 hmap_key_t k = {.data = key, .len = sizeof(*key)};
91
92 srn_map_t *old = AS_MAP(map);
93 srn_map_t *neu = ALLOC(ctx, srn_map_t);
94
95 neu->inner = value_map.insert(&value_map, &old->inner, &k, value);
96 return srn_value_make(ctx, VMap, metadata, (void *)neu);
97}
#define ALLOC(ctx, T)
Definition context.h:84
srn_value_t * srn_value_make(srn_context_t *ctx, srn_value_tag_t tag, srn_metadata_t *metadata, void *payload)
Creates a new serene value.
Definition core.c:36
#define TYPE(value_ref)
Definition core.h:165
@ VFalse
Definition core.h:115
@ VMap
Definition core.h:126
@ VTrue
Definition core.h:114
#define AS_MAP(value_ref)
Definition core.h:182
#define IS_A(value_ref, field)
Definition core.h:167
Error handling for the runtime.
@ ABSURD
Definition errors.h:76
hmap_t hmap_empty(const srn_context_t *ctx)
Create, initialize and return a new hashmap pinned to ctx.
Definition hashmap.c:655
void * hmap_lookup_ctl(const hmap_control_t *ctl, const hmap_t *hmap, const hmap_key_t *k, void *default_value)
Just like the hmap_lookup function but, it receives a hmap_control_t to customize the comparison and ...
Definition hashmap.c:638
hmap_t hmap_insert_ctl(const hmap_control_t *ctl, const hmap_t *hmap, hmap_key_t *k, void *v)
Just like the hmap_insert function but, it receives a hmap_control_t to customize the comparison and ...
Definition hashmap.c:594
hmap_key_t * hmap_copy_key(const hmap_t *hmap, const hmap_key_t *k)
The default copy_key hook.
Definition hashmap.c:678
This is an implementation of Compressed Hash-Array Mapped Prefix-tree, which is a bit-partitioned,...
HMAP_HASH_TYPE hmap_hash_t
Definition hashmap.h:61
srn_value_t * srn_map_assoc(srn_context_t *ctx, srn_metadata_t *metadata, srn_value_t *map, srn_value_t *key, srn_value_t *value)
Definition maps.c:71
srn_value_t * srn_map_empty(srn_context_t *ctx, srn_metadata_t *metadata)
Definition maps.c:64
static const hmap_control_t value_map
Definition maps.c:52
static bool srn_vmap_cmp(const hmap_t *hmap, const hmap_key_t *a, const hmap_key_t *b)
Definition maps.c:28
static hmap_hash_t srn_vmap_hash(const hmap_t *hmap, const hmap_key_t *k)
Definition maps.c:43
srn_hash_t srn_value_hash(const srn_context_t *ctx, const srn_value_t *v)
Compute the xxHash32 of a value using the engine seed.
Definition protocols.c:152
srn_value_t * srn_value_eq(const 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
bool srn_value_hashable(const srn_value_t *v)
Whether v can be a hash key.
Definition protocols.c:139
If we ever want to modify some of these behaviours for a new instance of hashmap, we should use this ...
Definition hashmap.h:109
Note: For key equality we use the memcpy function.
Definition hashmap.h:66
void * data
len 0 -> data == nullptr
Definition hashmap.h:68
const srn_context_t * map_ctx
The context that owns every allocation the map retains.
Definition hashmap.h:104
A persistent, immutable map.
Definition maps.h:29
hmap_t inner
Definition maps.h:30
#define PANIC_IF_NULL(ptr)
Definition utils.h:66
#define PANIC(msg)
Definition utils.h:53