this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "type-utils.h"
3
4#include "api-handle.h"
5#include "globals.h"
6#include "handles.h"
7#include "runtime.h"
8#include "symbols.h"
9#include "thread.h"
10
11namespace py {
12
13static const SymbolId kParamsSelfValue[] = {ID(self), ID(value)};
14static const SymbolId kParamsSelf[] = {ID(self)};
15
16RawObject newExtCode(Thread* thread, const Object& name,
17 View<SymbolId> parameters, word flags,
18 BuiltinFunction function, void* slot_value) {
19 HandleScope scope(thread);
20 Runtime* runtime = thread->runtime();
21 Object code_code(&scope,
22 SmallInt::fromAlignedCPtr(bit_cast<void*>(function)));
23 Tuple empty_tuple(&scope, runtime->emptyTuple());
24 Object varnames_obj(&scope, *empty_tuple);
25
26 word num_parameters = parameters.length();
27 if (num_parameters > 0) {
28 MutableTuple varnames(&scope, runtime->newMutableTuple(num_parameters));
29 for (word i = 0; i < num_parameters; i++) {
30 varnames.atPut(i, runtime->symbols()->at(parameters.get(i)));
31 }
32 varnames_obj = varnames.becomeImmutable();
33 }
34
35 word argcount = num_parameters - ((flags & Code::Flags::kVarargs) != 0) -
36 ((flags & Code::Flags::kVarkeyargs) != 0);
37 flags |= Code::Flags::kOptimized | Code::Flags::kNewlocals;
38
39 Object filename(&scope, Str::empty());
40 Object lnotab(&scope, Bytes::empty());
41 Object ptr(&scope, runtime->newIntFromCPtr(slot_value));
42 Tuple consts(&scope, runtime->newTupleWith1(ptr));
43 return runtime->newCode(argcount, /*posonlyargcount=*/num_parameters,
44 /*kwonlyargcount=*/0,
45 /*nlocals=*/num_parameters,
46 /*stacksize=*/0, flags, code_code, consts,
47 /*names=*/empty_tuple, varnames_obj,
48 /*freevars=*/empty_tuple, /*cellvars=*/empty_tuple,
49 filename, name, /*firstlineno=*/0, lnotab);
50}
51
52static ALIGN_16 RawObject getterWrapper(Thread* thread, Arguments args) {
53 PyGetSetDef* getset = reinterpret_cast<PyGetSetDef*>(getNativeFunc(thread));
54 getter func = getset->get;
55 void* closure = getset->closure;
56 PyObject* self = ApiHandle::newReference(thread->runtime(), args.get(0));
57 PyObject* result = (*func)(self, closure);
58 ApiHandle::decref(ApiHandle::fromPyObject(self));
59 return ApiHandle::checkFunctionResult(thread, result);
60}
61
62static RawObject getSetGetter(Thread* thread, const Object& name,
63 PyGetSetDef* def) {
64 if (def->get == nullptr) return NoneType::object();
65 HandleScope scope(thread);
66 Runtime* runtime = thread->runtime();
67 Code code(&scope, newExtCode(thread, name, kParamsSelf,
68 /*flags=*/0, getterWrapper,
69 reinterpret_cast<void*>(def)));
70 Object globals(&scope, NoneType::object());
71 Function function(&scope,
72 runtime->newFunctionWithCode(thread, name, code, globals));
73 if (def->doc != nullptr) {
74 Object doc(&scope, runtime->newStrFromCStr(def->doc));
75 function.setDoc(*doc);
76 }
77 return *function;
78}
79
80static ALIGN_16 RawObject setterWrapper(Thread* thread, Arguments args) {
81 PyGetSetDef* getset = reinterpret_cast<PyGetSetDef*>(getNativeFunc(thread));
82 setter func = getset->set;
83 void* closure = getset->closure;
84 Runtime* runtime = thread->runtime();
85 PyObject* self = ApiHandle::newReference(runtime, args.get(0));
86 PyObject* value = ApiHandle::newReference(runtime, args.get(1));
87 int result = func(self, value, closure);
88 ApiHandle::decref(ApiHandle::fromPyObject(self));
89 ApiHandle::decref(ApiHandle::fromPyObject(value));
90 if (result < 0) return Error::exception();
91 return NoneType::object();
92}
93
94static RawObject getSetSetter(Thread* thread, const Object& name,
95 PyGetSetDef* def) {
96 if (def->set == nullptr) return NoneType::object();
97 HandleScope scope(thread);
98 Runtime* runtime = thread->runtime();
99 Code code(&scope, newExtCode(thread, name, kParamsSelfValue,
100 /*flags=*/0, setterWrapper,
101 reinterpret_cast<void*>(def)));
102 Object globals(&scope, NoneType::object());
103 Function function(&scope,
104 runtime->newFunctionWithCode(thread, name, code, globals));
105 if (def->doc != nullptr) {
106 Object doc(&scope, runtime->newStrFromCStr(def->doc));
107 function.setDoc(*doc);
108 }
109 return *function;
110}
111
112RawObject newGetSet(Thread* thread, const Object& name, PyGetSetDef* def) {
113 HandleScope scope(thread);
114 Object getter(&scope, getSetGetter(thread, name, def));
115 Object setter(&scope, getSetSetter(thread, name, def));
116 Object none(&scope, NoneType::object());
117 return thread->runtime()->newProperty(getter, setter, none);
118}
119
120} // namespace py