summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2026-08-01 22:00:18 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2026-08-01 22:00:18 +0300
commita986dfc17093ae5b7a33a8fffecd2cabf49deee3 (patch)
tree4f13628f15c7061c76d1ad93493beb610bf01bbf
parentc9c04c869051def472b3d3e381ef0682b46bc67a (diff)
downloadfwdscript-a986dfc17093ae5b7a33a8fffecd2cabf49deee3.tar.gz
fwdscript-a986dfc17093ae5b7a33a8fffecd2cabf49deee3.zip
add builtin type checking
+ Rather terrible error messages, should be improved at some point, but seems to work for now
-rw-r--r--src/fwdscript.c96
1 files changed, 79 insertions, 17 deletions
diff --git a/src/fwdscript.c b/src/fwdscript.c
index 215f782..6b47ca0 100644
--- a/src/fwdscript.c
+++ b/src/fwdscript.c
@@ -226,7 +226,40 @@ static int fwdscript_get(struct fwdscript *s, struct fwdvals *args)
static int fwdscript_get_typecheck(struct fwdscript *s, struct fwdtypes *types)
{
- TODO();
+ (void)s;
+ size_t l = fwdtypes_len(types);
+ if (l != 4) {
+ /** @todo better error messages? */
+ fprintf(stderr, "expected 4 args, got %zu\n", l);
+ return -1;
+ }
+
+ enum fwdtype table = *fwdtypes_at(types, 0);
+ /* index can be whatever but would look something like */
+ //enum fwdtype index = fwdtypes_at(types, 1);
+ enum fwdtype err = *fwdtypes_at(types, 2);
+ enum fwdtype ok = *fwdtypes_at(types, 3);
+
+ if (table != FWDSCRIPT_TBL) {
+ fprintf(stderr, "expected /tbl, got %s\n",
+ fwdtype_str(table));
+ return -1;
+ }
+
+ if (err != FWDSCRIPT_CNT) {
+ fprintf(stderr, "expected /cnt, got %s\n",
+ fwdtype_str(err));
+ return -1;
+ }
+
+ if (ok != FWDSCRIPT_CNT) {
+ fprintf(stderr, "expected /cnt, got %s\n",
+ fwdtype_str(ok));
+ return -1;
+ }
+
+ /* check cnt args at runtime */
+ return 0;
}
static int fwdscript_abort(struct fwdscript *s, struct fwdvals *args)
@@ -236,7 +269,24 @@ static int fwdscript_abort(struct fwdscript *s, struct fwdvals *args)
static int fwdscript_abort_typecheck(struct fwdscript *s, struct fwdtypes *types)
{
- TODO();
+ (void)s;
+
+ /* I guess we could also accept anything that's convertible to string,
+ * so I guess number for now? */
+ size_t l = fwdtypes_len(types);
+ if (l != 1) {
+ fprintf(stderr, "expected 1 arg, got %zu\n", l);
+ return -1;
+ }
+
+ enum fwdtype msg = *fwdtypes_at(types, 0);
+ if (msg != FWDSCRIPT_STR) {
+ fprintf(stderr, "expected /str, got %s\n",
+ fwdtype_str(msg));
+ return -1;
+ }
+
+ return 0;
}
static int fwdscript_print(struct fwdscript *s, struct fwdvals *args)
@@ -246,7 +296,17 @@ static int fwdscript_print(struct fwdscript *s, struct fwdvals *args)
static int fwdscript_print_typecheck(struct fwdscript *s, struct fwdtypes *args)
{
- TODO();
+ (void)s;
+
+ /* we take any number of args as long as they're printable */
+ foreach(fwdtypes, type, args) {
+ if (*type != FWDSCRIPT_STR && *type != FWDSCRIPT_NUM) {
+ fprintf(stderr, "arg not printable\n");
+ return -1;
+ }
+ }
+
+ return 0;
}
static int fwdscript_register_builtins(struct fwdscript *s)
@@ -539,19 +599,13 @@ struct fwdast {
};
- union {
- /* node type and status */
- struct {
- bool moved;
- enum fwdtype t;
- };
+ /* node type and status */
+ bool moved;
+ enum fwdtype t;
- /* cmd args and cnt params */
- struct {
- size_t argc;
- struct fwdast *args;
- };
- };
+ /* cmd args and cnt params */
+ size_t argc;
+ struct fwdast *args;
size_t bodyc;
struct fwdast *body;
@@ -584,6 +638,7 @@ static void free_ast(struct fwdast *ast)
break;
case FWDAST_CMD:
+ free(ast->s);
free_asts(&args);
break;
@@ -594,6 +649,7 @@ static void free_ast(struct fwdast *ast)
break;
case FWDAST_CNT:
+ free(ast->s);
free_asts(&args);
free_asts(&body);
break;
@@ -995,7 +1051,7 @@ static void fwdscript_debug_tokens(struct fwdtokens *tokens)
break;
case FWDTOKEN_NUM:
- fprintf(stderr, "line %4zu: %s (%f)\n",
+ fprintf(stderr, "line %4zu: %s (%g)\n",
tok->line,
fwdtoken_kind_str(tok->kind),
tok->d);
@@ -1064,7 +1120,7 @@ static void fwdscript_debug_ast(struct fwdast *ast, int depth)
break;
case FWDAST_NUM:
- fprintf(stderr, "%*s+ num (%f)\n", depth, "|",
+ fprintf(stderr, "%*s+ num (%g)\n", depth, "|",
ast->d);
break;
@@ -1442,6 +1498,10 @@ static int fwdscript_parse(struct fwdscript *s, const char *buf)
return -1;
}
+ /** @todo this means that the global ctx in s will be illegal to
+ * reference after this point, which is presumably not ideal if we want
+ * to support modules. Will have to think of something better. */
+ free_ast(&top);
return 0;
}
@@ -1455,6 +1515,8 @@ static void fwdscript_destroy(struct fwdscript *s)
foreach(fwdbuiltins, builtin, &s->builtins) {
free(builtin.t->key);
}
+
+ fwdctx_destroy(&s->ctx);
fwdinsns_destroy(&s->insns);
fwdbuiltins_destroy(&s->builtins);
}