Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[interop] TruffleRuby does not allow binding modifications #2024

Closed
fniephaus opened this issue Jun 3, 2020 · 8 comments
Closed

[interop] TruffleRuby does not allow binding modifications #2024

fniephaus opened this issue Jun 3, 2020 · 8 comments
Assignees
Labels
Milestone

Comments

@fniephaus
Copy link
Member

fniephaus commented Jun 3, 2020

Steps to reproduce

context.getBindings("ruby").putMember("myGlobalObject", this) throws an "Unsupported operation Value.putMember(String, Object)`" error.

Expected behavior

myGlobalObject is set in Ruby's globals and consequently accessible through $myGlobalObject. Alternatively, Ruby's main object could be modified, but I'm not sure this makes sense.

@eregon mentioned that this is simply not (yet) implemented.

/cc @tmillich @TheoRadig

@eregon eregon added the polyglot label Jun 4, 2020
@eregon eregon self-assigned this Jun 4, 2020
@eregon
Copy link
Member

eregon commented Jun 4, 2020

A workaround is to context.eval("ruby", "$foo = 3"). I'll try to implement it.

@eregon
Copy link
Member

eregon commented Jun 4, 2020

Current global variables are exposed with their name including $ in top scopes, so bindings.getMember("$DEBUG") works but not bindings.getMember("DEBUG").

So I'll do the same for writing to it, it needs to be
bindings.putMember("$polyglot_interop_test", 42);
and not
bindings.putMember("polyglot_interop_test", 42);

Maybe we should change that, but then I'm afraid it might look confusing with e.g., accessing constants (not exposed in the top scopes currently), and potentially conflict with global methods (which can be read not written).

@fniephaus
Copy link
Member Author

Maybe we should change that, but then I'm afraid it might look confusing with e.g., accessing constants (not exposed in the top scopes currently), and potentially conflict with global methods (which can be read not written).

I see your point...but on the other hand, bindings.putMember(String, Object) may not be language-agnostic (you'd need to check if the bindings is Ruby and then append a $, so the semantics start leaking). I'm not sure it should be language-agnostic, let's double check with @chumer.

@eregon
Copy link
Member

eregon commented Jun 4, 2020

To some degree I think identifiers have to be language-specific.
For instance in languages which use a capital letter for variables (e.g., Erlang, Oz), I don't think putMember("foo") can work (foo is an atom).

In this case we want to differentiate methods on the main object, Object constants, and global variables, I think using the global variable syntax is a good way to achieve that.

@chumer
Copy link
Member

chumer commented Jun 4, 2020

I agree with @fniephaus, I don't think using the member name with some special symbol is a good solution to this problem. If you need to add a $ you can also evaluate a ruby snippet instead.
If the $ is part of the language syntax like periods then I'd not include it. Member names are no place for expressions.

@fniephaus
Copy link
Member Author

In TruffleSqueak, we have to deal with : in message identifiers. Since they almost always cause syntax errors in other languages (e.g. Array.with:with:(42, 21)), TruffleSqueak has a logic to covert _ magically (e.g. Array.with_with(42, 21) and Array.with_with_(42, 21) work and do the same). That's just another example of hiding language specifics from the general interop API.

@eregon
Copy link
Member

eregon commented Jun 4, 2020

I think what would be more natural, especially in REPL/snippets-like contexts would be to read/write local variables of the "interactive Sources Binding".
That way:

context.eval(Source.newBuilder("ruby", "foo = 14", "test").interactive(true).buildLiteral());
context.eval(Source.newBuilder("ruby", "foo", "test").interactive(true).buildLiteral()); // 14, already works
context.getBindings("ruby").getMember("foo") // 14, not yet supported

Which is likely what most users want when accessing language bindings.

It would probably make sense to try to get this to work non-interactive sources too, but that seems quite involved (notably, harder with #2025).

graalvmbot pushed a commit that referenced this issue Jun 4, 2020
@eregon
Copy link
Member

eregon commented Jun 4, 2020

78d31aa allows to write to global variables, with bindings.putMember("$foo", 42).
If you'd like to have access to local variables in the language bindings, let's discuss on a separate issue. => #2030

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants