From 61372b981933236805ad1464b12e138ec7fb7d5d Mon Sep 17 00:00:00 2001 From: lemon Date: Fri, 7 Feb 2025 17:56:25 +0100 Subject: parser: make read callback be buffered --- bench.lua | 2 +- pez.c | 45 +++++++++++++++++++++++++++++++-------------- pez.h | 3 ++- pez.png | Bin 0 -> 11408 bytes test.pez | 1 - ycomb.pez | 5 +++++ 6 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 pez.png create mode 100644 ycomb.pez diff --git a/bench.lua b/bench.lua index 18e8116..b653cc9 100644 --- a/bench.lua +++ b/bench.lua @@ -1,4 +1,4 @@ -function fib(n) +local function fib(n) if n < 2 then return n end return fib(n - 2) + fib(n - 1) end diff --git a/pez.c b/pez.c index 098b2ff..98f7d08 100644 --- a/pez.c +++ b/pez.c @@ -131,8 +131,10 @@ struct cmupval { typedef struct Comp { PezContext *cx; - int (*readcb)(void *); + PezReadFn *readcb; void *readud; + char rdbuf[1024]; + uint rdbufi, rdbufsiz; uint line, col; int peekchr; bool have_peekchr; @@ -2236,7 +2238,7 @@ initcore(PezContext *cx) /*******************/ static void -initcomp(Comp *cm, PezContext *cx, Proto *pr, int (*cb)(void *), void *ud) +initcomp(Comp *cm, PezContext *cx, Proto *pr, PezReadFn cb, void *ud) { memset(cm, 0, sizeof *cm); cm->cx = cx; @@ -2547,12 +2549,21 @@ endscope(Comp *cm) static int nextchr(Comp *cm) { - int c; + int c, n; if (cm->have_peekchr) { cm->have_peekchr = 0; return cm->peekchr; } - c = cm->readcb(cm->readud); + if (cm->rdbufsiz == 0) { + cm->rdbufi = 0; + if ((n = cm->readcb(cm->readud, cm->rdbuf, sizeof cm->rdbuf)) <= 0) + return EOF; + assert(n <= sizeof cm->rdbuf); + cm->rdbufsiz = n; + } + c = cm->rdbuf[cm->rdbufi++]; + cm->rdbufi %= sizeof cm->rdbuf; + --cm->rdbufsiz; if (c == '\n') { ++cm->line; cm->col = 0; @@ -3998,13 +4009,13 @@ block(Comp *cm, int endchr) /**************/ bool -pez_eval_cb(PezContext *cx, const char *fname, int (*cb)(void *), void *ud) +pez_eval_cb(PezContext *cx, const char *fname, PezReadFn cb, void *ud) { Val *stktop = cx->stktop; Proto *pr; Fn *fn; - struct fenv fenv = {0}; Comp cm; + struct fenv fenv = {0}; int gccanrun = cx->gccanrun; cx->gccanrun = 0; if (!(pr = newproto(cx, fname, "", /* line */ 1))) { @@ -4046,15 +4057,14 @@ Err: } static int -str_read_cb(void *ud) +str_read_cb(void *ud, char *dst, int n) { + int i; char **s = ud; - char c = **s; - if (c == 0) { - return EOF; + for (i = 0; **s && n > 0; ++i) { + *dst++ = *(*s)++; } - ++*s; - return c; + return i; } bool @@ -4064,10 +4074,17 @@ pez_eval_str(PezContext *cx, const char *fname, const char *str) return pez_eval_cb(cx, fname, str_read_cb, &str); } +static int +file_read_cb(void *ud, char *dst, int n) +{ + FILE *fp = ud; + return fread(dst, 1, n, fp); +} + bool pez_eval_file(PezContext *cx, const char *fname, FILE *fp) { assert(fp); - return pez_eval_cb(cx, fname, (int(*)(void *))fgetc, fp); + return pez_eval_cb(cx, fname, file_read_cb, fp); } static void * @@ -4327,7 +4344,7 @@ pez_checksig(PezContext *cx, int argc, const char *fn, const char *sig) for (; *sig; ++arg) { uint mask = 0; const char *this = sig; - int thisn; + int thisn = 0; int typ; typ = 1 << pez_typeof(cx, -argc + arg); do { diff --git a/pez.h b/pez.h index 081634b..2330f1b 100644 --- a/pez.h +++ b/pez.h @@ -33,6 +33,7 @@ typedef enum PezError { typedef struct PezContext PezContext; typedef void *PezAllocFn(void *userdata, void *ptr, size_t oldsize, size_t newsize); typedef bool PezCFn(PezContext *, int argc); +typedef int PezReadFn(void *userdata, char *dst, int n); PezContext *pez_new(PezAllocFn *alloc, void *userdata, size_t stacksize); void pez_del(PezContext *); @@ -49,7 +50,7 @@ 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_cb(PezContext *, const char *fname, PezReadFn cb, void *); bool pez_eval_str(PezContext *, const char *fname, const char *); bool pez_eval_file(PezContext *, const char *path, FILE *); diff --git a/pez.png b/pez.png new file mode 100644 index 0000000..e415103 Binary files /dev/null and b/pez.png differ diff --git a/test.pez b/test.pez index 7f35b30..cd7d608 100644 --- a/test.pez +++ b/test.pez @@ -34,7 +34,6 @@ printf["%a == %a\n", m[3,7], 3^7] acc } - printf["4+1+3: %a\n", add[4,1,3]] @gather: {[*] diff --git a/ycomb.pez b/ycomb.pez new file mode 100644 index 0000000..dff0f40 --- /dev/null +++ b/ycomb.pez @@ -0,0 +1,5 @@ +@Y: {[f] {[i] i[i]}[{[i] f[{[x] i[i][x]}]}]} + +@fact: {[n] Y[{[f] {[n] n == 0 ? 1 : n * f[n - 1]}}][n]} + +printf["%a\n", fact[5]] -- cgit v1.2.3