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
|
#ifndef __USCRIPT_VAL_H__
#define __USCRIPT_VAL_H__
#include "common.h"
#define get_num(v) (v.dat.number)
#define get_bool(v) (v.dat.boolean)
#define get_obj(v) (v.dat.obj)
#define get_str(v) (v.dat.str)
#define get_proto(v) (v.dat.proto)
#define get_func(v) (v.dat.func)
#define get_upval(v) (v.dat.upval)
#define create_num(n) ((struct us_val){.type=VAL_NUM, .dat={.number=(n)}})
#define create_bool(b) ((struct us_val){.type=VAL_BOOL, .dat={.boolean=(b)}})
#define create_zilch() ((struct us_val){.type=VAL_ZILCH, .dat={.number=0}})
#define wrap_str(o) ((struct us_val){.type=VAL_STR, .dat={.str=(o)}})
#define wrap_proto(o) ((struct us_val){.type=VAL_PROTO, .dat={.proto=(o)}})
#define wrap_func(o) ((struct us_val){.type=VAL_FUNC, .dat={.func=(o)}})
#define wrap_upval(o) ((struct us_val){.type=VAL_UPVAL, .dat={.upval=(o)}})
#define val_is_obj(v) (v.type >= VAL_STR)
#define proto_add_byte(func, op) da_append(u8, &(func)->bytecode, op)
enum val_type {
VAL_NUM,
VAL_BOOL,
VAL_ZILCH,
// Do not place any new object types before VAL_STR. Object types are
// detected by doing a comparison with VAL_STR. See val_is_obj().
VAL_STR,
VAL_PROTO,
VAL_FUNC,
VAL_UPVAL,
};
struct us_val {
enum val_type type;
union {
double number;
bool boolean;
struct us_obj *obj;
struct us_str *str;
struct us_proto *proto;
struct us_func *func;
struct us_upval *upval;
} dat;
};
struct us_obj {
// We don't need the object header for now; it will be useful in the
// future, though.
u8 _placeholder;
};
struct us_str {
struct us_obj header;
char *chars;
size_t len;
};
struct us_proto {
struct us_obj header;
const struct us_str *name;
struct us_val constants[UINT8_MAX];
u8 *bytecode; // dyn_arr
int* upval_locs;
int upvalc;
int argc;
bool is_variadic;
u8 nconstants;
};
struct us_func {
struct us_obj header;
struct us_proto *proto;
struct us_upval **upvals;
};
struct us_upval {
struct us_obj header;
struct us_val *loc;
struct us_val closed;
struct us_upval *next;
};
struct us_str *take_str(char *chars, int len);
struct us_str *copy_str(const char *chars, int len);
struct us_proto *create_proto(struct us_str *name);
struct us_func *create_func(struct us_proto *proto);
struct us_upval *create_upval(struct us_val *val);
void free_val(struct us_val v);
void proto_add_const(struct us_proto *func, struct us_val v);
bool vals_eql(struct us_val a, struct us_val b);
char *val_to_str(struct us_val v, int *len_out);
#endif // __USCRIPT_VAL_H__
|