Add Object.same(_,_) to access built-in equality even for classes that may override ==.

Had to add a new metaclass for Object since it now has its own static method so we
can't just use Class as its metaclass. (We don't want *every* class to have a same(_,_)
static method.)
This commit is contained in:
Bob Nystrom
2015-05-01 07:55:28 -07:00
parent a907c143c8
commit fcf4197139
6 changed files with 116 additions and 31 deletions
+39 -26
View File
@@ -937,6 +937,11 @@ DEF_PRIMITIVE(num_truncate)
RETURN_NUM(integer);
}
DEF_PRIMITIVE(object_same)
{
RETURN_BOOL(wrenValuesEqual(args[1], args[2]));
}
DEF_PRIMITIVE(object_not)
{
RETURN_VAL(FALSE_VAL);
@@ -1285,7 +1290,7 @@ static ObjClass* defineClass(WrenVM* vm, const char* name)
void wrenInitializeCore(WrenVM* vm)
{
// Define the root Object class. This has to be done a little specially
// because it has no superclass and an unusual metaclass (Class).
// because it has no superclass.
vm->objectClass = defineClass(vm, "Object");
PRIMITIVE(vm->objectClass, "!", object_not);
PRIMITIVE(vm->objectClass, "==(_)", object_eqeq);
@@ -1295,40 +1300,48 @@ void wrenInitializeCore(WrenVM* vm)
PRIMITIVE(vm->objectClass, "type", object_type);
PRIMITIVE(vm->objectClass, "<instantiate>", object_instantiate);
// Now we can define Class, which is a subclass of Object, but Object's
// metaclass.
// Now we can define Class, which is a subclass of Object.
vm->classClass = defineClass(vm, "Class");
// Now that Object and Class are defined, we can wire them up to each other.
wrenBindSuperclass(vm, vm->classClass, vm->objectClass);
vm->objectClass->obj.classObj = vm->classClass;
vm->classClass->obj.classObj = vm->classClass;
// Define the methods specific to Class after wiring up its superclass to
// prevent the inherited ones from overwriting them.
PRIMITIVE(vm->classClass, "<instantiate>", class_instantiate);
PRIMITIVE(vm->classClass, "name", class_name);
PRIMITIVE(vm->classClass, "supertype", class_supertype);
// Finally, we can define Object's metaclass which is a subclass of Class.
ObjClass* objectMetaclass = defineClass(vm, "Object metaclass");
// Wire up the metaclass relationships now that all three classes are built.
vm->objectClass->obj.classObj = objectMetaclass;
objectMetaclass->obj.classObj = vm->classClass;
vm->classClass->obj.classObj = vm->classClass;
// Do this after wiring up the metaclasses so objectMetaclass doesn't get
// collected.
wrenBindSuperclass(vm, objectMetaclass, vm->classClass);
PRIMITIVE(objectMetaclass, "same(_,_)", object_same);
// The core class diagram ends up looking like this, where single lines point
// to a class's superclass, and double lines point to its metaclass:
//
// .------------. .========.
// | | || ||
// v | v ||
// .---------. .--------------. ||
// | Object |==>| Class |==='
// '---------' '--------------'
// ^ ^
// | |
// .---------. .--------------. -.
// | Base |==>| Base.type | |
// '---------' '--------------' |
// ^ ^ | Hypothetical example classes
// | | |
// .---------. .--------------. |
// | Derived |==>| Derived.type | |
// '---------' '--------------' -'
// .------------------------------------. .====.
// | .---------------. | # #
// v | v | v #
// .---------. .-------------------. .-------. #
// | Object |==>| Object metaclass |==>| Class |=="
// '---------' '-------------------' '-------'
// ^ ^ ^ ^ ^
// | .--------------' # | #
// | | # | #
// .---------. .-------------------. # | # -.
// | Base |==>| Base metaclass |======" | # |
// '---------' '-------------------' | # |
// ^ | # |
// | .------------------' # | Example classes
// | | # |
// .---------. .-------------------. # |
// | Derived |==>| Derived metaclass |==========" |
// '---------' '-------------------' -'
// The rest of the classes can now be defined normally.
wrenInterpret(vm, "", coreLibSource);