From a8519434f058d0ab60bf7f90acc61997cb982cfa Mon Sep 17 00:00:00 2001 From: ubq323 Date: Wed, 26 Jun 2024 14:44:19 +0100 Subject: add cfunc type and rudimentary stdlib --- Makefile | 4 ++-- com.c | 3 +++ lib.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ lib.h | 8 ++++++++ util.h | 2 ++ val.c | 5 +++++ val.h | 7 +++++++ vm.c | 32 ++++++++++++++++++-------------- 8 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 lib.c create mode 100644 lib.h diff --git a/Makefile b/Makefile index 6a04158..f1d189a 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -CS=ast.c com.c dis.c ht.c mem.c prs.c state.c val.c vm.c -HS=ast.h chunk.h com.h dis.h ht.h mem.h prs.h state.h util.h val.h vm.h +CS=ast.c com.c dis.c ht.c lib.c mem.c prs.c state.c val.c vm.c +HS=ast.h chunk.h com.h dis.h ht.h lib.h mem.h prs.h state.h util.h val.h vm.h CFLAGS=$(EXTRA_CFLAGS) -g -O3 -lm -Wall -Wpedantic -Werror=implicit-function-declaration bth: $(CS) $(HS) Makefile diff --git a/com.c b/com.c index 73d7e46..fcb4fdf 100644 --- a/com.c +++ b/com.c @@ -8,6 +8,7 @@ #include "ast.h" #include "util.h" #include "prs.h" +#include "lib.h" #define BYTECODE(C) (C->ch->bc) @@ -517,6 +518,8 @@ int main(int argc, char **argv) { th.ch = &ch; S->th = &th; + load_stdlib(S); + return runvm(S); } #undef CHECK diff --git a/lib.c b/lib.c new file mode 100644 index 0000000..fe87abf --- /dev/null +++ b/lib.c @@ -0,0 +1,44 @@ +#include + +#include "lib.h" +#include "state.h" +#include "val.h" +#include "util.h" + +static Val fn_clock(State *S, int nargs, Val *args) { + return VAL_NUM((double)clock() / CLOCKS_PER_SEC); +} + +static Val fn_write(State *S, int nargs, Val *args) { + CHECK(nargs>0, "need 1 arg to write"); + print_val(args[0]); + return VAL_NIL; +} +static Val fn_say(State *S, int nargs, Val *args) { + CHECK(nargs>0, "need 1 arg to say"); + println_val(args[0]); + return VAL_NIL; +} + + + + +typedef struct { + char *name; + CFunc func; +} BuiltinFunc; +static BuiltinFunc builtin_funcs[] = { + { "clock", fn_clock }, + { "say", fn_say }, + { "write", fn_write }, + { 0 }, +}; + +void load_stdlib(State *S) { + for (BuiltinFunc *b = builtin_funcs; b->name != NULL; b++) { + ObjString *oname = objstring_copy_cstr(S, b->name); + ht_put(S, &S->globals, oname, VAL_CFUNC(b->func)); + } +} + + diff --git a/lib.h b/lib.h new file mode 100644 index 0000000..a82dbd9 --- /dev/null +++ b/lib.h @@ -0,0 +1,8 @@ +#ifndef _lib_h +#define _lib_h + +#include "state.h" + +void load_stdlib(State *S); + +#endif diff --git a/util.h b/util.h index b0f2658..7cbfa44 100644 --- a/util.h +++ b/util.h @@ -1,6 +1,8 @@ #ifndef _util_h #define _util_h +#include + #define CHECK(cond, ...) do { if (!(cond)) { fprintf(stderr, __VA_ARGS__); exit(1); } } while(0) #define ERROR(...) CHECK(false, __VA_ARGS__) diff --git a/val.c b/val.c index ec200d3..7c8b25a 100644 --- a/val.c +++ b/val.c @@ -76,6 +76,9 @@ void print_val(Val v) { break; } break; + case TY_CFUNC: + printf("[cfunc]"); + break; } } @@ -98,6 +101,7 @@ bool val_equal(Val a, Val b) { case TY_NUM: return AS_NUM(a) == AS_NUM(b); case TY_BOOL: return AS_BOOL(a) == AS_BOOL(b); case TY_OBJ: return AS_OBJ(a) == AS_OBJ(b); + case TY_CFUNC: return AS_CFUNC(a) == AS_CFUNC(b); default: return false; } } @@ -114,6 +118,7 @@ const char *typename_str(Val v) { case OTY_FUNC: return "Func"; } break; + case TY_CFUNC: return "cfunc"; } return "???"; } diff --git a/val.h b/val.h index 4ee76d2..90b60f2 100644 --- a/val.h +++ b/val.h @@ -7,13 +7,16 @@ typedef struct _val Val; typedef struct _obj Obj; +typedef struct _state State; +typedef Val (*CFunc)(State *S, int nargs, Val *args); typedef enum { TY_NIL, TY_NUM, TY_BOOL, TY_OBJ, + TY_CFUNC, } ValTy; typedef struct _val { @@ -22,6 +25,7 @@ typedef struct _val { double d; bool b; Obj *o; + CFunc f; } as; } Val; @@ -71,6 +75,7 @@ ObjFunc *objfunc_new(State *S, uint8_t arity); #define IS_NUM(x) (x.ty == TY_NUM) #define IS_BOOL(x) (x.ty == TY_BOOL) #define IS_OBJ(x) (x.ty == TY_OBJ) +#define IS_CFUNC(x) (x.ty == TY_CFUNC) #define IS_STRING(x) (is_obj_ty((x), OTY_STRING)) #define IS_FUNC(x) (is_obj_ty((x), OTY_FUNC)) @@ -78,6 +83,7 @@ ObjFunc *objfunc_new(State *S, uint8_t arity); #define AS_NUM(x) (x.as.d) #define AS_BOOL(x) (x.as.b) #define AS_OBJ(x) (x.as.o) +#define AS_CFUNC(x) (x.as.f) #define AS_STRING(x) ((ObjString*)AS_OBJ(x)) #define AS_CSTRING(x) (AS_STRING(x)->d) @@ -89,6 +95,7 @@ ObjFunc *objfunc_new(State *S, uint8_t arity); #define VAL_TRUE VAL_BOOL(1) #define VAL_FALSE VAL_BOOL(0) #define VAL_OBJ(x) ((Val){.ty=TY_OBJ, .as.o=(Obj*)(x) }) +#define VAL_CFUNC(x) ((Val){.ty=TY_CFUNC, .as.f=(CFunc)(x)}) static inline bool is_obj_ty(Val v, ObjTy t) { return IS_OBJ(v) && (AS_OBJ(v)->oty == t); diff --git a/vm.c b/vm.c index a5ffbc6..34660de 100644 --- a/vm.c +++ b/vm.c @@ -184,21 +184,25 @@ int runvm(State *S) { uint8_t len = RBYTE(); Val callee = PEEKN(len); - if (!IS_FUNC(callee)) { - fprintf(stderr,"can only call functions"); - exit(1); - } - ObjFunc *func = AS_FUNC(callee); - - StackFrame *sf = &th->rstack[th->rsp++]; - sf->ip = th->ip; - sf->ch = th->ch; - sf->fp = th->fp; - - th->ip = 0; - th->ch = &func->ch; - th->fp = th->sp - len; + if (IS_FUNC(callee)) { + ObjFunc *func = AS_FUNC(callee); + + StackFrame *sf = &th->rstack[th->rsp++]; + sf->ip = th->ip; + sf->ch = th->ch; + sf->fp = th->fp; + + th->ip = 0; + th->ch = &func->ch; + th->fp = th->sp - len; + } else if (IS_CFUNC(callee)) { + int nargs = len - 1; + Val *firstarg = &th->stack[th->sp - nargs]; + Val res = AS_CFUNC(callee)(S, len - 1, firstarg); + th->sp -= len; + PUSH(res); + } break; } -- cgit v1.2.3