Skip to content

Commit b1496f9

Browse files
committed
feat: support native functions
1 parent c290b02 commit b1496f9

8 files changed

Lines changed: 70 additions & 2 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ CFLAGS = -std=c99 -Wall -Wextra -Wno-unused-parameter -g
33
CTEST_FLAGS = -std=c99 -g
44
LDFLAGS = -lcriterion
55

6-
SOURCES = src/scanner.c src/chunk.c src/compiler.c src/debug.c src/memory.c src/value.c src/vm.c src/object.c src/table.c
6+
SOURCES = src/scanner.c src/chunk.c src/compiler.c src/debug.c src/memory.c src/value.c src/vm.c src/object.c src/table.c src/native_fn.c
77
TEST_SOURCES = tests/scanner_test.c
88

99
all: clox

src/memory.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ static void free_object(Obj* object)
3131
FREE(ObjFunction, object);
3232
break;
3333
}
34+
case OBJ_NATIVE:
35+
{
36+
FREE(ObjNative, object);
37+
break;
38+
}
3439
case OBJ_STRING:
3540
{
3641
ObjString* string = (ObjString*)object;

src/native_fn.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include "native_fn.h"
2+
#include <time.h>
3+
4+
Value clock_native(int arg_count, Value* args)
5+
{
6+
return NUMBER_VAL((double)clock() / CLOCKS_PER_SEC);
7+
}

src/native_fn.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef clox_native_fn_c
2+
#define clox_native_fn_c
3+
4+
#include "value.h"
5+
6+
Value clock_native(int arg_count, Value* args);
7+
8+
#endif

src/object.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ ObjFunction* new_function()
3333
return function;
3434
}
3535

36+
ObjNative* new_native(NativeFn function)
37+
{
38+
ObjNative* native = ALLOCATE_OBJ(ObjNative, OBJ_NATIVE);
39+
native->function = function;
40+
return native;
41+
}
42+
3643
static ObjString* allocate_string(char* chars, int length, u32 hash)
3744
{
3845
ObjString* string = ALLOCATE_OBJ(ObjString, OBJ_STRING);
@@ -106,6 +113,11 @@ void print_object(Value value)
106113
print_function(AS_FUNCTION(value));
107114
break;
108115
}
116+
case OBJ_NATIVE:
117+
{
118+
printf("<native fn>");
119+
break;
120+
}
109121
case OBJ_STRING:
110122
{
111123

src/object.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@
1010
#define IS_FUNCTION(value) is_obj_type(value, OBJ_FUNCTION);
1111
#define AS_FUNCTION(value) (((ObjFunction*)AS_OBJ(value)))
1212

13+
#define IS_NATIVE(value) is_obj_type(value, OBJ_NATIVE);
14+
#define AS_NATIVE(value) (((ObjNative*)AS_OBJ(value))->function)
15+
1316
#define IS_STRING(value) is_obj_type(value, OBJ_STRING)
1417
#define AS_STRING(value) ((ObjString*)AS_OBJ(value))
1518
#define AS_CSTRING(value) (((ObjString*)AS_OBJ(value))->chars)
1619

1720
typedef enum
1821
{
19-
OBJ_STRING,
2022
OBJ_FUNCTION,
23+
OBJ_NATIVE,
24+
OBJ_STRING,
2125
} ObjType;
2226

2327
struct Obj
@@ -34,6 +38,15 @@ typedef struct
3438
ObjString* name;
3539
} ObjFunction;
3640

41+
typedef Value (*NativeFn)(int arg_count, Value* args);
42+
43+
typedef struct
44+
{
45+
Obj obj;
46+
NativeFn function;
47+
48+
} ObjNative;
49+
3750
struct ObjString
3851
{
3952
Obj obj;
@@ -43,6 +56,7 @@ struct ObjString
4356
};
4457

4558
ObjFunction* new_function();
59+
ObjNative* new_native(NativeFn function);
4660
ObjString* take_string(char* chars, int length);
4761
ObjString* copy_string(const char* chars, int length);
4862
void print_object(Value value);

src/value.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef clox_value_h
22
#define clox_value_h
33

4+
#include <stdbool.h>
5+
46
typedef struct Obj Obj;
57
typedef struct ObjString ObjString;
68

src/vm.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "compiler.h"
99
#include "debug.h"
1010
#include "memory.h"
11+
#include "native_fn.h"
1112
#include "object.h"
1213
#include "table.h"
1314
#include "value.h"
@@ -45,12 +46,23 @@ static void runtime_error(const char* format, ...)
4546
}
4647
}
4748

49+
static void define_native(const char* name, NativeFn function)
50+
{
51+
push(OBJ_VAL(copy_string(name, (int)strlen(name))));
52+
push(OBJ_VAL(new_native(function)));
53+
table_set(&vm.globals, AS_STRING(vm.stack[0]), vm.stack[1]);
54+
pop();
55+
pop();
56+
}
57+
4858
void init_VM()
4959
{
5060
reset_stack();
5161
vm.objects = NULL;
5262
init_table(&vm.globals);
5363
init_table(&vm.strings);
64+
65+
define_native("clock", clock_native);
5466
}
5567

5668
void free_VM()
@@ -108,6 +120,14 @@ static bool call_value(Value callee, int arg_count)
108120
{
109121
return call(AS_FUNCTION(callee), arg_count);
110122
}
123+
case OBJ_NATIVE:
124+
{
125+
NativeFn native = AS_NATIVE(callee);
126+
Value result = native(arg_count, vm.stack_top - arg_count);
127+
vm.stack_top -= arg_count + 1;
128+
push(result);
129+
return true;
130+
}
111131
default:
112132
// No callable shit
113133
break;

0 commit comments

Comments
 (0)