musictheory / NilScript

Objective-C-style language superset of JavaScript with a tiny, simple runtime
Other
50 stars 5 forks source link

Question regarding runtime #81

Closed IngwiePhoenix closed 6 years ago

IngwiePhoenix commented 8 years ago

As of current, all classes, protocols and alike are stored inside the runtime's $oj_oj global variable. I'd like to ask something about it.

When generating the code, the original variable ends up with no result:

var Foo = $oj_oj._registerClass({ $oj_c_Foo:1 }, null, function($oj_s, $oj_m) { function Foo() { this.constructor = Foo;this.$oj_id = ++$oj_oj._id;}
$oj_s.$oj_f_greet = function() { console.log("Hi"); }
return Foo;});

In this case, Foo ends up as an empty variable.

My questions:

Kind regards, Ingwie

iccir commented 8 years ago

Actually, this is #80 :) It is a codegen artifact of the early oj 0.x days, when _registerClass() use to return the class itself (which was also an inconsistency, since using the variable back then would replace the class anyway with the global).

IngwiePhoenix commented 8 years ago

I see, I see.

So will OJ prefer the class within the global variable, or from the scoped variable?

iccir commented 8 years ago

Neither! Classes aren't actually variables! Try the following in Objective-C:

@interface Foo : NSObject
@end

@implementation Foo
@end

int main(int argc, const char * argv[])
{
    NSLog(@"%s", class_getName(Foo));
    return 0;
}

You might expect this to log "Foo" to the console, but it's actually a compiler error, because Foo isn't a variable at all. It's something that can only be messaged to via bracket syntax (you would need to do class_getName([Foo class])).

Likewise, in oj:

@implementation Foo
@end

oj.class_getName(Foo); // This should never work, as Foo is not a variable.
oj.class_getName([Foo class]); // Prints Foo.  Using Foo is fine as a *message receiver*
iccir commented 8 years ago

oj.class_getName(Foo) currently works inside of the Foo class, as the constructor is named Foo, that's a bug though!

IngwiePhoenix commented 8 years ago

Oh, I see! And here I thought the class objects - well, sort-of their prototypes - would be stored as properties of $oj_oj._cls and be pretty much variables. But - as I just learned, that is not the case. :)

So the classes are just registered in the global $oj_oj variable and that's it?

IngwiePhoenix commented 8 years ago

As expected.

test.m:10:32: error: unexpected interface name 'Foo': expected expression
    NSLog(@"%s", class_getName(Foo));
                               ^
1 warning and 1 error generated.

Now I understand. :)

Though it complained about the class_getName function not being declared; I bet I just forgot a header.

EDIT: Huh, now, that actually makes sense: #include <objc/runtime.h> is just like OJ's runtime.js. BTW, what happened to the folder structure plan, will the runtime move one level upwards? i.e. require("oj/runtime")

iccir commented 8 years ago

Internally, classes are stored on $oj_oj._cls, but the compiler will only transform an identifier into $oj_oj._cls.$oj_c_Foo when it is the receiver of a message expression (just like Obj-C). You can use oj.getClassList to get an array of all registered classes (this mimics objc_getClassList :) ).

Regarding runtime.js. It's in /lib with api.js. require("ojc") gets you api.js, how were you getting runtime before?

iccir commented 6 years ago

I don't think that there is any actionable items left in this issue - let me know if you have any additional questions!