Skip to content

Integrate foreign objects better with Ruby objects #2149

@eregon

Description

@eregon

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.

cc @rbotafogo @fniephaus @chumer

Metadata

Metadata

Assignees

Labels

polyglotUses multiple Truffle languages or host interop

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions