summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-05-06 16:40:18 +0200
committerlemon <lsof@mailbox.org>2025-05-06 16:40:18 +0200
commit2297267c65a30fc6212f92bde78748fd8b4dcd2f (patch)
tree1e1560a9609a6dddad4de3ba0deadc4e25de66ec
parent4c422d4ff80de1f5cd055c5f793dd936593ffbca (diff)
io#write, pusbool, checksig
-rw-r--r--pez.c47
-rw-r--r--pez.h3
2 files changed, 42 insertions, 8 deletions
diff --git a/pez.c b/pez.c
index 1f50cab..fac8308 100644
--- a/pez.c
+++ b/pez.c
@@ -2319,10 +2319,7 @@ f_ioread(PezContext *cx, int argc)
enum { CHUNK = 4096 };
char *buf;
- if (argc != 1 || !pez_isuserobj(cx, &file_ctype, -1)) {
- pez_error(cx, "io#read", "expected FILE");
- return 0;
- }
+ TRY(pez_checksig(cx, argc, "io#open", "#FILE, ?string", &file_ctype));
f = *(FILE **)pez_getuserobj(cx, &file_ctype, -1);
buf = malloc(capty = CHUNK);
while (!feof(f) && !ferror(f)) {
@@ -2340,6 +2337,24 @@ f_ioread(PezContext *cx, int argc)
}
static bool
+f_iowrite(PezContext *cx, int argc)
+{
+ FILE *f;
+ const char *s;
+ char s_[9];
+ int n;
+
+ TRY(pez_checksig(cx, argc, "io#write", "#FILE, string", &file_ctype));
+ f = *(FILE **)pez_getuserobj(cx, &file_ctype, -2);
+ s = pez_getstring(cx, s_, -1);
+ n = pez_length(cx, -1);
+ assert(f && s && n >= 0);
+ fwrite(s, 1, n, f);
+
+ return pez_push(cx, -2);
+}
+
+static bool
f_ioclose(PezContext *cx, int argc)
{
FILE **pf;
@@ -2365,6 +2380,7 @@ static const struct coredef { const char *n; PezCFn *f; } core[] = {
{ "assert", f_assert },
{ "io#open", f_ioopen },
{ "io#read", f_ioread },
+ { "io#write", f_iowrite },
{ "io#close", f_ioclose },
};
@@ -4385,6 +4401,12 @@ pez_pushnumber(PezContext *cx, PezNumber n)
}
bool
+pez_pushbool(PezContext *cx, bool x)
+{
+ return push(cx, box_bool(x));
+}
+
+bool
pez_pushint(PezContext *cx, int idx)
{
return push(cx, box_num(inttofix(idx)));
@@ -4494,7 +4516,7 @@ sigget(const char **s, bool *opt)
{
const char *t;
t = *s;
- assert((*t == '*' || aisalpha(*t) || *t == '?') && "bad sig");
+ assert((*t == '*' || aisalpha(*t) || *t == '?' || *t == '#') && "bad sig");
for (; **s && !aissep(**s); ++*s) ;
*opt = 0;
if (*t == '?') {
@@ -4509,10 +4531,13 @@ sigget(const char **s, bool *opt)
}
bool
-pez_checksig(PezContext *cx, int argc, const char *fn, const char *sig)
+pez_checksig(PezContext *cx, int argc, const char *fn, const char *sig, ...)
{
const char *osig = sig;
int arg = 0;
+ va_list ap;
+ const PezUserType *usertype;
+ va_start(ap, sig);
skipspaces(&sig);
for (; *sig; ++arg) {
uint mask = 0;
@@ -4523,6 +4548,7 @@ pez_checksig(PezContext *cx, int argc, const char *fn, const char *sig)
do {
bool opt;
const char *t = sigget(&sig, &opt);
+ usertype = NULL;
if (!strncmp(t, "any", 3)) mask |= ~0u;
else if (!strncmp(t, "void", 4)) mask |= 1 << PEZ_TVoid;
else if (!strncmp(t, "number", 6)) mask |= 1 << PEZ_TNumber;
@@ -4533,6 +4559,12 @@ pez_checksig(PezContext *cx, int argc, const char *fn, const char *sig)
else if (!strncmp(t, "record", 6)) mask |= 1 << PEZ_TRecord;
else if (!strncmp(t, "array", 5)) mask |= 1 << PEZ_TArray;
else if (!strncmp(t, "dilambda", 8)) mask |= 1 << PEZ_TDilambda;
+ else if (*t == '#') {
+ assert(!usertype);
+ mask = 1 << PEZ_TUserObj;
+ usertype = va_arg(ap, PezUserType *);
+ ++this;
+ }
else if (!strncmp(t, "applicable", 10)) {
mask |= 1 << PEZ_TFn | 1 << PEZ_TString | 1 << PEZ_TRecord
| 1 << PEZ_TArray | 1 << PEZ_TDilambda;
@@ -4556,7 +4588,7 @@ pez_checksig(PezContext *cx, int argc, const char *fn, const char *sig)
sig += *sig == '|';
skipspaces(&sig);
} while (*sig && *sig != ',');
- if ((typ & mask) == 0) {
+ if ((typ & mask) == 0 || (usertype && !pez_getuserobj(cx, usertype, -argc + arg))) {
pez_error(cx, fn, "arg #%d mismatch: expected %.*s, got %s",
arg, thisn, this + !aisalpha(*this), pez_typename(cx, -argc + arg));
return 0;
@@ -4569,6 +4601,7 @@ pez_checksig(PezContext *cx, int argc, const char *fn, const char *sig)
}
skipspaces(&sig);
}
+ va_end(ap);
if (arg < argc) {
pez_error(cx, fn, "too many args for [%s] (got %d)", osig, argc);
return 0;
diff --git a/pez.h b/pez.h
index f99b58b..d29344f 100644
--- a/pez.h
+++ b/pez.h
@@ -66,6 +66,7 @@ void pez_pop(PezContext *cx);
bool pez_push(PezContext *cx, int idx);
bool pez_pushvoid(PezContext *cx);
bool pez_pushnumber(PezContext *, PezNumber);
+bool pez_pushbool(PezContext *, bool);
bool pez_pushint(PezContext *, int);
bool pez_pushstring(PezContext *, const char *str, int len);
bool pez_pushglobal(PezContext *, const char *name);
@@ -82,7 +83,7 @@ bool pez_truthy(PezContext *, int idx);
int pez_typeof(PezContext *, int idx);
const char *pez_typename(PezContext *, int idx);
-bool pez_checksig(PezContext *, int argc, const char *fn, const char *sig);
+bool pez_checksig(PezContext *, int argc, const char *fn, const char *sig, ...);
bool pez_getnumber(PezContext *, PezNumber *, int idx);
bool pez_getbool(PezContext *, bool *, int idx);