Closed tamc closed 9 years ago
Yes, in general subclassing the built-ins does work since they expect their internal bit representation to be very specific and get horribly confused when you invoke one of the inherited built-in methods on the derived type.
I haven't implemented this yet, but my tentative plan is to just seal the built-in types and make it a runtime error to subclass them. Most of the functionality you'd want to inherit is in the (as-yet-undocumented!) Sequence
class, which you can subclass, so subclassing List
doesn't buy you much.
Thank you for filing this bug, though. It's absolutely a bug that it silently lets you try to do this and then vomits all over itself.
I thought that this issue would be an easy task to start contributing with wren, but my analytical powers seem to be fading as I cannot quite find out the superclass name/type.
Questions:
1) What built-ins should may NOT be subclassed?
[?] all where type > OBJ_CLASS
[ ] other: ....
2) Where should the afrore mentioned runtime-error should be triggered:
[?] wren_vm.c/runInterpreter inside CASE_CODE(IS).
[ ] wren_value.c/wrenNewXXX
[ ] wren_value.c/initObj
[ ] wren_value.c/wrenBindSuperclass
[ ] other: ....
3) What is the best way to find out the type of the requested superclass? It seems that everwhere I point my debugger to, the type is OBJ_CLASS.
I feel so stupid, that I cannot fullfill this task that seemed to be so trivial. But now that I started to dig in, I want to know more. Any pointers or tips are greatly appreciated.
1) What built-ins should may NOT be subclassed?
Basically, the ones that are backed by a C object whose type is not OBJ_INSTANCE
. That's:
OBJ_CLASS,
OBJ_CLOSURE,
OBJ_FIBER,
OBJ_FN,
OBJ_LIST,
OBJ_MAP,
OBJ_RANGE,
OBJ_STRING
2) Where should the afrore mentioned runtime-error should be triggered:
Probably in CASE_CODE(CLASS):
, right after:
// TODO: Handle the superclass not being a class object!
:)
3) What is the best way to find out the type of the requested superclass? It seems that everwhere I point my debugger to, the type is OBJ_CLASS.
The superclass is a class. Even the built-in types still have actual class objects for their classes, which is where their methods are defined. The problem with inheriting from a built-in type isn't that they don't have a real superclass—they do.
It's that the methods defined in that superclass assume the instance is a specific kind of C object. They will fail horribly if the receiver is an OBJ_INSTANCE
instead.
So what you'll need to check is, "Is the superclass the class of one of the forbidden built-in types?" To do that, it's probably just:
if (superclass == vm->classClass ||
superclass == vm->fnClass ||
...)
{
// Runtime error...
}
You may run into some weird corner case behavior when bootstrapping the core library on this, but hopefully not.
I feel so stupid, that I cannot fullfill this task that seemed to be so trivial.
Lots of things seem trivial before you know a lot of details. This definitely isn't a trivial task. You're pretty deep in the bowels of a C implementation of a programming language's metaobject protocol. It's tricky enough that I procrastinated doing it, after all. :)
This:
Gives this:
As of 84ead3bb18135657fb276ae09459e3be4717764d on OSX Yosemite
Is there a problem with subclassing built in classes?