Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1590,11 +1590,11 @@ Var getMethod(PKVM* vm, Var self, String* name, bool* is_method) {
return varGetAttrib(vm, self, name);
}

Closure* getSuperMethod(PKVM* vm, Var self, String* name) {
Class* super = getClass(vm, self)->super_class;
Closure* getSuperMethod(PKVM* vm, Class* class, String* name) {
Class* super = NULL == class ? NULL : class->super_class;
if (super == NULL) {
VM_SET_ERROR(vm, stringFormat(vm, "'$' object has no parent class.", \
varTypeName(self)));
VM_SET_ERROR(vm, stringFormat(vm, "'$' has no parent class.", \
class->name));
return NULL;
};

Expand Down
2 changes: 1 addition & 1 deletion src/core/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Var getMethod(PKVM* vm, Var self, String* name, bool* is_method);

// Returns the method (closure) from the instance's super class. If the method
// doesn't exists, it'll set an error on the VM.
Closure* getSuperMethod(PKVM* vm, Var self, String* name);
Closure* getSuperMethod(PKVM* vm, Class* class, String* name);

// Unlike getMethod this will not set error and will not try to get attribute
// with the same name. It'll return true if the method exists on [self], false
Expand Down
1 change: 1 addition & 0 deletions src/core/public.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ void pkClassAddMethod(PKVM* vm, PkHandle* cls,
// won't be garbage collected (class handle has reference to the module).

Closure* method = newClosure(vm, fn);
method->class = class_;
vmPopTempRef(vm); // fn.
vmPushTempRef(vm, &method->_super); // method.
{
Expand Down
1 change: 1 addition & 0 deletions src/core/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ struct Function {
struct Closure {
Object _super;

Class* class;
Function* fn;
Upvalue* upvalues[DYNAMIC_TAIL_ARRAY];
};
Expand Down
9 changes: 7 additions & 2 deletions src/core/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,8 @@ PkResult vmRunFiber(PKVM* vm, Fiber* fiber_) {
cls->ctor = method;
}

method->class = cls;

pkClosureBufferWrite(&cls->methods, vm, method);

DROP();
Expand Down Expand Up @@ -1198,7 +1200,9 @@ PkResult vmRunFiber(PKVM* vm, Fiber* fiber_) {
fiber->self = *fiber->ret; //< Self for the next call.
index = READ_SHORT();
name = moduleGetStringAt(module, (int)index);
Closure* super_method = getSuperMethod(vm, fiber->self, name);
Class* class = frame->closure->class;
if ( NULL == class ) class = getClass( vm, fiber->self );
Closure* super_method = getSuperMethod(vm, class, name);
CHECK_ERROR(); // Will return if super_method is NULL.
callable = VAR_OBJ(super_method);
goto L_do_call;
Expand Down Expand Up @@ -1253,6 +1257,7 @@ PkResult vmRunFiber(PKVM* vm, Fiber* fiber_) {
*fiber->ret = fiber->self;

closure = (const Closure*)(cls)->ctor;
const char* class_name = cls->name->data;
while (closure == NULL) {
cls = cls->super_class;
if (cls == NULL) break;
Expand All @@ -1263,7 +1268,7 @@ PkResult vmRunFiber(PKVM* vm, Fiber* fiber_) {
if (closure == NULL) {
if (argc != 0) {
String* msg = stringFormat(vm, "Expected exactly 0 argument(s) "
"for constructor $.", cls->name->data);
"for constructor $.", class_name );
RUNTIME_ERROR(msg);
}

Expand Down
13 changes: 13 additions & 0 deletions tests/lang/class.pk
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,20 @@ class B is A
end
end

class C is B
def _init()
super()
print("C init")
end
def foo()
print("C foo")
return super.foo()
end
end

b = B()
assert(b.foo() == "A.bar")
c = C()
assert(c.foo() == "A.bar")

print('ALL TESTS PASSED')