ccrma / chuck

ChucK Music Programming Language
http://chuck.stanford.edu/
GNU General Public License v2.0
777 stars 126 forks source link

Casting an instance of a type to a subtype won't allow for using its member methods #57

Open wasamasa opened 8 years ago

wasamasa commented 8 years ago

Sorry for the title. I'm currently writing a type system in ChucK and have defined a supertype with types extending it. It appears as if I cannot just cast an instance of the supertype into the more specific type and use its members instead of the more generic ones.

// String.ck
public class String
{
    string value;

    fun static String create(string value)
    {
        String s;
        value => s.value;
        return s;
    }
}
// Type.ck
public class Type
{
    string type;
    Object storage;
}
// StringType.ck
public class StringType extends Type
{
    "string" => type;

    fun string value()
    {
        return (storage$String).value;
    }
}
// example.ck
new Type @=> Type t;
"string" => t.type;
String.create("example") @=> t.storage;

<<< (t$StringType).value() >>>;
$ chuck String.ck Type.ck StringType.ck example.ck
chuck: chuck_instr.cpp:4774: virtual void Chuck_Instr_Dot_Member_Func::execute(Chuck_VM*, Chuck_VM_Shred*): Assertion `m_offset < obj->vtable->funcs.size()' failed.

What's notable is that if you add Type.value(), it is used in that case instead.

There doesn't appear to be a way to make use of StringType.value() other than writing a static method doing the same kind of access or creating a StringType object, writing the data into it and invoking its member.

I'm on Arch Linux, ChucK 1.3.5.2.

spencersalazar commented 8 years ago

I think the issue here is

new Type @=> Type t;

Basically the underlying object is at no point an instance of StringType, so casting it to StringType is undefined, and it has no reason to use StringType's value(). If you change it to

new StringType @=> Type t;

then it works like I think you want it to. You may also want to add a value() function to Type, in which case you can avoid casting altogether. ChucK will call the "youngest" function in the inheritance hierarchy of the underlying object.

This is more or less based on subclasses and polymorphism as implemented in C++ and Java.

wasamasa commented 8 years ago

OK, that makes sense. Still, is it to be expected that I get a raw assert displayed as opposed to the numerous compiler errors and exceptions I otherwise get for incorrect use of the language?