Skip to content

Commit bb0cee5

Browse files
committed
Repair passing additional arguments to Prism
1 parent beafe77 commit bb0cee5

File tree

3 files changed

+55
-18
lines changed

3 files changed

+55
-18
lines changed

src/main/java/org/truffleruby/debug/TruffleDebugNodes.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.List;
1818
import java.util.Map;
1919

20+
import com.oracle.truffle.api.CallTarget;
2021
import com.oracle.truffle.api.TruffleStackTrace;
2122
import com.oracle.truffle.api.TruffleStackTraceElement;
2223
import com.oracle.truffle.api.exception.AbstractTruffleException;
@@ -110,6 +111,7 @@
110111
import org.truffleruby.parser.RubySource;
111112
import org.truffleruby.parser.TranslatorEnvironment;
112113
import org.truffleruby.parser.YARPTranslatorDriver;
114+
import org.truffleruby.shared.TruffleRuby;
113115

114116
@CoreModule("Truffle::Debug")
115117
public abstract class TruffleDebugNodes {
@@ -1369,4 +1371,37 @@ private RubyRootNode parse(TStringWithEncoding sourceCode, boolean mainScript) {
13691371
}
13701372
}
13711373

1374+
@CoreMethod(names = "parse_public", onSingleton = true, required = 3)
1375+
@ImportStatic(ArrayGuards.class)
1376+
public abstract static class ParsePublicNode extends CoreMethodArrayArgumentsNode {
1377+
1378+
@TruffleBoundary
1379+
@Specialization(limit = "storageStrategyLimit()")
1380+
Object parsePublic(Object sourceCode, RubyArray parameters, RubyArray arguments,
1381+
@Bind("parameters.getStore()") Object parametersStore,
1382+
@Bind("arguments.getStore()") Object argumentsStore,
1383+
@CachedLibrary("parametersStore") ArrayStoreLibrary parametersStores,
1384+
@CachedLibrary("argumentsStore") ArrayStoreLibrary argumentsStores) {
1385+
String sourceCodeString = RubyGuards.getJavaString(sourceCode);
1386+
1387+
String[] names = new String[parameters.size];
1388+
Object[] values = new Object[arguments.size];
1389+
1390+
for (int i = 0; i < names.length; i++) {
1391+
Object name = parametersStores.read(parametersStore, i);
1392+
names[i] = RubyGuards.getJavaString(name);
1393+
}
1394+
1395+
for (int i = 0; i < values.length; i++) {
1396+
values[i] = argumentsStores.read(argumentsStore, i);
1397+
}
1398+
1399+
Source source = Source.newBuilder(TruffleRuby.LANGUAGE_ID, sourceCodeString, "parse_public.rb").build();
1400+
var env = getContext().getEnv();
1401+
1402+
CallTarget method = env.parsePublic(source, names);
1403+
return method.call(values);
1404+
}
1405+
}
1406+
13721407
}

src/main/java/org/truffleruby/parser/YARPTranslatorDriver.java

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public RootCallTarget parse(RubySource rubySource, ParserContext parserContext,
123123
* we look them up ourselves after being told they're in some parent scope. */
124124

125125
final TranslatorEnvironment parentEnvironment;
126-
final List<List<String>> localVariableNames = new ArrayList<>();
126+
final List<List<String>> localsInScopes = new ArrayList<>();
127127

128128
int blockDepth = 0;
129129
if (parentFrame != null) {
@@ -139,7 +139,7 @@ public RootCallTarget parse(RubySource rubySource, ParserContext parserContext,
139139
}
140140
}
141141

142-
localVariableNames.add(names);
142+
localsInScopes.add(names);
143143
frame = RubyArguments.getDeclarationFrame(frame);
144144
blockDepth++;
145145
}
@@ -150,7 +150,7 @@ public RootCallTarget parse(RubySource rubySource, ParserContext parserContext,
150150
}
151151

152152
if (argumentNames != null) {
153-
// TODO: add these variables and treat it more like an eval case
153+
localsInScopes.add(Arrays.asList(argumentNames));
154154
}
155155

156156
// Parse to the YARP AST
@@ -168,7 +168,7 @@ public RootCallTarget parse(RubySource rubySource, ParserContext parserContext,
168168
parseResult = context.getMetricsProfiler().callWithMetrics(
169169
"parsing",
170170
source.getName(),
171-
() -> parseToYARPAST(language, rubySource, localVariableNames,
171+
() -> parseToYARPAST(language, rubySource, localsInScopes,
172172
parseEnvironment));
173173
printParseTranslateExecuteMetric("after-parsing", context, source);
174174
}
@@ -356,25 +356,23 @@ private String getMethodName(ParserContext parserContext, MaterializedFrame pare
356356
}
357357

358358
public static ParseResult parseToYARPAST(RubyLanguage language, RubySource rubySource,
359-
List<List<String>> localVariableNames, ParseEnvironment parseEnvironment) {
359+
List<List<String>> localsInScopes, ParseEnvironment parseEnvironment) {
360360
TruffleSafepoint.poll(DummyNode.INSTANCE);
361361

362-
byte[] sourceBytes = rubySource.getBytes();
362+
// intern() to improve footprint
363+
String sourcePath = rubySource.getSourcePath(language).intern();
363364

364-
byte[] filepath;
365+
byte[] sourceBytes = rubySource.getBytes();
366+
final byte[] filepath = sourcePath.getBytes(Encodings.FILESYSTEM_CHARSET);
365367
int line = rubySource.getLineOffset() + 1;
366368
byte[] encoding = StringOperations.encodeAsciiBytes(rubySource.getEncoding().toString()); // encoding name is supposed to contain only ASCII characters
367369
boolean frozenStringLiteral = language.options.FROZEN_STRING_LITERALS;
368370
var version = ParsingOptions.SyntaxVersion.V3_3_0;
369-
byte[][][] scopes;
370371

371-
// intern() to improve footprint
372-
String sourcePath = rubySource.getSourcePath(language).intern();
373-
374-
if (rubySource.isEval()) {
375-
filepath = sourcePath.getBytes(Encodings.FILESYSTEM_CHARSET);
372+
byte[][][] scopes;
376373

377-
int scopesCount = localVariableNames.size();
374+
if (!localsInScopes.isEmpty()) {
375+
int scopesCount = localsInScopes.size();
378376
// Add one empty extra scope at the end to have local variables treated by Prism
379377
// as declared in the outer scope.
380378
// See https://github.com/ruby/prism/issues/2327 and https://github.com/ruby/prism/issues/2192
@@ -383,7 +381,7 @@ public static ParseResult parseToYARPAST(RubyLanguage language, RubySource rubyS
383381
for (int i = 0; i < scopesCount; i++) {
384382
// Local variables are in order from inner scope to outer one, but Prism expects order from outer to inner.
385383
// So we need to reverse the order
386-
var namesList = localVariableNames.get(scopesCount - 1 - i);
384+
var namesList = localsInScopes.get(scopesCount - 1 - i);
387385
byte[][] namesBytes = new byte[namesList.size()][];
388386
int j = 0;
389387
for (var name : namesList) {
@@ -395,9 +393,6 @@ public static ParseResult parseToYARPAST(RubyLanguage language, RubySource rubyS
395393

396394
scopes[scopes.length - 1] = new byte[][]{};
397395
} else {
398-
assert localVariableNames.isEmpty(); // parsing of the whole source file cannot have outer scopes
399-
400-
filepath = sourcePath.getBytes(Encodings.FILESYSTEM_CHARSET);
401396
scopes = new byte[0][][];
402397
}
403398

src/test-embedding/java/org/truffleruby/test/embedding/PolyglotInteropTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ public void testParameters() {
4040
}
4141
}
4242

43+
@Test
44+
public void testExecutingWithParameters() {
45+
try (Context polyglot = Context.create()) {
46+
assertEquals(3, polyglot.eval("ruby", "Truffle::Debug.parse_public 'a + b', ['a', 'b'], [1, 2]").asInt());
47+
}
48+
}
49+
4350
@Test
4451
public void testCallingMethods() {
4552
try (Context polyglot = Context.create()) {

0 commit comments

Comments
 (0)