Skip to content

Commit bdf6759

Browse files
committed
Add a spec that all InteropLibrary messages are exposed as Truffle::Interop methods
1 parent 51403f6 commit bdf6759

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

spec/truffle/interop/methods_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# truffleruby_primitives: true
2+
3+
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. This
4+
# code is released under a tri EPL/GPL/LGPL license. You can use it,
5+
# redistribute it and/or modify it under the terms of the:
6+
#
7+
# Eclipse Public License version 2.0, or
8+
# GNU General Public License version 2, or
9+
# GNU Lesser General Public License version 2.1.
10+
11+
require_relative '../../ruby/spec_helper'
12+
13+
describe "Truffle::Interop" do
14+
it "has a method for each InteropLibrary message" do
15+
all_methods = Primitive.interop_library_all_methods
16+
all_methods -= %w[getFactory getUncached]
17+
expected = all_methods.map do |name|
18+
name = name.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2.downcase}" }
19+
if name.start_with?('is_', 'has_', 'fits_')
20+
name += '?'
21+
end
22+
if name.start_with?('is_')
23+
name = name[3..-1]
24+
elsif name.start_with?('get_')
25+
name = name[4..-1]
26+
end
27+
name.to_sym
28+
end.sort
29+
30+
actual = Truffle::Interop.methods.sort
31+
32+
# pp expected
33+
# pp actual
34+
(expected - actual).should == []
35+
end
36+
end

src/main/java/org/truffleruby/interop/InteropNodes.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
package org.truffleruby.interop;
1111

1212
import java.io.IOException;
13+
import java.lang.reflect.Method;
14+
import java.lang.reflect.Modifier;
15+
import java.util.ArrayList;
16+
import java.util.List;
1317
import java.util.Map;
1418

1519
import com.oracle.truffle.api.dsl.CachedContext;
@@ -93,6 +97,36 @@ public static Object execute(Object receiver, Object[] args, InteropLibrary rece
9397
}
9498
}
9599

100+
@Primitive(name = "interop_library_all_methods")
101+
public abstract static class AllMethodsOfInteropLibrary extends PrimitiveArrayArgumentsNode {
102+
103+
private static final String[] METHODS = publicInteropLibraryMethods();
104+
105+
@TruffleBoundary
106+
@Specialization
107+
protected RubyArray allMethodsOfInteropLibrary() {
108+
Object[] store = new Object[METHODS.length];
109+
for (int i = 0; i < METHODS.length; i++) {
110+
store[i] = StringOperations
111+
.createString(this, StringOperations.encodeRope(METHODS[i], UTF8Encoding.INSTANCE));
112+
}
113+
return createArray(store);
114+
}
115+
116+
private static String[] publicInteropLibraryMethods() {
117+
List<String> methods = new ArrayList<>();
118+
for (Method method : InteropLibrary.class.getDeclaredMethods()) {
119+
if (Modifier.isPublic(method.getModifiers())) {
120+
if (!methods.contains(method.getName())) {
121+
methods.add(method.getName());
122+
}
123+
}
124+
}
125+
return methods.toArray(StringUtils.EMPTY_STRING_ARRAY);
126+
}
127+
128+
}
129+
96130
@CoreMethod(names = "import_file", onSingleton = true, required = 1)
97131
public abstract static class ImportFileNode extends CoreMethodArrayArgumentsNode {
98132

0 commit comments

Comments
 (0)