Skip to content

Commit 8ead66c

Browse files
committed
chore(err): errors restructured
1 parent 10838d6 commit 8ead66c

13 files changed

Lines changed: 307 additions & 524 deletions

File tree

core/error.c

Lines changed: 150 additions & 282 deletions
Large diffs are not rendered by default.

core/error.h

Lines changed: 71 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -7,172 +7,113 @@
77
#define ERROR_H
88

99
#include "rayforce.h"
10-
#include "nfo.h"
11-
#include "util.h"
10+
#include "ops.h"
1211

1312
// ============================================================================
14-
// Error Codes - Minimal set inspired by kdb+
13+
// Error Codes
1514
// ============================================================================
1615
typedef enum {
1716
EC_OK = 0, // No error
18-
EC_TYPE, // 'type - type mismatch
19-
EC_ARITY, // 'arity - wrong number of arguments
20-
EC_LENGTH, // 'length - list length mismatch
21-
EC_DOMAIN, // 'domain - value out of range
22-
EC_INDEX, // 'index - index out of bounds
23-
EC_VALUE, // 'value - undefined symbol
24-
EC_LIMIT, // 'limit - resource limit
25-
EC_OS, // 'os - system error
26-
EC_PARSE, // 'parse - parse error
27-
EC_NYI, // 'nyi - not yet implemented
28-
EC_USER, // '' - user raised
17+
EC_TYPE, // Type mismatch
18+
EC_ARITY, // Wrong number of arguments
19+
EC_LENGTH, // List length mismatch
20+
EC_DOMAIN, // Value out of range
21+
EC_INDEX, // Index out of bounds
22+
EC_VALUE, // Undefined symbol
23+
EC_LIMIT, // Resource limit
24+
EC_OS, // System error (wraps errno)
25+
EC_PARSE, // Parse error
26+
EC_NYI, // Not yet implemented
27+
EC_USER, // User raised
2928
EC_MAX
3029
} err_code_t;
3130

31+
#define ERR_MSG_SIZE 24 // sizeof(err_t) == 32
32+
33+
typedef struct err_t {
34+
u8_t code; // err_code_t
35+
union {
36+
struct {
37+
i8_t expected;
38+
i8_t actual;
39+
u8_t arg;
40+
u8_t field;
41+
} type;
42+
struct {
43+
i8_t need;
44+
i8_t have;
45+
u8_t arg;
46+
} arity;
47+
struct {
48+
i8_t need;
49+
i8_t have;
50+
u8_t arg;
51+
u8_t arg2;
52+
u8_t field;
53+
u8_t field2;
54+
} length;
55+
struct {
56+
i8_t idx;
57+
i8_t len;
58+
u8_t arg;
59+
u8_t field;
60+
} index;
61+
struct {
62+
u8_t arg;
63+
u8_t field;
64+
} domain;
65+
struct {
66+
i64_t sym;
67+
} value;
68+
struct {
69+
i32_t val;
70+
} limit;
71+
struct {
72+
i32_t no;
73+
} os;
74+
struct {
75+
i8_t type;
76+
} nyi;
77+
struct {
78+
char msg[ERR_MSG_SIZE];
79+
} user;
80+
};
81+
} err_t;
82+
83+
// ============================================================================
84+
// Error Creation - Set VM error context, return ERR_OBJ
3285
// ============================================================================
33-
// Type Classes for err_type() - use in 'expected' field (104-124 range unused)
34-
// ============================================================================
35-
#define TCLASS_NUMERIC 104 // I8,I16,I32,I64,F32,F64
36-
#define TCLASS_INTEGER 105 // I8,I16,I32,I64
37-
#define TCLASS_FLOAT 106 // F32,F64
38-
#define TCLASS_TEMPORAL 107 // DATE,TIME,TIMESTAMP,TIMESPAN
39-
#define TCLASS_COLLECTION 108 // LIST,DICT,TABLE
40-
#define TCLASS_CALLABLE 109 // LAMBDA,UNARY,BINARY,VARY
41-
#define TCLASS_ANY 110 // any type
42-
43-
#define IS_TCLASS(t) ((t) >= 104 && (t) <= 110)
44-
45-
// ============================================================================
46-
// Error Context - Unified 8-byte structure for all error types
47-
// ============================================================================
48-
// Encoding by error type:
49-
// EC_TYPE: arg, field, v1=expected, v2=actual
50-
// EC_ARITY: arg, v1=need, v2=have
51-
// EC_LENGTH: arg, arg2, field, field2, v1=need, v2=have
52-
// EC_INDEX: arg, field, v1=idx, v2=len
53-
// EC_DOMAIN: arg, field
54-
// EC_VALUE: i64 = symbol id (full 64-bit pointer)
55-
// EC_LIMIT: v1-v2 = limit (as i16)
56-
// EC_OS: v1-v4 = errno (as i32)
57-
// EC_NYI: v1 = type
58-
// ============================================================================
59-
typedef struct {
60-
u8_t arg; // argument index (1-based, 0 = none)
61-
u8_t arg2; // second argument (for mismatches between args, 1-based)
62-
u8_t field; // field index in arg (1-based, 0 = none)
63-
u8_t field2; // field in arg2 / subfield (1-based, 0 = none)
64-
i8_t v1; // expected type / need / idx / type
65-
i8_t v2; // actual type / have / len
66-
i8_t v3; // extra value (high byte for larger values)
67-
i8_t v4; // extra value / flags
68-
} err_ctx_t;
69-
70-
RAY_ASSERT(sizeof(err_ctx_t) == sizeof(i64_t), "err_ctx_t must fit in obj->i64");
71-
72-
// ============================================================================
73-
// Error Creation API
74-
// ============================================================================
75-
// All functions use positional context: arg/field indices (1-based, 0 = none)
76-
// The error formatter extracts sub-expressions from trace using these indices.
77-
78-
// Type mismatch: expected vs actual type at arg.field
7986
obj_p err_type(i8_t expected, i8_t actual, u8_t arg, u8_t field);
80-
81-
// Arity: wrong number of arguments
8287
obj_p err_arity(i8_t need, i8_t have, u8_t arg);
83-
84-
// Length mismatch: between arg.field and arg2.field2, or within arg.field
8588
obj_p err_length(i8_t need, i8_t have, u8_t arg, u8_t arg2, u8_t field, u8_t field2);
86-
87-
// Index out of bounds at arg.field
8889
obj_p err_index(i8_t idx, i8_t len, u8_t arg, u8_t field);
89-
90-
// Domain error at arg.field
9190
obj_p err_domain(u8_t arg, u8_t field);
92-
93-
// Undefined symbol
9491
obj_p err_value(i64_t sym);
95-
96-
// Resource limit exceeded
9792
obj_p err_limit(i32_t limit);
98-
99-
// OS/system error (captures errno)
10093
obj_p err_os(nil_t);
101-
102-
// User-raised error with message
10394
obj_p err_user(lit_p msg);
104-
105-
// Not yet implemented for type
10695
obj_p err_nyi(i8_t type);
107-
108-
// Parse error
10996
obj_p err_parse(nil_t);
110-
111-
// Internal: create error with code only (for deserialization/parsing)
11297
obj_p err_raw(err_code_t code);
11398

11499
// ============================================================================
115-
// Error Decoding API
100+
// Error Query
116101
// ============================================================================
117-
118102
err_code_t err_code(obj_p err);
119103
lit_p err_name(err_code_t code);
120-
121-
// Get context (returns pointer to ctx stored in obj->i64)
122-
err_ctx_t* err_ctx(obj_p err);
123-
124-
// Convenience accessors for unified context
125-
static inline u8_t err_get_arg(obj_p err) { return err_ctx(err)->arg; }
126-
static inline u8_t err_get_arg2(obj_p err) { return err_ctx(err)->arg2; }
127-
static inline u8_t err_get_field(obj_p err) { return err_ctx(err)->field; }
128-
static inline u8_t err_get_field2(obj_p err) { return err_ctx(err)->field2; }
129-
static inline i8_t err_get_v1(obj_p err) { return err_ctx(err)->v1; }
130-
static inline i8_t err_get_v2(obj_p err) { return err_ctx(err)->v2; }
131-
static inline i8_t err_get_v3(obj_p err) { return err_ctx(err)->v3; }
132-
static inline i8_t err_get_v4(obj_p err) { return err_ctx(err)->v4; }
133-
134-
// For EC_VALUE: symbol stored directly in i64
135-
static inline i64_t err_get_symbol(obj_p err) { return err->i64; }
136-
137-
// For EC_OS: errno stored across v1-v4 as i32
138-
static inline i32_t err_get_errno(obj_p err) {
139-
err_ctx_t* ctx = err_ctx(err);
140-
return (i32_t)(((u8_t)ctx->v1) | ((u8_t)ctx->v2 << 8) | ((u8_t)ctx->v3 << 16) | ((u8_t)ctx->v4 << 24));
141-
}
142-
143-
// User error message (stored after obj header)
144-
lit_p err_get_message(obj_p err);
145-
146-
// ============================================================================
147-
// String-based API (for deserialization)
148-
// ============================================================================
149-
150-
obj_p ray_err(lit_p msg); // parse string → error
151-
lit_p ray_err_msg(obj_p err); // error → string name
152-
153-
// ============================================================================
154-
// Error Info (for IPC serialization)
155-
// ============================================================================
156-
157-
// Returns a dict with all error information:
158-
// {code: `type; expected: `i64; actual: `c8; field: `from; trace: [...]}
104+
lit_p err_msg(obj_p err);
159105
obj_p err_info(obj_p err);
160106

107+
obj_p ray_err(lit_p msg); // Create user error
108+
161109
// ============================================================================
162110
// Helpers
163111
// ============================================================================
164-
165112
#define PANIC(...) \
166113
do { \
167114
fprintf(stderr, "panic %s:%d: ", __FILE__, __LINE__); \
168115
fprintf(stderr, __VA_ARGS__); \
169116
exit(1); \
170117
} while (0)
171118

172-
typedef struct loc_t {
173-
span_t span;
174-
obj_p file;
175-
obj_p source;
176-
} loc_t;
177-
178119
#endif // ERROR_H

core/eval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1022,7 +1022,7 @@ obj_p try_obj(obj_p obj, obj_p ctch) {
10221022
return err_arity(1, AS_LAMBDA(fn)->args->len, 0);
10231023
}
10241024
// Push error message as string for catch handler
1025-
vm_stack_push(str_fmt(-1, "%s", ray_err_msg(res)));
1025+
vm_stack_push(str_fmt(-1, "%s", err_msg(res)));
10261026
drop_obj(res);
10271027
res = call(fn, 1);
10281028
drop_obj(vm_stack_pop());

core/eval.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "mmap.h"
3131
#include "nfo.h"
3232
#include "util.h"
33+
#include "error.h"
3334

3435
// Forward declaration for query context (defined in query.h)
3536
struct query_ctx_t;
@@ -83,17 +84,18 @@ typedef struct vm_t {
8384
i32_t rp; // return stack pointer
8485
i32_t id; // VM id (thread index)
8586
// Pointers (40 bytes)
86-
obj_p fn; // current function (fn->env has local variables)
87-
struct heap_t *heap; // heap pointer
88-
struct pool_t *pool; // pool pointer
89-
obj_p nfo; // error source info
90-
obj_p trace; // error stack trace
87+
obj_p fn; // current function (fn->env has local variables)
88+
struct heap_t *heap; // heap pointer
89+
struct pool_t *pool; // pool pointer
90+
struct query_ctx_t *query_ctx; // query context stack (for table column resolution)
91+
timeit_t *timeit; // timeit (lazy allocated)
9192
// === Stacks ===
9293
obj_p ps[VM_STACK_SIZE]; // program stack
9394
ctx_t rs[VM_STACK_SIZE]; // return stack
9495
// === COLD section ===
95-
struct query_ctx_t *query_ctx; // query context stack (for table column resolution)
96-
timeit_t *timeit; // timeit (lazy allocated)
96+
obj_p nfo; // error source info
97+
obj_p trace; // error stack trace
98+
err_t err; // last error context (no allocation)
9799
} __attribute__((aligned(64))) * vm_p;
98100

99101
// Thread-local VM pointer

0 commit comments

Comments
 (0)