From 3da4016d5784adef217fff0ad1e3a0ceff76290f Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Tue, 22 Mar 2022 17:15:17 -0700 Subject: [PATCH] Chapter 24.7 --- clox/src/memory.c | 3 +++ clox/src/object.c | 9 +++++++++ clox/src/object.h | 11 +++++++++++ clox/src/vm.c | 22 ++++++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/clox/src/memory.c b/clox/src/memory.c index 8f8fd4a..e88b91f 100644 --- a/clox/src/memory.c +++ b/clox/src/memory.c @@ -23,6 +23,9 @@ static void freeObject(Obj *object) { FREE(ObjFunction, object); break; } + case OBJ_NATIVE: + FREE(ObjNative, object); + break; case OBJ_STRING: { ObjString *string = (ObjString *)object; FREE_ARRAY(char, string->chars, string->length + 1); diff --git a/clox/src/object.c b/clox/src/object.c index 2df533e..d4afccc 100644 --- a/clox/src/object.c +++ b/clox/src/object.c @@ -27,6 +27,12 @@ ObjFunction *newFunction() { return function; } +ObjNative *newNative(NativeFn function) { + ObjNative *native = ALLOCATE_OBJ(ObjNative, OBJ_NATIVE); + native->function = function; + return native; +} + static ObjString *allocateString(char *chars, int length, uint32_t hash) { ObjString *string = ALLOCATE_OBJ(ObjString, OBJ_STRING); string->length = length; @@ -81,6 +87,9 @@ void printObject(Value value) { case OBJ_FUNCTION: printFunction(AS_FUNCTION(value)); break; + case OBJ_NATIVE: + printf(""); + break; case OBJ_STRING: printf("%s", AS_CSTRING(value)); break; diff --git a/clox/src/object.h b/clox/src/object.h index 812c464..b5942d6 100644 --- a/clox/src/object.h +++ b/clox/src/object.h @@ -8,14 +8,17 @@ #define OBJ_TYPE(value) (AS_OBJ(value)->type) #define IS_FUNCTION(value) isObjType(value, OBJ_FUNCTION) +#define IS_NATIVE(value) isObjType(value, OBJ_NATIVE) #define IS_STRING(value) isObjType(value, OBJ_STRING) #define AS_FUNCTION(value) ((ObjFunction *)AS_OBJ(value)) +#define AS_NATIVE(value) (((ObjNative *)AS_OBJ(value))->function) #define AS_STRING(value) ((ObjString *)AS_OBJ(value)) #define AS_CSTRING(value) (((ObjString *)AS_OBJ(value))->chars) typedef enum { OBJ_FUNCTION, + OBJ_NATIVE, OBJ_STRING, } ObjType; @@ -31,6 +34,13 @@ typedef struct { ObjString *name; } ObjFunction; +typedef Value (*NativeFn)(int argCount, Value *args); + +typedef struct { + Obj obj; + NativeFn function; +} ObjNative; + struct ObjString { Obj obj; int length; @@ -39,6 +49,7 @@ struct ObjString { }; ObjFunction *newFunction(); +ObjNative *newNative(NativeFn function); ObjString *takeString(char *chars, int length); ObjString *copyString(const char *chars, int length); void printObject(Value value); diff --git a/clox/src/vm.c b/clox/src/vm.c index 0d8d638..bf7078c 100644 --- a/clox/src/vm.c +++ b/clox/src/vm.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "common.h" #include "compiler.h" @@ -11,6 +12,10 @@ VM vm; +static Value clockNative(int argCount, Value *args) { + return NUMBER_VAL((double)clock() / CLOCKS_PER_SEC); +} + static void resetStack() { vm.stackTop = vm.stack; vm.frameCount = 0; @@ -38,12 +43,22 @@ static void runtimeError(const char *format, ...) { resetStack(); } +static void defineNative(const char *name, NativeFn function) { + push(OBJ_VAL(copyString(name, (int)strlen(name)))); + push(OBJ_VAL(newNative(function))); + tableSet(&vm.globals, AS_STRING(vm.stack[0]), vm.stack[1]); + pop(); + pop(); +} + void initVM() { resetStack(); vm.objects = NULL; initTable(&vm.globals); initTable(&vm.strings); + + defineNative("clock", clockNative); } void freeVM() { @@ -88,6 +103,13 @@ static bool callValue(Value callee, int argCount) { switch (OBJ_TYPE(callee)) { case OBJ_FUNCTION: return call(AS_FUNCTION(callee), argCount); + case OBJ_NATIVE: { + NativeFn native = AS_NATIVE(callee); + Value result = native(argCount, vm.stackTop - argCount); + vm.stackTop -= argCount + 1; + push(result); + return true; + } default: break; }