diff options
author | ubq323 <ubq323@ubq323.website> | 2024-06-26 14:44:19 +0100 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2024-06-26 14:44:19 +0100 |
commit | a8519434f058d0ab60bf7f90acc61997cb982cfa (patch) | |
tree | e1858d42805e61afbd5c6c0b9d2f3b47bc8411ee | |
parent | 20584e520dfd44393aa66350b442e8a23e46c5a3 (diff) |
add cfunc type and rudimentary stdlib
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | com.c | 3 | ||||
-rw-r--r-- | lib.c | 44 | ||||
-rw-r--r-- | lib.h | 8 | ||||
-rw-r--r-- | util.h | 2 | ||||
-rw-r--r-- | val.c | 5 | ||||
-rw-r--r-- | val.h | 7 | ||||
-rw-r--r-- | vm.c | 32 |
8 files changed, 89 insertions, 16 deletions
@@ -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 @@ -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 @@ -0,0 +1,44 @@ +#include <time.h> + +#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)); + } +} + + @@ -0,0 +1,8 @@ +#ifndef _lib_h +#define _lib_h + +#include "state.h" + +void load_stdlib(State *S); + +#endif @@ -1,6 +1,8 @@ #ifndef _util_h #define _util_h +#include <stdio.h> + #define CHECK(cond, ...) do { if (!(cond)) { fprintf(stderr, __VA_ARGS__); exit(1); } } while(0) #define ERROR(...) CHECK(false, __VA_ARGS__) @@ -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 "???"; } @@ -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); @@ -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; } |