Skip to content

Commit 44ffcc3

Browse files
bjfisheregon
authored andcommitted
Adopt NodeLibrary, deprecate scope
* Move scope classes top-level when possible.
1 parent ec41098 commit 44ffcc3

16 files changed

+943
-425
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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+
12+
require_relative '../../ruby/spec_helper'
13+
require_relative 'fixtures/classes'
14+
15+
describe "Truffle::Interop.scope" do
16+
17+
# rubocop:disable Lint/UselessAssignment
18+
# rubocop:disable Lint/UnusedBlockArgument
19+
20+
it "returns the members" do
21+
b = :test
22+
def get_scope()
23+
a = 42
24+
Primitive.current_scope
25+
end
26+
scope = get_scope()
27+
Truffle::Interop.read_member(scope, "a").should == 42
28+
Truffle::Interop.members(scope).should == ["a", "self"]
29+
end
30+
31+
it "has a parent scope with the correct members" do
32+
def get_scopes()
33+
scope = nil
34+
a = :a
35+
["one"].each do |value|
36+
b = :b
37+
["two"].each do |inner|
38+
c = :c
39+
scope = Primitive.current_scope
40+
end
41+
end
42+
scope
43+
end
44+
scope = get_scopes()
45+
Truffle::Interop.members(scope).should == ["inner", "c", "value", "b", "scope", "a", "self"]
46+
scope["inner"].should == "two"
47+
scope["c"].should == :c
48+
scope["value"].should == "one"
49+
scope["b"].should == :b
50+
scope["a"].should == :a
51+
parent_scope = Truffle::Interop.scope_parent(scope)
52+
Truffle::Interop.members(parent_scope).should == ["value", "b", "scope", "a", "self"]
53+
parent_scope["b"].should == :b
54+
-> { parent_scope["missing"] }.should raise_error(NameError)
55+
parent_parent_scope = Truffle::Interop.scope_parent(parent_scope)
56+
Truffle::Interop.members(parent_parent_scope).should == ["scope", "a", "self"]
57+
end
58+
59+
it "allows reading and writing scope members" do
60+
def get_scopes()
61+
scope = nil
62+
a = :a
63+
["one"].each do |value|
64+
b = :b
65+
["two"].each do |inner|
66+
c = :c
67+
scope = Primitive.current_scope
68+
end
69+
end
70+
scope
71+
end
72+
scope = get_scopes()
73+
scope["inner"].should == "two"
74+
scope["inner"] = "three"
75+
scope["inner"].should == "three"
76+
77+
scope["c"].should == :c
78+
scope["c"] = :d
79+
scope["c"].should == "d"
80+
81+
scope["a"].should == :a
82+
scope["a"] = :b
83+
scope["a"].should == "b"
84+
85+
-> { scope["missing"] = "missing" }.should raise_error(NameError)
86+
end
87+
88+
89+
# rubocop:enable Lint/UselessAssignment
90+
# rubocop:enable Lint/UnusedBlockArgument
91+
92+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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+
12+
# rubocop:disable Lint/UselessAssignment
13+
14+
a = "a"
15+
16+
describe "NodeLibrary top scope" do
17+
it "returns the members" do
18+
b = "b"
19+
def get_top_scope
20+
c = "c"
21+
Primitive.top_scope
22+
end
23+
top_scope = get_top_scope()
24+
scope_members = Truffle::Interop.members(top_scope)
25+
["$stdout", "is_a?"].all? { |m| scope_members.include?(m) }.should == true
26+
top_scope["$stdout"].should == $stdout
27+
top_scope["is_a?"].should be_kind_of(Method)
28+
end
29+
end
30+
31+
# rubocop:enable Lint/UselessAssignment

src/main/java/org/truffleruby/RubyContext.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,10 @@ public String getPathRelativeToHome(String path) {
824824
}
825825
}
826826

827+
public Object getTopScopeObject() {
828+
return coreLibrary.topScopeObject;
829+
}
830+
827831
@TruffleBoundary
828832
public static String fileLine(SourceSection section) {
829833
if (section == null) {

src/main/java/org/truffleruby/RubyLanguage.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@
6464
import org.truffleruby.core.thread.RubyThread;
6565
import org.truffleruby.core.time.RubyTime;
6666
import org.truffleruby.core.tracepoint.RubyTracePoint;
67-
import org.truffleruby.debug.GlobalScope;
68-
import org.truffleruby.debug.LexicalScope;
6967
import org.truffleruby.extra.RubyAtomicReference;
7068
import org.truffleruby.extra.ffi.RubyPointer;
7169
import org.truffleruby.language.NotProvided;
@@ -85,16 +83,13 @@
8583
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
8684
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
8785
import com.oracle.truffle.api.RootCallTarget;
88-
import com.oracle.truffle.api.Scope;
8986
import com.oracle.truffle.api.Truffle;
9087
import com.oracle.truffle.api.TruffleLanguage;
9188
import com.oracle.truffle.api.TruffleLanguage.ContextPolicy;
9289
import com.oracle.truffle.api.TruffleLogger;
93-
import com.oracle.truffle.api.frame.Frame;
9490
import com.oracle.truffle.api.instrumentation.ProvidedTags;
9591
import com.oracle.truffle.api.instrumentation.StandardTags;
9692
import com.oracle.truffle.api.nodes.ExecutableNode;
97-
import com.oracle.truffle.api.nodes.Node;
9893
import com.oracle.truffle.api.utilities.CyclicAssumption;
9994
import org.truffleruby.stdlib.bigdecimal.RubyBigDecimal;
10095
import org.truffleruby.stdlib.digest.RubyDigest;
@@ -398,15 +393,8 @@ protected void disposeThread(RubyContext context, Thread thread) {
398393
}
399394

400395
@Override
401-
protected Iterable<Scope> findLocalScopes(RubyContext context, Node node, Frame frame) {
402-
return LexicalScope.getLexicalScopeFor(context, node, frame == null ? null : frame.materialize());
403-
}
404-
405-
@Override
406-
protected Iterable<Scope> findTopScopes(RubyContext context) {
407-
return Arrays.asList(
408-
GlobalScope.getGlobalScope(context.getCoreLibrary().globalVariables),
409-
Scope.newBuilder("main", context.getCoreLibrary().mainObject).build());
396+
protected Object getScope(RubyContext context) {
397+
return context.getTopScopeObject();
410398
}
411399

412400
public String getTruffleLanguageHome() {

src/main/java/org/truffleruby/core/CoreLibrary.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import org.truffleruby.core.string.RubyString;
4747
import org.truffleruby.core.string.StringOperations;
4848
import org.truffleruby.core.symbol.RubySymbol;
49+
import org.truffleruby.debug.GlobalVariablesObject;
50+
import org.truffleruby.debug.TopScopeObject;
4951
import org.truffleruby.extra.ffi.Pointer;
5052
import org.truffleruby.language.Nil;
5153
import org.truffleruby.language.NotProvided;
@@ -242,6 +244,7 @@ public class CoreLibrary {
242244
@CompilationFinal private GlobalVariableReader stderrReader;
243245

244246
@CompilationFinal public RubyBinding topLevelBinding;
247+
@CompilationFinal public TopScopeObject topScopeObject;
245248

246249
private final ConcurrentMap<String, Boolean> patchFiles;
247250

@@ -588,6 +591,8 @@ public CoreLibrary(RubyContext context) {
588591
argv = new RubyArray(arrayClass, RubyLanguage.arrayShape, ArrayStoreLibrary.INITIAL_STORE, 0);
589592

590593
globalVariables = new GlobalVariables();
594+
topScopeObject = new TopScopeObject(
595+
new Object[]{ new GlobalVariablesObject(globalVariables), mainObject });
591596

592597
patchFiles = initializePatching(context);
593598
}

src/main/java/org/truffleruby/core/binding/BindingNodes.java

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
import java.util.LinkedHashSet;
1313
import java.util.Set;
1414

15+
import com.oracle.truffle.api.dsl.CachedContext;
16+
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
17+
import com.oracle.truffle.api.dsl.GenerateUncached;
1518
import org.jcodings.specific.UTF8Encoding;
1619
import org.truffleruby.RubyContext;
1720
import org.truffleruby.RubyLanguage;
1821
import org.truffleruby.builtins.CoreMethod;
19-
import org.truffleruby.builtins.CoreMethodNode;
2022
import org.truffleruby.builtins.CoreModule;
2123
import org.truffleruby.builtins.Primitive;
2224
import org.truffleruby.builtins.PrimitiveArrayArgumentsNode;
@@ -30,6 +32,7 @@
3032
import org.truffleruby.core.string.StringNodes.MakeStringNode;
3133
import org.truffleruby.language.Nil;
3234
import org.truffleruby.language.RubyNode;
35+
import org.truffleruby.language.RubySourceNode;
3336
import org.truffleruby.language.Visibility;
3437
import org.truffleruby.language.arguments.ReadCallerFrameNode;
3538
import org.truffleruby.language.arguments.RubyArguments;
@@ -153,10 +156,18 @@ protected RubyBinding dup(RubyBinding binding) {
153156
}
154157

155158
@ImportStatic({ BindingNodes.class, FindDeclarationVariableNodes.class })
159+
@GenerateUncached
160+
@GenerateNodeFactory
156161
@CoreMethod(names = "local_variable_defined?", required = 1)
157162
@NodeChild(value = "binding", type = RubyNode.class)
158163
@NodeChild(value = "name", type = RubyNode.class)
159-
public abstract static class LocalVariableDefinedNode extends CoreMethodNode {
164+
public abstract static class LocalVariableDefinedNode extends RubySourceNode {
165+
166+
public static LocalVariableDefinedNode create() {
167+
return BindingNodesFactory.LocalVariableDefinedNodeFactory.create(null, null);
168+
}
169+
170+
public abstract boolean execute(RubyBinding binding, String name);
160171

161172
@CreateCast("name")
162173
protected RubyNode coerceToString(RubyNode name) {
@@ -177,30 +188,39 @@ protected boolean localVariableDefinedCached(RubyBinding binding, String name,
177188
}
178189

179190
@TruffleBoundary
180-
@Specialization(guards = "!isHiddenVariable(name)")
191+
@Specialization(guards = "!isHiddenVariable(name)", replaces = "localVariableDefinedCached")
181192
protected boolean localVariableDefinedUncached(RubyBinding binding, String name) {
182193
return FindDeclarationVariableNodes.findFrameSlotOrNull(name, binding.getFrame()) != null;
183194
}
184195

185196
@TruffleBoundary
186197
@Specialization(guards = "isHiddenVariable(name)")
187-
protected Object localVariableDefinedLastLine(RubyBinding binding, String name) {
198+
protected Object localVariableDefinedLastLine(RubyBinding binding, String name,
199+
@CachedContext(RubyLanguage.class) RubyContext context) {
188200
throw new RaiseException(
189-
getContext(),
190-
coreExceptions().nameError("Bad local variable name", binding, name, this));
201+
context,
202+
context.getCoreExceptions().nameError("Bad local variable name", binding, name, this));
191203
}
192204

193205
protected int getCacheLimit() {
194-
return getContext().getOptions().BINDING_LOCAL_VARIABLE_CACHE;
206+
return RubyLanguage.getCurrentContext().getOptions().BINDING_LOCAL_VARIABLE_CACHE;
195207
}
196208

197209
}
198210

199-
@CoreMethod(names = "local_variable_get", required = 1)
211+
@GenerateUncached
212+
@GenerateNodeFactory
200213
@NodeChild(value = "binding", type = RubyNode.class)
201214
@NodeChild(value = "name", type = RubyNode.class)
202215
@ImportStatic(BindingNodes.class)
203-
public abstract static class LocalVariableGetNode extends CoreMethodNode {
216+
@CoreMethod(names = "local_variable_get", required = 1)
217+
public abstract static class LocalVariableGetNode extends RubySourceNode {
218+
219+
public abstract Object execute(RubyBinding binding, String name);
220+
221+
public static LocalVariableGetNode create() {
222+
return BindingNodesFactory.LocalVariableGetNodeFactory.create(null, null);
223+
}
204224

205225
@CreateCast("name")
206226
protected RubyNode coerceToString(RubyNode name) {
@@ -209,38 +229,48 @@ protected RubyNode coerceToString(RubyNode name) {
209229

210230
@Specialization(guards = "!isHiddenVariable(name)")
211231
protected Object localVariableGet(RubyBinding binding, String name,
212-
@Cached FindAndReadDeclarationVariableNode readNode) {
232+
@Cached FindAndReadDeclarationVariableNode readNode,
233+
@CachedContext(RubyLanguage.class) RubyContext context) {
213234
MaterializedFrame frame = binding.getFrame();
214-
Object result = readNode.execute(frame, name);
235+
Object result = readNode.execute(frame, name, null);
215236
if (result == null) {
216237
throw new RaiseException(
217-
getContext(),
218-
coreExceptions().nameErrorLocalVariableNotDefined(name, binding, this));
238+
context,
239+
context.getCoreExceptions().nameErrorLocalVariableNotDefined(name, binding, this));
219240
}
220241
return result;
221242
}
222243

223244
@TruffleBoundary
224245
@Specialization(guards = "isHiddenVariable(name)")
225-
protected Object localVariableGetLastLine(RubyBinding binding, String name) {
246+
protected Object localVariableGetLastLine(RubyBinding binding, String name,
247+
@CachedContext(RubyLanguage.class) RubyContext context) {
226248
throw new RaiseException(
227-
getContext(),
228-
coreExceptions().nameError("Bad local variable name", binding, name, this));
249+
context,
250+
context.getCoreExceptions().nameError("Bad local variable name", binding, name, this));
229251
}
230252

231253
protected int getCacheLimit() {
232-
return getContext().getOptions().BINDING_LOCAL_VARIABLE_CACHE;
254+
return RubyLanguage.getCurrentContext().getOptions().BINDING_LOCAL_VARIABLE_CACHE;
233255
}
234256

235257
}
236258

237259
@ReportPolymorphism
260+
@GenerateUncached
261+
@GenerateNodeFactory
238262
@CoreMethod(names = "local_variable_set", required = 2)
239263
@NodeChild(value = "binding", type = RubyNode.class)
240264
@NodeChild(value = "name", type = RubyNode.class)
241265
@NodeChild(value = "value", type = RubyNode.class)
242266
@ImportStatic({ BindingNodes.class, FindDeclarationVariableNodes.class })
243-
public abstract static class LocalVariableSetNode extends CoreMethodNode {
267+
public abstract static class LocalVariableSetNode extends RubySourceNode {
268+
269+
public static LocalVariableSetNode create() {
270+
return BindingNodesFactory.LocalVariableSetNodeFactory.create(null, null, null);
271+
}
272+
273+
public abstract Object execute(RubyBinding binding, String name, Object value);
244274

245275
@CreateCast("name")
246276
protected RubyNode coerceToString(RubyNode name) {
@@ -285,7 +315,9 @@ protected Object localVariableSetNewCached(RubyBinding binding, String name, Obj
285315
}
286316

287317
@TruffleBoundary
288-
@Specialization(guards = "!isHiddenVariable(name)")
318+
@Specialization(
319+
guards = "!isHiddenVariable(name)",
320+
replaces = { "localVariableSetCached", "localVariableSetNewCached" })
289321
protected Object localVariableSetUncached(RubyBinding binding, String name, Object value) {
290322
MaterializedFrame frame = binding.getFrame();
291323
final FrameSlotAndDepth frameSlot = FindDeclarationVariableNodes.findFrameSlotOrNull(name, frame);
@@ -303,18 +335,19 @@ protected Object localVariableSetUncached(RubyBinding binding, String name, Obje
303335

304336
@TruffleBoundary
305337
@Specialization(guards = "isHiddenVariable(name)")
306-
protected Object localVariableSetLastLine(RubyBinding binding, String name, Object value) {
338+
protected Object localVariableSetLastLine(RubyBinding binding, String name, Object value,
339+
@CachedContext(RubyLanguage.class) RubyContext context) {
307340
throw new RaiseException(
308-
getContext(),
309-
coreExceptions().nameError("Bad local variable name", binding, name, this));
341+
context,
342+
context.getCoreExceptions().nameError("Bad local variable name", binding, name, this));
310343
}
311344

312345
protected WriteFrameSlotNode createWriteNode(FrameSlotAndDepth frameSlot) {
313346
return WriteFrameSlotNodeGen.create(frameSlot.slot);
314347
}
315348

316349
protected int getCacheLimit() {
317-
return getContext().getOptions().BINDING_LOCAL_VARIABLE_CACHE;
350+
return RubyLanguage.getCurrentContext().getOptions().BINDING_LOCAL_VARIABLE_CACHE;
318351
}
319352
}
320353

0 commit comments

Comments
 (0)