#ifndef PEZ_H_ #define PEZ_H_ #include #include #include #include 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, PEZ_TDilambda }; 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