com.oracle.graal.python.builtins.objects.NoneBuiltins Maven / Gradle / Ivy
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or
* data (collectively the "Software"), free of charge and under any and all
* copyright rights in the Software, and any and all patent rights owned or
* freely licensable by each licensor hereunder covering either (i) the
* unmodified Software as contributed to or provided by such licensor, or (ii)
* the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or at a
* minimum a reference to the UPL must be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.oracle.graal.python.builtins.objects;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.AttributeError;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___BOOL__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___GETATTRIBUTE__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___REPR__;
import static com.oracle.graal.python.nodes.StringLiterals.T_NONE;
import java.util.List;
import com.oracle.graal.python.builtins.Builtin;
import com.oracle.graal.python.builtins.CoreFunctions;
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
import com.oracle.graal.python.builtins.PythonBuiltins;
import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptor;
import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
import com.oracle.graal.python.nodes.util.CannotCastException;
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
import com.oracle.truffle.api.dsl.NodeFactory;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.strings.TruffleString;
@CoreFunctions(extendClasses = PythonBuiltinClassType.PNone)
public final class NoneBuiltins extends PythonBuiltins {
@Override
protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFactories() {
return NoneBuiltinsFactory.getFactories();
}
@Builtin(name = J___BOOL__, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
abstract static class BoolNode extends PythonUnaryBuiltinNode {
@Specialization
static boolean doNone(PNone none) {
assert none == PNone.NONE;
return false;
}
}
@Builtin(name = J___REPR__, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
abstract static class ReprNode extends PythonUnaryBuiltinNode {
@Specialization
static Object doNone(PNone none) {
assert none == PNone.NONE;
return T_NONE;
}
}
/**
* XXX CPython's None doesn't declare its own __getattribute__, it inherits the object one. We
* currently have to have one because of peculiarities in descriptor protocol. CPython has a
* slot wrapper for __get__ that converts None to NULL, which is then treated as a descriptor
* get on a type. object.__getattribute__ calls tp_descr_get which doesn't go through the
* wrapper, so the None stays as None. IOW you can't express descriptor gets on None in terms of
* __get__, i.e. None.__class__ is not the same as object.__dict__['__class__'].__get__(None,
* type(None)). Since we don't distinguish between method and slot calls, this is the current
* workaround that bypasses the descriptor __get__ handling and invokes the get function
* directly.
*/
@Builtin(name = J___GETATTRIBUTE__, minNumOfPositionalArgs = 2)
@GenerateNodeFactory
public abstract static class GetAttributeNode extends PythonBinaryBuiltinNode {
@Specialization
protected Object doIt(VirtualFrame frame, Object object, Object keyObj,
@Bind("this") Node inliningTarget,
@Cached LookupAttributeInMRONode.Dynamic lookup,
@Cached CallUnaryMethodNode callGet,
@Cached CastToTruffleStringNode castKeyToStringNode) {
TruffleString key;
try {
key = castKeyToStringNode.execute(inliningTarget, keyObj);
} catch (CannotCastException e) {
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.ATTR_NAME_MUST_BE_STRING, keyObj);
}
Object descr = lookup.execute(PythonBuiltinClassType.PNone, key);
if (descr == PNone.NO_VALUE) {
throw raise(AttributeError, ErrorMessages.OBJ_P_HAS_NO_ATTR_S, object, key);
}
if (descr instanceof GetSetDescriptor getSetDescriptor) {
// Bypass getset_descriptor.__get__
assert getSetDescriptor.getGet() != null;
return callGet.executeObject(frame, getSetDescriptor.getGet(), object);
}
return descr;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy