com.oracle.graal.python.builtins.modules.BuiltinFunctions Maven / Gradle / Ivy
/*
* Copyright (c) 2017, 2023, Oracle and/or its affiliates.
* Copyright (c) 2013, Regents of the University of California
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.oracle.graal.python.builtins.modules;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.DeprecationWarning;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RuntimeError;
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_FLUSH;
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_WRITE;
import static com.oracle.graal.python.builtins.objects.PNone.NO_VALUE;
import static com.oracle.graal.python.builtins.objects.PNotImplemented.NOT_IMPLEMENTED;
import static com.oracle.graal.python.compiler.RaisePythonExceptionErrorCallback.raiseSyntaxError;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ABS;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ALL;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ANY;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ASCII;
import static com.oracle.graal.python.nodes.BuiltinNames.J_BIN;
import static com.oracle.graal.python.nodes.BuiltinNames.J_BREAKPOINT;
import static com.oracle.graal.python.nodes.BuiltinNames.J_BUILTINS;
import static com.oracle.graal.python.nodes.BuiltinNames.J_CALLABLE;
import static com.oracle.graal.python.nodes.BuiltinNames.J_CHR;
import static com.oracle.graal.python.nodes.BuiltinNames.J_COMPILE;
import static com.oracle.graal.python.nodes.BuiltinNames.J_DELATTR;
import static com.oracle.graal.python.nodes.BuiltinNames.J_DIR;
import static com.oracle.graal.python.nodes.BuiltinNames.J_DIVMOD;
import static com.oracle.graal.python.nodes.BuiltinNames.J_EVAL;
import static com.oracle.graal.python.nodes.BuiltinNames.J_EXEC;
import static com.oracle.graal.python.nodes.BuiltinNames.J_FORMAT;
import static com.oracle.graal.python.nodes.BuiltinNames.J_GETATTR;
import static com.oracle.graal.python.nodes.BuiltinNames.J_HASATTR;
import static com.oracle.graal.python.nodes.BuiltinNames.J_HASH;
import static com.oracle.graal.python.nodes.BuiltinNames.J_HEX;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ID;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ISINSTANCE;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ISSUBCLASS;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ITER;
import static com.oracle.graal.python.nodes.BuiltinNames.J_LEN;
import static com.oracle.graal.python.nodes.BuiltinNames.J_MAX;
import static com.oracle.graal.python.nodes.BuiltinNames.J_MIN;
import static com.oracle.graal.python.nodes.BuiltinNames.J_NEXT;
import static com.oracle.graal.python.nodes.BuiltinNames.J_OCT;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ORD;
import static com.oracle.graal.python.nodes.BuiltinNames.J_POW;
import static com.oracle.graal.python.nodes.BuiltinNames.J_PRINT;
import static com.oracle.graal.python.nodes.BuiltinNames.J_REPR;
import static com.oracle.graal.python.nodes.BuiltinNames.J_ROUND;
import static com.oracle.graal.python.nodes.BuiltinNames.J_SETATTR;
import static com.oracle.graal.python.nodes.BuiltinNames.J_SORTED;
import static com.oracle.graal.python.nodes.BuiltinNames.J_SUM;
import static com.oracle.graal.python.nodes.BuiltinNames.J___BUILD_CLASS__;
import static com.oracle.graal.python.nodes.BuiltinNames.T_BREAKPOINTHOOK;
import static com.oracle.graal.python.nodes.BuiltinNames.T_EVAL;
import static com.oracle.graal.python.nodes.BuiltinNames.T_EXEC;
import static com.oracle.graal.python.nodes.BuiltinNames.T_STDOUT;
import static com.oracle.graal.python.nodes.BuiltinNames.T_SYS;
import static com.oracle.graal.python.nodes.BuiltinNames.T___BUILTINS__;
import static com.oracle.graal.python.nodes.BuiltinNames.T___DEBUG__;
import static com.oracle.graal.python.nodes.BuiltinNames.T___GRAALPYTHON__;
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___DICT__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___FORMAT__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___MRO_ENTRIES__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___NEXT__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___ROUND__;
import static com.oracle.graal.python.nodes.StringLiterals.T_EMPTY_STRING;
import static com.oracle.graal.python.nodes.StringLiterals.T_FALSE;
import static com.oracle.graal.python.nodes.StringLiterals.T_MINUS;
import static com.oracle.graal.python.nodes.StringLiterals.T_NEWLINE;
import static com.oracle.graal.python.nodes.StringLiterals.T_NONE;
import static com.oracle.graal.python.nodes.StringLiterals.T_SPACE;
import static com.oracle.graal.python.nodes.StringLiterals.T_STRICT;
import static com.oracle.graal.python.nodes.StringLiterals.T_STRING_SOURCE;
import static com.oracle.graal.python.nodes.StringLiterals.T_TRUE;
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached;
import static com.oracle.graal.python.util.PythonUtils.tsLiteral;
import static com.oracle.graal.python.util.PythonUtils.tsbCapacity;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.nio.charset.CodingErrorAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import com.oracle.graal.python.PythonFileDetector;
import com.oracle.graal.python.PythonLanguage;
import com.oracle.graal.python.annotations.ArgumentClinic;
import com.oracle.graal.python.builtins.Builtin;
import com.oracle.graal.python.builtins.CoreFunctions;
import com.oracle.graal.python.builtins.Python3Core;
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
import com.oracle.graal.python.builtins.PythonBuiltins;
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.HexNodeFactory;
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.OctNodeFactory;
import com.oracle.graal.python.builtins.modules.WarningsModuleBuiltins.WarnNode;
import com.oracle.graal.python.builtins.modules.ast.AstModuleBuiltins;
import com.oracle.graal.python.builtins.modules.io.IOModuleBuiltins;
import com.oracle.graal.python.builtins.modules.io.IONodes;
import com.oracle.graal.python.builtins.objects.PNone;
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary;
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAcquireLibrary;
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
import com.oracle.graal.python.builtins.objects.code.CodeNodes;
import com.oracle.graal.python.builtins.objects.code.PCode;
import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage;
import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes;
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetItem;
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetIterator;
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIterator;
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIteratorKey;
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIteratorNext;
import com.oracle.graal.python.builtins.objects.common.PHashingCollection;
import com.oracle.graal.python.builtins.objects.common.SequenceNodes.GetObjectArrayNode;
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
import com.oracle.graal.python.builtins.objects.dict.PDict;
import com.oracle.graal.python.builtins.objects.floats.FloatBuiltins;
import com.oracle.graal.python.builtins.objects.frame.PFrame;
import com.oracle.graal.python.builtins.objects.function.PArguments;
import com.oracle.graal.python.builtins.objects.function.PFunction;
import com.oracle.graal.python.builtins.objects.function.PKeyword;
import com.oracle.graal.python.builtins.objects.ints.PInt;
import com.oracle.graal.python.builtins.objects.list.ListBuiltins;
import com.oracle.graal.python.builtins.objects.list.ListBuiltins.ListSortNode;
import com.oracle.graal.python.builtins.objects.list.PList;
import com.oracle.graal.python.builtins.objects.module.PythonModule;
import com.oracle.graal.python.builtins.objects.object.ObjectNodes;
import com.oracle.graal.python.builtins.objects.object.PythonObject;
import com.oracle.graal.python.builtins.objects.str.PString;
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
import com.oracle.graal.python.builtins.objects.type.TypeBuiltins;
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode;
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
import com.oracle.graal.python.compiler.Compiler;
import com.oracle.graal.python.compiler.RaisePythonExceptionErrorCallback;
import com.oracle.graal.python.lib.GetNextNode;
import com.oracle.graal.python.lib.PyCallableCheckNode;
import com.oracle.graal.python.lib.PyEvalGetGlobals;
import com.oracle.graal.python.lib.PyEvalGetLocals;
import com.oracle.graal.python.lib.PyMappingCheckNode;
import com.oracle.graal.python.lib.PyNumberAsSizeNode;
import com.oracle.graal.python.lib.PyNumberIndexNode;
import com.oracle.graal.python.lib.PyObjectAsciiNode;
import com.oracle.graal.python.lib.PyObjectCallMethodObjArgs;
import com.oracle.graal.python.lib.PyObjectDir;
import com.oracle.graal.python.lib.PyObjectGetAttr;
import com.oracle.graal.python.lib.PyObjectGetIter;
import com.oracle.graal.python.lib.PyObjectHashNode;
import com.oracle.graal.python.lib.PyObjectIsTrueNode;
import com.oracle.graal.python.lib.PyObjectLookupAttr;
import com.oracle.graal.python.lib.PyObjectReprAsObjectNode;
import com.oracle.graal.python.lib.PyObjectSetItem;
import com.oracle.graal.python.lib.PyObjectSizeNode;
import com.oracle.graal.python.lib.PyObjectStrAsObjectNode;
import com.oracle.graal.python.lib.PyObjectStrAsTruffleStringNode;
import com.oracle.graal.python.lib.PyUnicodeFSDecoderNode;
import com.oracle.graal.python.nodes.BuiltinNames;
import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.PGuards;
import com.oracle.graal.python.nodes.PNodeWithContext;
import com.oracle.graal.python.nodes.PNodeWithRaise;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.SpecialAttributeNames;
import com.oracle.graal.python.nodes.SpecialMethodNames;
import com.oracle.graal.python.nodes.StringLiterals;
import com.oracle.graal.python.nodes.argument.ReadArgumentNode;
import com.oracle.graal.python.nodes.attributes.DeleteAttributeNode;
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
import com.oracle.graal.python.nodes.builtins.ListNodes;
import com.oracle.graal.python.nodes.builtins.ListNodes.ConstructListNode;
import com.oracle.graal.python.nodes.bytecode.GetAIterNode;
import com.oracle.graal.python.nodes.bytecode.PBytecodeRootNode;
import com.oracle.graal.python.nodes.call.CallDispatchNode;
import com.oracle.graal.python.nodes.call.CallNode;
import com.oracle.graal.python.nodes.call.GenericInvokeNode;
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
import com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode;
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
import com.oracle.graal.python.nodes.call.special.LookupAndCallTernaryNode;
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodSlotNode;
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
import com.oracle.graal.python.nodes.expression.BinaryArithmetic;
import com.oracle.graal.python.nodes.expression.BinaryArithmetic.AddNode;
import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
import com.oracle.graal.python.nodes.expression.BinaryOpNode;
import com.oracle.graal.python.nodes.expression.CoerceToBooleanNode;
import com.oracle.graal.python.nodes.expression.TernaryArithmetic;
import com.oracle.graal.python.nodes.frame.GetFrameLocalsNode;
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonClinicBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryClinicBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
import com.oracle.graal.python.nodes.object.GetClassNode;
import com.oracle.graal.python.nodes.object.GetClassNode.GetPythonObjectClassNode;
import com.oracle.graal.python.nodes.object.GetOrCreateDictNode;
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
import com.oracle.graal.python.nodes.util.CannotCastException;
import com.oracle.graal.python.nodes.util.CastToJavaLongExactNode;
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
import com.oracle.graal.python.pegparser.AbstractParser;
import com.oracle.graal.python.pegparser.ErrorCallback;
import com.oracle.graal.python.pegparser.FutureFeature;
import com.oracle.graal.python.pegparser.InputType;
import com.oracle.graal.python.pegparser.Parser;
import com.oracle.graal.python.pegparser.sst.ModTy;
import com.oracle.graal.python.pegparser.tokenizer.SourceRange;
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.PythonOptions;
import com.oracle.graal.python.runtime.exception.PException;
import com.oracle.graal.python.runtime.exception.PythonErrorType;
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
import com.oracle.graal.python.runtime.sequence.storage.BoolSequenceStorage;
import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage;
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
import com.oracle.graal.python.util.CharsetMapping;
import com.oracle.graal.python.util.PythonUtils;
import com.oracle.graal.python.util.Supplier;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.TruffleLanguage.Env;
import com.oracle.truffle.api.debug.Debugger;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Cached.Exclusive;
import com.oracle.truffle.api.dsl.Cached.Shared;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.GenerateCached;
import com.oracle.truffle.api.dsl.GenerateInline;
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
import com.oracle.truffle.api.dsl.Idempotent;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.NeverDefault;
import com.oracle.truffle.api.dsl.ReportPolymorphism;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.dsl.TypeSystemReference;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.ExplodeLoop.LoopExplosionKind;
import com.oracle.truffle.api.nodes.LoopNode;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
import com.oracle.truffle.api.profiles.InlinedCountingConditionProfile;
import com.oracle.truffle.api.profiles.InlinedLoopConditionProfile;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.strings.TruffleString;
import com.oracle.truffle.api.strings.TruffleString.Encoding;
import com.oracle.truffle.api.strings.TruffleStringBuilder;
import com.oracle.truffle.api.utilities.TriState;
@CoreFunctions(defineModule = J_BUILTINS, isEager = true)
public final class BuiltinFunctions extends PythonBuiltins {
@Override
protected List> getNodeFactories() {
return BuiltinFunctionsFactory.getFactories();
}
@Override
public void initialize(Python3Core core) {
addBuiltinConstant(T___GRAALPYTHON__, core.lookupBuiltinModule(T___GRAALPYTHON__));
addBuiltinConstant(T_NONE, PNone.NONE);
addBuiltinConstant(T_FALSE, false);
addBuiltinConstant(T_TRUE, true);
super.initialize(core);
}
@Override
public void postInitialize(Python3Core core) {
super.postInitialize(core);
PythonModule builtinsModule = core.lookupBuiltinModule(BuiltinNames.T_BUILTINS);
builtinsModule.setAttribute(T___DEBUG__, !core.getContext().getOption(PythonOptions.PythonOptimizeFlag));
}
// abs(x)
@Builtin(name = J_ABS, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
public abstract static class AbsNode extends PythonUnaryBuiltinNode {
@Specialization
public int absBoolean(boolean arg) {
return arg ? 1 : 0;
}
@Specialization
public double absDouble(double arg) {
return Math.abs(arg);
}
@Specialization
public Object absObject(VirtualFrame frame, Object object,
@Cached("create(T___ABS__)") LookupAndCallUnaryNode callAbs) {
Object result = callAbs.executeObject(frame, object);
if (result == NO_VALUE) {
throw raise(TypeError, ErrorMessages.BAD_OPERAND_FOR, "", "abs()", object);
}
return result;
}
}
enum AnyOrAllNodeType {
ALL,
ANY
}
/**
* Common class for all() and any() operations, as their logic and behaviors are very similar.
*/
@GenerateInline
@GenerateCached(false)
abstract static class AllOrAnySequenceStorageNode extends PNodeWithContext {
abstract boolean execute(VirtualFrame frame, Node inliningTarget, SequenceStorage storageObj, AnyOrAllNodeType nodeType);
@Specialization
static boolean doBoolSequence(VirtualFrame frame, Node inliningTarget, BoolSequenceStorage sequenceStorage, AnyOrAllNodeType nodeType,
@Shared @Cached InlinedLoopConditionProfile loopConditionProfile,
@Shared @Cached InlinedCountingConditionProfile earlyExitProfile,
@Shared @Cached PyObjectIsTrueNode isTrueNode) {
boolean[] internalArray = sequenceStorage.getInternalBoolArray();
int seqLength = sequenceStorage.length();
for (int i = 0; loopConditionProfile.profile(inliningTarget, i < seqLength); i++) {
if (nodeType == AnyOrAllNodeType.ALL && earlyExitProfile.profile(inliningTarget, !isTrueNode.execute(frame, inliningTarget, internalArray[i]))) {
LoopNode.reportLoopCount(inliningTarget, i);
return false;
} else if (nodeType == AnyOrAllNodeType.ANY && earlyExitProfile.profile(inliningTarget, isTrueNode.execute(frame, inliningTarget, internalArray[i]))) {
LoopNode.reportLoopCount(inliningTarget, i);
return true;
}
}
LoopNode.reportLoopCount(inliningTarget, seqLength);
return nodeType == AnyOrAllNodeType.ALL;
}
@Specialization
static boolean doIntSequence(VirtualFrame frame, Node inliningTarget, IntSequenceStorage sequenceStorage, AnyOrAllNodeType nodeType,
@Shared @Cached InlinedLoopConditionProfile loopConditionProfile,
@Shared @Cached InlinedCountingConditionProfile earlyExitProfile,
@Shared @Cached PyObjectIsTrueNode isTrueNode) {
int[] internalArray = sequenceStorage.getInternalIntArray();
int seqLength = sequenceStorage.length();
for (int i = 0; loopConditionProfile.profile(inliningTarget, i < seqLength); i++) {
if (nodeType == AnyOrAllNodeType.ALL && earlyExitProfile.profile(inliningTarget, !isTrueNode.execute(frame, inliningTarget, internalArray[i]))) {
LoopNode.reportLoopCount(inliningTarget, i);
return false;
} else if (nodeType == AnyOrAllNodeType.ANY && earlyExitProfile.profile(inliningTarget, isTrueNode.execute(frame, inliningTarget, internalArray[i]))) {
LoopNode.reportLoopCount(inliningTarget, i);
return true;
}
}
LoopNode.reportLoopCount(inliningTarget, seqLength);
return nodeType == AnyOrAllNodeType.ALL;
}
@Specialization
static boolean doGenericSequence(VirtualFrame frame, Node inliningTarget, SequenceStorage sequenceStorage, AnyOrAllNodeType nodeType,
@Shared @Cached InlinedLoopConditionProfile loopConditionProfile,
@Shared @Cached InlinedCountingConditionProfile earlyExitProfile,
@Shared @Cached PyObjectIsTrueNode isTrueNode) {
Object[] internalArray = sequenceStorage.getInternalArray();
int seqLength = sequenceStorage.length();
for (int i = 0; loopConditionProfile.profile(inliningTarget, i < seqLength); i++) {
if (nodeType == AnyOrAllNodeType.ALL && earlyExitProfile.profile(inliningTarget, !isTrueNode.execute(frame, inliningTarget, internalArray[i]))) {
LoopNode.reportLoopCount(inliningTarget, i);
return false;
} else if (nodeType == AnyOrAllNodeType.ANY && earlyExitProfile.profile(inliningTarget, isTrueNode.execute(frame, inliningTarget, internalArray[i]))) {
LoopNode.reportLoopCount(inliningTarget, i);
return true;
}
}
LoopNode.reportLoopCount(inliningTarget, seqLength);
return nodeType == AnyOrAllNodeType.ALL;
}
}
/**
* Common class for all() and any() operations, as their logic and behaviors are very similar.
*/
@GenerateInline(false) // footprint reduction 68 -> 50
abstract static class AllOrAnyHashingStorageNode extends PNodeWithContext {
abstract boolean execute(Frame frame, HashingStorage storageObj, AnyOrAllNodeType nodeType);
@Specialization
protected boolean doHashStorage(VirtualFrame frame, HashingStorage hashingStorage, AnyOrAllNodeType nodeType,
@Bind("this") Node inliningTarget,
@Cached PyObjectIsTrueNode isTrueNode,
@Cached InlinedLoopConditionProfile loopConditionProfile,
@Cached HashingStorageGetIterator getIter,
@Cached HashingStorageIteratorNext getIterNext,
@Cached HashingStorageIteratorKey getIterKey) {
HashingStorageIterator it = getIter.execute(inliningTarget, hashingStorage);
while (loopConditionProfile.profile(inliningTarget, getIterNext.execute(inliningTarget, hashingStorage, it))) {
Object key = getIterKey.execute(inliningTarget, hashingStorage, it);
if (nodeType == AnyOrAllNodeType.ALL) {
if (!isTrueNode.execute(frame, inliningTarget, key)) {
return false;
}
} else if (nodeType == AnyOrAllNodeType.ANY && isTrueNode.execute(frame, inliningTarget, key)) {
return true;
}
}
return nodeType == AnyOrAllNodeType.ALL;
}
}
@Builtin(name = J_ALL, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
public abstract static class AllNode extends PythonUnaryBuiltinNode {
@Specialization(guards = "cannotBeOverridden(object, inliningTarget, getClassNode)")
static boolean doList(VirtualFrame frame, PList object,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetPythonObjectClassNode getClassNode,
@Shared("allOrAnySeqNode") @Cached AllOrAnySequenceStorageNode allOrAnyNode) {
return allOrAnyNode.execute(frame, inliningTarget, object.getSequenceStorage(), AnyOrAllNodeType.ALL);
}
@Specialization(guards = "cannotBeOverridden(object, inliningTarget, getClassNode)")
static boolean doTuple(VirtualFrame frame, PTuple object,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetPythonObjectClassNode getClassNode,
@Shared("allOrAnySeqNode") @Cached AllOrAnySequenceStorageNode allOrAnyNode) {
return allOrAnyNode.execute(frame, inliningTarget, object.getSequenceStorage(), AnyOrAllNodeType.ALL);
}
@Specialization(guards = "cannotBeOverridden(object, inliningTarget, getClassNode)")
static boolean doHashColl(VirtualFrame frame, PHashingCollection object,
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetPythonObjectClassNode getClassNode,
@Cached AllOrAnyHashingStorageNode allOrAnyNode) {
return allOrAnyNode.execute(frame, object.getDictStorage(), AnyOrAllNodeType.ALL);
}
@Specialization
@SuppressWarnings("truffle-static-method")
boolean doObject(VirtualFrame frame, Object object,
@Bind("this") Node inliningTarget,
@Cached PyObjectGetIter getIter,
@Cached GetNextNode nextNode,
@Cached IsBuiltinObjectProfile errorProfile,
@Cached PyObjectIsTrueNode isTrueNode) {
Object iterator = getIter.execute(frame, inliningTarget, object);
int nbrIter = 0;
while (true) {
try {
Object next = nextNode.execute(frame, iterator);
nbrIter++;
if (!isTrueNode.execute(frame, inliningTarget, next)) {
return false;
}
} catch (PException e) {
e.expectStopIteration(inliningTarget, errorProfile);
break;
} finally {
LoopNode.reportLoopCount(this, nbrIter);
}
}
return true;
}
}
@Builtin(name = J_ANY, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
public abstract static class AnyNode extends PythonUnaryBuiltinNode {
@Specialization(guards = "cannotBeOverridden(object, inliningTarget, getClassNode)")
static boolean doList(VirtualFrame frame, PList object,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetPythonObjectClassNode getClassNode,
@Shared("allOrAnySeqNode") @Cached AllOrAnySequenceStorageNode allOrAnyNode) {
return allOrAnyNode.execute(frame, inliningTarget, object.getSequenceStorage(), AnyOrAllNodeType.ANY);
}
@Specialization(guards = "cannotBeOverridden(object, inliningTarget, getClassNode)")
static boolean doTuple(VirtualFrame frame, PTuple object,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetPythonObjectClassNode getClassNode,
@Shared("allOrAnySeqNode") @Cached AllOrAnySequenceStorageNode allOrAnyNode) {
return allOrAnyNode.execute(frame, inliningTarget, object.getSequenceStorage(), AnyOrAllNodeType.ANY);
}
@Specialization(guards = "cannotBeOverridden(object, inliningTarget, getClassNode)")
static boolean doHashColl(VirtualFrame frame, PHashingCollection object,
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getClassNode") @Cached GetPythonObjectClassNode getClassNode,
@Cached AllOrAnyHashingStorageNode allOrAnyNode) {
return allOrAnyNode.execute(frame, object.getDictStorage(), AnyOrAllNodeType.ANY);
}
@Specialization
@SuppressWarnings("truffle-static-method")
boolean doObject(VirtualFrame frame, Object object,
@Bind("this") Node inliningTarget,
@Cached PyObjectGetIter getIter,
@Cached GetNextNode nextNode,
@Cached IsBuiltinObjectProfile errorProfile,
@Cached PyObjectIsTrueNode isTrueNode) {
Object iterator = getIter.execute(frame, inliningTarget, object);
int nbrIter = 0;
while (true) {
try {
Object next = nextNode.execute(frame, iterator);
nbrIter++;
if (isTrueNode.execute(frame, inliningTarget, next)) {
return true;
}
} catch (PException e) {
e.expectStopIteration(inliningTarget, errorProfile);
break;
} finally {
LoopNode.reportLoopCount(this, nbrIter);
}
}
return false;
}
}
// bin(object)
@Builtin(name = J_BIN, minNumOfPositionalArgs = 1)
@TypeSystemReference(PythonArithmeticTypes.class)
@GenerateNodeFactory
public abstract static class BinNode extends PythonUnaryBuiltinNode {
static final TruffleString T_BIN_PREFIX = tsLiteral("0b");
static final TruffleString T_HEX_PREFIX = tsLiteral("0x");
static final TruffleString T_OCT_PREFIX = tsLiteral("0o");
@TruffleBoundary
protected TruffleString buildString(boolean isNegative, TruffleString number, TruffleStringBuilder.AppendStringNode appendStringNode, TruffleStringBuilder.ToStringNode toStringNode) {
TruffleStringBuilder sb = TruffleStringBuilder.create(TS_ENCODING, tsbCapacity(3) + number.byteLength(TS_ENCODING));
if (isNegative) {
appendStringNode.execute(sb, T_MINUS);
}
appendStringNode.execute(sb, prefix());
appendStringNode.execute(sb, number);
return toStringNode.execute(sb);
}
protected TruffleString prefix() {
return T_BIN_PREFIX;
}
@TruffleBoundary
protected String longToString(long x) {
return Long.toBinaryString(x);
}
@TruffleBoundary
protected String bigToString(BigInteger x) {
return x.toString(2);
}
@TruffleBoundary
protected BigInteger bigAbs(BigInteger x) {
return x.abs();
}
@Specialization
TruffleString doL(long x,
@Bind("this") Node inliningTarget,
@Exclusive @Cached InlinedConditionProfile isMinLong,
@Shared @Cached TruffleString.FromJavaStringNode fromJavaStringNode,
@Shared @Cached TruffleStringBuilder.AppendStringNode appendStringNode,
@Shared @Cached TruffleStringBuilder.ToStringNode toStringNode) {
if (isMinLong.profile(inliningTarget, x == Long.MIN_VALUE)) {
return buildString(true, fromJavaStringNode.execute(bigToString(bigAbs(PInt.longToBigInteger(x))), TS_ENCODING), appendStringNode, toStringNode);
}
return buildString(x < 0, fromJavaStringNode.execute(longToString(Math.abs(x)), TS_ENCODING), appendStringNode, toStringNode);
}
@Specialization
TruffleString doD(double x,
@Cached PRaiseNode raise) {
throw raise.raiseIntegerInterpretationError(x);
}
@Specialization
TruffleString doPI(PInt x,
@Shared @Cached TruffleString.FromJavaStringNode fromJavaStringNode,
@Shared @Cached TruffleStringBuilder.AppendStringNode appendStringNode,
@Shared @Cached TruffleStringBuilder.ToStringNode toStringNode) {
BigInteger value = x.getValue();
return buildString(value.signum() < 0, fromJavaStringNode.execute(bigToString(PInt.abs(value)), TS_ENCODING), appendStringNode, toStringNode);
}
@Specialization(replaces = {"doL", "doD", "doPI"})
@SuppressWarnings("truffle-static-method")
TruffleString doO(VirtualFrame frame, Object x,
@Bind("this") Node inliningTarget,
@Exclusive @Cached InlinedConditionProfile isMinLong,
@Cached PyNumberIndexNode indexNode,
@Cached PyNumberAsSizeNode asSizeNode,
@Cached InlinedBranchProfile isInt,
@Cached InlinedBranchProfile isLong,
@Cached InlinedBranchProfile isPInt,
@Shared @Cached TruffleString.FromJavaStringNode fromJavaStringNode,
@Shared @Cached TruffleStringBuilder.AppendStringNode appendStringNode,
@Shared @Cached TruffleStringBuilder.ToStringNode toStringNode) {
Object index = indexNode.execute(frame, inliningTarget, x);
if (index instanceof Boolean || index instanceof Integer) {
isInt.enter(inliningTarget);
return doL(asSizeNode.executeExact(frame, inliningTarget, index), inliningTarget, isMinLong, fromJavaStringNode, appendStringNode, toStringNode);
} else if (index instanceof Long) {
isLong.enter(inliningTarget);
return doL((long) index, inliningTarget, isMinLong, fromJavaStringNode, appendStringNode, toStringNode);
} else if (index instanceof PInt) {
isPInt.enter(inliningTarget);
return doPI((PInt) index, fromJavaStringNode, appendStringNode, toStringNode);
} else {
CompilerDirectives.transferToInterpreter();
throw raise(PythonBuiltinClassType.NotImplementedError, toTruffleStringUncached("bin/oct/hex with native integer subclasses"));
}
}
}
// oct(object)
@Builtin(name = J_OCT, minNumOfPositionalArgs = 1)
@TypeSystemReference(PythonArithmeticTypes.class)
@GenerateNodeFactory
public abstract static class OctNode extends BinNode {
@Override
@TruffleBoundary
protected String bigToString(BigInteger x) {
return x.toString(8);
}
@Override
@TruffleBoundary
protected String longToString(long x) {
return Long.toOctalString(x);
}
@Override
protected TruffleString prefix() {
return T_OCT_PREFIX;
}
@NeverDefault
public static OctNode create() {
return OctNodeFactory.create();
}
}
// hex(object)
@Builtin(name = J_HEX, minNumOfPositionalArgs = 1)
@TypeSystemReference(PythonArithmeticTypes.class)
@GenerateNodeFactory
public abstract static class HexNode extends BinNode {
@Override
@TruffleBoundary
protected String bigToString(BigInteger x) {
return x.toString(16);
}
@Override
@TruffleBoundary
protected String longToString(long x) {
return Long.toHexString(x);
}
@Override
protected TruffleString prefix() {
return T_HEX_PREFIX;
}
@NeverDefault
public static HexNode create() {
return HexNodeFactory.create();
}
}
// callable(object)
@Builtin(name = J_CALLABLE, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
public abstract static class CallableNode extends PythonBuiltinNode {
@Specialization(guards = "isCallable(callable)")
static boolean doCallable(@SuppressWarnings("unused") Object callable) {
return true;
}
@Specialization
static boolean doGeneric(Object object,
@Bind("this") Node inliningTarget,
@Cached PyCallableCheckNode callableCheck) {
return callableCheck.execute(inliningTarget, object);
}
}
// chr(i)
@Builtin(name = J_CHR, minNumOfPositionalArgs = 1, numOfPositionalOnlyArgs = 1, parameterNames = {"i"})
@GenerateNodeFactory
@ArgumentClinic(name = "i", conversion = ArgumentClinic.ClinicConversion.Int)
public abstract static class ChrNode extends PythonUnaryClinicBuiltinNode {
@Specialization
public TruffleString charFromInt(int arg,
@Cached TruffleString.FromCodePointNode fromCodePointNode) {
if (arg >= 0 && arg <= 1114111) {
return fromCodePointNode.execute(arg, TS_ENCODING, true);
} else {
throw raise(ValueError, ErrorMessages.ARG_NOT_IN_RANGE, "chr()", "0x110000");
}
}
@Override
protected ArgumentClinicProvider getArgumentClinic() {
return BuiltinFunctionsClinicProviders.ChrNodeClinicProviderGen.INSTANCE;
}
}
// hash(object)
@Builtin(name = J_HASH, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
public abstract static class HashNode extends PythonUnaryBuiltinNode {
@Specialization
long hash(VirtualFrame frame, Object object,
@Bind("this") Node inliningTarget,
@Cached PyObjectHashNode hashNode) {
return hashNode.execute(frame, inliningTarget, object);
}
}
// dir([object])
@Builtin(name = J_DIR, minNumOfPositionalArgs = 0, maxNumOfPositionalArgs = 1, numOfPositionalOnlyArgs = 1)
@GenerateNodeFactory
public abstract static class DirNode extends PythonBuiltinNode {
// logic like in 'Objects/object.c: _dir_locals'
@Specialization(guards = "isNoValue(object)")
Object locals(VirtualFrame frame, @SuppressWarnings("unused") Object object,
@Bind("this") Node inliningTarget,
@Cached PyEvalGetLocals getLocals,
@Cached("create(T_KEYS)") LookupAndCallUnaryNode callKeysNode,
@Cached ListBuiltins.ListSortNode sortNode,
@Cached ListNodes.ConstructListNode constructListNode) {
Object localsDict = getLocals.execute(frame, inliningTarget);
Object keysObj = callKeysNode.executeObject(frame, localsDict);
PList list = constructListNode.execute(frame, keysObj);
sortNode.execute(frame, list);
return list;
}
@Specialization(guards = "!isNoValue(object)")
static Object dir(VirtualFrame frame, Object object,
@Bind("this") Node inliningTarget,
@Cached PyObjectDir dir) {
return dir.execute(frame, inliningTarget, object);
}
}
// divmod(a, b)
@Builtin(name = J_DIVMOD, minNumOfPositionalArgs = 2)
@TypeSystemReference(PythonArithmeticTypes.class)
@GenerateNodeFactory
@ImportStatic(BinaryArithmetic.class)
public abstract static class DivModNode extends PythonBinaryBuiltinNode {
@Specialization(guards = "b != 0")
public PTuple doLong(long a, long b) {
return factory().createTuple(new Object[]{Math.floorDiv(a, b), Math.floorMod(a, b)});
}
@Specialization(replaces = "doLong")
public PTuple doLongZero(long a, long b) {
if (b == 0) {
throw raise(PythonErrorType.ZeroDivisionError, ErrorMessages.INTEGER_DIVISION_BY_ZERO);
}
return factory().createTuple(new Object[]{Math.floorDiv(a, b), Math.floorMod(a, b)});
}
@Specialization
public PTuple doDouble(double a, double b) {
if (b == 0) {
throw raise(PythonErrorType.ZeroDivisionError, ErrorMessages.DIVISION_BY_ZERO);
}
double q = Math.floor(a / b);
return factory().createTuple(new Object[]{q, FloatBuiltins.ModNode.mod(a, b)});
}
@Specialization
public Object doObject(VirtualFrame frame, Object a, Object b,
@Cached("DivMod.create()") BinaryOpNode callDivmod) {
return callDivmod.executeObject(frame, a, b);
}
}
// eval(expression, globals=None, locals=None)
@Builtin(name = J_EVAL, minNumOfPositionalArgs = 1, parameterNames = {"expression", "globals", "locals"})
@GenerateNodeFactory
public abstract static class EvalNode extends PythonBuiltinNode {
@Child protected CompileNode compileNode;
@Child private GenericInvokeNode invokeNode = GenericInvokeNode.create();
@Child private GetOrCreateDictNode getOrCreateDictNode;
protected void assertNoFreeVars(PCode code) {
Object[] freeVars = code.getFreeVars();
if (freeVars.length > 0) {
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.CODE_OBJ_NO_FREE_VARIABLES, getMode());
}
}
protected TruffleString getMode() {
return T_EVAL;
}
protected boolean isMapping(Node inliningTarget, PyMappingCheckNode mappingCheckNode, Object object) {
return mappingCheckNode.execute(inliningTarget, object);
}
protected boolean isAnyNone(Object object) {
return object instanceof PNone;
}
protected PCode createAndCheckCode(VirtualFrame frame, Object source) {
PCode code = getCompileNode().compile(frame, source, T_STRING_SOURCE, getMode(), -1, -1);
assertNoFreeVars(code);
return code;
}
private static void inheritGlobals(PFrame callerFrame, Object[] args) {
PArguments.setGlobals(args, callerFrame.getGlobals());
}
private static void inheritLocals(Node inliningTarget, PFrame callerFrame, Object[] args, GetFrameLocalsNode getFrameLocalsNode) {
Object callerLocals = getFrameLocalsNode.execute(inliningTarget, callerFrame);
setCustomLocals(args, callerLocals);
}
private static void setCustomLocals(Object[] args, Object locals) {
PArguments.setSpecialArgument(args, locals);
}
private void setBuiltinsInGlobals(VirtualFrame frame, Node inliningTarget, PDict globals, HashingCollectionNodes.SetItemNode setBuiltins, PythonModule builtins) {
if (builtins != null) {
PDict builtinsDict = getOrCreateDictNode(builtins);
setBuiltins.execute(frame, inliningTarget, globals, T___BUILTINS__, builtinsDict);
} else {
// This happens during context initialization
return;
}
}
private void setCustomGlobals(VirtualFrame frame, Node inliningTarget, PDict globals, HashingCollectionNodes.SetItemNode setBuiltins, Object[] args) {
PythonModule builtins = getContext().getBuiltins();
setBuiltinsInGlobals(frame, inliningTarget, globals, setBuiltins, builtins);
PArguments.setGlobals(args, globals);
}
@Specialization
@SuppressWarnings("truffle-static-method")
Object execInheritGlobalsInheritLocals(VirtualFrame frame, Object source, @SuppressWarnings("unused") PNone globals, @SuppressWarnings("unused") PNone locals,
@Bind("this") Node inliningTarget,
@Exclusive @Cached ReadCallerFrameNode readCallerFrameNode,
@Exclusive @Cached CodeNodes.GetCodeCallTargetNode getCt,
@Cached GetFrameLocalsNode getFrameLocalsNode) {
PCode code = createAndCheckCode(frame, source);
PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0);
Object[] args = PArguments.create();
inheritGlobals(callerFrame, args);
inheritLocals(inliningTarget, callerFrame, args, getFrameLocalsNode);
return invokeNode.execute(frame, getCt.execute(inliningTarget, code), args);
}
@Specialization
Object execCustomGlobalsGlobalLocals(VirtualFrame frame, Object source, PDict globals, @SuppressWarnings("unused") PNone locals,
@Bind("this") Node inliningTarget,
@Shared @Cached HashingCollectionNodes.SetItemNode setBuiltins,
@Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt) {
PCode code = createAndCheckCode(frame, source);
Object[] args = PArguments.create();
setCustomGlobals(frame, inliningTarget, globals, setBuiltins, args);
setCustomLocals(args, globals);
RootCallTarget rootCallTarget = getCt.execute(inliningTarget, code);
if (rootCallTarget == null) {
throw raise(ValueError, ErrorMessages.CANNOT_CREATE_CALL_TARGET, code);
}
return invokeNode.execute(frame, rootCallTarget, args);
}
@Specialization(guards = {"isMapping(inliningTarget, mappingCheckNode, locals)"})
@SuppressWarnings("truffle-static-method")
Object execInheritGlobalsCustomLocals(VirtualFrame frame, Object source, @SuppressWarnings("unused") PNone globals, Object locals,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared @Cached PyMappingCheckNode mappingCheckNode,
@Exclusive @Cached ReadCallerFrameNode readCallerFrameNode,
@Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt) {
PCode code = createAndCheckCode(frame, source);
PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0);
Object[] args = PArguments.create();
inheritGlobals(callerFrame, args);
setCustomLocals(args, locals);
return invokeNode.execute(frame, getCt.execute(inliningTarget, code), args);
}
@Specialization(guards = {"isMapping(inliningTarget, mappingCheckNode, locals)"})
@SuppressWarnings("truffle-static-method")
Object execCustomGlobalsCustomLocals(VirtualFrame frame, Object source, PDict globals, Object locals,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared @Cached PyMappingCheckNode mappingCheckNode,
@Shared @Cached HashingCollectionNodes.SetItemNode setBuiltins,
@Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt) {
PCode code = createAndCheckCode(frame, source);
Object[] args = PArguments.create();
setCustomGlobals(frame, inliningTarget, globals, setBuiltins, args);
setCustomLocals(args, locals);
return invokeNode.execute(frame, getCt.execute(inliningTarget, code), args);
}
@Specialization(guards = {"!isAnyNone(globals)", "!isDict(globals)"})
@SuppressWarnings("truffle-static-method")
PNone badGlobals(@SuppressWarnings("unused") Object source, Object globals, @SuppressWarnings("unused") Object locals) {
throw raise(TypeError, ErrorMessages.GLOBALS_MUST_BE_DICT, getMode(), globals);
}
@Specialization(guards = {"isAnyNone(globals) || isDict(globals)", "!isAnyNone(locals)", "!isMapping(inliningTarget, mappingCheckNode, locals)"})
@SuppressWarnings("truffle-static-method")
PNone badLocals(@SuppressWarnings("unused") Object source, @SuppressWarnings("unused") PDict globals, Object locals,
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared @Cached PyMappingCheckNode mappingCheckNode) {
throw raise(TypeError, ErrorMessages.LOCALS_MUST_BE_MAPPING, getMode(), locals);
}
private CompileNode getCompileNode() {
if (compileNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
compileNode = insert(CompileNode.create(false, shouldStripLeadingWhitespace()));
}
return compileNode;
}
private PDict getOrCreateDictNode(PythonObject object) {
if (getOrCreateDictNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
getOrCreateDictNode = insert(GetOrCreateDictNode.create());
}
return getOrCreateDictNode.executeCached(object);
}
protected boolean shouldStripLeadingWhitespace() {
return true;
}
}
@Builtin(name = J_EXEC, minNumOfPositionalArgs = 1, parameterNames = {"source", "globals", "locals"})
@GenerateNodeFactory
abstract static class ExecNode extends EvalNode {
protected abstract Object executeInternal(VirtualFrame frame);
@Override
protected TruffleString getMode() {
return T_EXEC;
}
@Override
public final Object execute(VirtualFrame frame) {
executeInternal(frame);
return PNone.NONE;
}
@Override
protected boolean shouldStripLeadingWhitespace() {
return false;
}
}
// compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
@Builtin(name = J_COMPILE, minNumOfPositionalArgs = 3, parameterNames = {"source", "filename", "mode", "flags", "dont_inherit", "optimize"}, keywordOnlyNames = {"_feature_version"})
@ArgumentClinic(name = "mode", conversion = ArgumentClinic.ClinicConversion.TString)
@ArgumentClinic(name = "flags", conversion = ArgumentClinic.ClinicConversion.Int, defaultValue = "0")
@ArgumentClinic(name = "dont_inherit", conversion = ArgumentClinic.ClinicConversion.IntToBoolean, defaultValue = "false")
@ArgumentClinic(name = "optimize", conversion = ArgumentClinic.ClinicConversion.Int, defaultValue = "-1")
@ArgumentClinic(name = "_feature_version", conversion = ArgumentClinic.ClinicConversion.Int, defaultValue = "-1")
@GenerateNodeFactory
public abstract static class CompileNode extends PythonClinicBuiltinNode {
// code.h
private static final int CO_NESTED = 0x0010;
private static final int CO_FUTURE_DIVISION = 0x20000;
private static final int CO_FUTURE_ABSOLUTE_IMPORT = 0x40000;
private static final int CO_FUTURE_WITH_STATEMENT = 0x80000;
private static final int CO_FUTURE_PRINT_FUNCTION = 0x100000;
private static final int CO_FUTURE_UNICODE_LITERALS = 0x200000;
private static final int CO_FUTURE_BARRY_AS_BDFL = FutureFeature.BARRY_AS_BDFL.flagValue;
private static final int CO_FUTURE_GENERATOR_STOP = 0x800000;
private static final int CO_FUTURE_ANNOTATIONS = FutureFeature.ANNOTATIONS.flagValue;
// compile.h
private static final int PyCF_MASK = CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS |
CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS;
private static final int PyCF_MASK_OBSOLETE = CO_NESTED;
private static final int PyCF_DONT_IMPLY_DEDENT = 0x0200;
public static final int PyCF_ONLY_AST = 0x0400;
public static final int PyCF_TYPE_COMMENTS = 0x1000;
public static final int PyCF_ALLOW_TOP_LEVEL_AWAIT = 0x2000;
private static final int PyCF_ALLOW_INCOMPLETE_INPUT = 0x4000;
private static final int PyCF_COMPILE_MASK = PyCF_ONLY_AST | PyCF_ALLOW_TOP_LEVEL_AWAIT | PyCF_TYPE_COMMENTS | PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT;
/**
* Decides whether this node should attempt to map the filename to a URI for the benefit of
* Truffle tooling
*/
private final boolean mayBeFromFile;
private final boolean lstrip;
public CompileNode(boolean mayBeFromFile, boolean lstrip) {
this.mayBeFromFile = mayBeFromFile;
this.lstrip = lstrip;
}
public CompileNode() {
this.mayBeFromFile = true;
this.lstrip = false;
}
public final PCode compile(VirtualFrame frame, Object source, TruffleString filename, TruffleString mode, int optimize, int featureVersion) {
return (PCode) executeInternal(frame, source, filename, mode, 0, false, optimize, featureVersion);
}
protected abstract Object executeInternal(VirtualFrame frame, Object source, TruffleString filename, TruffleString mode, int flags, boolean dontInherit, int optimize,
int featureVersion);
@Specialization
Object doCompile(VirtualFrame frame, TruffleString expression, TruffleString filename, TruffleString mode, int flags, boolean dontInherit, int optimize,
int featureVersion,
@Shared @Cached ReadCallerFrameNode readCallerFrame) {
if (!dontInherit) {
PFrame fr = readCallerFrame.executeWith(frame, 0);
PCode code = factory().createCode(fr.getTarget());
flags |= code.getFlags() & PyCF_MASK;
}
return compile(expression, filename, mode, flags, dontInherit, optimize, featureVersion);
}
@TruffleBoundary
Object compile(TruffleString expression, TruffleString filename, TruffleString mode, int flags, @SuppressWarnings("unused") boolean dontInherit, int optimize, int featureVersion) {
checkFlags(flags);
checkOptimize(optimize, optimize);
checkSource(expression);
TruffleString code = expression;
PythonContext context = getContext();
InputType type = getParserInputType(mode, flags);
if (type == InputType.FUNCTION_TYPE) {
if ((flags & PyCF_ONLY_AST) == 0) {
throw raise(ValueError, ErrorMessages.COMPILE_MODE_FUNC_TYPE_REQUIED_FLAG_ONLY_AST);
}
}
if (lstrip && !code.isEmpty()) {
int c = code.codePointAtIndexUncached(0, TS_ENCODING);
if (c == ' ' || c == '\t') {
code = code.substringUncached(1, code.codePointLengthUncached(TS_ENCODING) - 1, TS_ENCODING, true);
}
}
if ((flags & PyCF_ONLY_AST) != 0) {
Source source = PythonLanguage.newSource(context, code, filename, mayBeFromFile, PythonLanguage.MIME_TYPE);
RaisePythonExceptionErrorCallback errorCb = new RaisePythonExceptionErrorCallback(source, PythonOptions.isPExceptionWithJavaStacktrace(getLanguage()));
EnumSet compilerFlags = EnumSet.noneOf(AbstractParser.Flags.class);
if ((flags & PyCF_TYPE_COMMENTS) != 0) {
compilerFlags.add(AbstractParser.Flags.TYPE_COMMENTS);
}
if (featureVersion < 0) {
featureVersion = PythonLanguage.MINOR;
}
if (featureVersion < 7) {
compilerFlags.add(AbstractParser.Flags.ASYNC_HACKS);
}
Parser parser = Compiler.createParser(code.toJavaStringUncached(), errorCb, type, compilerFlags, featureVersion);
ModTy mod = (ModTy) parser.parse();
errorCb.triggerDeprecationWarnings();
return AstModuleBuiltins.sst2Obj(getContext(), mod);
}
CallTarget ct;
TruffleString finalCode = code;
Supplier createCode = () -> {
if (type == InputType.FILE) {
Source source = PythonLanguage.newSource(context, finalCode, filename, mayBeFromFile, PythonLanguage.getCompileMimeType(optimize, flags));
return context.getEnv().parsePublic(source);
} else if (type == InputType.EVAL) {
Source source = PythonLanguage.newSource(context, finalCode, filename, mayBeFromFile, PythonLanguage.getEvalMimeType(optimize, flags));
return context.getEnv().parsePublic(source);
} else {
Source source = PythonLanguage.newSource(context, finalCode, filename, mayBeFromFile, PythonLanguage.MIME_TYPE);
return context.getLanguage().parse(context, source, InputType.SINGLE, false, optimize, false, null, FutureFeature.fromFlags(flags));
}
};
if (getContext().isCoreInitialized()) {
ct = createCode.get();
} else {
ct = getContext().getLanguage().cacheCode(filename, createCode);
}
return wrapRootCallTarget((RootCallTarget) ct);
}
@Specialization(limit = "3")
@SuppressWarnings("truffle-static-method")
Object generic(VirtualFrame frame, Object wSource, Object wFilename, TruffleString mode, int flags, @SuppressWarnings("unused") boolean dontInherit, int optimize, int featureVersion,
@CachedLibrary(limit = "3") PythonBufferAcquireLibrary acquireLib,
@CachedLibrary(limit = "3") PythonBufferAccessLibrary bufferLib,
@Bind("this") Node inliningTarget,
@Cached CodecsModuleBuiltins.HandleDecodingErrorNode handleDecodingErrorNode,
@Cached PyObjectStrAsTruffleStringNode asStrNode,
@CachedLibrary("wSource") InteropLibrary interopLib,
@Cached PyUnicodeFSDecoderNode asPath,
@Cached WarnNode warnNode,
@Cached TruffleString.FromByteArrayNode fromByteArrayNode,
@Cached TruffleString.SwitchEncodingNode switchEncodingNode,
@Shared @Cached ReadCallerFrameNode readCallerFrame) {
if (wSource instanceof PCode) {
return wSource;
}
TruffleString filename;
// TODO use PyUnicode_FSDecode
if (acquireLib.hasBuffer(wFilename)) {
Object filenameBuffer = acquireLib.acquireReadonly(wFilename, frame, this);
try {
TruffleString utf8 = fromByteArrayNode.execute(bufferLib.getCopiedByteArray(filenameBuffer), Encoding.UTF_8, false);
filename = switchEncodingNode.execute(utf8, TS_ENCODING);
if (!(wFilename instanceof PBytes)) {
warnNode.warnFormat(frame, null, DeprecationWarning, 1, ErrorMessages.PATH_SHOULD_BE_STR_BYTES_PATHLIKE_NOT_P, wFilename);
}
} finally {
bufferLib.release(filenameBuffer, frame, this);
}
} else {
filename = asPath.execute(frame, wFilename);
}
if (!dontInherit) {
PFrame fr = readCallerFrame.executeWith(frame, 0);
PCode code = factory().createCode(fr.getTarget());
flags |= code.getFlags() & PyCF_MASK;
}
if (AstModuleBuiltins.isAst(getContext(), wSource)) {
ModTy mod = AstModuleBuiltins.obj2sst(getContext(), wSource, getParserInputType(mode, flags));
Source source = PythonUtils.createFakeSource(filename);
RootCallTarget rootCallTarget = getLanguage().compileForBytecodeInterpreter(getContext(), mod, source, false, optimize, null, null, flags);
return wrapRootCallTarget(rootCallTarget);
}
TruffleString source = sourceAsString(frame, inliningTarget, wSource, filename, interopLib, acquireLib, bufferLib, handleDecodingErrorNode, asStrNode, switchEncodingNode);
checkSource(source);
return compile(source, filename, mode, flags, dontInherit, optimize, featureVersion);
}
private PCode wrapRootCallTarget(RootCallTarget rootCallTarget) {
RootNode rootNode = rootCallTarget.getRootNode();
if (rootNode instanceof PBytecodeRootNode) {
((PBytecodeRootNode) rootNode).triggerDeferredDeprecationWarnings();
}
return factory().createCode(rootCallTarget);
}
private void checkSource(TruffleString source) throws PException {
if (source.indexOfCodePointUncached(0, 0, source.codePointLengthUncached(TS_ENCODING), TS_ENCODING) > -1) {
throw raise(ValueError, ErrorMessages.SRC_CODE_CANNOT_CONTAIN_NULL_BYTES);
}
}
private void checkOptimize(int optimize, Object kwOptimize) throws PException {
if (optimize < -1 || optimize > 2) {
throw raise(TypeError, ErrorMessages.INVALID_OPTIMIZE_VALUE, kwOptimize);
}
}
private void checkFlags(int flags) {
if ((flags & ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_COMPILE_MASK)) != 0) {
throw raise(ValueError, ErrorMessages.UNRECOGNIZED_FLAGS);
}
}
private InputType getParserInputType(TruffleString mode, int flags) {
if (mode.equalsUncached(T_EXEC, TS_ENCODING)) {
return InputType.FILE;
} else if (mode.equalsUncached(T_EVAL, TS_ENCODING)) {
return InputType.EVAL;
} else if (mode.equalsUncached(StringLiterals.T_SINGLE, TS_ENCODING)) {
return InputType.SINGLE;
} else if (mode.equalsUncached(StringLiterals.T_FUNC_TYPE, TS_ENCODING)) {
return InputType.FUNCTION_TYPE;
} else {
if ((flags & PyCF_ONLY_AST) != 0) {
throw raise(ValueError, ErrorMessages.COMPILE_MODE_MUST_BE_AST_ONLY);
} else {
throw raise(ValueError, ErrorMessages.COMPILE_MODE_MUST_BE);
}
}
}
// modeled after _Py_SourceAsString
TruffleString sourceAsString(VirtualFrame frame, Node inliningTarget, Object source, TruffleString filename, InteropLibrary interopLib, PythonBufferAcquireLibrary acquireLib,
PythonBufferAccessLibrary bufferLib,
CodecsModuleBuiltins.HandleDecodingErrorNode handleDecodingErrorNode, PyObjectStrAsTruffleStringNode asStrNode, TruffleString.SwitchEncodingNode switchEncodingNode) {
if (interopLib.isString(source)) {
try {
return switchEncodingNode.execute(interopLib.asTruffleString(source), TS_ENCODING);
} catch (UnsupportedMessageException e) {
throw CompilerDirectives.shouldNotReachHere(e);
}
} else {
// cpython checks for bytes and bytearray separately, but we deal with it as
// buffers, since that's fast for us anyway
Object buffer;
try {
buffer = acquireLib.acquireReadonly(source, frame, this);
} catch (PException e) {
throw raise(TypeError, ErrorMessages.ARG_D_MUST_BE_S, "compile()", 1, "string, bytes or AST object");
}
try {
byte[] bytes = bufferLib.getInternalOrCopiedByteArray(source);
int bytesLen = bufferLib.getBufferLength(source);
Charset charset = PythonFileDetector.findEncodingStrict(bytes, bytesLen);
TruffleString pythonEncodingNameFromJavaName = CharsetMapping.getPythonEncodingNameFromJavaName(charset.name());
CodecsModuleBuiltins.TruffleDecoder decoder = new CodecsModuleBuiltins.TruffleDecoder(pythonEncodingNameFromJavaName, charset, bytes, bytesLen, CodingErrorAction.REPORT);
if (!decoder.decodingStep(true)) {
try {
handleDecodingErrorNode.execute(decoder, T_STRICT, factory().createBytes(bytes, bytesLen));
throw CompilerDirectives.shouldNotReachHere();
} catch (PException e) {
throw raiseInvalidSyntax(filename, "(unicode error) %s", asStrNode.execute(frame, inliningTarget, e.getEscapedException()));
}
}
return decoder.getString();
} catch (PythonFileDetector.InvalidEncodingException e) {
throw raiseInvalidSyntax(filename, "(unicode error) %s", e.getEncodingName());
} finally {
bufferLib.release(buffer, frame, this);
}
}
}
@TruffleBoundary
private RuntimeException raiseInvalidSyntax(TruffleString filename, String format, Object... args) {
PythonContext context = getContext();
// Create non-empty source to avoid overwriting the message with "unexpected EOF"
Source source = PythonLanguage.newSource(context, T_SPACE, filename, mayBeFromFile, null);
SourceRange sourceRange = new SourceRange(1, 0, 1, 0);
TruffleString message = toTruffleStringUncached(String.format(format, args));
throw raiseSyntaxError(ErrorCallback.ErrorType.Syntax, sourceRange, message, source, PythonOptions.isPExceptionWithJavaStacktrace(context.getLanguage()));
}
public static CompileNode create(boolean mapFilenameToUri) {
return BuiltinFunctionsFactory.CompileNodeFactory.create(mapFilenameToUri, false, new ReadArgumentNode[]{});
}
public static CompileNode create(boolean mapFilenameToUri, boolean lstrip) {
return BuiltinFunctionsFactory.CompileNodeFactory.create(mapFilenameToUri, lstrip, new ReadArgumentNode[]{});
}
@Override
protected ArgumentClinicProvider getArgumentClinic() {
return BuiltinFunctionsClinicProviders.CompileNodeClinicProviderGen.INSTANCE;
}
}
// delattr(object, name)
@Builtin(name = J_DELATTR, minNumOfPositionalArgs = 2)
@GenerateNodeFactory
abstract static class DelAttrNode extends PythonBinaryBuiltinNode {
@Specialization
Object delattr(VirtualFrame frame, Object object, Object name,
@Bind("this") Node inliningTarget,
@Cached DeleteAttributeNode delNode) {
delNode.execute(frame, inliningTarget, object, name);
return PNone.NONE;
}
}
// getattr(object, name[, default])
@Builtin(name = J_GETATTR, minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3)
@GenerateNodeFactory
abstract static class GetAttrNode extends PythonTernaryBuiltinNode {
@Specialization(guards = "isNoValue(defaultValue)")
static Object getAttrNoDefault(VirtualFrame frame, Object primary, Object nameObj, @SuppressWarnings("unused") Object defaultValue,
@Bind("this") Node inliningTarget,
@Exclusive @Cached CastToTruffleStringNode cast,
@Exclusive @Cached PRaiseNode.Lazy raiseNode,
@Cached PyObjectGetAttr getAttr) {
TruffleString name = castName(inliningTarget, nameObj, cast, raiseNode);
return getAttr.execute(frame, inliningTarget, primary, name);
}
@Specialization(guards = "!isNoValue(defaultValue)")
static Object getAttrWithDefault(VirtualFrame frame, Object primary, Object nameObj, Object defaultValue,
@Bind("this") Node inliningTarget,
@Exclusive @Cached CastToTruffleStringNode cast,
@Exclusive @Cached PRaiseNode.Lazy raiseNode,
@Cached InlinedConditionProfile noValueProfile,
@Cached PyObjectLookupAttr lookupAttr) {
TruffleString name = castName(inliningTarget, nameObj, cast, raiseNode);
Object result = lookupAttr.execute(frame, inliningTarget, primary, name);
if (noValueProfile.profile(inliningTarget, result == NO_VALUE)) {
return defaultValue;
} else {
return result;
}
}
private static TruffleString castName(Node inliningTarget, Object nameObj, CastToTruffleStringNode cast, PRaiseNode.Lazy raiseNode) {
TruffleString name;
try {
name = cast.execute(inliningTarget, nameObj);
} catch (CannotCastException e) {
throw raiseNode.get(inliningTarget).raise(TypeError, ErrorMessages.GETATTR_ATTRIBUTE_NAME_MUST_BE_STRING);
}
return name;
}
}
// id(object)
@Builtin(name = J_ID, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
public abstract static class IdNode extends PythonUnaryBuiltinNode {
@Specialization
Object doObject(Object value,
@Cached ObjectNodes.GetIdNode getIdNode) {
return getIdNode.execute(value);
}
}
/**
* Base class for {@code isinstance} and {@code issubclass} that implements the recursive
* iteration of tuples passed as the second argument. The inheriting classes need to just
* provide the base for the recursion.
*/
public abstract static class RecursiveBinaryCheckBaseNode extends PythonBinaryBuiltinNode {
static final int MAX_EXPLODE_LOOP = 16; // is also shifted to the left by recursion depth
static final byte NON_RECURSIVE = Byte.MAX_VALUE;
protected final byte depth;
protected RecursiveBinaryCheckBaseNode(byte depth) {
this.depth = depth;
}
public abstract boolean executeWith(VirtualFrame frame, Object instance, Object cls);
@NeverDefault
protected final RecursiveBinaryCheckBaseNode createRecursive() {
return createRecursive((byte) (depth + 1));
}
@NeverDefault
protected final RecursiveBinaryCheckBaseNode createNonRecursive() {
return createRecursive(NON_RECURSIVE);
}
protected RecursiveBinaryCheckBaseNode createRecursive(@SuppressWarnings("unused") byte newDepth) {
throw new AbstractMethodError(); // Cannot be really abstract b/c Truffle DSL...
}
@Idempotent
protected int getMaxExplodeLoop() {
return MAX_EXPLODE_LOOP >> depth;
}
@Specialization(guards = {"depth < getNodeRecursionLimit()", "getLength(clsTuple) == cachedLen", "cachedLen < getMaxExplodeLoop()"}, //
limit = "getVariableArgumentInlineCacheLimit()")
@ExplodeLoop(kind = LoopExplosionKind.FULL_UNROLL_UNTIL_RETURN)
static boolean doTupleConstantLen(VirtualFrame frame, Object instance, PTuple clsTuple,
@Bind("this") Node inliningTarget,
@Cached("getLength(clsTuple)") int cachedLen,
@Shared @Cached GetObjectArrayNode getObjectArrayNode,
@Shared @Cached("createRecursive()") RecursiveBinaryCheckBaseNode recursiveNode) {
Object[] array = getObjectArrayNode.execute(inliningTarget, clsTuple);
for (int i = 0; i < cachedLen; i++) {
Object cls = array[i];
if (recursiveNode.executeWith(frame, instance, cls)) {
return true;
}
}
return false;
}
@Specialization(guards = "depth < getNodeRecursionLimit()", replaces = "doTupleConstantLen")
final boolean doRecursiveWithNode(VirtualFrame frame, Object instance, PTuple clsTuple,
@Bind("this") Node inliningTarget,
@Shared @Cached GetObjectArrayNode getObjectArrayNode,
@Shared @Cached("createRecursive()") RecursiveBinaryCheckBaseNode recursiveNode) {
for (Object cls : getObjectArrayNode.execute(inliningTarget, clsTuple)) {
if (recursiveNode.executeWith(frame, instance, cls)) {
return true;
}
}
return false;
}
@Specialization(guards = {"depth != NON_RECURSIVE", "depth >= getNodeRecursionLimit()"})
final boolean doRecursiveWithLoop(VirtualFrame frame, Object instance, PTuple clsTuple,
@Bind("this") Node inliningTarget,
@Shared @Cached GetObjectArrayNode getObjectArrayNode,
@Cached("createNonRecursive()") RecursiveBinaryCheckBaseNode node) {
PythonLanguage language = PythonLanguage.get(this);
Object state = IndirectCallContext.enter(frame, language, getContext(), this);
try {
// Note: we need actual recursion to trigger the stack overflow error like CPython
// Note: we need fresh RecursiveBinaryCheckBaseNode and cannot use "this", because
// other children of this executed by other specializations may assume they'll
// always get a non-null frame
return callRecursiveWithNodeTruffleBoundary(inliningTarget, instance, clsTuple, getObjectArrayNode, node);
} finally {
IndirectCallContext.exit(frame, PythonLanguage.get(this), getContext(), state);
}
}
@Specialization(guards = "depth == NON_RECURSIVE")
final boolean doRecursiveWithLoopReuseThis(VirtualFrame frame, Object instance, PTuple clsTuple,
@Bind("this") Node inliningTarget,
@Shared @Cached GetObjectArrayNode getObjectArrayNode) {
// This should be only called by doRecursiveWithLoop, now we have to reuse this to stop
// recursive node creation. It is OK, because now all specializations should always get
// null frame
assert frame == null;
return callRecursiveWithNodeTruffleBoundary(inliningTarget, instance, clsTuple, getObjectArrayNode, this);
}
@TruffleBoundary
private boolean callRecursiveWithNodeTruffleBoundary(Node inliningTarget, Object instance, PTuple clsTuple, GetObjectArrayNode getObjectArrayNode, RecursiveBinaryCheckBaseNode node) {
return doRecursiveWithNode(null, instance, clsTuple, inliningTarget, getObjectArrayNode, node);
}
protected static int getLength(PTuple t) {
return t.getSequenceStorage().length();
}
}
// isinstance(object, classinfo)
@Builtin(name = J_ISINSTANCE, minNumOfPositionalArgs = 2)
@GenerateNodeFactory
public abstract static class IsInstanceNode extends RecursiveBinaryCheckBaseNode {
protected IsInstanceNode(byte depth) {
super(depth);
}
protected IsInstanceNode() {
this((byte) 0);
}
@Override
public IsInstanceNode createRecursive(byte newDepth) {
return BuiltinFunctionsFactory.IsInstanceNodeFactory.create(newDepth);
}
private static TriState isInstanceCheckInternal(VirtualFrame frame, Node inliningTarget, Object instance, Object cls, LookupAndCallBinaryNode instanceCheckNode,
CoerceToBooleanNode castToBooleanNode) {
Object instanceCheckResult = instanceCheckNode.executeObject(frame, cls, instance);
if (instanceCheckResult == NOT_IMPLEMENTED) {
return TriState.UNDEFINED;
}
return TriState.valueOf(castToBooleanNode.executeBoolean(frame, inliningTarget, instanceCheckResult));
}
@Specialization(guards = "isPythonClass(cls)")
static boolean isInstance(VirtualFrame frame, Object instance, Object cls,
@Bind("this") Node inliningTarget,
@Shared("instanceCheck") @Cached("create(InstanceCheck)") LookupAndCallBinaryNode instanceCheckNode,
@Exclusive @Cached CoerceToBooleanNode.YesNode castToBooleanNode,
@Cached GetClassNode getClassNode,
@Cached IsSameTypeNode isSameTypeNode,
@Cached IsSubtypeNode isSubtypeNode) {
Object instanceClass = getClassNode.execute(inliningTarget, instance);
return isSameTypeNode.execute(inliningTarget, instanceClass, cls) || isSubtypeNode.execute(frame, instanceClass, cls)//
|| isInstanceCheckInternal(frame, inliningTarget, instance, cls, instanceCheckNode, castToBooleanNode) == TriState.TRUE;
}
@Specialization(guards = {"!isPTuple(cls)", "!isPythonClass(cls)"})
static boolean isInstance(VirtualFrame frame, Object instance, Object cls,
@Bind("this") Node inliningTarget,
@Shared("instanceCheck") @Cached("create(InstanceCheck)") LookupAndCallBinaryNode instanceCheckNode,
@Exclusive @Cached CoerceToBooleanNode.YesNode castToBooleanNode,
@Cached TypeBuiltins.InstanceCheckNode typeInstanceCheckNode) {
TriState check = isInstanceCheckInternal(frame, inliningTarget, instance, cls, instanceCheckNode, castToBooleanNode);
if (check == TriState.UNDEFINED) {
return typeInstanceCheckNode.executeWith(frame, cls, instance);
}
return check == TriState.TRUE;
}
}
// issubclass(class, classinfo)
@Builtin(name = J_ISSUBCLASS, minNumOfPositionalArgs = 2)
@GenerateNodeFactory
public abstract static class IsSubClassNode extends RecursiveBinaryCheckBaseNode {
public abstract boolean executeBoolean(VirtualFrame frame, Object derived, Object cls);
protected IsSubClassNode(byte depth) {
super(depth);
}
protected IsSubClassNode() {
this((byte) 0);
}
@Override
public IsSubClassNode createRecursive(byte newDepth) {
return BuiltinFunctionsFactory.IsSubClassNodeFactory.create(newDepth);
}
@Specialization(guards = "!isPTuple(cls)")
static boolean isSubclass(VirtualFrame frame, Object derived, Object cls,
@Bind("this") Node inliningTarget,
@Cached("create(Subclasscheck)") LookupAndCallBinaryNode subclassCheckNode,
@Cached CoerceToBooleanNode.YesNode castToBooleanNode,
@Cached IsSubtypeNode isSubtypeNode) {
Object instanceCheckResult = subclassCheckNode.executeObject(frame, cls, derived);
if (instanceCheckResult != NOT_IMPLEMENTED) {
return castToBooleanNode.executeBoolean(frame, inliningTarget, instanceCheckResult);
}
return isSubtypeNode.execute(frame, derived, cls);
}
@NeverDefault
public static IsSubClassNode create() {
return BuiltinFunctionsFactory.IsSubClassNodeFactory.create();
}
}
// iter(object[, sentinel])
@Builtin(name = J_ITER, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2)
@GenerateNodeFactory
@ReportPolymorphism
public abstract static class IterNode extends PythonBinaryBuiltinNode {
@Specialization(guards = "isNoValue(sentinel)")
static Object iter(VirtualFrame frame, Object object, @SuppressWarnings("unused") PNone sentinel,
@Bind("this") Node inliningTarget,
@Cached PyObjectGetIter getIter) {
return getIter.execute(frame, inliningTarget, object);
}
@Specialization(guards = {"callableCheck.execute(this, callable)", "!isNoValue(sentinel)"}, limit = "1")
@SuppressWarnings("truffle-static-method")
Object iter(Object callable, Object sentinel,
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Cached PyCallableCheckNode callableCheck) {
return factory().createSentinelIterator(callable, sentinel);
}
@Fallback
@SuppressWarnings("unused")
Object iterNotCallable(Object callable, Object sentinel) {
throw raise(TypeError, ErrorMessages.ITER_V_MUST_BE_CALLABLE);
}
}
// len(s)
@Builtin(name = J_LEN, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
public abstract static class LenNode extends PythonUnaryBuiltinNode {
@Specialization
public int len(VirtualFrame frame, Object obj,
@Bind("this") Node inliningTarget,
@Cached PyObjectSizeNode sizeNode) {
return sizeNode.execute(frame, inliningTarget, obj);
}
}
public abstract static class MinMaxNode extends PythonBuiltinNode {
@NeverDefault
protected final BinaryComparisonNode createComparison() {
if (this instanceof MaxNode) {
return BinaryComparisonNode.GtNode.create();
} else {
return BinaryComparisonNode.LtNode.create();
}
}
@Specialization(guards = "args.length == 0")
Object minmaxSequenceWithKey(VirtualFrame frame, Object arg1, @SuppressWarnings("unused") Object[] args, Object keywordArgIn, Object defaultVal,
@Bind("this") Node inliningTarget,
@Exclusive @Cached PyObjectGetIter getIter,
@Cached GetNextNode nextNode,
@Shared @Cached("createComparison()") BinaryComparisonNode compare,
@Exclusive @Cached CoerceToBooleanNode.YesNode castToBooleanNode,
@Exclusive @Cached CallNode.Lazy keyCall,
@Exclusive @Cached InlinedBranchProfile seenNonBoolean,
@Exclusive @Cached InlinedConditionProfile keywordArgIsNone,
@Exclusive @Cached IsBuiltinObjectProfile errorProfile1,
@Exclusive @Cached IsBuiltinObjectProfile errorProfile2,
@Exclusive @Cached InlinedConditionProfile hasDefaultProfile) {
boolean kwArgsAreNone = keywordArgIsNone.profile(inliningTarget, PGuards.isPNone(keywordArgIn));
Object keywordArg = kwArgsAreNone ? null : keywordArgIn;
Object iterator = getIter.execute(frame, inliningTarget, arg1);
Object currentValue;
try {
currentValue = nextNode.execute(frame, iterator);
} catch (PException e) {
e.expectStopIteration(inliningTarget, errorProfile1);
if (hasDefaultProfile.profile(inliningTarget, PGuards.isNoValue(defaultVal))) {
throw raise(PythonErrorType.ValueError, ErrorMessages.ARG_IS_EMPTY_SEQ, getName());
} else {
return defaultVal;
}
}
Object currentKey = applyKeyFunction(frame, inliningTarget, keywordArg, keyCall, currentValue);
int loopCount = 0;
try {
while (true) {
Object nextValue;
try {
nextValue = nextNode.execute(frame, iterator);
} catch (PException e) {
e.expectStopIteration(inliningTarget, errorProfile2);
break;
}
Object nextKey = applyKeyFunction(frame, inliningTarget, keywordArg, keyCall, nextValue);
boolean isTrue;
if (!seenNonBoolean.wasEntered(inliningTarget)) {
try {
isTrue = compare.executeBool(frame, nextKey, currentKey);
} catch (UnexpectedResultException e) {
seenNonBoolean.enter(inliningTarget);
isTrue = castToBooleanNode.executeBoolean(frame, inliningTarget, e.getResult());
}
} else {
isTrue = castToBooleanNode.executeBoolean(frame, inliningTarget, compare.executeObject(frame, nextKey, currentKey));
}
if (isTrue) {
currentKey = nextKey;
currentValue = nextValue;
}
loopCount++;
}
} finally {
LoopNode.reportLoopCount(this, loopCount < 0 ? Integer.MAX_VALUE : loopCount);
}
return currentValue;
}
private String getName() {
return this instanceof MaxNode ? "max" : "min";
}
@Specialization(guards = {"args.length != 0"})
@SuppressWarnings("truffle-static-method")
Object minmaxBinaryWithKey(VirtualFrame frame, Object arg1, Object[] args, Object keywordArgIn, Object defaultVal,
@Bind("this") Node inliningTarget,
@Shared @Cached("createComparison()") BinaryComparisonNode compare,
@Exclusive @Cached CallNode.Lazy keyCall,
@Exclusive @Cached CoerceToBooleanNode.YesNode castToBooleanNode,
@Exclusive @Cached InlinedBranchProfile seenNonBoolean,
@Exclusive @Cached InlinedConditionProfile keywordArgIsNone,
@Exclusive @Cached InlinedConditionProfile moreThanTwo,
@Exclusive @Cached InlinedLoopConditionProfile loopProfile,
@Exclusive @Cached InlinedConditionProfile hasDefaultProfile) {
boolean kwArgsAreNone = keywordArgIsNone.profile(inliningTarget, PGuards.isPNone(keywordArgIn));
Object keywordArg = kwArgsAreNone ? null : keywordArgIn;
if (!hasDefaultProfile.profile(inliningTarget, PGuards.isNoValue(defaultVal))) {
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.CANNOT_SPECIFY_DEFAULT_FOR_S, getName());
}
Object currentValue = arg1;
Object currentKey = applyKeyFunction(frame, inliningTarget, keywordArg, keyCall, currentValue);
Object nextValue = args[0];
Object nextKey = applyKeyFunction(frame, inliningTarget, keywordArg, keyCall, nextValue);
boolean isTrue;
if (!seenNonBoolean.wasEntered(inliningTarget)) {
try {
isTrue = compare.executeBool(frame, nextKey, currentKey);
} catch (UnexpectedResultException e) {
seenNonBoolean.enter(inliningTarget);
isTrue = castToBooleanNode.executeBoolean(frame, inliningTarget, e.getResult());
}
} else {
isTrue = castToBooleanNode.executeBoolean(frame, inliningTarget, compare.executeObject(frame, nextKey, currentKey));
}
if (isTrue) {
currentKey = nextKey;
currentValue = nextValue;
}
if (moreThanTwo.profile(inliningTarget, args.length > 1)) {
loopProfile.profileCounted(inliningTarget, args.length);
LoopNode.reportLoopCount(this, args.length);
for (int i = 0; loopProfile.inject(inliningTarget, i < args.length); i++) {
nextValue = args[i];
nextKey = applyKeyFunction(frame, inliningTarget, keywordArg, keyCall, nextValue);
if (!seenNonBoolean.wasEntered(inliningTarget)) {
try {
isTrue = compare.executeBool(frame, nextKey, currentKey);
} catch (UnexpectedResultException e) {
seenNonBoolean.enter(inliningTarget);
isTrue = castToBooleanNode.executeBoolean(frame, inliningTarget, e.getResult());
}
} else {
isTrue = castToBooleanNode.executeBoolean(frame, inliningTarget, compare.executeObject(frame, nextKey, currentKey));
}
if (isTrue) {
currentKey = nextKey;
currentValue = nextValue;
}
}
}
return currentValue;
}
private static Object applyKeyFunction(VirtualFrame frame, Node inliningTarget, Object keywordArg, CallNode.Lazy keyCall, Object currentValue) {
return keywordArg == null ? currentValue : keyCall.get(inliningTarget).execute(frame, keywordArg, new Object[]{currentValue}, PKeyword.EMPTY_KEYWORDS);
}
}
// max(iterable, *[, key])
// max(arg1, arg2, *args[, key])
@Builtin(name = J_MAX, minNumOfPositionalArgs = 1, takesVarArgs = true, keywordOnlyNames = {"key", "default"}, doc = "max(iterable, *[, default=obj, key=func]) -> value\n" +
"max(arg1, arg2, *args, *[, key=func]) -> value\n\n" + "With a single iterable argument, return its biggest item. The\n" +
"default keyword-only argument specifies an object to return if\n" + "the provided iterable is empty.\n" + "With two or more arguments, return the largest argument.")
@GenerateNodeFactory
public abstract static class MaxNode extends MinMaxNode {
}
// min(iterable, *[, key])
// min(arg1, arg2, *args[, key])
@Builtin(name = J_MIN, minNumOfPositionalArgs = 1, takesVarArgs = true, keywordOnlyNames = {"key", "default"})
@GenerateNodeFactory
public abstract static class MinNode extends MinMaxNode {
}
// next(iterator[, default])
@SuppressWarnings("unused")
@Builtin(name = J_NEXT, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2)
@GenerateNodeFactory
public abstract static class NextNode extends PythonBinaryBuiltinNode {
@Specialization
public Object next(VirtualFrame frame, Object iterator, Object defaultObject,
@Bind("this") Node inliningTarget,
@Cached InlinedConditionProfile defaultIsNoValue,
@Cached("createNextCall()") LookupAndCallUnaryNode callNode,
@Cached IsBuiltinObjectProfile errorProfile) {
if (defaultIsNoValue.profile(inliningTarget, PGuards.isNoValue(defaultObject))) {
return callNode.executeObject(frame, iterator);
} else {
try {
return callNode.executeObject(frame, iterator);
} catch (PException e) {
e.expectStopIteration(inliningTarget, errorProfile);
return defaultObject;
}
}
}
@NeverDefault
protected LookupAndCallUnaryNode createNextCall() {
return LookupAndCallUnaryNode.create(T___NEXT__, () -> new LookupAndCallUnaryNode.NoAttributeHandler() {
@Override
public Object execute(Object iterator) {
throw raise(TypeError, ErrorMessages.OBJ_ISNT_ITERATOR, iterator);
}
});
}
}
// ord(c)
@Builtin(name = J_ORD, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
@ImportStatic(PGuards.class)
public abstract static class OrdNode extends PythonBuiltinNode {
@Specialization
@TruffleBoundary
public int ord(TruffleString chr,
@Shared @Cached TruffleString.CodePointLengthNode codePointLengthNode,
@Shared @Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
int len = codePointLengthNode.execute(chr, TS_ENCODING);
if (len != 1) {
throw raise(TypeError, ErrorMessages.EXPECTED_CHARACTER_BUT_STRING_FOUND, "ord()", len);
}
return codePointAtIndexNode.execute(chr, 0, TS_ENCODING);
}
@Specialization
public int ord(PString pchr,
@Bind("this") Node inliningTarget,
@Cached CastToTruffleStringNode castToStringNode,
@Shared @Cached TruffleString.CodePointLengthNode codePointLengthNode,
@Shared @Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
TruffleString chr;
try {
chr = castToStringNode.execute(inliningTarget, pchr);
} catch (CannotCastException e) {
throw CompilerDirectives.shouldNotReachHere(e);
}
return ord(chr, codePointLengthNode, codePointAtIndexNode);
}
@Specialization
@SuppressWarnings("truffle-static-method")
public long ord(PBytesLike chr,
@Bind("this") Node inliningTarget,
@Cached CastToJavaLongExactNode castNode,
@Cached SequenceStorageNodes.GetItemNode getItemNode) {
int len = chr.getSequenceStorage().length();
if (len != 1) {
throw raise(TypeError, ErrorMessages.EXPECTED_CHARACTER_BUT_STRING_FOUND, "ord()", len);
}
return castNode.execute(inliningTarget, getItemNode.execute(chr.getSequenceStorage(), 0));
}
@Specialization(guards = {"!isString(obj)", "!isBytes(obj)"})
public Object ord(@SuppressWarnings("unused") Object obj) {
throw raise(TypeError, ErrorMessages.S_EXPECTED_STRING_OF_LEN_BUT_P, "ord()", "1", "obj");
}
}
// print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
@Builtin(name = J_PRINT, takesVarArgs = true, keywordOnlyNames = {"sep", "end", "file", "flush"}, doc = "\n" +
"print(value, ..., sep=' ', end='\\n', file=sys.stdout, flush=False)\n" +
"\n" +
"Prints the values to a stream, or to sys.stdout by default.\n" +
"Optional keyword arguments:\n" +
"file: a file-like object (stream); defaults to the current sys.stdout.\n" +
"sep: string inserted between values, default a space.\n" +
"end: string appended after the last value, default a newline.\n" +
"flush: whether to forcibly flush the stream.")
@GenerateNodeFactory
public abstract static class PrintNode extends PythonBuiltinNode {
@Child private ReadAttributeFromObjectNode readStdout;
@CompilationFinal private PythonModule cachedSys;
@Specialization
@SuppressWarnings("unused")
PNone printNoKeywords(VirtualFrame frame, Object[] values, PNone sep, PNone end, PNone file, PNone flush,
@Bind("this") Node inliningTarget,
@Shared("getWriteMethod") @Cached PyObjectGetAttr getWriteMethod,
@Shared("callWrite") @Cached CallNode callWrite,
@Shared("callFlush") @Cached PyObjectCallMethodObjArgs callFlush,
@Shared("strNode") @Cached PyObjectStrAsObjectNode strNode) {
Object stdout = getStdout();
return printAllGiven(frame, values, T_SPACE, T_NEWLINE, stdout, false, inliningTarget, getWriteMethod, callWrite, callFlush, strNode);
}
@Specialization(guards = {"!isNone(file)", "!isNoValue(file)"})
static PNone printAllGiven(VirtualFrame frame, Object[] values, TruffleString sep, TruffleString end, Object file, boolean flush,
@Bind("this") Node inliningTarget,
@Shared("getWriteMethod") @Cached PyObjectGetAttr getWriteMethod,
@Shared("callWrite") @Cached CallNode callWrite,
@Shared("callFlush") @Cached PyObjectCallMethodObjArgs callFlush,
@Shared("strNode") @Cached PyObjectStrAsObjectNode strNode) {
int lastValue = values.length - 1;
// Note: the separate lookup is necessary due to different __getattr__ treatment than
// method lookup
Object writeMethod = getWriteMethod.execute(frame, inliningTarget, file, T_WRITE);
for (int i = 0; i < lastValue; i++) {
callWrite.execute(frame, writeMethod, strNode.execute(frame, inliningTarget, values[i]));
callWrite.execute(frame, writeMethod, sep);
}
if (lastValue >= 0) {
callWrite.execute(frame, writeMethod, strNode.execute(frame, inliningTarget, values[lastValue]));
}
callWrite.execute(frame, writeMethod, end);
if (flush) {
callFlush.execute(frame, inliningTarget, file, T_FLUSH);
}
return PNone.NONE;
}
@Specialization(replaces = {"printAllGiven", "printNoKeywords"})
@SuppressWarnings("truffle-static-method")
PNone printGeneric(VirtualFrame frame, Object[] values, Object sepIn, Object endIn, Object fileIn, Object flushIn,
@Bind("this") Node inliningTarget,
@Cached CastToTruffleStringNode castSep,
@Cached CastToTruffleStringNode castEnd,
@Cached CoerceToBooleanNode.YesNode castFlush,
@Cached PRaiseNode raiseNode,
@Exclusive @Cached PyObjectGetAttr getWriteMethod,
@Exclusive @Cached CallNode callWrite,
@Exclusive @Cached PyObjectCallMethodObjArgs callFlush,
@Exclusive @Cached PyObjectStrAsObjectNode strNode) {
TruffleString sep;
try {
sep = sepIn instanceof PNone ? T_SPACE : castSep.execute(inliningTarget, sepIn);
} catch (CannotCastException e) {
throw raiseNode.raise(PythonBuiltinClassType.TypeError, ErrorMessages.SEP_MUST_BE_NONE_OR_STRING, sepIn);
}
TruffleString end;
try {
end = endIn instanceof PNone ? T_NEWLINE : castEnd.execute(inliningTarget, endIn);
} catch (CannotCastException e) {
throw raiseNode.raise(PythonBuiltinClassType.TypeError, ErrorMessages.S_MUST_BE_NONE_OR_STRING, "end", sepIn);
}
Object file;
if (fileIn instanceof PNone) {
file = getStdout();
} else {
file = fileIn;
}
boolean flush;
if (flushIn instanceof PNone) {
flush = false;
} else {
flush = castFlush.executeBoolean(frame, inliningTarget, flushIn);
}
return printAllGiven(frame, values, sep, end, file, flush, inliningTarget, getWriteMethod, callWrite, callFlush, strNode);
}
private Object getStdout() {
PythonModule sys;
if (getLanguage().isSingleContext()) {
if (cachedSys == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
cachedSys = getContext().lookupBuiltinModule(T_SYS);
}
sys = cachedSys;
} else {
if (cachedSys != null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
cachedSys = null;
}
sys = getContext().lookupBuiltinModule(T_SYS);
}
if (readStdout == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
readStdout = insert(ReadAttributeFromObjectNode.create());
}
Object stdout = readStdout.execute(sys, T_STDOUT);
if (stdout instanceof PNone) {
throw raise(RuntimeError, ErrorMessages.LOST_SYSSTDOUT);
}
return stdout;
}
}
// repr(object)
@Builtin(name = J_REPR, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
public abstract static class ReprNode extends PythonUnaryBuiltinNode {
@Specialization
static Object repr(VirtualFrame frame, Object obj,
@Bind("this") Node inliningTarget,
@Cached PyObjectReprAsObjectNode reprNode) {
return reprNode.execute(frame, inliningTarget, obj);
}
}
// format(object, [format_spec])
@Builtin(name = J_FORMAT, minNumOfPositionalArgs = 1, parameterNames = {"object", "format_spec"})
@GenerateNodeFactory
@ImportStatic(PGuards.class)
public abstract static class FormatNode extends PythonBinaryBuiltinNode {
@Specialization(guards = "isNoValue(formatSpec)")
Object format(VirtualFrame frame, Object obj, @SuppressWarnings("unused") PNone formatSpec,
@Shared("callFormat") @Cached("create(Format)") LookupAndCallBinaryNode callFormat) {
return format(frame, obj, T_EMPTY_STRING, callFormat);
}
@Specialization(guards = "!isNoValue(formatSpec)")
Object format(VirtualFrame frame, Object obj, Object formatSpec,
@Shared("callFormat") @Cached("create(Format)") LookupAndCallBinaryNode callFormat) {
Object res = callFormat.executeObject(frame, obj, formatSpec);
if (res == NO_VALUE) {
throw raise(TypeError, ErrorMessages.TYPE_DOESNT_DEFINE_FORMAT, obj);
}
if (!PGuards.isString(res)) {
throw raise(TypeError, ErrorMessages.S_MUST_RETURN_S_NOT_P, T___FORMAT__, "str", res);
}
return res;
}
@NeverDefault
public static FormatNode create() {
return BuiltinFunctionsFactory.FormatNodeFactory.create();
}
}
// ascii(object)
@Builtin(name = J_ASCII, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
abstract static class AsciiNode extends PythonUnaryBuiltinNode {
@Specialization
public static TruffleString ascii(VirtualFrame frame, Object obj,
@Bind("this") Node inliningTarget,
@Cached PyObjectAsciiNode asciiNode) {
return asciiNode.execute(frame, inliningTarget, obj);
}
}
// round(number[, ndigits])
@Builtin(name = J_ROUND, minNumOfPositionalArgs = 1, parameterNames = {"number", "ndigits"})
@GenerateNodeFactory
public abstract static class RoundNode extends PythonBuiltinNode {
@Specialization
Object round(VirtualFrame frame, Object x, @SuppressWarnings("unused") PNone n,
@Cached("create(Round)") LookupAndCallUnaryNode callRound) {
Object result = callRound.executeObject(frame, x);
if (result == PNone.NO_VALUE) {
throw raise(TypeError, ErrorMessages.TYPE_DOESNT_DEFINE_METHOD, x, T___ROUND__);
}
return result;
}
@Specialization(guards = "!isPNone(n)")
Object round(VirtualFrame frame, Object x, Object n,
@Cached("create(Round)") LookupAndCallBinaryNode callRound) {
Object result = callRound.executeObject(frame, x, n);
if (result == NOT_IMPLEMENTED) {
throw raise(TypeError, ErrorMessages.TYPE_DOESNT_DEFINE_METHOD, x, T___ROUND__);
}
return result;
}
}
// setattr(object, name, value)
@Builtin(name = J_SETATTR, minNumOfPositionalArgs = 3)
@GenerateNodeFactory
public abstract static class SetAttrNode extends PythonTernaryBuiltinNode {
@Specialization
Object setAttr(VirtualFrame frame, Object object, Object key, Object value,
@Cached SetAttributeNode.Dynamic setAttrNode) {
setAttrNode.execute(frame, object, key, value);
return PNone.NONE;
}
}
// hasattr(object, name)
@Builtin(name = J_HASATTR, minNumOfPositionalArgs = 2)
@GenerateNodeFactory
public abstract static class HasAttrNode extends PythonBinaryBuiltinNode {
@Specialization
boolean hasAttr(VirtualFrame frame, Object object, Object key,
@Bind("this") Node inliningTarget,
@Cached PyObjectLookupAttr pyObjectLookupAttr) {
return pyObjectLookupAttr.execute(frame, inliningTarget, object, key) != PNone.NO_VALUE;
}
}
// sorted(iterable, key, reverse)
@Builtin(name = J_SORTED, minNumOfPositionalArgs = 1, parameterNames = {"$self"}, keywordOnlyNames = {"key", "reverse"})
@ArgumentClinic(name = "reverse", conversion = ArgumentClinic.ClinicConversion.IntToBoolean, defaultValue = "false")
@GenerateNodeFactory
public abstract static class SortedNode extends PythonClinicBuiltinNode {
public abstract Object executeInternal(VirtualFrame frame, Object iterable, Object keyfunc, boolean reverse);
@Specialization
Object sorted(VirtualFrame frame, Object iterable, Object keyfunc, boolean reverse,
@Cached ConstructListNode constructListNode,
@Cached ListSortNode sortNode) {
PList list = constructListNode.execute(frame, iterable);
sortNode.execute(frame, list, keyfunc, reverse);
return list;
}
@Override
protected ArgumentClinicProvider getArgumentClinic() {
return BuiltinFunctionsClinicProviders.SortedNodeClinicProviderGen.INSTANCE;
}
}
@Builtin(name = J_BREAKPOINT, takesVarArgs = true, takesVarKeywordArgs = true)
@GenerateNodeFactory
public abstract static class BreakPointNode extends PythonBuiltinNode {
@Child private ReadAttributeFromObjectNode getBreakpointhookNode;
@Child private CallNode callNode;
@Specialization
public Object doIt(VirtualFrame frame, Object[] args, PKeyword[] kwargs,
@Bind("this") Node inliningTarget,
@Cached HashingStorageGetItem getItem) {
if (getDebuggerSessionCount() > 0) {
// we already have a Truffle debugger attached, it'll stop here
return PNone.NONE;
} else if (getContext().isInitialized()) {
if (callNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
getBreakpointhookNode = insert(ReadAttributeFromObjectNode.create());
callNode = insert(CallNode.create());
}
PDict sysModules = getContext().getSysModules();
Object sysModule = getItem.execute(inliningTarget, sysModules.getDictStorage(), T_SYS);
Object breakpointhook = getBreakpointhookNode.execute(sysModule, T_BREAKPOINTHOOK);
if (breakpointhook == PNone.NO_VALUE) {
throw raise(PythonBuiltinClassType.RuntimeError, ErrorMessages.LOST_SYSBREAKPOINTHOOK);
}
return callNode.execute(frame, breakpointhook, args, kwargs);
} else {
return PNone.NONE;
}
}
@TruffleBoundary
private int getDebuggerSessionCount() {
return Debugger.find(getContext().getEnv()).getSessionCount();
}
}
@Builtin(name = J_POW, minNumOfPositionalArgs = 2, parameterNames = {"base", "exp", "mod"})
@GenerateNodeFactory
public abstract static class PowNode extends PythonTernaryBuiltinNode {
@NeverDefault
static BinaryOpNode binaryPow() {
return BinaryArithmetic.Pow.create();
}
@NeverDefault
static LookupAndCallTernaryNode ternaryPow() {
return TernaryArithmetic.Pow.create();
}
@Specialization
Object binary(VirtualFrame frame, Object x, Object y, @SuppressWarnings("unused") PNone z,
@Cached("binaryPow()") BinaryOpNode powNode) {
return powNode.executeObject(frame, x, y);
}
@Specialization(guards = "!isPNone(z)")
Object ternary(VirtualFrame frame, Object x, Object y, Object z,
@Cached("ternaryPow()") LookupAndCallTernaryNode powNode) {
return powNode.execute(frame, x, y, z);
}
}
// sum(iterable[, start])
@Builtin(name = J_SUM, minNumOfPositionalArgs = 1, parameterNames = {"iterable", "start"})
@GenerateNodeFactory
public abstract static class SumFunctionNode extends PythonBuiltinNode {
@Child private LookupAndCallUnaryNode next = LookupAndCallUnaryNode.create(SpecialMethodSlot.Next);
@Child private AddNode add = AddNode.create();
@Specialization(rewriteOn = UnexpectedResultException.class)
int sumIntNone(VirtualFrame frame, Object arg1, @SuppressWarnings("unused") PNone start,
@Bind("this") Node inliningTarget,
@Shared @Cached IsBuiltinObjectProfile errorProfile1,
@Shared @Cached IsBuiltinObjectProfile errorProfile2,
@Shared @Cached IsBuiltinObjectProfile errorProfile3,
@Shared("getIter") @Cached PyObjectGetIter getIter) throws UnexpectedResultException {
return sumIntInternal(frame, arg1, 0, getIter, inliningTarget, errorProfile1, errorProfile2, errorProfile3);
}
@Specialization(rewriteOn = UnexpectedResultException.class)
int sumIntInt(VirtualFrame frame, Object arg1, int start,
@Bind("this") Node inliningTarget,
@Shared @Cached IsBuiltinObjectProfile errorProfile1,
@Shared @Cached IsBuiltinObjectProfile errorProfile2,
@Shared @Cached IsBuiltinObjectProfile errorProfile3,
@Shared("getIter") @Cached PyObjectGetIter getIter) throws UnexpectedResultException {
return sumIntInternal(frame, arg1, start, getIter, inliningTarget, errorProfile1, errorProfile2, errorProfile3);
}
private int sumIntInternal(VirtualFrame frame, Object arg1, int start, PyObjectGetIter getIter,
Node inliningTarget, IsBuiltinObjectProfile errorProfile1,
IsBuiltinObjectProfile errorProfile2, IsBuiltinObjectProfile errorProfile3) throws UnexpectedResultException {
Object iterator = getIter.execute(frame, inliningTarget, arg1);
int value = start;
while (true) {
int nextValue;
try {
nextValue = PGuards.expectInteger(next.executeObject(frame, iterator));
} catch (PException e) {
e.expectStopIteration(inliningTarget, errorProfile1);
return value;
} catch (UnexpectedResultException e) {
Object newValue = add.executeObject(frame, value, e.getResult());
throw new UnexpectedResultException(iterateGeneric(frame, iterator, newValue, inliningTarget, errorProfile2));
}
try {
value = add.executeInt(frame, value, nextValue);
} catch (UnexpectedResultException e) {
throw new UnexpectedResultException(iterateGeneric(frame, iterator, e.getResult(), inliningTarget, errorProfile3));
}
}
}
@Specialization(rewriteOn = UnexpectedResultException.class)
double sumDoubleDouble(VirtualFrame frame, Object arg1, double start,
@Bind("this") Node inliningTarget,
@Shared @Cached IsBuiltinObjectProfile errorProfile1,
@Shared @Cached IsBuiltinObjectProfile errorProfile2,
@Shared @Cached IsBuiltinObjectProfile errorProfile3,
// dummy inline profile, so it can be @Shared, to optimize generated code:
@SuppressWarnings("unused") @Shared @Cached InlinedConditionProfile hasStart,
@Shared("getIter") @Cached PyObjectGetIter getIter) throws UnexpectedResultException {
return sumDoubleInternal(frame, arg1, start, getIter, inliningTarget, errorProfile1, errorProfile2, errorProfile3);
}
private double sumDoubleInternal(VirtualFrame frame, Object arg1, double start, PyObjectGetIter getIter,
Node inliningTarget, IsBuiltinObjectProfile errorProfile1,
IsBuiltinObjectProfile errorProfile2, IsBuiltinObjectProfile errorProfile3) throws UnexpectedResultException {
Object iterator = getIter.execute(frame, inliningTarget, arg1);
double value = start;
while (true) {
double nextValue;
try {
nextValue = PGuards.expectDouble(next.executeObject(frame, iterator));
} catch (PException e) {
e.expectStopIteration(inliningTarget, errorProfile1);
return value;
} catch (UnexpectedResultException e) {
Object newValue = add.executeObject(frame, value, e.getResult());
throw new UnexpectedResultException(iterateGeneric(frame, iterator, newValue, inliningTarget, errorProfile2));
}
try {
value = add.executeDouble(frame, value, nextValue);
} catch (UnexpectedResultException e) {
throw new UnexpectedResultException(iterateGeneric(frame, iterator, e.getResult(), inliningTarget, errorProfile3));
}
}
}
@Specialization(replaces = {"sumIntNone", "sumIntInt", "sumDoubleDouble"})
Object sum(VirtualFrame frame, Object arg1, Object start,
@Bind("this") Node inliningTarget,
@Shared @Cached IsBuiltinObjectProfile errorProfile1,
@Shared("getIter") @Cached PyObjectGetIter getIter,
@Shared @Cached InlinedConditionProfile hasStart) {
if (PGuards.isString(start)) {
throw raise(TypeError, ErrorMessages.CANT_SUM_STRINGS);
} else if (start instanceof PBytes) {
throw raise(TypeError, ErrorMessages.CANT_SUM_BYTES);
} else if (start instanceof PByteArray) {
throw raise(TypeError, ErrorMessages.CANT_SUM_BYTEARRAY);
}
Object iterator = getIter.execute(frame, inliningTarget, arg1);
return iterateGeneric(frame, iterator, hasStart.profile(inliningTarget, start != NO_VALUE) ? start : 0, inliningTarget, errorProfile1);
}
private Object iterateGeneric(VirtualFrame frame, Object iterator, Object start, Node inliningTarget, IsBuiltinObjectProfile errorProfile) {
Object value = start;
while (true) {
Object nextValue;
try {
nextValue = next.executeObject(frame, iterator);
} catch (PException e) {
e.expectStopIteration(inliningTarget, errorProfile);
return value;
}
value = add.executeObject(frame, value, nextValue);
}
}
}
@Builtin(name = "globals", needsFrame = true, alwaysNeedsCallerFrame = true)
@GenerateNodeFactory
abstract static class GlobalsNode extends PythonBuiltinNode {
private final ConditionProfile condProfile = ConditionProfile.create();
@Specialization
public Object globals(VirtualFrame frame,
@Bind("this") Node inliningTarget,
@Cached PyEvalGetGlobals getGlobals,
@Cached GetOrCreateDictNode getDict) {
Object globals = getGlobals.execute(frame, inliningTarget);
if (condProfile.profile(globals instanceof PythonModule)) {
return getDict.execute(inliningTarget, globals);
} else {
return globals;
}
}
}
@Builtin(name = "locals", needsFrame = true, alwaysNeedsCallerFrame = true)
@GenerateNodeFactory
abstract static class LocalsNode extends PythonBuiltinNode {
@Specialization
Object locals(VirtualFrame frame,
@Bind("this") Node inliningTarget,
@Cached PyEvalGetLocals getLocals) {
return getLocals.execute(frame, inliningTarget);
}
}
@Builtin(name = "vars", maxNumOfPositionalArgs = 1)
@GenerateNodeFactory
abstract static class VarsNode extends PythonUnaryBuiltinNode {
@Specialization(guards = "isNoValue(none)")
static Object vars(VirtualFrame frame, @SuppressWarnings("unused") PNone none,
@Bind("this") Node inliningTarget,
@Cached PyEvalGetLocals getLocals) {
return getLocals.execute(frame, inliningTarget);
}
@Specialization(guards = "!isNoValue(obj)")
@SuppressWarnings("truffle-static-method")
Object vars(VirtualFrame frame, Object obj,
@Bind("this") Node inliningTarget,
@Cached PyObjectLookupAttr lookupAttr) {
Object dict = lookupAttr.execute(frame, inliningTarget, obj, T___DICT__);
if (dict == NO_VALUE) {
throw raise(TypeError, ErrorMessages.VARS_ARGUMENT_MUST_HAVE_DICT);
}
return dict;
}
}
@Builtin(name = "open", minNumOfPositionalArgs = 1, parameterNames = {"file", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener"})
@ArgumentClinic(name = "mode", conversionClass = IONodes.CreateIOModeNode.class, args = "true")
@ArgumentClinic(name = "buffering", conversion = ArgumentClinic.ClinicConversion.Int, defaultValue = "-1", useDefaultForNone = true)
@ArgumentClinic(name = "encoding", conversion = ArgumentClinic.ClinicConversion.TString, defaultValue = "PNone.NONE", useDefaultForNone = true)
@ArgumentClinic(name = "errors", conversion = ArgumentClinic.ClinicConversion.TString, defaultValue = "PNone.NONE", useDefaultForNone = true)
@ArgumentClinic(name = "newline", conversion = ArgumentClinic.ClinicConversion.TString, defaultValue = "PNone.NONE", useDefaultForNone = true)
@ArgumentClinic(name = "closefd", conversion = ArgumentClinic.ClinicConversion.Boolean, defaultValue = "true", useDefaultForNone = true)
@ImportStatic(IONodes.IOMode.class)
@GenerateNodeFactory
public abstract static class OpenNode extends IOModuleBuiltins.IOOpenNode {
/*
* XXX: (mq) CPython defines `builtins.open` by importing `OpenWrapper` from the `io` module
* see ('Python/pylifecycle.c:init_set_builtins_open'). `io.OpenWrapper` is set to
* `_io.open`. However, the process seems redundant and expensive in our case. So, here, we
* skip this and define `open` in `io` and `builtins` modules at once.
*/
@Override
protected ArgumentClinicProvider getArgumentClinic() {
return BuiltinFunctionsClinicProviders.OpenNodeClinicProviderGen.INSTANCE;
}
}
@ImportStatic(SpecialMethodNames.class)
abstract static class UpdateBasesNode extends PNodeWithRaise {
abstract PTuple execute(PTuple bases, Object[] arguments, int nargs);
@Specialization
PTuple update(PTuple bases, Object[] arguments, int nargs,
@Bind("this") Node inliningTarget,
@Cached PythonObjectFactory factory,
@Cached PyObjectLookupAttr getMroEntries,
@Cached CallUnaryMethodNode callMroEntries) {
CompilerAsserts.neverPartOfCompilation();
ArrayList
© 2015 - 2024 Weber Informatics LLC | Privacy Policy