Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
d5ba641b
Commit
d5ba641b
authored
Dec 13, 2014
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'getitem'
parents
15e86e4f
01a0b1a7
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
883 additions
and
109 deletions
+883
-109
Makefile
Makefile
+1
-0
src/capi/modsupport.cpp
src/capi/modsupport.cpp
+145
-9
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+459
-15
src/capi/types.h
src/capi/types.h
+6
-7
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+5
-4
src/runtime/builtin_modules/sys.cpp
src/runtime/builtin_modules/sys.cpp
+1
-1
src/runtime/capi.cpp
src/runtime/capi.cpp
+14
-6
src/runtime/classobj.cpp
src/runtime/classobj.cpp
+4
-4
src/runtime/dict.cpp
src/runtime/dict.cpp
+1
-1
src/runtime/generator.cpp
src/runtime/generator.cpp
+2
-2
src/runtime/inline/xrange.cpp
src/runtime/inline/xrange.cpp
+3
-3
src/runtime/iterobject.cpp
src/runtime/iterobject.cpp
+1
-1
src/runtime/list.cpp
src/runtime/list.cpp
+1
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+16
-2
src/runtime/set.cpp
src/runtime/set.cpp
+1
-1
src/runtime/str.cpp
src/runtime/str.cpp
+1
-1
src/runtime/super.cpp
src/runtime/super.cpp
+1
-1
src/runtime/tuple.cpp
src/runtime/tuple.cpp
+2
-1
src/runtime/types.cpp
src/runtime/types.cpp
+32
-29
src/runtime/types.h
src/runtime/types.h
+26
-4
test/test_extension/slots_test.c
test/test_extension/slots_test.c
+142
-12
test/tests/capi_slots.py
test/tests/capi_slots.py
+19
-4
No files found.
Makefile
View file @
d5ba641b
...
...
@@ -142,6 +142,7 @@ COMMON_CXXFLAGS += -fexceptions -fno-rtti
COMMON_CXXFLAGS
+=
-Wno-invalid-offsetof
# allow the use of "offsetof", and we'll just have to make sure to only use it legally.
COMMON_CXXFLAGS
+=
-DENABLE_INTEL_JIT_EVENTS
=
$(ENABLE_INTEL_JIT_EVENTS)
COMMON_CXXFLAGS
+=
-I
$(DEPS_DIR)
/pypa-install/include
COMMON_CXXFLAGS
+=
-Wno-comment
ifeq
($(ENABLE_VALGRIND),0)
COMMON_CXXFLAGS
+=
-DNVALGRIND
...
...
src/capi/modsupport.cpp
View file @
d5ba641b
...
...
@@ -32,24 +32,160 @@ namespace pyston {
#define FLAG_SIZE_T 1
static
PyObject
*
va_build_value
(
const
char
*
fmt
,
va_list
va
,
int
flags
)
{
int
len
=
strlen
(
fmt
);
if
(
len
==
0
)
return
None
;
static
int
countformat
(
const
char
*
format
,
int
endchar
)
{
int
count
=
0
;
int
level
=
0
;
while
(
level
>
0
||
*
format
!=
endchar
)
{
switch
(
*
format
)
{
case
'\0'
:
/* Premature end */
PyErr_SetString
(
PyExc_SystemError
,
"unmatched paren in format"
);
return
-
1
;
case
'('
:
case
'['
:
case
'{'
:
if
(
level
==
0
)
count
++
;
level
++
;
break
;
case
')'
:
case
']'
:
case
'}'
:
level
--
;
break
;
case
'#'
:
case
'&'
:
case
','
:
case
':'
:
case
' '
:
case
'\t'
:
break
;
default:
if
(
level
==
0
)
count
++
;
}
format
++
;
}
return
count
;
}
static
PyObject
*
do_mktuple
(
const
char
**
,
va_list
*
,
int
,
int
,
int
)
noexcept
;
// static PyObject *do_mklist(const char**, va_list *, int, int, int) noexcept;
// static PyObject *do_mkdict(const char**, va_list *, int, int, int) noexcept;
static
PyObject
*
do_mkvalue
(
const
char
**
,
va_list
*
,
int
)
noexcept
;
static
PyObject
*
do_mkvalue
(
const
char
**
p_format
,
va_list
*
p_va
,
int
flags
)
noexcept
{
for
(;;)
{
switch
(
*
(
*
p_format
)
++
)
{
case
'('
:
return
do_mktuple
(
p_format
,
p_va
,
')'
,
countformat
(
*
p_format
,
')'
),
flags
);
#if 0
case '[':
return do_mklist(p_format, p_va, ']', countformat(*p_format, ']'), flags);
case '{':
return do_mkdict(p_format, p_va, '}', countformat(*p_format, '}'), flags);
#endif
if
(
len
==
1
)
{
switch
(
*
fmt
)
{
case
'b'
:
case
'B'
:
case
'h'
:
case
'i'
:
return
PyInt_FromLong
((
long
)
va_arg
(
va
,
int
));
return
PyInt_FromLong
((
long
)
va_arg
(
*
p_va
,
int
));
case
'H'
:
return
PyInt_FromLong
((
long
)
va_arg
(
*
p_va
,
unsigned
int
));
case
'N'
:
case
'S'
:
case
'O'
:
if
(
**
p_format
==
'&'
)
{
typedef
PyObject
*
(
*
converter
)(
void
*
);
converter
func
=
va_arg
(
*
p_va
,
converter
);
void
*
arg
=
va_arg
(
*
p_va
,
void
*
);
++*
p_format
;
return
(
*
func
)(
arg
);
}
else
{
PyObject
*
v
;
v
=
va_arg
(
*
p_va
,
PyObject
*
);
if
(
v
!=
NULL
)
{
if
(
*
(
*
p_format
-
1
)
!=
'N'
)
Py_INCREF
(
v
);
}
else
if
(
!
PyErr_Occurred
())
/* If a NULL was passed
* because a call that should
* have constructed a value
* failed, that's OK, and we
* pass the error on; but if
* no error occurred it's not
* clear that the caller knew
* what she was doing. */
PyErr_SetString
(
PyExc_SystemError
,
"NULL object passed to Py_BuildValue"
);
return
v
;
}
default:
RELEASE_ASSERT
(
0
,
"%c"
,
*
fmt
);
RELEASE_ASSERT
(
0
,
"%c"
,
*
((
*
p_format
)
-
1
)
);
}
}
abort
();
}
static
PyObject
*
do_mktuple
(
const
char
**
p_format
,
va_list
*
p_va
,
int
endchar
,
int
n
,
int
flags
)
noexcept
{
PyObject
*
v
;
int
i
;
int
itemfailed
=
0
;
if
(
n
<
0
)
return
NULL
;
if
((
v
=
PyTuple_New
(
n
))
==
NULL
)
return
NULL
;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
w
=
do_mkvalue
(
p_format
,
p_va
,
flags
);
if
(
w
==
NULL
)
{
itemfailed
=
1
;
Py_INCREF
(
Py_None
);
w
=
Py_None
;
}
PyTuple_SET_ITEM
(
v
,
i
,
w
);
}
if
(
itemfailed
)
{
/* do_mkvalue() should have already set an error */
Py_DECREF
(
v
);
return
NULL
;
}
if
(
**
p_format
!=
endchar
)
{
Py_DECREF
(
v
);
PyErr_SetString
(
PyExc_SystemError
,
"Unmatched paren in format"
);
return
NULL
;
}
if
(
endchar
)
++*
p_format
;
return
v
;
}
static
PyObject
*
va_build_value
(
const
char
*
fmt
,
va_list
va
,
int
flags
)
{
int
n
=
countformat
(
fmt
,
'\0'
);
if
(
n
<
0
)
return
NULL
;
if
(
n
==
0
)
return
None
;
va_list
lva
;
__va_copy
(
lva
,
va
);
if
(
n
==
1
)
return
do_mkvalue
(
&
fmt
,
&
lva
,
flags
);
return
do_mktuple
(
&
fmt
,
&
lva
,
'\0'
,
n
,
flags
);
}
RELEASE_ASSERT
(
0
,
""
);
extern
"C"
PyObject
*
Py_VaBuildValue
(
const
char
*
format
,
va_list
va
)
{
return
va_build_value
(
format
,
va
,
0
);
}
extern
"C"
PyObject
*
_Py_BuildValue_SizeT
(
const
char
*
fmt
,
...)
{
...
...
src/capi/typeobject.cpp
View file @
d5ba641b
...
...
@@ -52,7 +52,243 @@ static PyObject* wrap_unaryfunc(PyObject* self, PyObject* args, void* wrapped) {
return
(
*
func
)(
self
);
}
PyObject
*
Py_CallPythonNew
(
PyTypeObject
*
self
,
PyObject
*
args
,
PyObject
*
kwds
)
{
static
PyObject
*
wrap_binaryfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
binaryfunc
func
=
(
binaryfunc
)
wrapped
;
PyObject
*
other
;
if
(
!
check_num_args
(
args
,
1
))
return
NULL
;
other
=
PyTuple_GET_ITEM
(
args
,
0
);
return
(
*
func
)(
self
,
other
);
}
static
Py_ssize_t
getindex
(
PyObject
*
self
,
PyObject
*
arg
)
noexcept
{
Py_ssize_t
i
;
i
=
PyNumber_AsSsize_t
(
arg
,
PyExc_OverflowError
);
if
(
i
==
-
1
&&
PyErr_Occurred
())
return
-
1
;
if
(
i
<
0
)
{
PySequenceMethods
*
sq
=
Py_TYPE
(
self
)
->
tp_as_sequence
;
if
(
sq
&&
sq
->
sq_length
)
{
Py_ssize_t
n
=
(
*
sq
->
sq_length
)(
self
);
if
(
n
<
0
)
return
-
1
;
i
+=
n
;
}
}
return
i
;
}
static
PyObject
*
wrap_lenfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
lenfunc
func
=
(
lenfunc
)
wrapped
;
Py_ssize_t
res
;
if
(
!
check_num_args
(
args
,
0
))
return
NULL
;
res
=
(
*
func
)(
self
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
return
PyInt_FromLong
((
long
)
res
);
}
static
PyObject
*
wrap_indexargfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
ssizeargfunc
func
=
(
ssizeargfunc
)
wrapped
;
PyObject
*
o
;
Py_ssize_t
i
;
if
(
!
PyArg_UnpackTuple
(
args
,
""
,
1
,
1
,
&
o
))
return
NULL
;
i
=
PyNumber_AsSsize_t
(
o
,
PyExc_OverflowError
);
if
(
i
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
return
(
*
func
)(
self
,
i
);
}
static
PyObject
*
wrap_sq_item
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
ssizeargfunc
func
=
(
ssizeargfunc
)
wrapped
;
PyObject
*
arg
;
Py_ssize_t
i
;
if
(
PyTuple_GET_SIZE
(
args
)
==
1
)
{
arg
=
PyTuple_GET_ITEM
(
args
,
0
);
i
=
getindex
(
self
,
arg
);
if
(
i
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
return
(
*
func
)(
self
,
i
);
}
check_num_args
(
args
,
1
);
assert
(
PyErr_Occurred
());
return
NULL
;
}
static
PyObject
*
wrap_ssizessizeargfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
ssizessizeargfunc
func
=
(
ssizessizeargfunc
)
wrapped
;
Py_ssize_t
i
,
j
;
if
(
!
PyArg_ParseTuple
(
args
,
"nn"
,
&
i
,
&
j
))
return
NULL
;
return
(
*
func
)(
self
,
i
,
j
);
}
static
PyObject
*
wrap_sq_setitem
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
ssizeobjargproc
func
=
(
ssizeobjargproc
)
wrapped
;
Py_ssize_t
i
;
int
res
;
PyObject
*
arg
,
*
value
;
if
(
!
PyArg_UnpackTuple
(
args
,
""
,
2
,
2
,
&
arg
,
&
value
))
return
NULL
;
i
=
getindex
(
self
,
arg
);
if
(
i
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
res
=
(
*
func
)(
self
,
i
,
value
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
static
PyObject
*
wrap_sq_delitem
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
ssizeobjargproc
func
=
(
ssizeobjargproc
)
wrapped
;
Py_ssize_t
i
;
int
res
;
PyObject
*
arg
;
if
(
!
check_num_args
(
args
,
1
))
return
NULL
;
arg
=
PyTuple_GET_ITEM
(
args
,
0
);
i
=
getindex
(
self
,
arg
);
if
(
i
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
res
=
(
*
func
)(
self
,
i
,
NULL
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
static
PyObject
*
wrap_ssizessizeobjargproc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
ssizessizeobjargproc
func
=
(
ssizessizeobjargproc
)
wrapped
;
Py_ssize_t
i
,
j
;
int
res
;
PyObject
*
value
;
if
(
!
PyArg_ParseTuple
(
args
,
"nnO"
,
&
i
,
&
j
,
&
value
))
return
NULL
;
res
=
(
*
func
)(
self
,
i
,
j
,
value
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
static
PyObject
*
wrap_delslice
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
ssizessizeobjargproc
func
=
(
ssizessizeobjargproc
)
wrapped
;
Py_ssize_t
i
,
j
;
int
res
;
if
(
!
PyArg_ParseTuple
(
args
,
"nn"
,
&
i
,
&
j
))
return
NULL
;
res
=
(
*
func
)(
self
,
i
,
j
,
NULL
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
/* XXX objobjproc is a misnomer; should be objargpred */
static
PyObject
*
wrap_objobjproc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
objobjproc
func
=
(
objobjproc
)
wrapped
;
int
res
;
PyObject
*
value
;
if
(
!
check_num_args
(
args
,
1
))
return
NULL
;
value
=
PyTuple_GET_ITEM
(
args
,
0
);
res
=
(
*
func
)(
self
,
value
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
else
return
PyBool_FromLong
(
res
);
}
static
PyObject
*
wrap_objobjargproc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
objobjargproc
func
=
(
objobjargproc
)
wrapped
;
int
res
;
PyObject
*
key
,
*
value
;
if
(
!
PyArg_UnpackTuple
(
args
,
""
,
2
,
2
,
&
key
,
&
value
))
return
NULL
;
res
=
(
*
func
)(
self
,
key
,
value
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
static
PyObject
*
wrap_delitem
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
objobjargproc
func
=
(
objobjargproc
)
wrapped
;
int
res
;
PyObject
*
key
;
if
(
!
check_num_args
(
args
,
1
))
return
NULL
;
key
=
PyTuple_GET_ITEM
(
args
,
0
);
res
=
(
*
func
)(
self
,
key
,
NULL
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
static
PyObject
*
lookup_maybe
(
PyObject
*
self
,
const
char
*
attrstr
,
PyObject
**
attrobj
)
{
PyObject
*
res
;
// TODO: CPython uses the attrobj as a cache
Box
*
obj
=
typeLookup
(
self
->
cls
,
attrstr
,
NULL
);
if
(
obj
)
return
processDescriptor
(
obj
,
self
,
self
->
cls
);
return
obj
;
}
// Copied from CPython:
static
PyObject
*
call_method
(
PyObject
*
o
,
const
char
*
name
,
PyObject
**
nameobj
,
const
char
*
format
,
...)
noexcept
{
va_list
va
;
PyObject
*
args
,
*
func
=
0
,
*
retval
;
va_start
(
va
,
format
);
func
=
lookup_maybe
(
o
,
name
,
nameobj
);
if
(
func
==
NULL
)
{
va_end
(
va
);
if
(
!
PyErr_Occurred
())
PyErr_SetObject
(
PyExc_AttributeError
,
*
nameobj
);
return
NULL
;
}
if
(
format
&&
*
format
)
args
=
Py_VaBuildValue
(
format
,
va
);
else
args
=
PyTuple_New
(
0
);
va_end
(
va
);
if
(
args
==
NULL
)
return
NULL
;
assert
(
PyTuple_Check
(
args
));
retval
=
PyObject_Call
(
func
,
args
,
NULL
);
Py_DECREF
(
args
);
Py_DECREF
(
func
);
return
retval
;
}
PyObject
*
slot_tp_new
(
PyTypeObject
*
self
,
PyObject
*
args
,
PyObject
*
kwds
)
noexcept
{
try
{
// TODO: runtime ICs?
Box
*
new_attr
=
typeLookup
(
self
,
_new_str
,
NULL
);
...
...
@@ -65,7 +301,7 @@ PyObject* Py_CallPythonNew(PyTypeObject* self, PyObject* args, PyObject* kwds) {
}
}
PyObject
*
Py_CallPythonCall
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kwds
)
{
PyObject
*
slot_tp_call
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kwds
)
noexcept
{
try
{
Py_FatalError
(
"this function is untested"
);
...
...
@@ -76,7 +312,7 @@ PyObject* Py_CallPythonCall(PyObject* self, PyObject* args, PyObject* kwds) {
}
}
PyObject
*
Py_CallPythonRepr
(
PyObject
*
self
)
{
PyObject
*
slot_tp_repr
(
PyObject
*
self
)
noexcept
{
try
{
return
repr
(
self
);
}
catch
(
Box
*
e
)
{
...
...
@@ -84,18 +320,173 @@ PyObject* Py_CallPythonRepr(PyObject* self) {
}
}
PyObject
*
slot_sq_item
(
PyObject
*
self
,
Py_ssize_t
i
)
noexcept
{
try
{
return
getitem
(
self
,
boxInt
(
i
));
}
catch
(
Box
*
e
)
{
abort
();
}
}
static
Py_ssize_t
slot_sq_length
(
PyObject
*
self
)
{
static
PyObject
*
len_str
;
PyObject
*
res
=
call_method
(
self
,
"__len__"
,
&
len_str
,
"()"
);
Py_ssize_t
len
;
if
(
res
==
NULL
)
return
-
1
;
len
=
PyInt_AsSsize_t
(
res
);
Py_DECREF
(
res
);
if
(
len
<
0
)
{
if
(
!
PyErr_Occurred
())
PyErr_SetString
(
PyExc_ValueError
,
"__len__() should return >= 0"
);
return
-
1
;
}
return
len
;
}
static
PyObject
*
slot_sq_slice
(
PyObject
*
self
,
Py_ssize_t
i
,
Py_ssize_t
j
)
{
static
PyObject
*
getslice_str
;
if
(
PyErr_WarnPy3k
(
"in 3.x, __getslice__ has been removed; "
"use __getitem__"
,
1
)
<
0
)
return
NULL
;
return
call_method
(
self
,
"__getslice__"
,
&
getslice_str
,
"nn"
,
i
,
j
);
}
static
int
slot_sq_ass_item
(
PyObject
*
self
,
Py_ssize_t
index
,
PyObject
*
value
)
{
PyObject
*
res
;
static
PyObject
*
delitem_str
,
*
setitem_str
;
if
(
value
==
NULL
)
res
=
call_method
(
self
,
"__delitem__"
,
&
delitem_str
,
"(n)"
,
index
);
else
res
=
call_method
(
self
,
"__setitem__"
,
&
setitem_str
,
"(nO)"
,
index
,
value
);
if
(
res
==
NULL
)
return
-
1
;
Py_DECREF
(
res
);
return
0
;
}
static
int
slot_sq_ass_slice
(
PyObject
*
self
,
Py_ssize_t
i
,
Py_ssize_t
j
,
PyObject
*
value
)
{
PyObject
*
res
;
static
PyObject
*
delslice_str
,
*
setslice_str
;
if
(
value
==
NULL
)
{
if
(
PyErr_WarnPy3k
(
"in 3.x, __delslice__ has been removed; "
"use __delitem__"
,
1
)
<
0
)
return
-
1
;
res
=
call_method
(
self
,
"__delslice__"
,
&
delslice_str
,
"(nn)"
,
i
,
j
);
}
else
{
if
(
PyErr_WarnPy3k
(
"in 3.x, __setslice__ has been removed; "
"use __setitem__"
,
1
)
<
0
)
return
-
1
;
res
=
call_method
(
self
,
"__setslice__"
,
&
setslice_str
,
"(nnO)"
,
i
,
j
,
value
);
}
if
(
res
==
NULL
)
return
-
1
;
Py_DECREF
(
res
);
return
0
;
}
static
int
slot_sq_contains
(
PyObject
*
self
,
PyObject
*
value
)
{
PyObject
*
func
,
*
res
,
*
args
;
int
result
=
-
1
;
static
PyObject
*
contains_str
;
func
=
lookup_maybe
(
self
,
"__contains__"
,
&
contains_str
);
if
(
func
!=
NULL
)
{
args
=
PyTuple_Pack
(
1
,
value
);
if
(
args
==
NULL
)
res
=
NULL
;
else
{
res
=
PyObject_Call
(
func
,
args
,
NULL
);
Py_DECREF
(
args
);
}
Py_DECREF
(
func
);
if
(
res
!=
NULL
)
{
result
=
PyObject_IsTrue
(
res
);
Py_DECREF
(
res
);
}
}
else
if
(
!
PyErr_Occurred
())
{
/* Possible results: -1 and 1 */
Py_FatalError
(
"unimplemented"
);
// result = (int)_PySequence_IterSearch(self, value, PY_ITERSEARCH_CONTAINS);
}
return
result
;
}
// Copied from CPython:
#define SLOT0(FUNCNAME, OPSTR) \
static PyObject* FUNCNAME(PyObject* self) noexcept { \
static PyObject* cache_str; \
return call_method(self, OPSTR, &cache_str, "()"); \
}
#define SLOT1(FUNCNAME, OPSTR, ARG1TYPE, ARGCODES) \
static PyObject* FUNCNAME(PyObject* self, ARG1TYPE arg1) noexcept { \
static PyObject* cache_str; \
return call_method(self, OPSTR, &cache_str, "(" ARGCODES ")", arg1); \
}
#define slot_mp_length slot_sq_length
SLOT1
(
slot_mp_subscript
,
"__getitem__"
,
PyObject
*
,
"O"
)
static
int
slot_mp_ass_subscript
(
PyObject
*
self
,
PyObject
*
key
,
PyObject
*
value
)
{
PyObject
*
res
;
static
PyObject
*
delitem_str
,
*
setitem_str
;
if
(
value
==
NULL
)
res
=
call_method
(
self
,
"__delitem__"
,
&
delitem_str
,
"(O)"
,
key
);
else
res
=
call_method
(
self
,
"__setitem__"
,
&
setitem_str
,
"(OO)"
,
key
,
value
);
if
(
res
==
NULL
)
return
-
1
;
Py_DECREF
(
res
);
return
0
;
}
typedef
wrapper_def
slotdef
;
static
void
**
slotptr
(
BoxedClass
*
self
,
int
offset
)
{
// TODO handle indices into the indirected portions (tp_as_sequence, etc)
char
*
ptr
=
reinterpret_cast
<
char
*>
(
self
);
return
reinterpret_cast
<
void
**>
(
ptr
+
offset
);
static
void
**
slotptr
(
BoxedClass
*
type
,
int
offset
)
{
// We use the index into PyHeapTypeObject as the canonical way to represent offsets, even though we are not
// (currently) using that object representation
// copied from CPython:
/* Note: this depends on the order of the members of PyHeapTypeObject! */
assert
(
offset
>=
0
);
assert
((
size_t
)
offset
<
offsetof
(
PyHeapTypeObject
,
as_buffer
));
char
*
ptr
;
if
((
size_t
)
offset
>=
offsetof
(
PyHeapTypeObject
,
as_sequence
))
{
ptr
=
(
char
*
)
type
->
tp_as_sequence
;
offset
-=
offsetof
(
PyHeapTypeObject
,
as_sequence
);
}
else
if
((
size_t
)
offset
>=
offsetof
(
PyHeapTypeObject
,
as_mapping
))
{
ptr
=
(
char
*
)
type
->
tp_as_mapping
;
offset
-=
offsetof
(
PyHeapTypeObject
,
as_mapping
);
}
else
if
((
size_t
)
offset
>=
offsetof
(
PyHeapTypeObject
,
as_number
))
{
ptr
=
(
char
*
)
type
->
tp_as_number
;
offset
-=
offsetof
(
PyHeapTypeObject
,
as_number
);
}
else
{
ptr
=
(
char
*
)
type
;
}
if
(
ptr
!=
NULL
)
ptr
+=
offset
;
return
(
void
**
)
ptr
;
}
static
void
update_one_slot
(
BoxedClass
*
self
,
const
slotdef
&
p
)
{
// TODO: CPython version is significantly more sophisticated
void
**
ptr
=
slotptr
(
self
,
p
.
offset
);
assert
(
ptr
);
if
(
!
ptr
)
{
assert
(
!
typeLookup
(
self
,
p
.
name
,
NULL
)
&&
"I don't think this case should happen? CPython handles it though"
);
return
;
}
if
(
typeLookup
(
self
,
p
.
name
,
NULL
))
*
ptr
=
p
.
function
;
...
...
@@ -103,11 +494,66 @@ static void update_one_slot(BoxedClass* self, const slotdef& p) {
*
ptr
=
NULL
;
}
// Copied from CPython:
#define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
{ NAME, offsetof(PyTypeObject, SLOT), (void*)(FUNCTION), WRAPPER, PyDoc_STR(DOC), 0 }
#define FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS) \
{ NAME, offsetof(PyTypeObject, SLOT), (void*)(FUNCTION), WRAPPER, PyDoc_STR(DOC), FLAGS }
#define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
{ NAME, offsetof(PyHeapTypeObject, SLOT), (void*)(FUNCTION), WRAPPER, PyDoc_STR(DOC), 0 }
#define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC)
#define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER, DOC)
#define NBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, DOC)
#define UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, "x." NAME "() <==> " DOC)
#define IBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, "x." NAME "(y) <==> x" DOC "y")
#define BINSLOT(NAME, SLOT, FUNCTION, DOC) \
ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, "x." NAME "(y) <==> x" DOC "y")
#define RBINSLOT(NAME, SLOT, FUNCTION, DOC) \
ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, "x." NAME "(y) <==> y" DOC "x")
#define BINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \
ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, "x." NAME "(y) <==> " DOC)
#define RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \
ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, "x." NAME "(y) <==> " DOC)
static
slotdef
slotdefs
[]
=
{
{
"__repr__"
,
offsetof
(
PyTypeObject
,
tp_repr
),
(
void
*
)
&
Py_CallPythonRepr
,
wrap_unaryfunc
,
0
},
{
"__call__"
,
offsetof
(
PyTypeObject
,
tp_call
),
(
void
*
)
&
Py_CallPythonCall
,
(
wrapperfunc
)
wrap_call
,
PyWrapperFlag_KEYWORDS
},
{
"__new__"
,
offsetof
(
PyTypeObject
,
tp_new
),
(
void
*
)
&
Py_CallPythonNew
,
NULL
,
0
},
TPSLOT
(
"__repr__"
,
tp_repr
,
slot_tp_repr
,
wrap_unaryfunc
,
"x.__repr__() <==> repr(x)"
),
FLSLOT
(
"__call__"
,
tp_call
,
slot_tp_call
,
(
wrapperfunc
)
wrap_call
,
"x.__call__(...) <==> x(...)"
,
PyWrapperFlag_KEYWORDS
),
TPSLOT
(
"__new__"
,
tp_new
,
slot_tp_new
,
NULL
,
""
),
MPSLOT
(
"__len__"
,
mp_length
,
slot_mp_length
,
wrap_lenfunc
,
"x.__len__() <==> len(x)"
),
MPSLOT
(
"__getitem__"
,
mp_subscript
,
slot_mp_subscript
,
wrap_binaryfunc
,
"x.__getitem__(y) <==> x[y]"
),
MPSLOT
(
"__setitem__"
,
mp_ass_subscript
,
slot_mp_ass_subscript
,
wrap_objobjargproc
,
"x.__setitem__(i, y) <==> x[i]=y"
),
MPSLOT
(
"__delitem__"
,
mp_ass_subscript
,
slot_mp_ass_subscript
,
wrap_delitem
,
"x.__delitem__(y) <==> del x[y]"
),
SQSLOT
(
"__len__"
,
sq_length
,
slot_sq_length
,
wrap_lenfunc
,
"x.__len__() <==> len(x)"
),
/* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
The logic in abstract.c always falls back to nb_add/nb_multiply in
this case. Defining both the nb_* and the sq_* slots to call the
user-defined methods has unexpected side-effects, as shown by
test_descr.notimplemented() */
SQSLOT
(
"__add__"
,
sq_concat
,
NULL
,
wrap_binaryfunc
,
"x.__add__(y) <==> x+y"
),
SQSLOT
(
"__mul__"
,
sq_repeat
,
NULL
,
wrap_indexargfunc
,
"x.__mul__(n) <==> x*n"
),
SQSLOT
(
"__rmul__"
,
sq_repeat
,
NULL
,
wrap_indexargfunc
,
"x.__rmul__(n) <==> n*x"
),
SQSLOT
(
"__getitem__"
,
sq_item
,
slot_sq_item
,
wrap_sq_item
,
"x.__getitem__(y) <==> x[y]"
),
SQSLOT
(
"__getslice__"
,
sq_slice
,
slot_sq_slice
,
wrap_ssizessizeargfunc
,
"x.__getslice__(i, j) <==> x[i:j]
\n
\
\n
\
Use of negative indices is not supported."
),
SQSLOT
(
"__setitem__"
,
sq_ass_item
,
slot_sq_ass_item
,
wrap_sq_setitem
,
"x.__setitem__(i, y) <==> x[i]=y"
),
SQSLOT
(
"__delitem__"
,
sq_ass_item
,
slot_sq_ass_item
,
wrap_sq_delitem
,
"x.__delitem__(y) <==> del x[y]"
),
SQSLOT
(
"__setslice__"
,
sq_ass_slice
,
slot_sq_ass_slice
,
wrap_ssizessizeobjargproc
,
"x.__setslice__(i, j, y) <==> x[i:j]=y
\n
\
\n
\
Use of negative indices is not supported."
),
SQSLOT
(
"__delslice__"
,
sq_ass_slice
,
slot_sq_ass_slice
,
wrap_delslice
,
"x.__delslice__(i, j) <==> del x[i:j]
\n
\
\n
\
Use of negative indices is not supported."
),
SQSLOT
(
"__contains__"
,
sq_contains
,
slot_sq_contains
,
wrap_objobjproc
,
"x.__contains__(y) <==> y in x"
),
SQSLOT
(
"__iadd__"
,
sq_inplace_concat
,
NULL
,
wrap_binaryfunc
,
"x.__iadd__(y) <==> x+=y"
),
SQSLOT
(
"__imul__"
,
sq_inplace_repeat
,
NULL
,
wrap_indexargfunc
,
"x.__imul__(y) <==> x*=y"
),
};
static
void
init_slotdefs
()
{
...
...
@@ -195,7 +641,7 @@ static void add_operators(BoxedClass* cls) {
continue
;
// TODO PyObject_HashNotImplemented
cls
->
giveAttr
(
p
.
name
,
new
BoxedWrapperDescriptor
(
&
p
,
cls
));
cls
->
giveAttr
(
p
.
name
,
new
BoxedWrapperDescriptor
(
&
p
,
cls
,
*
ptr
));
}
if
(
cls
->
tp_new
)
...
...
@@ -215,8 +661,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) {
RELEASE_ASSERT
(
cls
->
tp_setattr
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_compare
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_as_number
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_as_sequence
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_as_mapping
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_hash
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_str
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_getattro
==
NULL
||
cls
->
tp_getattro
==
PyObject_GenericGetAttr
,
""
);
...
...
src/capi/types.h
View file @
d5ba641b
...
...
@@ -27,7 +27,7 @@ struct wrapper_def {
int
offset
;
void
*
function
;
// "generic" handler that gets put in the tp_* slot which proxies to the python version
wrapperfunc
wrapper
;
// "wrapper" that ends up getting called by the Python-visible WrapperDescr
// exists in CPython: const char* doc
const
char
*
doc
;
int
flags
;
// exists in CPython: PyObject *name_strobj
};
...
...
@@ -83,8 +83,9 @@ class BoxedWrapperDescriptor : public Box {
public:
const
wrapper_def
*
wrapper
;
BoxedClass
*
type
;
BoxedWrapperDescriptor
(
const
wrapper_def
*
wrapper
,
BoxedClass
*
type
)
:
Box
(
wrapperdescr_cls
),
wrapper
(
wrapper
),
type
(
type
)
{}
void
*
wrapped
;
BoxedWrapperDescriptor
(
const
wrapper_def
*
wrapper
,
BoxedClass
*
type
,
void
*
wrapped
)
:
Box
(
wrapperdescr_cls
),
wrapper
(
wrapper
),
type
(
type
),
wrapped
(
wrapped
)
{}
static
Box
*
__get__
(
BoxedWrapperDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
);
};
...
...
@@ -104,14 +105,12 @@ public:
int
flags
=
self
->
descr
->
wrapper
->
flags
;
wrapperfunc
wrapper
=
self
->
descr
->
wrapper
->
wrapper
;
assert
(
self
->
descr
->
wrapper
->
offset
>
0
);
char
*
ptr
=
(
char
*
)
self
->
descr
->
type
+
self
->
descr
->
wrapper
->
offset
;
void
*
wrapped
=
*
reinterpret_cast
<
void
**>
(
ptr
);
if
(
flags
&
PyWrapperFlag_KEYWORDS
)
{
wrapperfunc_kwds
wk
=
(
wrapperfunc_kwds
)
wrapper
;
return
(
*
wk
)(
self
->
obj
,
args
,
wrapped
,
kwds
);
return
(
*
wk
)(
self
->
obj
,
args
,
self
->
descr
->
wrapped
,
kwds
);
}
else
{
return
(
*
wrapper
)(
self
->
obj
,
args
,
wrapped
);
return
(
*
wrapper
)(
self
->
obj
,
args
,
self
->
descr
->
wrapped
);
}
abort
();
}
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
d5ba641b
...
...
@@ -497,7 +497,7 @@ Box* exceptionRepr(Box* b) {
static
BoxedClass
*
makeBuiltinException
(
BoxedClass
*
base
,
const
char
*
name
)
{
BoxedClass
*
cls
=
new
BoxedClass
(
type_cls
,
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
sizeof
(
BoxedException
),
false
);
=
new
Boxed
Heap
Class
(
type_cls
,
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
sizeof
(
BoxedException
),
false
);
cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
name
));
cls
->
giveAttr
(
"__module__"
,
boxStrConstant
(
"exceptions"
));
...
...
@@ -521,7 +521,7 @@ extern "C" PyObject* PyErr_NewException(char* name, PyObject* _base, PyObject* d
try
{
BoxedClass
*
base
=
Exception
;
BoxedClass
*
cls
=
new
BoxedClass
(
type_cls
,
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
sizeof
(
BoxedException
),
true
);
=
new
Boxed
Heap
Class
(
type_cls
,
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
sizeof
(
BoxedException
),
true
);
char
*
dot_pos
=
strchr
(
name
,
'.'
);
RELEASE_ASSERT
(
dot_pos
,
""
);
...
...
@@ -702,7 +702,7 @@ void setupBuiltins() {
builtins_module
->
giveAttr
(
"print"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
print
,
NONE
,
0
,
0
,
true
,
true
)));
notimplemented_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
notimplemented_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
notimplemented_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"NotImplementedType"
));
notimplemented_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
notimplementedRepr
,
STR
,
1
)));
notimplemented_cls
->
freeze
();
...
...
@@ -795,7 +795,8 @@ void setupBuiltins() {
builtins_module
->
giveAttr
(
"issubclass"
,
issubclass_obj
);
enumerate_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedEnumerate
::
gcHandler
,
0
,
sizeof
(
BoxedEnumerate
),
false
);
enumerate_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
BoxedEnumerate
::
gcHandler
,
0
,
sizeof
(
BoxedEnumerate
),
false
);
enumerate_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"enumerate"
));
enumerate_cls
->
giveAttr
(
"__new__"
,
...
...
src/runtime/builtin_modules/sys.cpp
View file @
d5ba641b
...
...
@@ -126,7 +126,7 @@ void setupSys() {
sys_module
->
giveAttr
(
"maxint"
,
boxInt
(
PYSTON_INT_MAX
));
sys_flags_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
BoxedSysFlags
::
gcHandler
,
0
,
sizeof
(
BoxedSysFlags
),
false
);
sys_flags_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
BoxedSysFlags
::
gcHandler
,
0
,
sizeof
(
BoxedSysFlags
),
false
);
sys_flags_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"flags"
));
sys_flags_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedSysFlags
::
__new__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
...
...
src/runtime/capi.cpp
View file @
d5ba641b
...
...
@@ -322,7 +322,10 @@ extern "C" int PyObject_Not(PyObject* o) {
extern
"C"
PyObject
*
PyObject_Call
(
PyObject
*
callable_object
,
PyObject
*
args
,
PyObject
*
kw
)
{
try
{
return
runtimeCall
(
callable_object
,
ArgPassSpec
(
0
,
0
,
true
,
true
),
args
,
kw
,
NULL
,
NULL
,
NULL
);
if
(
kw
)
return
runtimeCall
(
callable_object
,
ArgPassSpec
(
0
,
0
,
true
,
true
),
args
,
kw
,
NULL
,
NULL
,
NULL
);
else
return
runtimeCall
(
callable_object
,
ArgPassSpec
(
0
,
0
,
true
,
false
),
args
,
NULL
,
NULL
,
NULL
,
NULL
);
}
catch
(
Box
*
b
)
{
Py_FatalError
(
"unimplemented"
);
}
...
...
@@ -699,7 +702,12 @@ extern "C" PyObject* PyNumber_ToBase(PyObject* n, int base) {
}
extern
"C"
Py_ssize_t
PyNumber_AsSsize_t
(
PyObject
*
o
,
PyObject
*
exc
)
{
Py_FatalError
(
"unimplemented"
);
RELEASE_ASSERT
(
o
->
cls
!=
long_cls
,
"unhandled"
);
RELEASE_ASSERT
(
o
->
cls
==
int_cls
,
"??"
);
int64_t
n
=
static_cast
<
BoxedInt
*>
(
o
)
->
n
;
static_assert
(
sizeof
(
n
)
==
sizeof
(
Py_ssize_t
),
""
);
return
n
;
}
extern
"C"
Py_ssize_t
PyUnicode_GET_SIZE
(
PyObject
*
)
{
...
...
@@ -753,7 +761,7 @@ BoxedModule* importTestExtension(const std::string& name) {
}
void
setupCAPI
()
{
capifunc_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedCApiFunction
),
false
);
capifunc_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedCApiFunction
),
false
);
capifunc_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"capifunc"
));
capifunc_cls
->
giveAttr
(
"__repr__"
,
...
...
@@ -765,7 +773,7 @@ void setupCAPI() {
capifunc_cls
->
freeze
();
method_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMethodDescriptor
),
false
);
method_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMethodDescriptor
),
false
);
method_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"method"
));
method_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__get__
,
UNKNOWN
,
3
)));
...
...
@@ -773,13 +781,13 @@ void setupCAPI() {
0
,
true
,
true
)));
method_cls
->
freeze
();
wrapperdescr_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperDescriptor
),
false
);
wrapperdescr_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperDescriptor
),
false
);
wrapperdescr_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"wrapper_descriptor"
));
wrapperdescr_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperDescriptor
::
__get__
,
UNKNOWN
,
3
)));
wrapperdescr_cls
->
freeze
();
wrapperobject_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperObject
),
false
);
wrapperobject_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperObject
),
false
);
wrapperobject_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"method-wrapper"
));
wrapperobject_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperObject
::
__call__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
...
...
src/runtime/classobj.cpp
View file @
d5ba641b
...
...
@@ -241,10 +241,10 @@ Box* instanceSetitem(Box* _inst, Box* key, Box* value) {
}
void
setupClassobj
()
{
classobj_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedClassobj
::
gcHandler
,
offsetof
(
BoxedClassobj
,
attrs
),
sizeof
(
BoxedClassobj
),
false
);
instance_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedInstance
::
gcHandler
,
offsetof
(
BoxedInstance
,
attrs
),
sizeof
(
BoxedInstance
),
false
);
classobj_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
BoxedClassobj
::
gcHandler
,
offsetof
(
BoxedClassobj
,
attrs
),
sizeof
(
BoxedClassobj
),
false
);
instance_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
BoxedInstance
::
gcHandler
,
offsetof
(
BoxedInstance
,
attrs
),
sizeof
(
BoxedInstance
),
false
);
classobj_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"classobj"
));
...
...
src/runtime/dict.cpp
View file @
d5ba641b
...
...
@@ -378,7 +378,7 @@ extern "C" void dictIteratorGCHandler(GCVisitor* v, Box* b) {
}
void
setupDict
()
{
dict_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
dictIteratorGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
);
dict_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
dictIteratorGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
);
dict_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"dict"
));
dict_cls
->
giveAttr
(
"__len__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
dictLen
,
BOXED_INT
,
1
)));
...
...
src/runtime/generator.cpp
View file @
d5ba641b
...
...
@@ -177,8 +177,8 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
void
setupGenerator
()
{
generator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
generatorGCHandler
,
offsetof
(
BoxedGenerator
,
attrs
),
sizeof
(
BoxedGenerator
),
false
);
generator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
generatorGCHandler
,
offsetof
(
BoxedGenerator
,
attrs
),
sizeof
(
BoxedGenerator
),
false
);
generator_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"generator"
));
generator_cls
->
giveAttr
(
"__iter__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorIter
,
typeFromClass
(
generator_cls
),
1
)));
...
...
src/runtime/inline/xrange.cpp
View file @
d5ba641b
...
...
@@ -113,10 +113,10 @@ Box* xrangeIter(Box* self) {
}
void
setupXrange
()
{
xrange_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedXrange
),
false
);
xrange_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedXrange
),
false
);
xrange_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"xrange"
));
xrange_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedXrangeIterator
::
xrangeIteratorGCHandler
,
0
,
sizeof
(
BoxedXrangeIterator
),
false
);
xrange_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
BoxedXrangeIterator
::
xrangeIteratorGCHandler
,
0
,
sizeof
(
BoxedXrangeIterator
),
false
);
xrange_iterator_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"rangeiterator"
));
xrange_cls
->
giveAttr
(
...
...
src/runtime/iterobject.cpp
View file @
d5ba641b
...
...
@@ -57,7 +57,7 @@ Box* seqiterNext(Box* s) {
}
void
setupIter
()
{
seqiter_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedSeqIter
),
false
);
seqiter_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedSeqIter
),
false
);
seqiter_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"iterator"
));
seqiter_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqiterNext
,
UNKNOWN
,
1
)));
...
...
src/runtime/list.cpp
View file @
d5ba641b
...
...
@@ -553,7 +553,7 @@ Box* listEq(BoxedList* self, Box* rhs) {
}
void
setupList
()
{
list_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
listIteratorGCHandler
,
0
,
sizeof
(
BoxedList
),
false
);
list_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
listIteratorGCHandler
,
0
,
sizeof
(
BoxedList
),
false
);
list_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"list"
));
...
...
src/runtime/objmodel.cpp
View file @
d5ba641b
...
...
@@ -389,6 +389,20 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_
gc
::
registerPermanentRoot
(
this
);
}
BoxedHeapClass
::
BoxedHeapClass
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
)
:
BoxedClass
(
metaclass
,
base
,
gc_visit
,
attrs_offset
,
instance_size
,
is_user_defined
),
ht_name
(
NULL
),
ht_slots
(
NULL
)
{
tp_as_number
=
&
as_number
;
tp_as_mapping
=
&
as_mapping
;
tp_as_sequence
=
&
as_sequence
;
tp_as_buffer
=
&
as_buffer
;
// just make sure these get zero-initialized:
assert
(
as_sequence
.
sq_item
==
NULL
);
}
std
::
string
getFullNameOfClass
(
BoxedClass
*
cls
)
{
Box
*
b
=
cls
->
getattr
(
"__name__"
);
assert
(
b
);
...
...
@@ -3272,10 +3286,10 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
BoxedClass
*
made
;
if
(
base
->
instancesHaveAttrs
())
{
made
=
new
BoxedClass
(
cls
,
base
,
NULL
,
base
->
attrs_offset
,
base
->
tp_basicsize
,
true
);
made
=
new
Boxed
Heap
Class
(
cls
,
base
,
NULL
,
base
->
attrs_offset
,
base
->
tp_basicsize
,
true
);
}
else
{
assert
(
base
->
tp_basicsize
%
sizeof
(
void
*
)
==
0
);
made
=
new
BoxedClass
(
cls
,
base
,
NULL
,
base
->
tp_basicsize
,
base
->
tp_basicsize
+
sizeof
(
HCAttrs
),
true
);
made
=
new
Boxed
Heap
Class
(
cls
,
base
,
NULL
,
base
->
tp_basicsize
,
base
->
tp_basicsize
+
sizeof
(
HCAttrs
),
true
);
}
made
->
giveAttr
(
"__module__"
,
boxString
(
getCurrentModule
()
->
name
()));
...
...
src/runtime/set.cpp
View file @
d5ba641b
...
...
@@ -216,7 +216,7 @@ void setupSet() {
set_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"set"
));
frozenset_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"frozenset"
));
set_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
setIteratorGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
set_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
setIteratorGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
set_iterator_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"setiterator"
));
set_iterator_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
setiteratorHasnext
,
BOXED_BOOL
,
1
)));
...
...
src/runtime/str.cpp
View file @
d5ba641b
...
...
@@ -1037,7 +1037,7 @@ static PyBufferProcs string_as_buffer = {
};
void
setupStr
()
{
str_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
strIteratorGCHandler
,
0
,
sizeof
(
BoxedString
),
false
);
str_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
strIteratorGCHandler
,
0
,
sizeof
(
BoxedString
),
false
);
str_iterator_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"striterator"
));
str_iterator_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedStringIterator
::
hasnext
,
BOXED_BOOL
,
1
)));
...
...
src/runtime/super.cpp
View file @
d5ba641b
...
...
@@ -125,7 +125,7 @@ Box* superNew(Box* _cls, Box* _type, Box* obj) {
}
void
setupSuper
()
{
super_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedSuper
::
gcHandler
,
0
,
sizeof
(
BoxedSuper
),
false
);
super_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
BoxedSuper
::
gcHandler
,
0
,
sizeof
(
BoxedSuper
),
false
);
super_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"super"
));
...
...
src/runtime/tuple.cpp
View file @
d5ba641b
...
...
@@ -382,7 +382,8 @@ extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
void
setupTuple
()
{
tuple_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
tupleIteratorGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
);
tuple_iterator_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
tupleIteratorGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
);
tuple_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"tuple"
));
...
...
src/runtime/types.cpp
View file @
d5ba641b
...
...
@@ -780,21 +780,22 @@ void setupRuntime() {
root_hcls
=
HiddenClass
::
makeRoot
();
gc
::
registerPermanentRoot
(
root_hcls
);
object_cls
=
new
BoxedClass
(
NULL
,
NULL
,
&
boxGCHandler
,
0
,
sizeof
(
Box
),
false
);
type_cls
=
new
BoxedClass
(
NULL
,
object_cls
,
&
typeGCHandler
,
offsetof
(
BoxedClass
,
attrs
),
sizeof
(
BoxedClass
),
false
);
object_cls
=
new
BoxedHeapClass
(
NULL
,
NULL
,
&
boxGCHandler
,
0
,
sizeof
(
Box
),
false
);
type_cls
=
new
BoxedHeapClass
(
NULL
,
object_cls
,
&
typeGCHandler
,
offsetof
(
BoxedClass
,
attrs
),
sizeof
(
BoxedClass
),
false
);
type_cls
->
cls
=
type_cls
;
object_cls
->
cls
=
type_cls
;
none_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
none_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
None
=
new
Box
(
none_cls
);
gc
::
registerPermanentRoot
(
None
);
// You can't actually have an instance of basestring
basestring_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
basestring_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
// TODO we leak all the string data!
str_cls
=
new
BoxedClass
(
type_cls
,
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedString
),
false
);
unicode_cls
=
new
BoxedClass
(
type_cls
,
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedUnicode
),
false
);
str_cls
=
new
Boxed
Heap
Class
(
type_cls
,
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedString
),
false
);
unicode_cls
=
new
Boxed
Heap
Class
(
type_cls
,
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedUnicode
),
false
);
// It wasn't safe to add __base__ attributes until object+type+str are set up, so do that now:
type_cls
->
giveAttr
(
"__base__"
,
object_cls
);
...
...
@@ -804,40 +805,42 @@ void setupRuntime() {
object_cls
->
giveAttr
(
"__base__"
,
None
);
tuple_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
tupleGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
);
tuple_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
tupleGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
);
EmptyTuple
=
new
BoxedTuple
({});
gc
::
registerPermanentRoot
(
EmptyTuple
);
module_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
offsetof
(
BoxedModule
,
attrs
),
sizeof
(
BoxedModule
),
false
);
module_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
NULL
,
offsetof
(
BoxedModule
,
attrs
),
sizeof
(
BoxedModule
),
false
);
// TODO it'd be nice to be able to do these in the respective setupType methods,
// but those setup methods probably want access to these objects.
// We could have a multi-stage setup process, but that seems overkill for now.
bool_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedBool
),
false
);
int_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedInt
),
false
);
complex_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedComplex
),
false
);
bool_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedBool
),
false
);
int_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedInt
),
false
);
complex_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedComplex
),
false
);
// TODO we're leaking long memory!
long_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedLong
),
false
);
float_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFloat
),
false
);
function_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedFunction
,
attrs
),
sizeof
(
BoxedFunction
),
false
);
long_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedLong
),
false
);
float_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFloat
),
false
);
function_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedFunction
,
attrs
),
sizeof
(
BoxedFunction
),
false
);
instancemethod_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
instancemethodGCHandler
,
0
,
sizeof
(
BoxedInstanceMethod
),
false
);
list_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
listGCHandler
,
0
,
sizeof
(
BoxedList
),
false
);
slice_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
sliceGCHandler
,
0
,
sizeof
(
BoxedSlice
),
false
);
dict_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
dictGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
);
file_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFile
),
false
);
set_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
frozenset_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
member_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
);
closure_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
closureGCHandler
,
offsetof
(
BoxedClosure
,
attrs
),
sizeof
(
BoxedClosure
),
false
);
property_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
propertyGCHandler
,
0
,
sizeof
(
BoxedProperty
),
false
);
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
instancemethodGCHandler
,
0
,
sizeof
(
BoxedInstanceMethod
),
false
);
list_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
listGCHandler
,
0
,
sizeof
(
BoxedList
),
false
);
slice_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
sliceGCHandler
,
0
,
sizeof
(
BoxedSlice
),
false
);
dict_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
dictGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
);
file_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFile
),
false
);
set_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
frozenset_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
member_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
);
closure_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
closureGCHandler
,
offsetof
(
BoxedClosure
,
attrs
),
sizeof
(
BoxedClosure
),
false
);
property_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
propertyGCHandler
,
0
,
sizeof
(
BoxedProperty
),
false
);
staticmethod_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
staticmethodGCHandler
,
0
,
sizeof
(
BoxedStaticmethod
),
false
);
classmethod_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
classmethodGCHandler
,
0
,
sizeof
(
BoxedClassmethod
),
false
);
attrwrapper_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
AttrWrapper
::
gcHandler
,
0
,
sizeof
(
AttrWrapper
),
false
);
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
staticmethodGCHandler
,
0
,
sizeof
(
BoxedStaticmethod
),
false
);
classmethod_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
classmethodGCHandler
,
0
,
sizeof
(
BoxedClassmethod
),
false
);
attrwrapper_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
AttrWrapper
::
gcHandler
,
0
,
sizeof
(
AttrWrapper
),
false
);
STR
=
typeFromClass
(
str_cls
);
BOXED_INT
=
typeFromClass
(
int_cls
);
...
...
src/runtime/types.h
View file @
d5ba641b
...
...
@@ -172,6 +172,13 @@ class conservative_unordered_map
:
public
std
::
unordered_map
<
K
,
V
,
Hash
,
KeyEqual
,
StlCompatAllocator
<
std
::
pair
<
const
K
,
V
>
>
>
{};
class
BoxedClass
:
public
BoxVar
{
public:
typedef
void
(
*
gcvisit_func
)(
GCVisitor
*
,
Box
*
);
protected:
BoxedClass
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
);
public:
PyTypeObject_BODY
;
...
...
@@ -195,7 +202,6 @@ public:
// Is NULL iff this is object_cls
BoxedClass
*
base
;
typedef
void
(
*
gcvisit_func
)(
GCVisitor
*
,
Box
*
);
gcvisit_func
gc_visit
;
// Offset of the HCAttrs object or 0 if there are no hcattrs.
...
...
@@ -217,12 +223,21 @@ public:
// will need to update this once we support tp_getattr-style overriding:
bool
hasGenericGetattr
()
{
return
true
;
}
BoxedClass
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
);
void
freeze
();
};
class
BoxedHeapClass
:
public
BoxedClass
{
public:
PyNumberMethods
as_number
;
PyMappingMethods
as_mapping
;
PySequenceMethods
as_sequence
;
PyBufferProcs
as_buffer
;
PyObject
*
ht_name
,
*
ht_slots
;
BoxedHeapClass
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
);
};
static_assert
(
sizeof
(
pyston
::
Box
)
==
sizeof
(
struct
_object
),
""
);
static_assert
(
offsetof
(
pyston
::
Box
,
cls
)
==
offsetof
(
struct
_object
,
ob_type
),
""
);
...
...
@@ -234,6 +249,13 @@ static_assert(offsetof(pyston::BoxedClass, base) == offsetof(struct _typeobject,
static_assert
(
offsetof
(
pyston
::
BoxedClass
,
gc_visit
)
==
offsetof
(
struct
_typeobject
,
_gcvisit_func
),
""
);
static_assert
(
sizeof
(
pyston
::
BoxedClass
)
==
sizeof
(
struct
_typeobject
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
base
)
==
offsetof
(
PyHeapTypeObject
,
ht_type
.
_base
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
as_number
)
==
offsetof
(
PyHeapTypeObject
,
as_number
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
as_mapping
)
==
offsetof
(
PyHeapTypeObject
,
as_mapping
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
as_sequence
)
==
offsetof
(
PyHeapTypeObject
,
as_sequence
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
as_buffer
)
==
offsetof
(
PyHeapTypeObject
,
as_buffer
),
""
);
static_assert
(
sizeof
(
pyston
::
BoxedHeapClass
)
==
sizeof
(
PyHeapTypeObject
),
""
);
class
HiddenClass
:
public
ConservativeGCObject
{
private:
...
...
test/test_extension/slots_test.c
View file @
d5ba641b
...
...
@@ -29,7 +29,7 @@ slots_tester_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
static
PyObject
*
slots_tester_repr
(
slots_tester_object
*
obj
)
slots_tester_
seq_
repr
(
slots_tester_object
*
obj
)
{
char
buf
[
80
];
snprintf
(
buf
,
sizeof
(
buf
),
"<my custom repr: %d>"
,
obj
->
n
);
...
...
@@ -37,7 +37,7 @@ slots_tester_repr(slots_tester_object *obj)
}
static
PyObject
*
slots_tester_call
(
slots_tester_object
*
obj
,
PyObject
*
args
,
PyObject
*
kw
)
slots_tester_
seq_
call
(
slots_tester_object
*
obj
,
PyObject
*
args
,
PyObject
*
kw
)
{
if
(
!
PyArg_ParseTuple
(
args
,
""
))
return
NULL
;
...
...
@@ -45,11 +45,33 @@ slots_tester_call(slots_tester_object *obj, PyObject *args, PyObject *kw)
return
PyInt_FromLong
(
obj
->
n
);
}
PyDoc_STRVAR
(
slots_tester_doc
,
"slots_tester doc"
);
static
PyObject
*
slots_tester_seq_item
(
slots_tester_object
*
obj
,
Py_ssize_t
i
)
{
if
(
i
<
0
||
i
>=
5
)
{
PyErr_SetString
(
PyExc_IndexError
,
"tuple index out of range"
);
return
NULL
;
}
return
PyInt_FromLong
(
i
+
obj
->
n
);
}
PyDoc_STRVAR
(
slots_tester_seq_doc
,
"slots_tester_seq doc"
);
static
PyTypeObject
slots_tester
=
{
static
PySequenceMethods
slots_tester_seq_as_sequence
=
{
(
lenfunc
)
0
,
(
binaryfunc
)
0
,
/* sq_concat */
(
ssizeargfunc
)
0
,
/* sq_repeat */
(
ssizeargfunc
)
slots_tester_seq_item
,
/* sq_item */
(
ssizessizeargfunc
)
0
,
/* sq_slice */
0
,
/* sq_ass_item */
0
,
/* sq_ass_slice */
(
objobjproc
)
0
,
/* sq_contains */
};
static
PyTypeObject
slots_tester_seq
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"slots_test.slots_tester"
,
/* tp_name */
"slots_test.slots_tester
_seq
"
,
/* tp_name */
sizeof
(
slots_tester_object
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
...
...
@@ -58,18 +80,83 @@ static PyTypeObject slots_tester = {
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_compare */
(
reprfunc
)
slots_tester_repr
,
/* tp_repr */
(
reprfunc
)
slots_tester_
seq_
repr
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
&
slots_tester_seq_as_sequence
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
(
ternaryfunc
)
slots_tester_call
,
/* tp_call */
(
ternaryfunc
)
slots_tester_seq_call
,
/* tp_call */
0
,
/* tp_str */
0
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
,
/* tp_flags */
slots_tester_seq_doc
,
/* tp_doc */
0
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
0
,
/* tp_iter */
0
,
/* tp_iternext */
0
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
0
,
/* tp_init */
0
,
/* tp_alloc */
slots_tester_new
,
/* tp_new */
0
,
/* tp_free */
};
static
Py_ssize_t
slots_tester_map_length
(
slots_tester_object
*
obj
)
{
return
obj
->
n
;
}
static
PyObject
*
slots_tester_map_subscript
(
slots_tester_object
*
obj
,
PyObject
*
key
)
{
int
n2
=
PyInt_AsLong
(
key
);
return
PyInt_FromLong
(
n2
+
obj
->
n
);
}
static
int
slots_tester_map_ass_sub
(
slots_tester_object
*
obj
,
PyObject
*
key
,
PyObject
*
value
)
{
int
n2
=
PyInt_AsLong
(
key
);
printf
(
"Assigning to subscript for object with n=%d, key=%d, set/delete=%d
\n
"
,
obj
->
n
,
n2
,
!!
value
);
return
0
;
}
static
PyMappingMethods
slots_tester_map_asmapping
=
{
(
lenfunc
)
slots_tester_map_length
,
/*mp_length*/
(
binaryfunc
)
slots_tester_map_subscript
,
/*mp_subscript*/
(
objobjargproc
)
slots_tester_map_ass_sub
,
/*mp_ass_subscript*/
};
static
PyTypeObject
slots_tester_map
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"slots_test.slots_tester_map"
,
/* tp_name */
sizeof
(
slots_tester_object
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
0
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_compare */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
&
slots_tester_map_asmapping
,
/* tp_as_mapping */
0
,
/* tp_hash */
0
,
/* tp_call */
0
,
/* tp_str */
0
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
,
/* tp_flags */
slots_tester_doc
,
/* tp_doc */
0
,
/* tp_doc */
0
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
...
...
@@ -120,6 +207,44 @@ call_funcs(PyObject* _module, PyObject* args) {
printf
(
"tp_call doesnt exist
\n
"
);
}
if
(
cls
->
tp_as_mapping
)
{
printf
(
"tp_as_mapping exists
\n
"
);
PyMappingMethods
*
map
=
cls
->
tp_as_mapping
;
if
(
map
->
mp_subscript
)
{
PyObject
*
rtn
=
map
->
mp_subscript
(
obj
,
PyInt_FromLong
(
1
));
printf
(
"mp_subscript exists and returned
\n
"
);
Py_DECREF
(
rtn
);
}
else
{
printf
(
"mp_subscript does not exist
\n
"
);
}
if
(
map
->
mp_length
)
{
Py_ssize_t
rtn
=
map
->
mp_length
(
obj
);
printf
(
"mp_length exists and returned %ld
\n
"
,
rtn
);
}
}
else
{
printf
(
"tp_as_mapping doesnt exist
\n
"
);
}
if
(
cls
->
tp_as_sequence
)
{
printf
(
"tp_as_sequence exists
\n
"
);
PySequenceMethods
*
seq
=
cls
->
tp_as_sequence
;
if
(
seq
->
sq_length
)
{
Py_ssize_t
rtn
=
seq
->
sq_length
(
obj
);
printf
(
"sq_length exists and returned %ld
\n
"
,
rtn
);
}
if
(
seq
->
sq_item
)
{
PyObject
*
rtn
=
cls
->
tp_as_sequence
->
sq_item
(
obj
,
1
);
printf
(
"sq_item exists and returned
\n
"
);
Py_DECREF
(
rtn
);
}
}
else
{
printf
(
"tp_as_sequence doesnt exist
\n
"
);
}
Py_DECREF
(
obj
);
Py_RETURN_NONE
;
...
...
@@ -139,12 +264,17 @@ initslots_test(void)
if
(
m
==
NULL
)
return
;
int
res
=
PyType_Ready
(
&
slots_tester
);
int
res
=
PyType_Ready
(
&
slots_tester_seq
);
if
(
res
<
0
)
return
;
res
=
PyType_Ready
(
&
slots_tester_map
);
if
(
res
<
0
)
return
;
// Not sure if the result of PyInt_FromLong needs to be decref'd
PyDict_SetItemString
(
slots_tester
.
tp_dict
,
"set_through_tpdict"
,
PyInt_FromLong
(
123
));
PyDict_SetItemString
(
slots_tester
_seq
.
tp_dict
,
"set_through_tpdict"
,
PyInt_FromLong
(
123
));
PyModule_AddObject
(
m
,
"SlotsTester"
,
(
PyObject
*
)
&
slots_tester
);
PyModule_AddObject
(
m
,
"SlotsTesterSeq"
,
(
PyObject
*
)
&
slots_tester_seq
);
PyModule_AddObject
(
m
,
"SlotsTesterMap"
,
(
PyObject
*
)
&
slots_tester_map
);
}
test/tests/capi_slots.py
View file @
d5ba641b
import
slots_test
for
i
in
xrange
(
3
):
t
=
slots_test
.
SlotsTester
(
i
+
5
)
print
t
,
repr
(
t
),
t
()
t
=
slots_test
.
SlotsTester
Seq
(
i
+
5
)
print
t
,
repr
(
t
),
t
()
,
t
[
2
]
print
slots_test
.
SlotsTester
.
set_through_tpdict
,
slots_test
.
SlotsTester
(
5
).
set_through_tpdict
# print slots_test.SlotsTesterSeq.__doc__
print
slots_test
.
SlotsTesterSeq
.
set_through_tpdict
,
slots_test
.
SlotsTesterSeq
(
5
).
set_through_tpdict
for
i
in
xrange
(
3
):
t
=
slots_test
.
SlotsTesterMap
(
i
+
5
)
print
len
(
t
),
t
[
2
]
t
[
1
]
=
5
del
t
[
2
]
class
C
(
object
):
def
__repr__
(
self
):
print
"__repr__()"
return
"<C object>"
def
__getitem__
(
self
,
idx
):
print
"__getitem__"
,
idx
return
idx
-
5
def
__len__
(
self
):
print
"__len__"
return
3
slots_test
.
call_funcs
(
C
())
# Test to make sure that updating an existing class also updates the tp_* slots:
def
repr2
(
self
):
return
"repr2()"
C
.
repr2
=
repr2
C
.
__repr__
=
repr2
slots_test
.
call_funcs
(
C
())
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment