-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpi_object.h
More file actions
597 lines (470 loc) · 14.9 KB
/
Copy pathpi_object.h
File metadata and controls
597 lines (470 loc) · 14.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
#ifndef PI_OBJECT_H
#define PI_OBJECT_H
#include <stdint.h>
#ifndef __EMSCRIPTEN__
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#else
typedef struct SDL_Rect
{
int x;
int y;
int w;
int h;
} SDL_Rect;
#endif
#include "pi_value.h"
#include "pi_list.h"
#include "pi_table.h"
#include "common.h"
#define OBJ_TYPE(o) (AS_OBJ(o)->type)
#define IS_OBJ_TYPE(o, _type) (IS_OBJ(o) && AS_OBJ(o)->type == _type)
#define IS_STRING(o) IS_OBJ_TYPE(o, OBJ_STRING)
#define IS_LIST(o) IS_OBJ_TYPE(o, OBJ_LIST)
#define IS_TENSOR(o) IS_OBJ_TYPE(o, OBJ_TENSOR)
#define IS_NUM_LIST(o) (IS_LIST(o) && AS_LIST(o)->is_numeric)
#define IS_MAP(o) IS_OBJ_TYPE(o, OBJ_MAP)
#define IS_CLASS(o) IS_OBJ_TYPE(o, OBJ_CLASS)
#define IS_INSTANCE(o) IS_OBJ_TYPE(o, OBJ_INSTANCE)
#define IS_OBJECT(o) (IS_MAP(o) && AS_MAP(o)->proto != NULL)
#define IS_MODULE(o) IS_OBJ_TYPE(o, OBJ_MODULE)
#define IS_FUN(o) IS_OBJ_TYPE(o, OBJ_FUN)
#define IS_RANGE(o) IS_OBJ_TYPE(o, OBJ_RANGE)
#define IS_SLICE(o) IS_OBJ_TYPE(o, OBJ_SLICE)
#define IS_SET(o) IS_OBJ_TYPE(o, OBJ_SET)
#define IS_TUPLE(o) IS_OBJ_TYPE(o, OBJ_TUPLE)
#define IS_CONTEXT(o) IS_OBJ_TYPE(o, OBJ_CONTEXT)
#define IS_CHART(o) IS_OBJ_TYPE(o, OBJ_CHART)
#define IS_CHART3D(o) IS_OBJ_TYPE(o, OBJ_CHART3D)
#define IS_EVENT(o) IS_OBJ_TYPE(o, OBJ_EVENT)
#define IS_IMAGE(o) IS_OBJ_TYPE(o, OBJ_IMAGE)
#define AS_IMAGE(o) ((ObjImage *)AS_OBJ(o))
#define IS_COLLECTION(o) (IS_LIST(o) || IS_TENSOR(o) || IS_MAP(o) || IS_SET(o) || IS_TUPLE(o) || IS_STRING(o))
#define IS_SEQUENCE(o) (IS_LIST(o) || IS_STRING(o) || IS_TUPLE(o))
#define AS_STRING(o) ((PiString *)AS_OBJ(o))
#define AS_LIST(o) ((PiList *)AS_OBJ(o))
#define AS_TENSOR(o) ((PiTensor *)AS_OBJ(o))
#define AS_MAP(o) ((PiMap *)AS_OBJ(o))
#define AS_CLASS(o) ((PiClass *)AS_OBJ(o))
#define AS_INSTANCE(o) ((PiInstance *)AS_OBJ(o))
#define AS_MODULE(o) ((ObjModule *)AS_OBJ(o))
#define AS_RANGE(o) ((PiRange *)AS_OBJ(o))
#define AS_SLICE(o) ((PiSlice *)AS_OBJ(o))
#define AS_SET(o) ((PiSet *)AS_OBJ(o))
#define AS_TUPLE(o) ((PiTuple *)AS_OBJ(o))
#define AS_FUN(o) ((Function *)AS_OBJ(o))
#define AS_CODE(o) ((ObjCode *)AS_OBJ(o))
#define AS_FILE(o) ((ObjFile *)AS_OBJ(o))
#define AS_CONTEXT(o) ((PiContext *)AS_OBJ(o))
#define AS_CHART(o) ((PiChart *)AS_OBJ(o))
#define AS_CHART3D(o) ((PiChart3D *)AS_OBJ(o))
#define AS_EVENT(o) ((PiEvent *)AS_OBJ(o))
#define AS_CSTRING(o) AS_STRING(o)->chars
#define AS_CLIST(o) AS_LIST(o)->items
#define AS_CMAP(o) AS_MAP(o)->table
#define PISTR_SIZE(o) AS_STRING(o)->length
#define PIMAP_SIZE(o) AS_MAP(o)->table->size
#define PILIST_SIZE(o) AS_LIST(o)->items->size
#define COL_LENGTH(o) (IS_LIST(o) ? PILIST_SIZE(o) : PISTR_SIZE(o))
#define PILIST_GETAT(o, i, t) (*(t *)list_getAt(AS_CLIST(o), i))
typedef enum
{
OBJ_STRING,
OBJ_LIST,
OBJ_TENSOR,
OBJ_MAP,
OBJ_CLASS,
OBJ_INSTANCE,
OBJ_SET,
OBJ_TUPLE,
OBJ_MODULE,
OBJ_RANGE,
OBJ_SLICE,
OBJ_FUN,
OBJ_CODE,
OBJ_FILE,
OBJ_IMAGE,
OBJ_SPRITE,
OBJ_MODEL3D,
OBJ_SOUND,
OBJ_CONTEXT, // drawing context
OBJ_CHART, // chart context
OBJ_CHART3D, // 3D chart context
OBJ_EVENT,
} o_type;
typedef struct ObjModule ObjModule;
typedef struct PiMap PiMap;
typedef struct PiClass PiClass;
typedef struct PiInstance PiInstance;
typedef enum
{
GC_WHITE, // Unmarked, potentially unreachable
GC_GRAY, // Marked but children not yet processed
GC_BLACK // Marked and all children processed
} GCColor;
struct Object
{
o_type type;
uint64_t id;
bool is_marked; // Flag to indicate if the object is marked for garbage collection
bool in_gcList; // Flag to indicate if the object is in the GC list
GCColor gc_color;
struct Object *next;
};
typedef struct
{
char name[32]; // event name, e.g. "click"
Value *fns[MAX_HANDLERS]; // registered pilang callables
int count; // number of registered handlers
} HandlerList;
typedef struct
{
Object object;
char *type; // Event type string
EventType event_type; // Enum for fast switching
// Common fields
int x, y; // Position for mouse events
int dx, dy; // Delta for motion/scroll
char *key; // Key name for keyboard events
int button; // Button number for mouse events
bool pressed; // Pressed state for key/mouse
int width, height; // New size for resize events
} PiEvent;
typedef struct
{
PiEvent **events;
int head;
int tail;
int count;
int capacity;
} EventQueue;
typedef struct
{
Object object;
char *chars;
size_t length;
uint32_t hash;
int current;
} PiString;
typedef struct
{
Object object;
double start;
double end;
double step;
double current; // Iterator state: current value in the range
} PiRange;
typedef struct
{
Object object;
double start;
double stop;
double step;
} PiSlice;
typedef struct
{
Object object;
list_t *items;
int current; // Iterator state
bool is_numeric; // Flag to indicate if the list contains only double values
bool is_matrix; // Flag to indicate if the list is a 2D matrix
// Matrix dimensions
int rows;
int cols;
} PiList;
typedef enum
{
TN_FLOAT32,
TN_FLOAT64,
TN_INT32,
TN_INT64,
} TN_TYPE;
typedef struct
{
Object object; // Object header
union
{
float *f32; /* TN_FLOAT32 - 32-bit IEEE float */
double *f64; /* TN_FLOAT64 - 64-bit IEEE double */
int32_t *i32; /* TN_INT32 - 32-bit signed integer */
int64_t *i64; /* TN_INT64 - 64-bit signed integer */
void *raw; /* untyped pointer used for float casts in getFlat */
} data; // union for different data types
TN_TYPE type; // data type (e.g., float32, int64)
int *shape; // array of dimensions
int *strides; // steps in memory for each dimension
int ndim; // number of dimensions
int size; // total number of elements
int rows; // cached shape[0] for rank-2 matrix compatibility helpers
int cols; // cached shape[1] for rank-2 matrix compatibility helpers
int current; // Iterator state along the first dimension
} PiTensor;
struct PiClass
{
Object object;
char *name;
table_t *methods; // instance methods
table_t *static_fields;
table_t *slots; // instance field name -> slot index
int slot_count;
PiClass *super;
};
struct PiInstance
{
Object object;
PiClass *_class;
Value *slots; // fast instance fields
bool *slot_used;
int slot_capacity;
table_t *fields; // optional dynamic fallback
};
#define BOUND_CACHE_SIZE 8
typedef struct
{
uint32_t key_hash; // fast pre-filter, avoids most strcmp
Object *key; // bound key
PiMap *proto; // which prototype this method came from
uint64_t proto_version; // proto->version at cache time, detects structural change
Value bound_fn; // the already-bound Function value
} BoundCache;
#define MAP_IS_INSTANCE 0x01
#define MAP_LOCKED 0x02
#define MAP_BRACKET 0x04
#define MAP_HAS_COMPUTE 0x08
#define MAP_HAS_RCOMPUTE 0x10
#define MAP_HAS_FLAG(map, flag) (((map)->flags & (flag)) != 0)
#define MAP_SET_FLAG(map, flag, value) \
do \
{ \
if (value) \
(map)->flags |= (uint8_t)(flag); \
else \
(map)->flags &= (uint8_t)~(uint8_t)(flag); \
} while (0)
typedef struct PiMap
{
Object object;
table_t *table;
// Lazily-created cache of bound prototype methods. Keeping it separate
// from table prevents method caching from changing visible properties.
// table_t *bound_methods;
BoundCache *bound_cache; // NULL for plain dicts, allocated on first method call for instances
// chached current key-value pair for iteration
Object *_key;
Value _value;
// map version number for detecting modifications during iteration
uint64_t version;
// owner version number for detecting modifications in the owner map during iteration
uint64_t owner_version;
struct PiMap *owner;
char *intrinsic_name;
Value *slots; // only non-NULL when is_instance == true
uint32_t slot_count;
uint8_t flags; // MAP_* bitset for locked/bracket/instance/compute state
// Reference to the superclass instance for inheritance (if any)
Object *super_instance;
struct PiMap *proto; // Prototype map for inheritance and method lookup
// int current; // Iterator state
ht_iter it;
} PiMap;
typedef struct
{
Object object;
void *table; // private hash table backing this PiSet
int current; // iterator state for traversing the set
} PiSet;
typedef struct
{
Object object;
list_t *items; // List of values for tuple
int current; // Iterator state
} PiTuple;
/* Resolved global slots belong to compiled code, not to a VM instance. */
typedef struct GlobalCache
{
Value *slots[UINT8_MAX + 1];
table_t *globals;
list_t *names;
} GlobalCache;
typedef struct
{
Object object;
list_t *data;
list_t *param_names; // Parameter names for functions using this code
bool need_args;
bool need_kwargs;
bool method_need_args;
bool method_need_kwargs;
GlobalCache global_cache;
uint32_t hash;
} ObjCode;
typedef struct
{
Object object;
FILE *fp;
bool closed;
char *mode;
char *filename;
} ObjFile;
#ifndef __EMSCRIPTEN__
typedef struct
{
Object object;
SDL_Surface *surface;
} ObjImage;
ObjImage *new_image(SDL_Surface *surface);
#endif
struct PiChart3D;
// Update PiContext structure
typedef struct PiContext
{
Object object;
// Existing fields
void *window;
void *renderer;
int width, height;
bool running;
float tx, ty, sx, sy, angle, alpha;
void *font; // default font
void *_transform_stack; // stack of _transformState
void *userdata; /* PiDraw extra state (_transform stack, font, fps); owned by builtin/pi_draw.c */
Value frame_callback;
SDL_Rect clip_rect; // clipping rectangle
bool clip_enabled;
// Event handling
HandlerList handlers[EVENT_COUNT];
// Event queue (using simple array or list)
EventQueue *eventQueue;
// FPS tracking
uint32_t last_fps_time;
int frame_count;
double current_fps;
bool plot_subplots_cleared;
// Mouse state
int mouse_x, mouse_y;
uint32_t mouse_buttons;
struct PiChart3D *active_plot3d;
} PiContext;
typedef struct
{
Object object;
PiContext *ctx; // where to draw
list_t *series; // list of plotted data
list_t *colors; // optional styling
double xmin, xmax;
double ymin, ymax;
bool has_bounds;
bool show_grid;
bool show_axes;
bool show_ticks;
int subplot_rows;
int subplot_cols;
int subplot_index;
char *title;
char *xlabel;
char *ylabel;
} PiChart;
typedef struct PiChart3D
{
Object object;
PiContext *ctx;
list_t *series;
bool show_grid;
bool show_axes;
int subplot_rows;
int subplot_cols;
int subplot_index;
double azimuth;
double elevation;
double distance;
char *title;
char *xlabel;
char *ylabel;
char *zlabel;
} PiChart3D;
uint32_t string_hash(char *chars, size_t length);
Object *alloc_object(size_t size, o_type type);
Object *new_pistring(char *str);
PiString *copy_pistring(char *chars, int length);
Object *new_list(list_t *items);
Object *new_tensor(int ndim, int *shape, TN_TYPE type);
Object *new_tensorUninit(int ndim, int *shape, TN_TYPE type);
double tensor_get(PiTensor *tensor, int *indices);
void tensor_set(PiTensor *tensor, int *indices, double value);
double tensor_getFlat(PiTensor *tensor, int index);
void tensor_setFlat(PiTensor *tensor, int index, double value);
Object *tensor_rowAsList(PiTensor *tensor, int row);
Object *new_map(table_t *table, bool is_instance);
static inline Value get_boundCache(PiMap *instance,
uint32_t key_hash,
Object *key,
PiMap *proto)
{
BoundCache *cache = instance->bound_cache;
if (!cache)
return NEW_NIL();
for (int i = 0; i < BOUND_CACHE_SIZE; i++)
{
if (cache[i].proto == proto &&
cache[i].key_hash == key_hash &&
cache[i].proto_version == proto->version &&
cache[i].key == key)
{
return cache[i].bound_fn;
}
}
return NEW_NIL();
}
static inline void put_boundCache(PiMap *instance,
uint32_t key_hash,
Object *key,
PiMap *proto,
Value bound_fn)
{
if (!instance->bound_cache)
{
instance->bound_cache = calloc(BOUND_CACHE_SIZE, sizeof(BoundCache));
if (!instance->bound_cache)
return; // allocation failure: silently skip caching, correctness unaffected
}
int slot = (int)(key_hash & (BOUND_CACHE_SIZE - 1));
instance->bound_cache[slot].key_hash = key_hash;
instance->bound_cache[slot].key = key;
instance->bound_cache[slot].proto = proto;
instance->bound_cache[slot].proto_version = proto->version;
instance->bound_cache[slot].bound_fn = bound_fn;
}
Object *new_set(void); // Create empty set
bool set_add(PiSet *set, Value value); // Add element
bool set_has(PiSet *set, Value value); // Check membership
bool set_remove(PiSet *set, Value value); // Remove element
int set_size(PiSet *set); // Get size
Value set_get(PiSet *set, int index); // Get value by iteration order
void set_clear(PiSet *set); // Remove all elements
void set_free(PiSet *set); // Free memory
Object *new_tuple(list_t *items);
Object *new_file(FILE *file, char *filename, char *mode);
Value map_get(PiMap *map, Value key);
Value map_getValueByKey(PiMap *map, const char *key);
void map_dirty(PiMap *map);
void map_set(PiMap *map, Value key, Value value);
bool map_has(PiMap *map, Value key);
bool map_delete(PiMap *map, Value key);
PiMap *map_owner(PiMap *map, Value key);
int map_size(PiMap *map);
Object *new_range(double start, double end, double step);
Object *new_slice(double start, double end, double step);
uint32_t code_hash(uint8_t *code);
Object *new_code(list_t *code);
Object *new_context();
Object *new_chart(PiContext *ctx);
Object *new_chart3d(PiContext *ctx);
Object *new_event(const char *type, EventType event_type);
void iter_reset(Object *col);
bool iter_hasNext(Object *col);
Value iter_next(Object *col);
bool is_iterable(Object *obj);
int get_index(int index, int length);
int slice_index(int index, int length, int step);
Value get_slice(Object *sequence, double start, double end, double step);
#endif