Skip to content

Commit 4149f27

Browse files
committed
feat: implement method referencing and calling methods using boudMethods
1 parent 50df5ee commit 4149f27

4 files changed

Lines changed: 66 additions & 13 deletions

File tree

src/memory.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ static void blacken_object(Obj* object)
9292
#endif // DEbUG_LOG_GC
9393
switch (object->type)
9494
{
95+
case OBJ_BOUND_METHOD:
96+
ObjBoundMethod* bound = (ObjBoundMethod*)object;
97+
mark_value(bound->receiver);
98+
mark_object((Obj*)bound->method);
99+
break;
95100
case OBJ_CLASS:
96101
ObjClass* klass = (ObjClass*)object;
97102
mark_object((Obj*)klass->name);
@@ -133,6 +138,9 @@ static void free_object(Obj* object)
133138

134139
switch (object->type)
135140
{
141+
case OBJ_BOUND_METHOD:
142+
FREE(ObjBoundMethod, object);
143+
break;
136144
case OBJ_CLASS:
137145
ObjClass* klass = (ObjClass*)object;
138146
free_table(&klass->methods);

src/object.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ static Obj* allocate_object(size_t size, ObjType type)
2929
return object;
3030
}
3131

32+
ObjBoundMethod* new_bound_method(Value receiver, ObjClosure* method)
33+
{
34+
ObjBoundMethod* bound = ALLOCATE_OBJ(ObjBoundMethod, OBJ_BOUND_METHOD);
35+
bound->receiver = receiver;
36+
bound->method = method;
37+
return bound;
38+
}
39+
3240
ObjClass* new_class(ObjString* name)
3341
{
3442
ObjClass* klass = ALLOCATE_OBJ(ObjClass, OBJ_CLASS);
@@ -157,6 +165,9 @@ void print_object(Value value)
157165

158166
switch (OBJ_TYPE(value))
159167
{
168+
case OBJ_BOUND_METHOD:
169+
print_function(AS_BOUND_METHOD(value)->method->function);
170+
break;
160171
case OBJ_CLASS:
161172
printf("%s", AS_CLASS(value)->name->chars);
162173
break;

src/object.h

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
#define OBJ_TYPE(value) (AS_OBJ(value)->type)
1010

11+
#define IS_BOUND_METHOD(value) is_obj_type(value, OBJ_BOUND_METHOD)
12+
#define AS_BOUND_METHOD(value) ((ObjBoundMethod*)AS_OBJ(value))
13+
1114
#define IS_CLASS(value) is_obj_type(value, OBJ_CLASS)
1215
#define AS_CLASS(value) ((ObjClass*)AS_OBJ(value))
1316

@@ -29,6 +32,7 @@
2932

3033
typedef enum
3134
{
35+
OBJ_BOUND_METHOD,
3236
OBJ_CLASS,
3337
OBJ_CLOSURE,
3438
OBJ_FUNCTION,
@@ -87,29 +91,37 @@ typedef struct
8791
int upvalue_count;
8892
} ObjClosure;
8993

90-
typedef struct ObjClass
94+
typedef struct
9195
{
9296
Obj obj;
9397
ObjString* name;
9498
Table methods;
9599
} ObjClass;
96100

97-
typedef struct ObjInstance
101+
typedef struct
98102
{
99103
Obj obj;
100104
ObjClass* klass;
101105
Table fields;
102106
} ObjInstance;
103107

104-
ObjClass* new_class(ObjString* name);
105-
ObjClosure* new_closure(ObjFunction* function);
106-
ObjFunction* new_function();
107-
ObjInstance* new_instance(ObjClass* klass);
108-
ObjNative* new_native(NativeFn function);
109-
ObjString* take_string(char* chars, int length);
110-
ObjString* copy_string(const char* chars, int length);
111-
ObjUpvalue* new_upvalue(Value* slot);
112-
void print_object(Value value);
108+
typedef struct
109+
{
110+
Obj obj;
111+
Value receiver;
112+
ObjClosure* method;
113+
} ObjBoundMethod;
114+
115+
ObjBoundMethod* new_bound_method(Value receiver, ObjClosure* method);
116+
ObjClass* new_class(ObjString* name);
117+
ObjClosure* new_closure(ObjFunction* function);
118+
ObjFunction* new_function();
119+
ObjInstance* new_instance(ObjClass* klass);
120+
ObjNative* new_native(NativeFn function);
121+
ObjString* take_string(char* chars, int length);
122+
ObjString* copy_string(const char* chars, int length);
123+
ObjUpvalue* new_upvalue(Value* slot);
124+
void print_object(Value value);
113125

114126
static inline bool is_obj_type(Value value, ObjType type)
115127
{

src/vm.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ static bool call_value(Value callee, int arg_count)
124124
{
125125
switch (OBJ_TYPE(callee))
126126
{
127+
case OBJ_BOUND_METHOD:
128+
ObjBoundMethod* bound = AS_BOUND_METHOD(callee);
129+
return call(bound->method, arg_count);
127130
case OBJ_INSTANCE:
128131
ObjClass* klass = AS_CLASS(callee);
129132
vm.stack_top[-arg_count - 1] = OBJ_VAL(new_instance(klass));
@@ -148,6 +151,21 @@ static bool call_value(Value callee, int arg_count)
148151
return false;
149152
}
150153

154+
static bool bind_method(ObjClass* klass, ObjString* name)
155+
{
156+
Value method;
157+
if (!table_get(&klass->methods, name, &method))
158+
{
159+
runtime_error("Undefined property %s", name->chars);
160+
return false;
161+
}
162+
163+
ObjBoundMethod* bound = new_bound_method(peek(0), AS_CLOSURE(method));
164+
pop();
165+
push(OBJ_VAL(bound));
166+
return true;
167+
}
168+
151169
static void close_upvalues(Value* last)
152170
{
153171
while (vm.open_upvalues != NULL && vm.open_upvalues->location >= last)
@@ -343,8 +361,12 @@ static InterpretResult run()
343361
push(value);
344362
break;
345363
}
346-
runtime_error("Undefined property %s", name->chars);
347-
return INTERPRET_RUNTIME_ERROR;
364+
365+
if (!bind_method(instance->klass, name))
366+
{
367+
return INTERPRET_RUNTIME_ERROR;
368+
}
369+
break;
348370
}
349371
case OP_SET_PROPERTY:
350372
{

0 commit comments

Comments
 (0)