diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index 3fe026c02b..3e9c7a05b5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -65,6 +65,7 @@ import com.oracle.graal.python.runtime.PythonParser.ParserMode; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.interop.InteropMap; +import com.oracle.graal.python.util.PFunctionArgsFinder; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; @@ -359,8 +360,21 @@ protected boolean isVisible(PythonContext context, Object value) { protected Iterable findLocalScopes(PythonContext context, Node node, Frame frame) { ArrayList scopes = new ArrayList<>(); for (Scope s : super.findLocalScopes(context, node, frame)) { - scopes.add(s); + if (frame == null) { + PFunctionArgsFinder argsFinder = new PFunctionArgsFinder(node); + + Scope.Builder scopeBuilder = Scope.newBuilder(s.getName(), s.getVariables()) + .node(s.getNode()) + .receiver(s.getReceiverName(), s.getReceiver()) + .rootInstance(s.getRootInstance()) + .arguments(argsFinder.collectArgs()); + + scopes.add(scopeBuilder.build()); + } else { + scopes.add(s); + } } + if (frame != null) { PythonObject globals = PArguments.getGlobalsSafe(frame); if (globals != null) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PFunctionArgsFinder.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PFunctionArgsFinder.java new file mode 100644 index 0000000000..8f5b757898 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PFunctionArgsFinder.java @@ -0,0 +1,62 @@ +package com.oracle.graal.python.util; + +import com.oracle.graal.python.nodes.PRootNode; +import com.oracle.graal.python.nodes.argument.ReadArgumentNode; +import com.oracle.graal.python.nodes.frame.WriteIdentifierNode; +import com.oracle.graal.python.runtime.interop.InteropArray; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.NodeUtil; +import com.oracle.truffle.api.nodes.RootNode; + +import java.util.LinkedList; +import java.util.List; + +public class PFunctionArgsFinder { + private final RootNode rootNode; + + public PFunctionArgsFinder(Node node) { + this.rootNode = node.getRootNode(); + assert rootNode instanceof PRootNode; + } + + public ArgumentListObject collectArgs() { + List arguments = new LinkedList<>(); + + NodeUtil.findAllNodeInstances(rootNode, ReadArgumentNode.class).forEach(readArgumentNode -> { + WriteIdentifierNode identifierNode = NodeUtil.findParent(readArgumentNode, WriteIdentifierNode.class); + if (identifierNode != null) { + arguments.add(identifierNode.getIdentifier().toString()); + } + }); + + return new ArgumentListObject(arguments.toArray(new String[0])); + } + + @ExportLibrary(InteropLibrary.class) + static final class ArgumentListObject implements TruffleObject { + final String[] args; + + private ArgumentListObject(String[] args) { + this.args = args; + } + + @SuppressWarnings("unused") + @ExportMessage + boolean hasMembers() { + return true; + } + + @SuppressWarnings("unused") + @ExportMessage + @TruffleBoundary + Object getMembers(boolean includeInternal) { + return new InteropArray(args); + } + } + +}