-
Notifications
You must be signed in to change notification settings - Fork 194
Description
Currently, foreign objects are handled specially in OutgoingForeignCallNode
.
They are given a Ruby class, Truffle::Interop::Foreign
but actually methods are not looked there, all method calls are directly dispatched to OutgoingForeignCallNode
instead.
I think a better design would be to have a set of modules and classes for foreign objects, and make foreign objects behave more like Ruby objects by using the normal Ruby method lookup.
When a Ruby method would not be found, we would check members with isMemberInvocable
and either invokeMember
or readMember
, instead of calling method_missing
.
So we could have something like Polyglot::ForeignArray < Polyglot::ForeignObject < Object
and Polyglot::ForeignArray
would include Enumerable
.
Then we could easily define the logic in Ruby.
All Object , Kernel, and BasicObject methods should then also handle foreign objects.
Given that a foreign object might have multiple traits:
https://github.com/oracle/graal/blob/68ce20c37071cfa91146f437eb6ab6ccffbd0759/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropLibrary.java#L129-L145
we should probably use modules to represent those traits that map to Ruby concepts.
So we'd have module Polyglot::Trait::ForeignArray
, module Polyglot::Trait::ForeignProc
, etc.
And we'd need classes to compose them like (an object must be the instance of a class, not of a module)
module Polyglot::Trait::ForeignArray
include Enumerable
def each
...
end
end
class Polyglot::ForeignArray < Polyglot::ForeignObject
include Polyglot::Trait::ForeignArray
end
class Polyglot::ForeignArrayProc < Polyglot::ForeignObject
include Polyglot::Trait::ForeignArray
include Polyglot::Trait::ForeignProc
end
(just a sketch, we might want to think more about names)
foreign_object.class
would actually return one of these classes, and we'll need an efficient way to compute that as it would be used for every method call on a foreign object.
Internally, to get the class of a foreign object, we'd probably want to add RubyLibrary#getMetaClass()
and RubyLibrary#getLogicalClass()
and implement them for foreign objects.