|
7 | 7 | #define ERROR_H |
8 | 8 |
|
9 | 9 | #include "rayforce.h" |
10 | | -#include "nfo.h" |
11 | | -#include "util.h" |
| 10 | +#include "ops.h" |
12 | 11 |
|
13 | 12 | // ============================================================================ |
14 | | -// Error Codes - Minimal set inspired by kdb+ |
| 13 | +// Error Codes |
15 | 14 | // ============================================================================ |
16 | 15 | typedef enum { |
17 | 16 | 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 |
29 | 28 | EC_MAX |
30 | 29 | } err_code_t; |
31 | 30 |
|
| 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 |
32 | 85 | // ============================================================================ |
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 |
79 | 86 | obj_p err_type(i8_t expected, i8_t actual, u8_t arg, u8_t field); |
80 | | - |
81 | | -// Arity: wrong number of arguments |
82 | 87 | 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 |
85 | 88 | 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 |
88 | 89 | obj_p err_index(i8_t idx, i8_t len, u8_t arg, u8_t field); |
89 | | - |
90 | | -// Domain error at arg.field |
91 | 90 | obj_p err_domain(u8_t arg, u8_t field); |
92 | | - |
93 | | -// Undefined symbol |
94 | 91 | obj_p err_value(i64_t sym); |
95 | | - |
96 | | -// Resource limit exceeded |
97 | 92 | obj_p err_limit(i32_t limit); |
98 | | - |
99 | | -// OS/system error (captures errno) |
100 | 93 | obj_p err_os(nil_t); |
101 | | - |
102 | | -// User-raised error with message |
103 | 94 | obj_p err_user(lit_p msg); |
104 | | - |
105 | | -// Not yet implemented for type |
106 | 95 | obj_p err_nyi(i8_t type); |
107 | | - |
108 | | -// Parse error |
109 | 96 | obj_p err_parse(nil_t); |
110 | | - |
111 | | -// Internal: create error with code only (for deserialization/parsing) |
112 | 97 | obj_p err_raw(err_code_t code); |
113 | 98 |
|
114 | 99 | // ============================================================================ |
115 | | -// Error Decoding API |
| 100 | +// Error Query |
116 | 101 | // ============================================================================ |
117 | | - |
118 | 102 | err_code_t err_code(obj_p err); |
119 | 103 | 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); |
159 | 105 | obj_p err_info(obj_p err); |
160 | 106 |
|
| 107 | +obj_p ray_err(lit_p msg); // Create user error |
| 108 | + |
161 | 109 | // ============================================================================ |
162 | 110 | // Helpers |
163 | 111 | // ============================================================================ |
164 | | - |
165 | 112 | #define PANIC(...) \ |
166 | 113 | do { \ |
167 | 114 | fprintf(stderr, "panic %s:%d: ", __FILE__, __LINE__); \ |
168 | 115 | fprintf(stderr, __VA_ARGS__); \ |
169 | 116 | exit(1); \ |
170 | 117 | } while (0) |
171 | 118 |
|
172 | | -typedef struct loc_t { |
173 | | - span_t span; |
174 | | - obj_p file; |
175 | | - obj_p source; |
176 | | -} loc_t; |
177 | | - |
178 | 119 | #endif // ERROR_H |
0 commit comments