aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom Willemse2022-03-22 17:15:17 -0700
committerGravatar Tom Willemse2022-03-22 17:15:17 -0700
commit3da4016d5784adef217fff0ad1e3a0ceff76290f (patch)
treeef7c41c0a013b2e9a5212f9f3b74bdfb85e84336
parentbaedf99f635735c50936bb555e4a77058ec9e2e0 (diff)
downloadcrafting-interpreters-3da4016d5784adef217fff0ad1e3a0ceff76290f.tar.gz
crafting-interpreters-3da4016d5784adef217fff0ad1e3a0ceff76290f.zip
Chapter 24.7
-rw-r--r--clox/src/memory.c3
-rw-r--r--clox/src/object.c9
-rw-r--r--clox/src/object.h11
-rw-r--r--clox/src/vm.c22
4 files changed, 45 insertions, 0 deletions
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("<native fn>");
+ 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 <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include <time.h>
#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;
}