Skip to content

Commit f49688f

Browse files
committed
[Truffle] Eval with a supplied binding should assign new variables within that binding.
1 parent a4e929d commit f49688f

File tree

4 files changed

+30
-24
lines changed

4 files changed

+30
-24
lines changed

spec/truffle/tags/core/kernel/eval_tags.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
fails:Kernel#eval evaluates within the scope of the eval
22
fails:Kernel#eval evaluates such that consts are scoped to the class of the eval
3-
fails:Kernel#eval allows a binding to be captured inside an eval
4-
fails:Kernel#eval uses the same scope for local variables when given the same binding
53
fails:Kernel#eval sets constants at the toplevel from inside a block
64
fails:Kernel#eval uses the filename of the binding if none is provided
75
fails:Kernel#eval uses the receiver as self inside the eval

truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ protected RubyBinding getCallerBinding(VirtualFrame frame) {
540540
public Object eval(VirtualFrame frame, RubyString source, UndefinedPlaceholder binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
541541
notDesignedForCompilation();
542542

543-
return eval(source, getCallerBinding(frame), filename, lineNumber);
543+
return getContext().eval(source.getBytes(), getCallerBinding(frame), true, this);
544544
}
545545

546546
@Specialization
@@ -555,36 +555,49 @@ public Object eval(VirtualFrame frame, RubyString source, RubyNilClass noBinding
555555
public Object eval(RubyString source, RubyBinding binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
556556
notDesignedForCompilation();
557557

558-
return getContext().eval(source.getBytes(), binding, this);
558+
return getContext().eval(source.getBytes(), binding, false, this);
559559
}
560560

561561
@Specialization
562562
public Object eval(RubyString source, RubyBinding binding, RubyString filename, UndefinedPlaceholder lineNumber) {
563563
notDesignedForCompilation();
564564

565565
// TODO (nirvdrum Dec. 29, 2014) Do something with the supplied filename.
566-
return getContext().eval(source.getBytes(), binding, this);
566+
return getContext().eval(source.getBytes(), binding, false, this);
567567
}
568568

569569
@Specialization
570570
public Object eval(RubyString source, RubyBinding binding, RubyString filename, int lineNumber) {
571571
notDesignedForCompilation();
572572

573573
// TODO (nirvdrum Dec. 29, 2014) Do something with the supplied filename and lineNumber.
574-
return getContext().eval(source.getBytes(), binding, this);
574+
return getContext().eval(source.getBytes(), binding, false, this);
575575
}
576576

577577
@Specialization(guards = "!isRubyString(arguments[0])")
578578
public Object eval(VirtualFrame frame, RubyBasicObject object, UndefinedPlaceholder binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
579579
notDesignedForCompilation();
580580

581-
return eval(frame, object, getCallerBinding(frame), filename, lineNumber);
581+
return evalCoerced(frame, object, getCallerBinding(frame), true, filename, lineNumber);
582582
}
583583

584584
@Specialization(guards = "!isRubyString(arguments[0])")
585585
public Object eval(VirtualFrame frame, RubyBasicObject object, RubyBinding binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
586586
notDesignedForCompilation();
587587

588+
return evalCoerced(frame, object, binding, false, filename, lineNumber);
589+
}
590+
591+
@Specialization(guards = "!isRubyBinding(arguments[1])")
592+
public Object eval(RubyBasicObject source, RubyBasicObject badBinding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
593+
throw new RaiseException(
594+
getContext().getCoreLibrary().typeError(
595+
String.format("wrong argument type %s (expected binding)",
596+
badBinding.getLogicalClass().getName()),
597+
this));
598+
}
599+
600+
private Object evalCoerced(VirtualFrame frame, RubyBasicObject object, RubyBinding binding, boolean ownScopeForAssignments, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
588601
Object coerced;
589602

590603
try {
@@ -601,7 +614,7 @@ public Object eval(VirtualFrame frame, RubyBasicObject object, RubyBinding bindi
601614
}
602615

603616
if (coerced instanceof RubyString) {
604-
return getContext().eval(((RubyString) coerced).getBytes(), binding, this);
617+
return getContext().eval(((RubyString) coerced).getBytes(), binding, ownScopeForAssignments, this);
605618
} else {
606619
throw new RaiseException(
607620
getContext().getCoreLibrary().typeError(
@@ -612,15 +625,6 @@ public Object eval(VirtualFrame frame, RubyBasicObject object, RubyBinding bindi
612625
this));
613626
}
614627
}
615-
616-
@Specialization(guards = "!isRubyBinding(arguments[1])")
617-
public Object eval(RubyBasicObject source, RubyBasicObject badBinding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
618-
throw new RaiseException(
619-
getContext().getCoreLibrary().typeError(
620-
String.format("wrong argument type %s (expected binding)",
621-
badBinding.getLogicalClass().getName()),
622-
this));
623-
}
624628
}
625629

626630
@CoreMethod(names = "exec", isModuleFunction = true, required = 1, argumentsAsArray = true)

truffle/src/main/java/org/jruby/truffle/runtime/RubyContext.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,17 @@ public Object eval(ByteList code, Object self, RubyNode currentNode) {
207207
return execute(this, source, code.getEncoding(), TranslatorDriver.ParserContext.TOP_LEVEL, self, null, currentNode, NodeWrapper.IDENTITY);
208208
}
209209

210-
public Object eval(ByteList code, RubyBinding binding, RubyNode currentNode) {
210+
public Object eval(ByteList code, RubyBinding binding, boolean ownScopeForAssignments, RubyNode currentNode) {
211211
final Source source = Source.fromText(code, "(eval)");
212-
return execute(this, source, code.getEncoding(), TranslatorDriver.ParserContext.TOP_LEVEL, binding.getSelf(), binding.getFrame(), currentNode, NodeWrapper.IDENTITY);
212+
return execute(this, source, code.getEncoding(), TranslatorDriver.ParserContext.TOP_LEVEL, binding.getSelf(), binding.getFrame(), ownScopeForAssignments, currentNode, NodeWrapper.IDENTITY);
213213
}
214214

215215
public Object execute(RubyContext context, Source source, Encoding defaultEncoding, TranslatorDriver.ParserContext parserContext, Object self, MaterializedFrame parentFrame, RubyNode currentNode, NodeWrapper wrapper) {
216-
final RubyRootNode rootNode = translator.parse(context, source, defaultEncoding, parserContext, parentFrame, currentNode, wrapper);
216+
return execute(context, source, defaultEncoding, parserContext, self, parentFrame, true, currentNode, wrapper);
217+
}
218+
219+
public Object execute(RubyContext context, Source source, Encoding defaultEncoding, TranslatorDriver.ParserContext parserContext, Object self, MaterializedFrame parentFrame, boolean ownScopeForAssignments, RubyNode currentNode, NodeWrapper wrapper) {
220+
final RubyRootNode rootNode = translator.parse(context, source, defaultEncoding, parserContext, parentFrame, ownScopeForAssignments, currentNode, wrapper);
217221
final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
218222

219223
// TODO(CS): we really need a method here - it's causing problems elsewhere

truffle/src/main/java/org/jruby/truffle/translator/TranslatorDriver.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public RubyNode parse(RubyContext context, org.jruby.ast.Node parseTree, org.jru
6666
return translator.compileFunctionNode(null, "(unknown)", argsNode, bodyNode, sharedMethod);
6767
}
6868

69-
public RubyRootNode parse(RubyContext context, Source source, Encoding defaultEncoding, ParserContext parserContext, MaterializedFrame parentFrame, RubyNode currentNode, NodeWrapper wrapper) {
69+
public RubyRootNode parse(RubyContext context, Source source, Encoding defaultEncoding, ParserContext parserContext, MaterializedFrame parentFrame, boolean ownScopeForAssignments, RubyNode currentNode, NodeWrapper wrapper) {
7070
// Set up the JRuby parser
7171

7272
final org.jruby.parser.Parser parser = new org.jruby.parser.Parser(context.getRuntime());
@@ -113,14 +113,14 @@ public RubyRootNode parse(RubyContext context, Source source, Encoding defaultEn
113113
throw new RaiseException(new RubyException(context.getCoreLibrary().getSyntaxErrorClass(), context.makeString(message), RubyCallStack.getBacktrace(currentNode)));
114114
}
115115

116-
return parse(currentNode, context, source, parserContext, parentFrame, node, wrapper);
116+
return parse(currentNode, context, source, parserContext, parentFrame, ownScopeForAssignments, node, wrapper);
117117
}
118118

119-
public RubyRootNode parse(RubyNode currentNode, RubyContext context, Source source, ParserContext parserContext, MaterializedFrame parentFrame, org.jruby.ast.RootNode rootNode, NodeWrapper wrapper) {
119+
public RubyRootNode parse(RubyNode currentNode, RubyContext context, Source source, ParserContext parserContext, MaterializedFrame parentFrame, boolean ownScopeForAssignments, org.jruby.ast.RootNode rootNode, NodeWrapper wrapper) {
120120
final SourceSection sourceSection = source.createSection("<main>", 0, source.getCode().length());
121121
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, context.getRootLexicalScope(), "<main>", false, rootNode, false);
122122

123-
final TranslatorEnvironment environment = new TranslatorEnvironment(context, environmentForFrame(context, parentFrame), this, allocateReturnID(), true, false, sharedMethodInfo, sharedMethodInfo.getName(), false);
123+
final TranslatorEnvironment environment = new TranslatorEnvironment(context, environmentForFrame(context, parentFrame), this, allocateReturnID(), ownScopeForAssignments, false, sharedMethodInfo, sharedMethodInfo.getName(), false);
124124

125125
// Get the DATA constant
126126

0 commit comments

Comments
 (0)