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
|
#ifndef PEZ_H_
#define PEZ_H_
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
typedef int32_t PezNumber;
enum {
PEZ_TVoid,
PEZ_TObject,
PEZ_TNumber,
PEZ_TBool,
PEZ_TString,
PEZ_TFnProto,
PEZ_TUpval,
PEZ_TFn,
PEZ_TTuple,
PEZ_TRecord,
PEZ_TArray,
};
typedef enum PezError {
PEZ_EStack = 1,
PEZ_ENoMem,
PEZ_ESyntax,
PEZ_ERuntime,
} PezError;
typedef struct PezContext PezContext;
typedef void *PezAllocFn(void *userdata, void *ptr, size_t oldsize, size_t newsize);
typedef bool PezCFn(PezContext *, int argc);
PezContext *pez_new(PezAllocFn *alloc, void *userdata, size_t stacksize);
void pez_del(PezContext *);
/*
* opts:
* NULL -> reset debug options
* 'b': enable print bytecode to stderr
* 'G': stress GC
* 'g': print GC debug info
*/
void pez_debug(PezContext *, const char *opts);
int pez_geterrno(PezContext *);
const char *pez_geterr(PezContext *cx);
bool pez_eval_cb(PezContext *, const char *fname, int (*cb)(void *), void *);
bool pez_eval_str(PezContext *, const char *fname, const char *);
bool pez_eval_file(PezContext *, const char *path, FILE *);
int pez_top(PezContext *);
void pez_pop(PezContext *cx);
bool pez_push(PezContext *cx, int idx);
bool pez_pushvoid(PezContext *cx);
bool pez_pushnumber(PezContext *, PezNumber);
bool pez_pushint(PezContext *, int);
bool pez_pushstring(PezContext *, const char *str, int len);
bool pez_pushglobal(PezContext *, const char *name);
bool pez_isvoid(PezContext *, int idx);
bool pez_isnumber(PezContext *, int idx);
bool pez_isbool(PezContext *, int idx);
bool pez_isstring(PezContext *, int idx);
bool pez_isfunction(PezContext *, int idx);
bool pez_isarray(PezContext *, int idx);
const char *pez_typename(PezContext *, int idx);
bool pez_getnumber(PezContext *, PezNumber *, int idx);
bool pez_getbool(PezContext *, bool *, int idx);
const char *pez_getstring(PezContext *, char buf[8], int idx);
const char *pez_fnname(PezContext *, int idx);
int pez_length(PezContext *cx, int idx);
void pez_error(PezContext *cx, const char *fn, const char *fmt, ...);
bool pez_apply(PezContext *cx, int argc);
bool pez_setapply(PezContext *cx, int argc);
bool pez_iget(PezContext *cx, int idx, int arg);
static inline double
pez_numtof(PezNumber x) { return x / 4096.0; }
static inline PezNumber
pez_ftonum(double x) { return x * 4096.0; }
static inline PezNumber
pez_fixmul(PezNumber a, PezNumber b)
{
int64_t tmp = (int64_t)a * b;
// tmp += (1 << 11); // rounding
return tmp >> 12;
}
static inline PezNumber
pez_fixdiv(PezNumber a, PezNumber b)
{
int64_t tmp;
if (b == 0) {
return a >= 0 ? INT32_MAX : INT32_MIN;
}
tmp = (uint64_t)a << 12;
/*
if ((tmp < 0) == (b < 0)) {
tmp += b >> 1;
} else {
tmp -= b >> 1;
}
*/
return tmp / b;
}
static inline PezNumber
pez_fixmod(PezNumber a, PezNumber b)
{
if (b == 0) {
return 0;
} else if (b < 0) {
return -a % -b;
}
return a % b;
}
#endif
|