@@ -40,9 +40,37 @@ int char_str_cmp(ray_t* a, ray_t* b, int *out) {
4040 return 0 ;
4141}
4242
43+ /* Lexicographic compare of two SYM atoms. Fast path: equal interned
44+ * ids ⇒ identical text ⇒ 0, no global-table lookup. Slow path: pull
45+ * the backing STR via ray_sym_str and delegate to ray_str_cmp, which
46+ * uses the 12-byte SSO inline path for short symbols.
47+ *
48+ * If a sym_str lookup fails (NULL — e.g. corrupted intern table or
49+ * uninitialised state) we fall back to comparing the raw interned ids
50+ * rather than declaring the unequal symbols equal. Stable, never
51+ * silently collapses distinct symbols. */
52+ int sym_atom_cmp (ray_t * a , ray_t * b ) {
53+ if (a -> i64 == b -> i64 ) return 0 ;
54+ ray_t * sa = ray_sym_str (a -> i64 );
55+ ray_t * sb = ray_sym_str (b -> i64 );
56+ int r ;
57+ if (sa && sb ) {
58+ r = ray_str_cmp (sa , sb );
59+ } else {
60+ /* Fallback: order by interned id (stable, total). Same sign
61+ * convention as memcmp: negative if a < b, positive if a > b. */
62+ r = (a -> i64 < b -> i64 ) ? -1 : 1 ;
63+ }
64+ if (sa ) ray_release (sa );
65+ if (sb ) ray_release (sb );
66+ return r ;
67+ }
68+
4369/* Comparison */
4470ray_t * ray_gt_fn (ray_t * a , ray_t * b ) {
4571 { int c ; if (char_str_cmp (a , b , & c ) == 0 ) return make_bool (c > 0 ? 1 : 0 ); }
72+ if (a -> type == - RAY_SYM && b -> type == - RAY_SYM )
73+ return make_bool (sym_atom_cmp (a , b ) > 0 ? 1 : 0 );
4674 if (a -> type == - RAY_GUID && b -> type == - RAY_GUID )
4775 return make_bool (memcmp (ray_data (a -> obj ), ray_data (b -> obj ), 16 ) > 0 ? 1 : 0 );
4876 /* Temporal comparison (same or cross-temporal via nanosecond conversion) */
@@ -63,6 +91,8 @@ ray_t* ray_gt_fn(ray_t* a, ray_t* b) {
6391
6492ray_t * ray_lt_fn (ray_t * a , ray_t * b ) {
6593 { int c ; if (char_str_cmp (a , b , & c ) == 0 ) return make_bool (c < 0 ? 1 : 0 ); }
94+ if (a -> type == - RAY_SYM && b -> type == - RAY_SYM )
95+ return make_bool (sym_atom_cmp (a , b ) < 0 ? 1 : 0 );
6696 if (a -> type == - RAY_GUID && b -> type == - RAY_GUID )
6797 return make_bool (memcmp (ray_data (a -> obj ), ray_data (b -> obj ), 16 ) < 0 ? 1 : 0 );
6898 if (is_temporal (a ) && is_temporal (b )) {
@@ -82,6 +112,8 @@ ray_t* ray_lt_fn(ray_t* a, ray_t* b) {
82112
83113ray_t * ray_gte_fn (ray_t * a , ray_t * b ) {
84114 { int c ; if (char_str_cmp (a , b , & c ) == 0 ) return make_bool (c >= 0 ? 1 : 0 ); }
115+ if (a -> type == - RAY_SYM && b -> type == - RAY_SYM )
116+ return make_bool (sym_atom_cmp (a , b ) >= 0 ? 1 : 0 );
85117 if (a -> type == - RAY_GUID && b -> type == - RAY_GUID )
86118 return make_bool (memcmp (ray_data (a -> obj ), ray_data (b -> obj ), 16 ) >= 0 ? 1 : 0 );
87119 if (is_temporal (a ) && is_temporal (b )) {
@@ -102,6 +134,8 @@ ray_t* ray_gte_fn(ray_t* a, ray_t* b) {
102134
103135ray_t * ray_lte_fn (ray_t * a , ray_t * b ) {
104136 { int c ; if (char_str_cmp (a , b , & c ) == 0 ) return make_bool (c <= 0 ? 1 : 0 ); }
137+ if (a -> type == - RAY_SYM && b -> type == - RAY_SYM )
138+ return make_bool (sym_atom_cmp (a , b ) <= 0 ? 1 : 0 );
105139 if (a -> type == - RAY_GUID && b -> type == - RAY_GUID )
106140 return make_bool (memcmp (ray_data (a -> obj ), ray_data (b -> obj ), 16 ) <= 0 ? 1 : 0 );
107141 if (is_temporal (a ) && is_temporal (b )) {
@@ -215,6 +249,34 @@ ray_t* ray_or_fn(ray_t* a, ray_t* b) {
215249 return make_bool ((is_truthy (a ) || is_truthy (b )) ? 1 : 0 );
216250}
217251
252+ /* Variadic left-fold over the binary kernels. (and a b c) folds as
253+ * (and (and a b) c) — same shape Lisp/Clojure use. */
254+ ray_t * ray_and_vary_fn (ray_t * * args , int64_t n ) {
255+ if (n < 2 ) return ray_error ("arity" , "expected at least 2 args, got %lld" , (long long )n );
256+ ray_t * acc = ray_and_fn (args [0 ], args [1 ]);
257+ if (!acc || RAY_IS_ERR (acc )) return acc ;
258+ for (int64_t i = 2 ; i < n ; i ++ ) {
259+ ray_t * next = ray_and_fn (acc , args [i ]);
260+ ray_release (acc );
261+ if (!next || RAY_IS_ERR (next )) return next ;
262+ acc = next ;
263+ }
264+ return acc ;
265+ }
266+
267+ ray_t * ray_or_vary_fn (ray_t * * args , int64_t n ) {
268+ if (n < 2 ) return ray_error ("arity" , "expected at least 2 args, got %lld" , (long long )n );
269+ ray_t * acc = ray_or_fn (args [0 ], args [1 ]);
270+ if (!acc || RAY_IS_ERR (acc )) return acc ;
271+ for (int64_t i = 2 ; i < n ; i ++ ) {
272+ ray_t * next = ray_or_fn (acc , args [i ]);
273+ ray_release (acc );
274+ if (!next || RAY_IS_ERR (next )) return next ;
275+ acc = next ;
276+ }
277+ return acc ;
278+ }
279+
218280/* Unary */
219281ray_t * ray_not_fn (ray_t * x ) {
220282 /* Element-wise for bool vectors */
0 commit comments