Skip to content

Commit e18d712

Browse files
committed
support for function construction (e.g., types.FunctionType(...))
1 parent 88771f3 commit e18d712

File tree

3 files changed

+98
-10
lines changed

3 files changed

+98
-10
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@
6868
import com.oracle.graal.python.builtins.objects.bytes.BytesUtils;
6969
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
7070
import com.oracle.graal.python.builtins.objects.bytes.PIBytesLike;
71+
import com.oracle.graal.python.builtins.objects.cell.PCell;
7172
import com.oracle.graal.python.builtins.objects.cext.CExtNodes;
7273
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
74+
import com.oracle.graal.python.builtins.objects.code.PCode;
7375
import com.oracle.graal.python.builtins.objects.common.HashingStorage.DictEntry;
7476
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes;
7577
import com.oracle.graal.python.builtins.objects.common.PHashingCollection;
@@ -1480,9 +1482,19 @@ public PZip zip(PythonClass cls, Object[] args,
14801482
public abstract static class FunctionNode extends PythonBuiltinNode {
14811483

14821484
@Specialization
1485+
public PFunction function(PythonClass cls, PCode code, PDict globals, String name, @SuppressWarnings("unused") PNone defaultArgs, @SuppressWarnings("unused") PNone closure) {
1486+
return factory().createFunction(name, cls.getName(), code.getArity(), code.getRootCallTarget(), code.getFrameDescriptor(), globals, null);
1487+
}
1488+
1489+
@Specialization
1490+
public PFunction function(PythonClass cls, PCode code, PDict globals, String name, @SuppressWarnings("unused") PTuple defaultArgs, PTuple closure) {
1491+
return factory().createFunction(name, cls.getName(), code.getArity(), code.getRootCallTarget(), code.getFrameDescriptor(), globals, (PCell[])closure.getArray());
1492+
}
1493+
1494+
@Fallback
14831495
@SuppressWarnings("unused")
1484-
public PFunction function(Object cls, Object code, PDict globals, String name, PTuple defaultArgs, PTuple closure) {
1485-
throw raise(NotImplementedError, "function construction not implemented");
1496+
public PFunction function(Object cls, Object code, Object globals, Object name, Object defaultArgs, Object closure) {
1497+
throw raise(TypeError, "function construction not supported for (%p, %p, %p, %p, %p, %p)", cls, code, globals, name, defaultArgs, closure);
14861498
}
14871499
}
14881500

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.util.List;
4646
import java.util.Set;
4747

48+
import com.oracle.graal.python.builtins.objects.function.Arity;
4849
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
4950
import com.oracle.graal.python.builtins.objects.type.PythonClass;
5051
import com.oracle.graal.python.nodes.ModuleRootNode;
@@ -57,12 +58,19 @@
5758
import com.oracle.graal.python.nodes.generator.GeneratorFunctionRootNode;
5859
import com.oracle.graal.python.runtime.PythonCore;
5960
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
61+
import com.oracle.truffle.api.RootCallTarget;
62+
import com.oracle.truffle.api.Truffle;
63+
import com.oracle.truffle.api.frame.FrameDescriptor;
6064
import com.oracle.truffle.api.nodes.Node;
6165
import com.oracle.truffle.api.nodes.NodeUtil;
6266
import com.oracle.truffle.api.nodes.RootNode;
6367
import com.oracle.truffle.api.source.SourceSection;
6468

6569
public class PCode extends PythonBuiltinObject {
70+
private final long FLAG_POS_GENERATOR = 5;
71+
private final long FLAG_POS_VAR_ARGS = 2;
72+
private final long FLAG_POS_VAR_KW_ARGS = 3;
73+
6674
private final RootNode rootNode;
6775
private final PythonCore core;
6876

@@ -101,6 +109,11 @@ public class PCode extends PythonBuiltinObject {
101109
// tuple of names of cell variables (referenced by containing scopes)
102110
private Object[] cellvars;
103111

112+
// internal cache for keyword names
113+
private Arity.KeywordName[] keywordNames;
114+
// internal cache for the FrameDescriptor
115+
private FrameDescriptor frameDescriptor;
116+
104117
public PCode(PythonClass cls, RootNode rootNode, PythonCore core) {
105118
super(cls);
106119
this.rootNode = rootNode;
@@ -223,17 +236,17 @@ private void extractArgStats() {
223236
this.flags = 0;
224237
RootNode funcRootNode = rootNode;
225238
if (funcRootNode instanceof GeneratorFunctionRootNode) {
226-
flags |= (1 << 5);
239+
flags |= (1 << FLAG_POS_GENERATOR);
227240
funcRootNode = ((GeneratorFunctionRootNode) funcRootNode).getFunctionRootNode();
228241
}
229242

230243
// 0x04 - *arguments
231244
if (NodeUtil.findAllNodeInstances(funcRootNode, ReadVarArgsNode.class).size() == 1) {
232-
flags |= (1 << 2);
245+
flags |= (1 << FLAG_POS_VAR_ARGS);
233246
}
234247
// 0x08 - **keywords
235248
if (NodeUtil.findAllNodeInstances(funcRootNode, ReadVarKeywordsNode.class).size() == 1) {
236-
flags |= (1 << 3);
249+
flags |= (1 << FLAG_POS_VAR_KW_ARGS);
237250
}
238251

239252
this.freevars = extractFreeVars(rootNode);
@@ -242,6 +255,7 @@ private void extractArgStats() {
242255
Set<String> cellVarsSet = asSet((String[]) cellvars);
243256

244257
List<ReadKeywordNode> readKeywordNodes = NodeUtil.findAllNodeInstances(funcRootNode, ReadKeywordNode.class);
258+
keywordNames = new Arity.KeywordName[readKeywordNodes.size()];
245259
List<ReadIndexedArgumentNode> readIndexedArgumentNodes = NodeUtil.findAllNodeInstances(funcRootNode, ReadIndexedArgumentNode.class);
246260

247261
Set<String> kwNames = getKeywordArgumentNames(readKeywordNodes);
@@ -254,7 +268,9 @@ private void extractArgStats() {
254268
this.argcount = readIndexedArgumentNodes.size();
255269
this.kwonlyargcount = 0;
256270

257-
for (ReadKeywordNode kwNode : readKeywordNodes) {
271+
for(int i = 0; i < readKeywordNodes.size(); i++) {
272+
ReadKeywordNode kwNode = readKeywordNodes.get(i);
273+
keywordNames[i++] = new Arity.KeywordName(kwNode.getName(), kwNode.isRequired());
258274
if (!kwNode.canBePositional()) {
259275
kwonlyargcount++;
260276
}
@@ -375,4 +391,58 @@ public Object getNames() {
375391
public Object getLnotab() {
376392
return lnotab;
377393
}
394+
395+
public Arity.KeywordName[] getKeywordNames() {
396+
if (keywordNames == null && rootNode != null) {
397+
extractArgStats();
398+
}
399+
return keywordNames;
400+
}
401+
402+
public boolean isGenerator() {
403+
long flags = getFlags();
404+
return (flags & (1 << FLAG_POS_GENERATOR)) > 0;
405+
}
406+
407+
public boolean takesVarArgs() {
408+
long flags = getFlags();
409+
return (flags & (1 << FLAG_POS_VAR_ARGS)) > 0;
410+
}
411+
412+
public boolean takesVarKeywordArgs() {
413+
long flags = getFlags();
414+
return (flags & (1 << FLAG_POS_VAR_KW_ARGS)) > 0;
415+
}
416+
417+
public Arity getArity() {
418+
return new Arity(this.getName(), this.getArgcount(), this.getArgcount() + this.getKwonlyargcount(), this.takesVarKeywordArgs(), this.takesVarArgs(), this.getKeywordNames());
419+
}
420+
421+
@TruffleBoundary
422+
private FrameDescriptor createFrameDescriptor() {
423+
FrameDescriptor fd = new FrameDescriptor();
424+
for (Object identifier: varnames) {
425+
fd.addFrameSlot(identifier);
426+
}
427+
return fd;
428+
}
429+
430+
public FrameDescriptor getFrameDescriptor() {
431+
if (frameDescriptor == null) {
432+
if (rootNode != null) {
433+
frameDescriptor = rootNode.getFrameDescriptor();
434+
} else {
435+
frameDescriptor = createFrameDescriptor();
436+
}
437+
}
438+
return frameDescriptor;
439+
}
440+
441+
@TruffleBoundary
442+
public RootCallTarget getRootCallTarget() {
443+
if (rootNode != null) {
444+
return Truffle.getRuntime().createCallTarget(rootNode);
445+
}
446+
return null;
447+
}
378448
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/Arity.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ public class Arity {
5050
@CompilationFinal(dimensions = 1) private final String[] parameterIds;
5151
@CompilationFinal(dimensions = 1) private final KeywordName[] keywordNames;
5252

53+
public Arity(String functionName, int minNumOfPositionalArgs, int maxNumOfPositionalArgs,
54+
boolean takesVarKeywordArgs, boolean takesVarArgs,
55+
KeywordName[] keywordNames) {
56+
this(functionName, minNumOfPositionalArgs, maxNumOfPositionalArgs,
57+
takesVarKeywordArgs, takesVarArgs, false,
58+
null, keywordNames);
59+
}
60+
5361
public Arity(String functionName, int minNumOfPositionalArgs, int maxNumOfPositionalArgs,
5462
boolean takesVarKeywordArgs, boolean takesVarArgs,
5563
List<KeywordName> keywordNames) {
@@ -85,13 +93,11 @@ public Arity(String functionName, int minNumOfPositionalArgs, int maxNumOfPositi
8593
}
8694

8795
public static Arity createOneArgumentWithVarKwArgs(String functionName) {
88-
return new Arity(functionName, 1, 1,
89-
true, false, null);
96+
return new Arity(functionName, 1, 1, true, false, (KeywordName[]) null);
9097
}
9198

9299
public static Arity createVarArgsAndKwArgsOnly(String functionName) {
93-
return new Arity(functionName, 0, 0,
94-
true, true, null);
100+
return new Arity(functionName, 0, 0, true, true, (KeywordName[]) null);
95101
}
96102

97103
@TruffleBoundary

0 commit comments

Comments
 (0)