Skip to content

Commit 4fe0c3e

Browse files
committed
feat(core): introduce TYPE_EXT for handling any external types inside rayforce vm
1 parent 83f9b97 commit 4fe0c3e

File tree

5 files changed

+127
-24
lines changed

5 files changed

+127
-24
lines changed

core/dynlib.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626

2727
#include "rayforce.h"
2828

29+
typedef struct ext_t {
30+
raw_p ptr;
31+
nil_t (*drop)(raw_p);
32+
} *ext_p;
33+
2934
typedef struct dynlib_t {
3035
obj_p path;
3136
raw_p handle;

core/rayforce.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "heap.h"
3030
#include "items.h"
3131
#include "lambda.h"
32-
#include "mmap.h"
32+
#include "dynlib.h"
3333
#include "ops.h"
3434
#include "runtime.h"
3535
#include "serde.h"
@@ -351,6 +351,22 @@ obj_p anymap(obj_p sym, obj_p vec) {
351351
return e;
352352
}
353353

354+
obj_p external(raw_p ptr, nil_t (*drop)(raw_p)) {
355+
obj_p o;
356+
357+
o = (obj_p)heap_alloc(sizeof(struct obj_t) + sizeof(struct ext_t));
358+
o->type = TYPE_EXT;
359+
o->mmod = MMOD_INTERNAL;
360+
o->rc = 1;
361+
o->len = 0;
362+
o->attrs = 0;
363+
ext_p ext = (ext_p)AS_C8(o);
364+
ext->ptr = ptr;
365+
ext->drop = drop;
366+
367+
return o;
368+
}
369+
354370
obj_p resize_obj(obj_p* obj, i64_t len) {
355371
i64_t elem_size, obj_size;
356372
obj_p new_obj;
@@ -2846,6 +2862,7 @@ nil_t __attribute__((hot)) drop_obj(obj_p obj) {
28462862

28472863
u32_t rc;
28482864
i64_t i, l;
2865+
ext_p ext;
28492866

28502867
// Never drop NULL_OBJ or ERR_OBJ (static global singletons)
28512868
if (obj == NULL_OBJ || obj == ERR_OBJ)
@@ -2924,6 +2941,11 @@ nil_t __attribute__((hot)) drop_obj(obj_p obj) {
29242941
case TYPE_ERR:
29252942
// Static singletons - never free
29262943
return;
2944+
case TYPE_EXT:
2945+
ext = (ext_p)AS_C8(obj);
2946+
ext->drop(ext->ptr);
2947+
heap_free(obj);
2948+
return;
29272949
default:
29282950
if (IS_EXTERNAL_SIMPLE(obj)) {
29292951
drop_obj(runtime_fdmap_pop(runtime_get(), obj));

core/rayforce.h

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ typedef u8_t guid_t[16];
8888
#define TYPE_UNARY 101
8989
#define TYPE_BINARY 102
9090
#define TYPE_VARY 103
91+
#define TYPE_EXT 124
9192
#define TYPE_TOKEN 125
9293

9394
// Special Types
@@ -138,28 +139,29 @@ typedef obj_p list_t;
138139
extern u8_t version(nil_t); // get version as u8_t (major - 5 bits, minor - 3 bits)
139140

140141
// Constructors
141-
extern obj_p null(i8_t type); // create null atom of type
142-
extern obj_p nullv(i8_t type, i64_t len); // create null list of type and length
143-
extern obj_p atom(i8_t type); // create atom of type
144-
extern obj_p vn_list(i64_t len, ...); // create list from values
145-
extern obj_p vector(i8_t type, i64_t len); // create vector of type
146-
extern obj_p vn_symbol(i64_t len, ...); // create vector symbols from strings
147-
extern obj_p b8(b8_t val); // bool atom
148-
extern obj_p u8(u8_t val); // byte atom
149-
extern obj_p c8(c8_t c); // char
150-
extern obj_p i16(i16_t val); // i16 atom
151-
extern obj_p i32(i32_t val); // i32 atom
152-
extern obj_p i64(i64_t val); // i64 atom
153-
extern obj_p f64(f64_t val); // f64 atom
154-
extern obj_p symbol(lit_p ptr, i64_t len); // symbol
155-
extern obj_p symboli64(i64_t id); // symbol from i64
156-
extern obj_p adate(i32_t val); // date
157-
extern obj_p atime(i32_t val); // time
158-
extern obj_p timestamp(i64_t val); // timestamp
159-
extern obj_p guid(const guid_t buf); // GUID
160-
extern obj_p vn_c8(lit_p fmt, ...); // string from format
161-
extern obj_p enumerate(obj_p sym, obj_p vec); // enum
162-
extern obj_p anymap(obj_p sym, obj_p vec); // anymap
142+
extern obj_p null(i8_t type); // create null atom of type
143+
extern obj_p nullv(i8_t type, i64_t len); // create null list of type and length
144+
extern obj_p atom(i8_t type); // create atom of type
145+
extern obj_p vn_list(i64_t len, ...); // create list from values
146+
extern obj_p vector(i8_t type, i64_t len); // create vector of type
147+
extern obj_p vn_symbol(i64_t len, ...); // create vector symbols from strings
148+
extern obj_p b8(b8_t val); // bool atom
149+
extern obj_p u8(u8_t val); // byte atom
150+
extern obj_p c8(c8_t c); // char
151+
extern obj_p i16(i16_t val); // i16 atom
152+
extern obj_p i32(i32_t val); // i32 atom
153+
extern obj_p i64(i64_t val); // i64 atom
154+
extern obj_p f64(f64_t val); // f64 atom
155+
extern obj_p symbol(lit_p ptr, i64_t len); // symbol
156+
extern obj_p symboli64(i64_t id); // symbol from i64
157+
extern obj_p adate(i32_t val); // date
158+
extern obj_p atime(i32_t val); // time
159+
extern obj_p timestamp(i64_t val); // timestamp
160+
extern obj_p guid(const guid_t buf); // GUID
161+
extern obj_p vn_c8(lit_p fmt, ...); // string from format
162+
extern obj_p enumerate(obj_p sym, obj_p vec); // enum
163+
extern obj_p anymap(obj_p sym, obj_p vec); // anymap
164+
extern obj_p external(raw_p ptr, nil_t (*drop)(raw_p)); // external
163165

164166
#define B8(len) (vector(TYPE_B8, len)) // bool vector
165167
#define U8(len) (vector(TYPE_U8, len)) // byte vector

tests/ext.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2025 Anton Kundenko <singaraiona@gmail.com>
3+
* All rights reserved.
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in all
13+
* copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
* SOFTWARE.
22+
*/
23+
24+
#include "../core/dynlib.h"
25+
#include "../core/heap.h"
26+
27+
static i32_t dropped_val = 0;
28+
29+
nil_t drop_ext(raw_p ptr) {
30+
i32_t* val = (i32_t*)ptr;
31+
dropped_val = *val;
32+
heap_free(val);
33+
}
34+
35+
test_result_t test_external() {
36+
obj_p o, c;
37+
i32_t* val;
38+
ext_p ext;
39+
40+
dropped_val = 0;
41+
42+
val = heap_alloc(sizeof(i32_t));
43+
*val = 42;
44+
45+
o = external((raw_p)val, drop_ext);
46+
47+
if (o->type != TYPE_EXT) {
48+
char msg[100];
49+
sprintf(msg, "Type must be TYPE_EXT (%d), got %d", TYPE_EXT, o->type);
50+
FAIL(strdup(msg));
51+
}
52+
TEST_ASSERT(rc_obj(o) == 1, "Refcount must be 1");
53+
54+
// Check if the external pointer is correctly stored
55+
// Note: AS_C8(o) returns pointer to payload after obj_t header
56+
// So we cast that payload to ext_p
57+
ext = (ext_p)AS_C8(o);
58+
TEST_ASSERT(ext->ptr == val, "External pointer mismatch");
59+
60+
c = clone_obj(o);
61+
TEST_ASSERT(rc_obj(o) == 2, "Refcount must be 2 after clone");
62+
63+
drop_obj(c);
64+
TEST_ASSERT(rc_obj(o) == 1, "Refcount must be 1 after drop");
65+
TEST_ASSERT(dropped_val == 0, "Drop handler must not be called yet");
66+
67+
drop_obj(o);
68+
TEST_ASSERT(dropped_val == 42, "Drop handler must be called");
69+
70+
PASS();
71+
}

tests/main.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ nil_t on_skip(str_p msg) { printf("%sSkipped%s (%s)\n", YELLOW, RESET, msg ? msg
182182
#include "lang.c"
183183
#include "serde.c"
184184
#include "parted.c"
185+
#include "ext.c"
185186

186187
// Add tests here
187188
test_entry_t tests[] = {
@@ -408,6 +409,7 @@ test_entry_t tests[] = {
408409
{"test_parted_count_i16", test_parted_count_i16},
409410
{"test_parted_count_i32", test_parted_count_i32},
410411
{"test_parted_count_time", test_parted_count_time},
412+
{"test_external", test_external},
411413
};
412414
// ---
413415

@@ -423,7 +425,8 @@ i32_t main() {
423425

424426
i32_t num_failed = num_tests - num_passed - num_skipped;
425427
if (num_failed > 0)
426-
printf("%sPassed%s %d/%d tests (%d skipped, %d failed).\n", YELLOW, RESET, num_passed, num_tests, num_skipped, num_failed);
428+
printf("%sPassed%s %d/%d tests (%d skipped, %d failed).\n", YELLOW, RESET, num_passed, num_tests, num_skipped,
429+
num_failed);
427430
else if (num_skipped > 0)
428431
printf("%sAll tests passed!%s (%d skipped)\n", GREEN, RESET, num_skipped);
429432
else

0 commit comments

Comments
 (0)