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
39859d79
Commit
39859d79
authored
Mar 03, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'multiple_inheritance'
parents
53dc9612
fee6818c
Changes
28
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
1080 additions
and
196 deletions
+1080
-196
Makefile
Makefile
+12
-12
src/asm_writing/rewriter.cpp
src/asm_writing/rewriter.cpp
+13
-2
src/capi/abstract.cpp
src/capi/abstract.cpp
+5
-4
src/capi/modsupport.cpp
src/capi/modsupport.cpp
+39
-2
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+531
-11
src/capi/typeobject.h
src/capi/typeobject.h
+8
-1
src/gc/heap.cpp
src/gc/heap.cpp
+1
-1
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+7
-5
src/runtime/builtin_modules/sys.cpp
src/runtime/builtin_modules/sys.cpp
+2
-1
src/runtime/builtin_modules/thread.cpp
src/runtime/builtin_modules/thread.cpp
+4
-4
src/runtime/capi.cpp
src/runtime/capi.cpp
+8
-5
src/runtime/classobj.cpp
src/runtime/classobj.cpp
+4
-4
src/runtime/dict.cpp
src/runtime/dict.cpp
+9
-7
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
+5
-4
src/runtime/list.cpp
src/runtime/list.cpp
+17
-4
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+130
-59
src/runtime/set.cpp
src/runtime/set.cpp
+2
-1
src/runtime/str.cpp
src/runtime/str.cpp
+2
-2
src/runtime/super.cpp
src/runtime/super.cpp
+61
-6
src/runtime/traceback.cpp
src/runtime/traceback.cpp
+2
-2
src/runtime/tuple.cpp
src/runtime/tuple.cpp
+2
-1
src/runtime/types.cpp
src/runtime/types.cpp
+85
-42
src/runtime/types.h
src/runtime/types.h
+19
-6
test/tests/multiple_inheritance.py
test/tests/multiple_inheritance.py
+94
-0
test/tests/super.py
test/tests/super.py
+8
-0
tools/tester.py
tools/tester.py
+5
-5
No files found.
Makefile
View file @
39859d79
...
...
@@ -404,26 +404,26 @@ check:
@# jit_prof forces the use of GCC as the compiler, which can expose other errors, so just build it and see what happens
:
$(MAKE)
pyston_prof
@
# and run some basic tests to make sure it works:
$(
call
checksha,./pyston_prof
-
c
q
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-
c
qn
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-
c
qO
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-q
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-qn
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-qO
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(MAKE)
check_release
echo
"All tests passed"
quick_check
:
$(MAKE)
pyston_dbg
$(
call
checksha,./pyston_dbg
-
c
q
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_dbg
-
c
qn
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_dbg
-
c
qO
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_dbg
-q
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_dbg
-qn
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_dbg
-qO
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(MAKE)
pyston
$(
call
checksha,./pyston
-
c
q
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston
-
c
qn
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston
-
c
qO
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston
-q
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston
-qn
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston
-qO
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(MAKE)
pyston_prof
$(
call
checksha,./pyston_prof
-
c
q
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-
c
qn
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-
c
qO
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-q
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-qn
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
$(
call
checksha,./pyston_prof
-qO
$(TESTS_DIR)
/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d
)
Makefile.local
:
echo
"Creating default Makefile.local"
...
...
src/asm_writing/rewriter.cpp
View file @
39859d79
...
...
@@ -180,7 +180,13 @@ void RewriterVar::addAttrGuard(int offset, uint64_t val, bool negate) {
}
void
Rewriter
::
_addAttrGuard
(
RewriterVar
*
var
,
int
offset
,
uint64_t
val
,
bool
negate
)
{
assembler
::
Register
var_reg
=
var
->
getInReg
();
// TODO if var is a constant, we will end up emitting something like
// mov $0x123, %rax
// cmp $0x10(%rax), %rdi
// when we could just do
// cmp ($0x133), %rdi
assembler
::
Register
var_reg
=
var
->
getInReg
(
Location
::
any
(),
/* allow_constant_in_reg */
true
);
if
(
isLargeConstant
(
val
))
{
assembler
::
Register
reg
=
allocReg
(
Location
::
any
(),
/* otherThan */
var_reg
);
assert
(
reg
!=
var_reg
);
...
...
@@ -206,7 +212,12 @@ RewriterVar* RewriterVar::getAttr(int offset, Location dest, assembler::MovType
}
void
Rewriter
::
_getAttr
(
RewriterVar
*
result
,
RewriterVar
*
ptr
,
int
offset
,
Location
dest
,
assembler
::
MovType
type
)
{
assembler
::
Register
ptr_reg
=
ptr
->
getInReg
();
// TODO if var is a constant, we will end up emitting something like
// mov $0x123, %rax
// mov $0x10(%rax), %rdi
// when we could just do
// mov ($0x133), %rdi
assembler
::
Register
ptr_reg
=
ptr
->
getInReg
(
Location
::
any
(),
/* allow_constant_in_reg */
true
);
// It's okay to bump the use now, since it's fine to allocate the result
// in the same register as ptr
...
...
src/capi/abstract.cpp
View file @
39859d79
...
...
@@ -293,15 +293,16 @@ extern "C" PyObject* PyObject_CallFunctionObjArgs(PyObject* callable, ...) noexc
}
extern
"C"
PyObject
*
PyObject_CallObject
(
PyObject
*
obj
,
PyObject
*
args
)
noexcept
{
RELEASE_ASSERT
(
args
,
""
);
// actually it looks like this is allowed to be NULL
RELEASE_ASSERT
(
args
->
cls
==
tuple_cls
,
""
);
// TODO do something like this? not sure if this is safe; will people expect that calling into a known function
// won't end up doing a GIL check?
// threading::GLDemoteRegion _gil_demote;
try
{
Box
*
r
=
runtimeCall
(
obj
,
ArgPassSpec
(
0
,
0
,
true
,
false
),
args
,
NULL
,
NULL
,
NULL
,
NULL
);
Box
*
r
;
if
(
args
)
r
=
runtimeCall
(
obj
,
ArgPassSpec
(
0
,
0
,
true
,
false
),
args
,
NULL
,
NULL
,
NULL
,
NULL
);
else
r
=
runtimeCall
(
obj
,
ArgPassSpec
(
0
,
0
,
false
,
false
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
return
r
;
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
...
...
src/capi/modsupport.cpp
View file @
39859d79
...
...
@@ -82,7 +82,7 @@ static int _ustrlen(Py_UNICODE* u) {
#endif
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_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
;
...
...
@@ -92,10 +92,10 @@ static PyObject* do_mkvalue(const char** p_format, va_list* p_va, int flags) noe
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
);
#if 0
case '{':
return do_mkdict(p_format, p_va, '}', countformat(*p_format, '}'), flags);
#endif
...
...
@@ -239,6 +239,43 @@ static PyObject* do_mktuple(const char** p_format, va_list* p_va, int endchar, i
return
v
;
}
static
PyObject
*
do_mklist
(
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
;
v
=
PyList_New
(
n
);
if
(
v
==
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
;
}
PyList_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
)
noexcept
{
int
n
=
countformat
(
fmt
,
'\0'
);
...
...
src/capi/typeobject.cpp
View file @
39859d79
...
...
@@ -1466,6 +1466,508 @@ static void add_operators(BoxedClass* cls) noexcept {
add_tp_new_wrapper
(
cls
);
}
static
void
type_mro_modified
(
PyTypeObject
*
type
,
PyObject
*
bases
)
{
/*
Check that all base classes or elements of the mro of type are
able to be cached. This function is called after the base
classes or mro of the type are altered.
Unset HAVE_VERSION_TAG and VALID_VERSION_TAG if the type
inherits from an old-style class, either directly or if it
appears in the MRO of a new-style class. No support either for
custom MROs that include types that are not officially super
types.
Called from mro_internal, which will subsequently be called on
each subclass when their mro is recursively updated.
*/
Py_ssize_t
i
,
n
;
int
clear
=
0
;
if
(
!
PyType_HasFeature
(
type
,
Py_TPFLAGS_HAVE_VERSION_TAG
))
return
;
n
=
PyTuple_GET_SIZE
(
bases
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
b
=
PyTuple_GET_ITEM
(
bases
,
i
);
PyTypeObject
*
cls
;
if
(
!
PyType_Check
(
b
))
{
clear
=
1
;
break
;
}
cls
=
(
PyTypeObject
*
)
b
;
if
(
!
PyType_HasFeature
(
cls
,
Py_TPFLAGS_HAVE_VERSION_TAG
)
||
!
PyType_IsSubtype
(
type
,
cls
))
{
clear
=
1
;
break
;
}
}
if
(
clear
)
type
->
tp_flags
&=
~
(
Py_TPFLAGS_HAVE_VERSION_TAG
|
Py_TPFLAGS_VALID_VERSION_TAG
);
}
static
int
extra_ivars
(
PyTypeObject
*
type
,
PyTypeObject
*
base
)
noexcept
{
size_t
t_size
=
type
->
tp_basicsize
;
size_t
b_size
=
base
->
tp_basicsize
;
assert
(
t_size
>=
b_size
);
/* Else type smaller than base! */
if
(
type
->
tp_itemsize
||
base
->
tp_itemsize
)
{
/* If itemsize is involved, stricter rules */
return
t_size
!=
b_size
||
type
->
tp_itemsize
!=
base
->
tp_itemsize
;
}
if
(
type
->
tp_weaklistoffset
&&
base
->
tp_weaklistoffset
==
0
&&
type
->
tp_weaklistoffset
+
sizeof
(
PyObject
*
)
==
t_size
&&
type
->
tp_flags
&
Py_TPFLAGS_HEAPTYPE
)
t_size
-=
sizeof
(
PyObject
*
);
if
(
type
->
tp_dictoffset
&&
base
->
tp_dictoffset
==
0
&&
type
->
tp_dictoffset
+
sizeof
(
PyObject
*
)
==
t_size
&&
type
->
tp_flags
&
Py_TPFLAGS_HEAPTYPE
)
t_size
-=
sizeof
(
PyObject
*
);
// Pyston change:
if
(
type
->
instancesHaveHCAttrs
()
&&
!
base
->
instancesHaveHCAttrs
())
t_size
-=
sizeof
(
HCAttrs
);
return
t_size
!=
b_size
;
}
static
PyTypeObject
*
solid_base
(
PyTypeObject
*
type
)
noexcept
{
PyTypeObject
*
base
;
if
(
type
->
tp_base
)
base
=
solid_base
(
type
->
tp_base
);
else
base
=
object_cls
;
if
(
extra_ivars
(
type
,
base
))
return
type
;
else
return
base
;
}
PyTypeObject
*
best_base
(
PyObject
*
bases
)
noexcept
{
Py_ssize_t
i
,
n
;
PyTypeObject
*
base
,
*
winner
,
*
candidate
,
*
base_i
;
PyObject
*
base_proto
;
assert
(
PyTuple_Check
(
bases
));
n
=
PyTuple_GET_SIZE
(
bases
);
assert
(
n
>
0
);
base
=
NULL
;
winner
=
NULL
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
base_proto
=
PyTuple_GET_ITEM
(
bases
,
i
);
if
(
PyClass_Check
(
base_proto
))
continue
;
if
(
!
PyType_Check
(
base_proto
))
{
PyErr_SetString
(
PyExc_TypeError
,
"bases must be types"
);
return
NULL
;
}
base_i
=
(
PyTypeObject
*
)
base_proto
;
// Pyston change: we require things are already ready
if
(
base_i
->
tp_dict
==
NULL
)
{
assert
(
base_i
->
is_pyston_class
);
#if 0
if (PyType_Ready(base_i) < 0)
return NULL;
#endif
}
candidate
=
solid_base
(
base_i
);
if
(
winner
==
NULL
)
{
winner
=
candidate
;
base
=
base_i
;
}
else
if
(
PyType_IsSubtype
(
winner
,
candidate
))
;
else
if
(
PyType_IsSubtype
(
candidate
,
winner
))
{
winner
=
candidate
;
base
=
base_i
;
}
else
{
PyErr_SetString
(
PyExc_TypeError
,
"multiple bases have "
"instance lay-out conflict"
);
return
NULL
;
}
}
if
(
base
==
NULL
)
PyErr_SetString
(
PyExc_TypeError
,
"a new-style class can't have only classic bases"
);
return
base
;
}
static
int
fill_classic_mro
(
PyObject
*
mro
,
PyObject
*
cls
)
{
PyObject
*
bases
,
*
base
;
Py_ssize_t
i
,
n
;
assert
(
PyList_Check
(
mro
));
assert
(
PyClass_Check
(
cls
));
i
=
PySequence_Contains
(
mro
,
cls
);
if
(
i
<
0
)
return
-
1
;
if
(
!
i
)
{
if
(
PyList_Append
(
mro
,
cls
)
<
0
)
return
-
1
;
}
Py_FatalError
(
"unimplemented"
);
// We should add multiple inheritance for old-style classes
#if 0
bases = ((PyClassObject*)cls)->cl_bases;
assert(bases && PyTuple_Check(bases));
n = PyTuple_GET_SIZE(bases);
for (i = 0; i < n; i++) {
base = PyTuple_GET_ITEM(bases, i);
if (fill_classic_mro(mro, base) < 0)
return -1;
}
return 0;
#endif
}
static
PyObject
*
classic_mro
(
PyObject
*
cls
)
{
PyObject
*
mro
;
assert
(
PyClass_Check
(
cls
));
mro
=
PyList_New
(
0
);
if
(
mro
!=
NULL
)
{
if
(
fill_classic_mro
(
mro
,
cls
)
==
0
)
return
mro
;
Py_DECREF
(
mro
);
}
return
NULL
;
}
/*
Method resolution order algorithm C3 described in
"A Monotonic Superclass Linearization for Dylan",
by Kim Barrett, Bob Cassel, Paul Haahr,
David A. Moon, Keith Playford, and P. Tucker Withington.
(OOPSLA 1996)
Some notes about the rules implied by C3:
No duplicate bases.
It isn't legal to repeat a class in a list of base classes.
The next three properties are the 3 constraints in "C3".
Local precendece order.
If A precedes B in C's MRO, then A will precede B in the MRO of all
subclasses of C.
Monotonicity.
The MRO of a class must be an extension without reordering of the
MRO of each of its superclasses.
Extended Precedence Graph (EPG).
Linearization is consistent if there is a path in the EPG from
each class to all its successors in the linearization. See
the paper for definition of EPG.
*/
static
int
tail_contains
(
PyObject
*
list
,
int
whence
,
PyObject
*
o
)
{
Py_ssize_t
j
,
size
;
size
=
PyList_GET_SIZE
(
list
);
for
(
j
=
whence
+
1
;
j
<
size
;
j
++
)
{
if
(
PyList_GET_ITEM
(
list
,
j
)
==
o
)
return
1
;
}
return
0
;
}
static
PyObject
*
class_name
(
PyObject
*
cls
)
{
PyObject
*
name
=
PyObject_GetAttrString
(
cls
,
"__name__"
);
if
(
name
==
NULL
)
{
PyErr_Clear
();
Py_XDECREF
(
name
);
name
=
PyObject_Repr
(
cls
);
}
if
(
name
==
NULL
)
return
NULL
;
if
(
!
PyString_Check
(
name
))
{
Py_DECREF
(
name
);
return
NULL
;
}
return
name
;
}
static
int
check_duplicates
(
PyObject
*
list
)
{
Py_ssize_t
i
,
j
,
n
;
/* Let's use a quadratic time algorithm,
assuming that the bases lists is short.
*/
n
=
PyList_GET_SIZE
(
list
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
o
=
PyList_GET_ITEM
(
list
,
i
);
for
(
j
=
i
+
1
;
j
<
n
;
j
++
)
{
if
(
PyList_GET_ITEM
(
list
,
j
)
==
o
)
{
o
=
class_name
(
o
);
PyErr_Format
(
PyExc_TypeError
,
"duplicate base class %s"
,
o
?
PyString_AS_STRING
(
o
)
:
"?"
);
Py_XDECREF
(
o
);
return
-
1
;
}
}
}
return
0
;
}
/* Raise a TypeError for an MRO order disagreement.
It's hard to produce a good error message. In the absence of better
insight into error reporting, report the classes that were candidates
to be put next into the MRO. There is some conflict between the
order in which they should be put in the MRO, but it's hard to
diagnose what constraint can't be satisfied.
*/
static
void
set_mro_error
(
PyObject
*
to_merge
,
int
*
remain
)
noexcept
{
Py_ssize_t
i
,
n
,
off
,
to_merge_size
;
char
buf
[
1000
];
PyObject
*
k
,
*
v
;
PyObject
*
set
=
PyDict_New
();
if
(
!
set
)
return
;
to_merge_size
=
PyList_GET_SIZE
(
to_merge
);
for
(
i
=
0
;
i
<
to_merge_size
;
i
++
)
{
PyObject
*
L
=
PyList_GET_ITEM
(
to_merge
,
i
);
if
(
remain
[
i
]
<
PyList_GET_SIZE
(
L
))
{
PyObject
*
c
=
PyList_GET_ITEM
(
L
,
remain
[
i
]);
if
(
PyDict_SetItem
(
set
,
c
,
Py_None
)
<
0
)
{
Py_DECREF
(
set
);
return
;
}
}
}
n
=
PyDict_Size
(
set
);
off
=
PyOS_snprintf
(
buf
,
sizeof
(
buf
),
"Cannot create a \
consistent method resolution
\n
order (MRO) for bases"
);
i
=
0
;
while
(
PyDict_Next
(
set
,
&
i
,
&
k
,
&
v
)
&&
(
size_t
)
off
<
sizeof
(
buf
))
{
PyObject
*
name
=
class_name
(
k
);
off
+=
PyOS_snprintf
(
buf
+
off
,
sizeof
(
buf
)
-
off
,
" %s"
,
name
?
PyString_AS_STRING
(
name
)
:
"?"
);
Py_XDECREF
(
name
);
if
(
--
n
&&
(
size_t
)(
off
+
1
)
<
sizeof
(
buf
))
{
buf
[
off
++
]
=
','
;
buf
[
off
]
=
'\0'
;
}
}
PyErr_SetString
(
PyExc_TypeError
,
buf
);
Py_DECREF
(
set
);
}
static
int
pmerge
(
PyObject
*
acc
,
PyObject
*
to_merge
)
noexcept
{
Py_ssize_t
i
,
j
,
to_merge_size
,
empty_cnt
;
int
*
remain
;
int
ok
;
to_merge_size
=
PyList_GET_SIZE
(
to_merge
);
/* remain stores an index into each sublist of to_merge.
remain[i] is the index of the next base in to_merge[i]
that is not included in acc.
*/
remain
=
(
int
*
)
PyMem_MALLOC
(
SIZEOF_INT
*
to_merge_size
);
if
(
remain
==
NULL
)
return
-
1
;
for
(
i
=
0
;
i
<
to_merge_size
;
i
++
)
remain
[
i
]
=
0
;
again:
empty_cnt
=
0
;
for
(
i
=
0
;
i
<
to_merge_size
;
i
++
)
{
PyObject
*
candidate
;
PyObject
*
cur_list
=
PyList_GET_ITEM
(
to_merge
,
i
);
if
(
remain
[
i
]
>=
PyList_GET_SIZE
(
cur_list
))
{
empty_cnt
++
;
continue
;
}
/* Choose next candidate for MRO.
The input sequences alone can determine the choice.
If not, choose the class which appears in the MRO
of the earliest direct superclass of the new class.
*/
candidate
=
PyList_GET_ITEM
(
cur_list
,
remain
[
i
]);
for
(
j
=
0
;
j
<
to_merge_size
;
j
++
)
{
PyObject
*
j_lst
=
PyList_GET_ITEM
(
to_merge
,
j
);
if
(
tail_contains
(
j_lst
,
remain
[
j
],
candidate
))
{
goto
skip
;
/* continue outer loop */
}
}
ok
=
PyList_Append
(
acc
,
candidate
);
if
(
ok
<
0
)
{
PyMem_Free
(
remain
);
return
-
1
;
}
for
(
j
=
0
;
j
<
to_merge_size
;
j
++
)
{
PyObject
*
j_lst
=
PyList_GET_ITEM
(
to_merge
,
j
);
if
(
remain
[
j
]
<
PyList_GET_SIZE
(
j_lst
)
&&
PyList_GET_ITEM
(
j_lst
,
remain
[
j
])
==
candidate
)
{
remain
[
j
]
++
;
}
}
goto
again
;
skip:
;
}
if
(
empty_cnt
==
to_merge_size
)
{
PyMem_FREE
(
remain
);
return
0
;
}
set_mro_error
(
to_merge
,
remain
);
PyMem_FREE
(
remain
);
return
-
1
;
}
static
PyObject
*
mro_implementation
(
PyTypeObject
*
type
)
noexcept
{
Py_ssize_t
i
,
n
;
int
ok
;
PyObject
*
bases
,
*
result
;
PyObject
*
to_merge
,
*
bases_aslist
;
// Pyston change: we require things are already ready
if
(
type
->
tp_dict
==
NULL
)
{
assert
(
type
->
is_pyston_class
);
#if 0
if (PyType_Ready(type) < 0)
return NULL;
#endif
}
/* Find a superclass linearization that honors the constraints
of the explicit lists of bases and the constraints implied by
each base class.
to_merge is a list of lists, where each list is a superclass
linearization implied by a base class. The last element of
to_merge is the declared list of bases.
*/
bases
=
type
->
tp_bases
;
assert
(
type
->
tp_bases
);
assert
(
type
->
tp_bases
->
cls
==
tuple_cls
);
n
=
PyTuple_GET_SIZE
(
bases
);
to_merge
=
PyList_New
(
n
+
1
);
if
(
to_merge
==
NULL
)
return
NULL
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
base
=
PyTuple_GET_ITEM
(
bases
,
i
);
PyObject
*
parentMRO
;
if
(
PyType_Check
(
base
))
parentMRO
=
PySequence_List
(((
PyTypeObject
*
)
base
)
->
tp_mro
);
else
parentMRO
=
classic_mro
(
base
);
if
(
parentMRO
==
NULL
)
{
Py_DECREF
(
to_merge
);
return
NULL
;
}
PyList_SET_ITEM
(
to_merge
,
i
,
parentMRO
);
}
bases_aslist
=
PySequence_List
(
bases
);
if
(
bases_aslist
==
NULL
)
{
Py_DECREF
(
to_merge
);
return
NULL
;
}
/* This is just a basic sanity check. */
if
(
check_duplicates
(
bases_aslist
)
<
0
)
{
Py_DECREF
(
to_merge
);
Py_DECREF
(
bases_aslist
);
return
NULL
;
}
PyList_SET_ITEM
(
to_merge
,
n
,
bases_aslist
);
result
=
Py_BuildValue
(
"[O]"
,
(
PyObject
*
)
type
);
if
(
result
==
NULL
)
{
Py_DECREF
(
to_merge
);
return
NULL
;
}
ok
=
pmerge
(
result
,
to_merge
);
Py_DECREF
(
to_merge
);
if
(
ok
<
0
)
{
Py_DECREF
(
result
);
return
NULL
;
}
return
result
;
}
// Pyston change: made this non-static
PyObject
*
mro_external
(
PyObject
*
self
)
noexcept
{
PyTypeObject
*
type
=
(
PyTypeObject
*
)
self
;
return
mro_implementation
(
type
);
}
static
int
mro_internal
(
PyTypeObject
*
type
)
noexcept
{
PyObject
*
mro
,
*
result
,
*
tuple
;
int
checkit
=
0
;
if
(
Py_TYPE
(
type
)
==
&
PyType_Type
)
{
result
=
mro_implementation
(
type
);
}
else
{
static
PyObject
*
mro_str
;
checkit
=
1
;
mro
=
lookup_method
((
PyObject
*
)
type
,
"mro"
,
&
mro_str
);
if
(
mro
==
NULL
)
return
-
1
;
result
=
PyObject_CallObject
(
mro
,
NULL
);
Py_DECREF
(
mro
);
}
if
(
result
==
NULL
)
return
-
1
;
tuple
=
PySequence_Tuple
(
result
);
Py_DECREF
(
result
);
if
(
tuple
==
NULL
)
return
-
1
;
if
(
checkit
)
{
Py_ssize_t
i
,
len
;
PyObject
*
cls
;
PyTypeObject
*
solid
;
solid
=
solid_base
(
type
);
len
=
PyTuple_GET_SIZE
(
tuple
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
PyTypeObject
*
t
;
cls
=
PyTuple_GET_ITEM
(
tuple
,
i
);
if
(
PyClass_Check
(
cls
))
continue
;
else
if
(
!
PyType_Check
(
cls
))
{
PyErr_Format
(
PyExc_TypeError
,
"mro() returned a non-class ('%.500s')"
,
Py_TYPE
(
cls
)
->
tp_name
);
Py_DECREF
(
tuple
);
return
-
1
;
}
t
=
(
PyTypeObject
*
)
cls
;
if
(
!
PyType_IsSubtype
(
solid
,
solid_base
(
t
)))
{
PyErr_Format
(
PyExc_TypeError
,
"mro() returned base with unsuitable layout ('%.500s')"
,
t
->
tp_name
);
Py_DECREF
(
tuple
);
return
-
1
;
}
}
}
type
->
tp_mro
=
tuple
;
type_mro_modified
(
type
,
type
->
tp_mro
);
/* corner case: the old-style super class might have been hidden
from the custom MRO */
type_mro_modified
(
type
,
type
->
tp_bases
);
PyType_Modified
(
type
);
return
0
;
}
extern
"C"
int
PyType_IsSubtype
(
PyTypeObject
*
a
,
PyTypeObject
*
b
)
noexcept
{
return
isSubclass
(
a
,
b
);
}
...
...
@@ -1769,20 +2271,31 @@ static void inherit_slots(PyTypeObject* type, PyTypeObject* base) noexcept {
}
}
//
PystonType_Ready
is for the common code between PyType_Ready (which is just for extension classes)
//
commonClassSetup
is for the common code between PyType_Ready (which is just for extension classes)
// and our internal type-creation endpoints (BoxedClass::BoxedClass()).
// TODO: Move more of the duplicated logic into here.
void
PystonType_Ready
(
BoxedClass
*
cls
)
{
inherit_special
(
cls
,
cls
->
tp_base
);
void
commonClassSetup
(
BoxedClass
*
cls
)
{
if
(
cls
->
tp_bases
==
NULL
)
{
if
(
cls
->
tp_base
)
cls
->
tp_bases
=
new
BoxedTuple
({
cls
->
tp_base
});
else
cls
->
tp_bases
=
new
BoxedTuple
({});
}
/
/ This is supposed to be over the MRO but we don't support multiple inheritance yet:
BoxedClass
*
b
=
cls
->
tp_base
;
while
(
b
)
{
// Not sure when this could fail; maybe not in Pyston right now but apparently it can in CPython:
if
(
PyType_Check
(
b
)
)
inherit_slots
(
cls
,
b
);
/
* Calculate method resolution order */
if
(
mro_internal
(
cls
)
<
0
)
throwCAPIException
();
if
(
cls
->
tp_base
)
inherit_special
(
cls
,
cls
->
tp_base
);
b
=
b
->
tp_base
;
assert
(
cls
->
tp_mro
);
assert
(
cls
->
tp_mro
->
cls
==
tuple_cls
);
for
(
auto
b
:
static_cast
<
BoxedTuple
*>
(
cls
->
tp_mro
)
->
elts
)
{
if
(
b
==
cls
)
continue
;
if
(
PyType_Check
(
b
))
inherit_slots
(
cls
,
static_cast
<
BoxedClass
*>
(
b
));
}
}
...
...
@@ -1791,6 +2304,8 @@ extern "C" void PyType_Modified(PyTypeObject* type) noexcept {
}
extern
"C"
int
PyType_Ready
(
PyTypeObject
*
cls
)
noexcept
{
ASSERT
(
!
cls
->
is_pyston_class
,
"should not call this on Pyston classes"
);
gc
::
registerNonheapRootObject
(
cls
);
// unhandled fields:
...
...
@@ -1864,7 +2379,12 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
getset
->
get
,
(
void
(
*
)(
Box
*
,
Box
*
,
void
*
))
getset
->
set
,
getset
->
closure
));
}
PystonType_Ready
(
cls
);
try
{
commonClassSetup
(
cls
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
1
;
}
if
(
!
cls
->
hasattr
(
"__doc__"
))
{
if
(
cls
->
tp_doc
)
{
...
...
src/capi/typeobject.h
View file @
39859d79
...
...
@@ -23,7 +23,14 @@ namespace pyston {
bool
update_slot
(
BoxedClass
*
self
,
const
std
::
string
&
attr
)
noexcept
;
void
fixup_slot_dispatchers
(
BoxedClass
*
self
)
noexcept
;
void
PystonType_Ready
(
BoxedClass
*
cls
);
void
commonClassSetup
(
BoxedClass
*
cls
);
// We need to expose these due to our different file organization (they
// are defined as part of the CPython copied into typeobject.c, but used
// from Pyston code).
// We could probably unify things more but that's for later.
PyTypeObject
*
best_base
(
PyObject
*
bases
)
noexcept
;
PyObject
*
mro_external
(
PyObject
*
self
)
noexcept
;
}
#endif
src/gc/heap.cpp
View file @
39859d79
...
...
@@ -630,8 +630,8 @@ LargeArena::LargeFreeChunk* LargeArena::get_from_size_list(LargeFreeChunk** list
section
->
free_chunk_map
[
i
]
=
0
;
}
assert
(
section
->
num_free_chunks
>=
size
>>
CHUNK_BITS
);
section
->
num_free_chunks
-=
size
>>
CHUNK_BITS
;
assert
(
section
->
num_free_chunks
>=
0
);
return
free_chunks
;
}
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
39859d79
...
...
@@ -730,7 +730,7 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name, int
if
(
size
==
0
)
size
=
base
->
tp_basicsize
;
BoxedClass
*
cls
=
new
BoxedHeapClass
(
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
size
,
false
,
name
);
BoxedClass
*
cls
=
BoxedHeapClass
::
create
(
type_cls
,
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
size
,
false
,
name
);
cls
->
giveAttr
(
"__module__"
,
boxStrConstant
(
"exceptions"
));
if
(
base
==
object_cls
)
{
...
...
@@ -954,7 +954,8 @@ Box* pydumpAddr(Box* p) {
void
setupBuiltins
()
{
builtins_module
=
createModule
(
"__builtin__"
,
"__builtin__"
);
BoxedHeapClass
*
ellipsis_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
,
"ellipsis"
);
BoxedHeapClass
*
ellipsis_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
,
"ellipsis"
);
Box
*
Ellipsis
=
new
(
ellipsis_cls
)
Box
();
assert
(
Ellipsis
->
cls
);
gc
::
registerPermanentRoot
(
Ellipsis
);
...
...
@@ -967,7 +968,8 @@ void setupBuiltins() {
builtins_module
->
giveAttr
(
"print"
,
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
print
,
NONE
,
0
,
0
,
true
,
true
),
"print"
));
notimplemented_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
,
"NotImplementedType"
);
notimplemented_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
,
"NotImplementedType"
);
notimplemented_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
notimplementedRepr
,
STR
,
1
)));
notimplemented_cls
->
freeze
();
NotImplemented
=
new
(
notimplemented_cls
)
Box
();
...
...
@@ -1046,8 +1048,8 @@ void setupBuiltins() {
builtins_module
->
giveAttr
(
"__import__"
,
new
BoxedBuiltinFunctionOrMethod
(
import_func
,
"__import__"
,
{
None
,
None
,
None
,
new
BoxedInt
(
-
1
)
}));
enumerate_cls
=
new
BoxedHeapClass
(
object_cls
,
&
BoxedEnumerate
::
gcHandler
,
0
,
sizeof
(
BoxedEnumerate
),
false
,
"enumerate"
);
enumerate_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
BoxedEnumerate
::
gcHandler
,
0
,
sizeof
(
BoxedEnumerate
),
false
,
"enumerate"
);
enumerate_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedEnumerate
::
new_
,
UNKNOWN
,
3
,
1
,
false
,
false
),
{
boxInt
(
0
)
}));
...
...
src/runtime/builtin_modules/sys.cpp
View file @
39859d79
...
...
@@ -294,7 +294,8 @@ void setupSys() {
sys_module
->
giveAttr
(
"maxint"
,
boxInt
(
PYSTON_INT_MAX
));
sys_flags_cls
=
new
BoxedHeapClass
(
object_cls
,
BoxedSysFlags
::
gcHandler
,
0
,
sizeof
(
BoxedSysFlags
),
false
,
"flags"
);
sys_flags_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
BoxedSysFlags
::
gcHandler
,
0
,
sizeof
(
BoxedSysFlags
),
false
,
"flags"
);
sys_flags_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedSysFlags
::
__new__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
#define ADD(name) \
...
...
src/runtime/builtin_modules/thread.cpp
View file @
39859d79
...
...
@@ -179,7 +179,7 @@ void setupThread() {
thread_module
->
giveAttr
(
"stack_size"
,
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
stackSize
,
BOXED_INT
,
0
),
"stack_size"
));
thread_lock_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedThreadLock
),
false
,
"lock"
);
thread_lock_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedThreadLock
),
false
,
"lock"
);
thread_lock_cls
->
giveAttr
(
"__module__"
,
boxStrConstant
(
"thread"
));
thread_lock_cls
->
giveAttr
(
"acquire"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedThreadLock
::
acquire
,
BOXED_BOOL
,
2
,
1
,
false
,
false
),
...
...
@@ -191,13 +191,13 @@ void setupThread() {
thread_lock_cls
->
giveAttr
(
"__exit__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedThreadLock
::
exit
,
NONE
,
4
)));
thread_lock_cls
->
freeze
();
thread_local_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedThreadLocal
),
false
,
"_local"
);
thread_local_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedThreadLocal
),
false
,
"_local"
);
thread_local_cls
->
giveAttr
(
"__module__"
,
boxStrConstant
(
"thread"
));
thread_local_cls
->
freeze
();
thread_module
->
giveAttr
(
"_local"
,
thread_local_cls
);
BoxedClass
*
ThreadError
=
new
BoxedHeapClass
(
Exception
,
NULL
,
Exception
->
attrs_offset
,
Exception
->
tp_basicsize
,
false
,
"error"
);
BoxedClass
*
ThreadError
=
BoxedHeapClass
::
create
(
type_cls
,
Exception
,
NULL
,
Exception
->
attrs_offset
,
Exception
->
tp_basicsize
,
false
,
"error"
);
ThreadError
->
giveAttr
(
"__module__"
,
boxStrConstant
(
"thread"
));
ThreadError
->
freeze
();
...
...
src/runtime/capi.cpp
View file @
39859d79
...
...
@@ -501,6 +501,8 @@ extern "C" Py_ssize_t PySequence_Index(PyObject* o, PyObject* value) noexcept {
extern
"C"
PyObject
*
PySequence_Tuple
(
PyObject
*
o
)
noexcept
{
if
(
o
->
cls
==
tuple_cls
)
return
o
;
if
(
PyList_Check
(
o
))
return
PyList_AsTuple
(
o
);
Py_FatalError
(
"unimplemented"
);
}
...
...
@@ -1543,7 +1545,7 @@ static Box* methodGetDoc(Box* b, void*) {
}
void
setupCAPI
()
{
capifunc_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedCApiFunction
),
false
,
"capifunc"
);
capifunc_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedCApiFunction
),
false
,
"capifunc"
);
capifunc_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedCApiFunction
::
__repr__
,
UNKNOWN
,
1
)));
...
...
@@ -1554,7 +1556,7 @@ void setupCAPI() {
capifunc_cls
->
freeze
();
method_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMethodDescriptor
),
false
,
"method"
);
method_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMethodDescriptor
),
false
,
"method"
);
method_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__get__
,
UNKNOWN
,
3
)));
method_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__call__
,
UNKNOWN
,
2
,
...
...
@@ -1562,13 +1564,14 @@ void setupCAPI() {
method_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
methodGetDoc
,
NULL
,
NULL
));
method_cls
->
freeze
();
wrapperdescr_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperDescriptor
),
false
,
"wrapper_descriptor"
);
wrapperdescr_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperDescriptor
),
false
,
"wrapper_descriptor"
);
wrapperdescr_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperDescriptor
::
__get__
,
UNKNOWN
,
3
)));
wrapperdescr_cls
->
freeze
();
wrapperobject_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperObject
),
false
,
"method-wrapper"
);
wrapperobject_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperObject
),
false
,
"method-wrapper"
);
wrapperobject_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperObject
::
__call__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
wrapperobject_cls
->
freeze
();
...
...
src/runtime/classobj.cpp
View file @
39859d79
...
...
@@ -270,10 +270,10 @@ Box* instanceSetitem(Box* _inst, Box* key, Box* value) {
}
void
setupClassobj
()
{
classobj_cls
=
new
BoxedHeapClass
(
object_cls
,
&
BoxedClassobj
::
gcHandler
,
offsetof
(
BoxedClassobj
,
attrs
)
,
sizeof
(
BoxedClassobj
),
false
,
"classobj"
);
instance_cls
=
new
BoxedHeapClass
(
object_cls
,
&
BoxedInstance
::
gcHandler
,
offsetof
(
BoxedInstance
,
attrs
)
,
sizeof
(
BoxedInstance
),
false
,
"instance"
);
classobj_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
BoxedClassobj
::
gcHandler
,
offsetof
(
BoxedClassobj
,
attrs
),
sizeof
(
BoxedClassobj
),
false
,
"classobj"
);
instance_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
BoxedInstance
::
gcHandler
,
offsetof
(
BoxedInstance
,
attrs
),
sizeof
(
BoxedInstance
),
false
,
"instance"
);
classobj_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
classobjNew
,
UNKNOWN
,
4
,
0
,
false
,
false
)));
...
...
src/runtime/dict.cpp
View file @
39859d79
...
...
@@ -572,13 +572,15 @@ static Box* dict_repr(PyObject* self) noexcept {
}
void
setupDict
()
{
dict_iterator_cls
=
new
BoxedHeapClass
(
object_cls
,
&
dictIteratorGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
,
"dictionary-itemiterator"
);
dict_keys_cls
=
new
BoxedHeapClass
(
object_cls
,
&
dictViewGCHandler
,
0
,
sizeof
(
BoxedDictView
),
false
,
"dict_keys"
);
dict_values_cls
=
new
BoxedHeapClass
(
object_cls
,
&
dictViewGCHandler
,
0
,
sizeof
(
BoxedDictView
),
false
,
"dict_values"
);
dict_items_cls
=
new
BoxedHeapClass
(
object_cls
,
&
dictViewGCHandler
,
0
,
sizeof
(
BoxedDictView
),
false
,
"dict_items"
);
dict_iterator_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
dictIteratorGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
,
"dictionary-itemiterator"
);
dict_keys_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
dictViewGCHandler
,
0
,
sizeof
(
BoxedDictView
),
false
,
"dict_keys"
);
dict_values_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
dictViewGCHandler
,
0
,
sizeof
(
BoxedDictView
),
false
,
"dict_values"
);
dict_items_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
dictViewGCHandler
,
0
,
sizeof
(
BoxedDictView
),
false
,
"dict_items"
);
dict_cls
->
giveAttr
(
"__len__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
dictLen
,
BOXED_INT
,
1
)));
dict_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
dictNew
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
...
...
src/runtime/generator.cpp
View file @
39859d79
...
...
@@ -298,8 +298,8 @@ void generatorDestructor(Box* b) {
}
void
setupGenerator
()
{
generator_cls
=
new
BoxedHeapClass
(
object_cls
,
&
generatorGCHandler
,
offsetof
(
BoxedGenerator
,
attrs
),
sizeof
(
BoxedGenerator
),
false
,
"generator"
);
generator_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
generatorGCHandler
,
offsetof
(
BoxedGenerator
,
attrs
),
sizeof
(
BoxedGenerator
),
false
,
"generator"
);
generator_cls
->
simple_destructor
=
generatorDestructor
;
generator_cls
->
giveAttr
(
"__iter__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorIter
,
typeFromClass
(
generator_cls
),
1
)));
...
...
src/runtime/inline/xrange.cpp
View file @
39859d79
...
...
@@ -178,9 +178,9 @@ Box* xrangeReversed(Box* self) {
}
void
setupXrange
()
{
xrange_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedXrange
),
false
,
"xrange"
);
xrange_iterator_cls
=
new
BoxedHeapClass
(
object_cls
,
&
BoxedXrangeIterator
::
xrangeIteratorGCHandler
,
0
,
sizeof
(
BoxedXrangeIterator
),
false
,
"rangeiterator"
);
xrange_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedXrange
),
false
,
"xrange"
);
xrange_iterator_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
BoxedXrangeIterator
::
xrangeIteratorGCHandler
,
0
,
sizeof
(
BoxedXrangeIterator
),
false
,
"rangeiterator"
);
xrange_cls
->
giveAttr
(
"__new__"
,
...
...
src/runtime/iterobject.cpp
View file @
39859d79
...
...
@@ -141,7 +141,8 @@ extern "C" PyObject* PySeqIter_New(PyObject* seq) noexcept {
}
void
setupIter
()
{
seqiter_cls
=
new
BoxedHeapClass
(
object_cls
,
seqiterGCVisit
,
0
,
sizeof
(
BoxedSeqIter
),
false
,
"iterator"
);
seqiter_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
seqiterGCVisit
,
0
,
sizeof
(
BoxedSeqIter
),
false
,
"iterator"
);
seqiter_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqiterNext
,
UNKNOWN
,
1
)));
seqiter_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqiterHasnext
,
BOXED_BOOL
,
1
)));
...
...
@@ -149,7 +150,7 @@ void setupIter() {
seqiter_cls
->
freeze
();
seqreviter_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedSeqIter
),
false
,
"reversed"
);
seqreviter_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedSeqIter
),
false
,
"reversed"
);
seqreviter_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqiterNext
,
UNKNOWN
,
1
)));
seqreviter_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqreviterHasnext
,
BOXED_BOOL
,
1
)));
...
...
@@ -157,8 +158,8 @@ void setupIter() {
seqreviter_cls
->
freeze
();
iterwrapper_cls
=
new
BoxedHeapClass
(
object_cls
,
iterwrapperGCVisit
,
0
,
sizeof
(
BoxedIterWrapper
),
false
,
"iterwrapper"
);
iterwrapper_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
iterwrapperGCVisit
,
0
,
sizeof
(
BoxedIterWrapper
),
false
,
"iterwrapper"
);
iterwrapper_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
iterwrapperNext
,
UNKNOWN
,
1
)));
iterwrapper_cls
->
giveAttr
(
"__hasnext__"
,
...
...
src/runtime/list.cpp
View file @
39859d79
...
...
@@ -49,6 +49,19 @@ extern "C" PyObject** PyList_Items(PyObject* op) noexcept {
return
&
static_cast
<
BoxedList
*>
(
op
)
->
elts
->
elts
[
0
];
}
extern
"C"
PyObject
*
PyList_AsTuple
(
PyObject
*
v
)
noexcept
{
PyObject
*
w
;
PyObject
**
p
,
**
q
;
Py_ssize_t
n
;
if
(
v
==
NULL
||
!
PyList_Check
(
v
))
{
PyErr_BadInternalCall
();
return
NULL
;
}
auto
l
=
static_cast
<
BoxedList
*>
(
v
);
return
new
BoxedTuple
(
BoxedTuple
::
GCVector
(
l
->
elts
->
elts
,
l
->
elts
->
elts
+
l
->
size
));
}
extern
"C"
Box
*
listRepr
(
BoxedList
*
self
)
{
LOCK_REGION
(
self
->
lock
.
asRead
());
...
...
@@ -751,10 +764,10 @@ extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, P
}
void
setupList
()
{
list_iterator_cls
=
new
BoxedHeapClass
(
object_cls
,
&
listIteratorGCHandler
,
0
,
sizeof
(
BoxedList
),
false
,
"listiterator"
);
list_reverse_iterator_cls
=
new
BoxedHeapClass
(
object_cls
,
&
listIteratorGCHandler
,
0
,
sizeof
(
BoxedListIterator
)
,
false
,
"listreverseiterator"
);
list_iterator_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
listIteratorGCHandler
,
0
,
sizeof
(
BoxedList
),
false
,
"listiterator"
);
list_reverse_iterator_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
listIteratorGCHandler
,
0
,
sizeof
(
BoxedListIterator
),
false
,
"listreverseiterator"
);
list_cls
->
giveAttr
(
"__len__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
listLen
,
BOXED_INT
,
1
)));
...
...
src/runtime/objmodel.cpp
View file @
39859d79
...
...
@@ -195,10 +195,11 @@ bool isInstance(Box* obj, BoxedClass* cls) {
extern
"C"
bool
isSubclass
(
BoxedClass
*
child
,
BoxedClass
*
parent
)
{
// TODO the class is allowed to override this using __subclasscheck__
while
(
child
)
{
if
(
child
==
parent
)
assert
(
child
->
tp_mro
);
assert
(
child
->
tp_mro
->
cls
==
tuple_cls
);
for
(
auto
b
:
static_cast
<
BoxedTuple
*>
(
child
->
tp_mro
)
->
elts
)
{
if
(
b
==
parent
)
return
true
;
child
=
child
->
tp_base
;
}
return
false
;
}
...
...
@@ -314,7 +315,10 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
if
(
cls
==
NULL
)
{
assert
(
type_cls
==
NULL
);
}
else
{
assert
(
isSubclass
(
cls
,
type_cls
));
// The (cls == type_cls) part of the check is important because during bootstrapping
// we might not have set up enough stuff in order to do proper subclass checking,
// but those clases will either have cls == NULL or cls == type_cls
assert
(
cls
==
type_cls
||
isSubclass
(
cls
,
type_cls
));
}
assert
(
tp_dealloc
==
NULL
);
...
...
@@ -349,26 +353,23 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
gc
::
registerPermanentRoot
(
this
);
}
BoxedHeapClass
::
BoxedHeapClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
,
const
std
::
string
&
name
)
:
BoxedHeapClass
(
base
,
gc_visit
,
attrs_offset
,
instance_size
,
is_user_defined
,
new
BoxedString
(
name
))
{
void
BoxedClass
::
finishInitialization
()
{
commonClassSetup
(
this
);
}
BoxedHeapClass
::
BoxedHeapClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
)
:
BoxedClass
(
base
,
gc_visit
,
attrs_offset
,
instance_size
,
is_user_defined
),
ht_name
(
NULL
),
ht_slots
(
NULL
)
{
// This constructor is only used for bootstrapping purposes to be called for types that
// are initialized before str_cls.
// Therefore, we assert that str_cls is uninitialized to make sure this isn't called at
// an inappropriate time.
assert
(
str_cls
==
NULL
);
bool
is_user_defined
,
BoxedString
*
name
)
:
BoxedClass
(
base
,
gc_visit
,
attrs_offset
,
instance_size
,
is_user_defined
),
ht_name
(
name
),
ht_slots
(
NULL
)
{
tp_as_number
=
&
as_number
;
tp_as_mapping
=
&
as_mapping
;
tp_as_sequence
=
&
as_sequence
;
tp_as_buffer
=
&
as_buffer
;
tp_flags
|=
Py_TPFLAGS_HEAPTYPE
;
if
(
!
ht_name
)
assert
(
str_cls
==
NULL
);
else
tp_name
=
ht_name
->
s
.
c_str
();
memset
(
&
as_number
,
0
,
sizeof
(
as_number
));
memset
(
&
as_mapping
,
0
,
sizeof
(
as_mapping
));
...
...
@@ -376,21 +377,26 @@ BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attr
memset
(
&
as_buffer
,
0
,
sizeof
(
as_buffer
));
}
BoxedHeapClass
::
BoxedHeapClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
,
BoxedString
*
name
)
:
BoxedClass
(
base
,
gc_visit
,
attrs_offset
,
instance_size
,
is_user_defined
),
ht_name
(
name
),
ht_slots
(
NULL
)
{
BoxedHeapClass
*
BoxedHeapClass
::
create
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
,
const
std
::
string
&
name
)
{
return
create
(
metaclass
,
base
,
gc_visit
,
attrs_offset
,
instance_size
,
is_user_defined
,
new
BoxedString
(
name
),
NULL
);
}
tp_as_number
=
&
as_number
;
tp_as_mapping
=
&
as_mapping
;
tp_as_sequence
=
&
as_sequence
;
tp_as_buffer
=
&
as_buffer
;
tp_name
=
ht_name
->
s
.
c_str
();
tp_flags
|=
Py_TPFLAGS_HEAPTYPE
;
BoxedHeapClass
*
BoxedHeapClass
::
create
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
,
BoxedString
*
name
,
BoxedTuple
*
bases
)
{
BoxedHeapClass
*
made
=
new
(
metaclass
)
BoxedHeapClass
(
base
,
gc_visit
,
attrs_offset
,
instance_size
,
is_user_defined
,
name
);
memset
(
&
as_number
,
0
,
sizeof
(
as_number
));
memset
(
&
as_mapping
,
0
,
sizeof
(
as_mapping
));
memset
(
&
as_sequence
,
0
,
sizeof
(
as_sequence
));
memset
(
&
as_buffer
,
0
,
sizeof
(
as_buffer
));
// While it might be ok if these were set, it'd indicate a difference in
// expectations as to who was going to calculate them:
assert
(
!
made
->
tp_mro
);
assert
(
!
made
->
tp_bases
);
made
->
tp_bases
=
bases
;
made
->
finishInitialization
();
assert
(
made
->
tp_mro
);
return
made
;
}
std
::
string
getFullNameOfClass
(
BoxedClass
*
cls
)
{
...
...
@@ -656,19 +662,45 @@ Box* typeLookup(BoxedClass* cls, const std::string& attr, GetattrRewriteArgs* re
RewriterVar
*
obj_saved
=
rewrite_args
->
obj
;
val
=
cls
->
getattr
(
attr
,
rewrite_args
);
assert
(
rewrite_args
->
out_success
);
if
(
!
val
and
cls
->
tp_base
)
{
auto
_mro
=
cls
->
tp_mro
;
assert
(
_mro
->
cls
==
tuple_cls
);
BoxedTuple
*
mro
=
static_cast
<
BoxedTuple
*>
(
_mro
);
// Guarding approach:
// Guard on the value of the tp_mro slot, which should be a tuple and thus be
// immutable. Then we don't have to figure out the guards to emit that check
// the individual mro entries.
// We can probably move this guard to after we call getattr() on the given cls.
//
// TODO this can fail if we replace the mro with another mro that lives in the same
// address.
obj_saved
->
addAttrGuard
(
offsetof
(
BoxedClass
,
tp_mro
),
(
intptr_t
)
mro
);
for
(
auto
base
:
mro
->
elts
)
{
rewrite_args
->
out_success
=
false
;
rewrite_args
->
obj
=
obj_saved
->
getAttr
(
offsetof
(
BoxedClass
,
tp_base
));
val
=
typeLookup
(
cls
->
tp_base
,
attr
,
rewrite_args
);
if
(
base
==
cls
)
{
// Small optimization: don't have to load the class again since it was given to us in
// a register.
assert
(
rewrite_args
->
obj
==
obj_saved
);
}
else
{
rewrite_args
->
obj
=
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
base
,
Location
::
any
());
}
val
=
base
->
getattr
(
attr
,
rewrite_args
);
assert
(
rewrite_args
->
out_success
);
if
(
val
)
return
val
;
}
return
val
;
return
NULL
;
}
else
{
val
=
cls
->
getattr
(
attr
,
NULL
);
if
(
!
val
and
cls
->
tp_base
)
return
typeLookup
(
cls
->
tp_base
,
attr
,
NULL
);
return
val
;
assert
(
cls
->
tp_mro
);
assert
(
cls
->
tp_mro
->
cls
==
tuple_cls
);
for
(
auto
b
:
static_cast
<
BoxedTuple
*>
(
cls
->
tp_mro
)
->
elts
)
{
val
=
b
->
getattr
(
attr
,
NULL
);
if
(
val
)
return
val
;
}
return
NULL
;
}
}
...
...
@@ -1521,9 +1553,8 @@ extern "C" Box* getattr(Box* obj, const char* attr) {
// This doesn't belong here either:
if
(
strcmp
(
attr
,
"__bases__"
)
==
0
&&
isSubclass
(
obj
->
cls
,
type_cls
))
{
BoxedClass
*
cls
=
static_cast
<
BoxedClass
*>
(
obj
);
if
(
cls
->
tp_base
)
return
new
BoxedTuple
({
static_cast
<
BoxedClass
*>
(
obj
)
->
tp_base
});
return
EmptyTuple
;
assert
(
cls
->
tp_bases
);
return
cls
->
tp_bases
;
}
}
...
...
@@ -2031,10 +2062,16 @@ extern "C" void dump(void* p) {
auto
cls
=
static_cast
<
BoxedClass
*>
(
b
);
printf
(
"Type name: %s
\n
"
,
getFullNameOfClass
(
cls
).
c_str
());
printf
(
"MRO: %s"
,
getFullNameOfClass
(
cls
).
c_str
());
while
(
cls
->
tp_base
)
{
printf
(
" -> %s"
,
getFullNameOfClass
(
cls
->
tp_base
).
c_str
());
cls
=
cls
->
tp_base
;
printf
(
"MRO:"
);
if
(
cls
->
tp_mro
&&
cls
->
tp_mro
->
cls
==
tuple_cls
)
{
bool
first
=
true
;
for
(
auto
b
:
static_cast
<
BoxedTuple
*>
(
cls
->
tp_mro
)
->
elts
)
{
if
(
!
first
)
printf
(
" ->"
);
first
=
false
;
printf
(
" %s"
,
getFullNameOfClass
(
static_cast
<
BoxedClass
*>
(
b
)).
c_str
());
}
}
printf
(
"
\n
"
);
}
...
...
@@ -3572,10 +3609,10 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
if
(
!
isSubclass
(
_cls
->
cls
,
type_cls
))
raiseExcHelper
(
TypeError
,
"type.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
));
BoxedClass
*
cls
=
static_cast
<
BoxedClass
*>
(
_cls
);
if
(
!
isSubclass
(
cls
,
type_cls
))
raiseExcHelper
(
TypeError
,
"type.__new__(%s): %s is not a subtype of type"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
BoxedClass
*
metatype
=
static_cast
<
BoxedClass
*>
(
_cls
);
if
(
!
isSubclass
(
metatype
,
type_cls
))
raiseExcHelper
(
TypeError
,
"type.__new__(%s): %s is not a subtype of type"
,
getNameOfClass
(
metatype
),
getNameOfClass
(
metatype
));
if
(
arg2
==
NULL
)
{
assert
(
arg3
==
NULL
);
...
...
@@ -3592,30 +3629,65 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
RELEASE_ASSERT
(
arg1
->
cls
==
str_cls
,
""
);
BoxedString
*
name
=
static_cast
<
BoxedString
*>
(
arg1
);
BoxedClass
*
base
;
if
(
bases
->
elts
.
size
()
==
0
)
{
bases
=
new
BoxedTuple
({
object_cls
});
}
RELEASE_ASSERT
(
bases
->
elts
.
size
()
==
1
,
""
);
Box
*
_base
=
bases
->
elts
[
0
];
RELEASE_ASSERT
(
isSubclass
(
_base
->
cls
,
type_cls
),
""
);
base
=
static_cast
<
BoxedClass
*>
(
_base
);
// Ported from CPython:
int
nbases
=
bases
->
elts
.
size
();
BoxedClass
*
winner
=
metatype
;
for
(
auto
tmp
:
bases
->
elts
)
{
auto
tmptype
=
tmp
->
cls
;
if
(
tmptype
==
classobj_cls
)
continue
;
if
(
isSubclass
(
winner
,
tmptype
))
continue
;
if
(
isSubclass
(
tmptype
,
winner
))
{
winner
=
tmptype
;
continue
;
}
raiseExcHelper
(
TypeError
,
"metaclass conflict: "
"the metaclass of a derived class "
"must be a (non-strict) subclass "
"of the metaclasses of all its bases"
);
}
if
((
base
->
tp_flags
&
Py_TPFLAGS_BASETYPE
)
==
0
)
if
(
winner
!=
metatype
)
{
if
(
getattr
(
winner
,
"__new__"
)
!=
getattr
(
type_cls
,
"__new__"
))
{
RELEASE_ASSERT
(
0
,
"untested"
);
return
callattr
(
winner
,
&
new_str
,
CallattrFlags
({.
cls_only
=
true
,
.
null_on_nonexistent
=
false
}),
ArgPassSpec
(
3
),
arg1
,
arg2
,
arg3
,
_args
+
1
,
NULL
);
}
metatype
=
winner
;
}
BoxedClass
*
base
=
best_base
(
bases
);
checkAndThrowCAPIException
();
assert
(
base
);
if
(
!
PyType_HasFeature
(
base
,
Py_TPFLAGS_BASETYPE
))
raiseExcHelper
(
TypeError
,
"type '%.100s' is not an acceptable base type"
,
base
->
tp_name
);
assert
(
isSubclass
(
base
->
cls
,
type_cls
));
// TODO I don't think we have to implement the __slots__ memory savings behavior
// (we get almost all of that automatically with hidden classes), but adding a __slots__
// adds other restrictions (ex for multiple inheritance) that we won't end up enforcing.
// I guess it should be ok if we're more permissive?
// auto slots = PyDict_GetItemString(attr_dict, "__slots__");
// RELEASE_ASSERT(!slots, "__slots__ unsupported");
BoxedClass
*
made
;
if
(
base
->
instancesHaveDictAttrs
()
||
base
->
instancesHaveHCAttrs
())
{
made
=
new
(
cls
)
BoxedHeapClass
(
base
,
NULL
,
base
->
attrs_offset
,
base
->
tp_basicsize
,
true
,
name
);
made
=
BoxedHeapClass
::
create
(
metatype
,
base
,
NULL
,
base
->
attrs_offset
,
base
->
tp_basicsize
,
true
,
name
,
bases
);
}
else
{
assert
(
base
->
tp_basicsize
%
sizeof
(
void
*
)
==
0
);
made
=
new
(
cls
)
BoxedHeapClass
(
base
,
NULL
,
base
->
tp_basicsize
,
base
->
tp_basicsize
+
sizeof
(
HCAttrs
),
true
,
name
);
made
=
BoxedHeapClass
::
create
(
metatype
,
base
,
NULL
,
base
->
tp_basicsize
,
base
->
tp_basicsize
+
sizeof
(
HCAttrs
),
true
,
name
,
bases
);
}
// TODO: how much of these should be in BoxedClass::finishInitialization()?
made
->
tp_dictoffset
=
base
->
tp_dictoffset
;
for
(
const
auto
&
p
:
attr_dict
->
d
)
{
...
...
@@ -3630,7 +3702,6 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
made
->
tp_new
=
base
->
tp_new
;
PystonType_Ready
(
made
);
fixup_slot_dispatchers
(
made
);
if
(
base
->
tp_alloc
==
&
PystonType_GenericAlloc
)
...
...
src/runtime/set.cpp
View file @
39859d79
...
...
@@ -246,7 +246,8 @@ Box* setNonzero(BoxedSet* self) {
using
namespace
pyston
::
set
;
void
setupSet
()
{
set_iterator_cls
=
new
BoxedHeapClass
(
object_cls
,
&
setIteratorGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
,
"setiterator"
);
set_iterator_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
setIteratorGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
,
"setiterator"
);
set_iterator_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
setiteratorHasnext
,
BOXED_BOOL
,
1
)));
set_iterator_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
setiteratorNext
,
UNKNOWN
,
1
)));
...
...
src/runtime/str.cpp
View file @
39859d79
...
...
@@ -2208,8 +2208,8 @@ void setupStr() {
str_cls
->
simple_destructor
=
strDestructor
;
str_cls
->
tp_flags
|=
Py_TPFLAGS_HAVE_NEWBUFFER
;
str_iterator_cls
=
new
BoxedHeapClass
(
object_cls
,
&
strIteratorGCHandler
,
0
,
sizeof
(
BoxedStringIterator
),
false
,
"striterator"
);
str_iterator_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
strIteratorGCHandler
,
0
,
sizeof
(
BoxedStringIterator
),
false
,
"striterator"
);
str_iterator_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedStringIterator
::
hasnext
,
BOXED_BOOL
,
1
)));
str_iterator_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedStringIterator
::
next
,
STR
,
1
)));
...
...
src/runtime/super.cpp
View file @
39859d79
...
...
@@ -16,6 +16,7 @@
#include <sstream>
#include "capi/types.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/objmodel.h"
...
...
@@ -66,15 +67,68 @@ Box* superGetattribute(Box* _s, Box* _attr) {
}
if
(
!
skip
)
{
// We don't support multiple inheritance yet, so the lookup order is simple:
Box
*
r
=
typeLookup
(
s
->
type
->
tp_base
,
attr
->
s
,
NULL
);
if
(
r
)
{
return
processDescriptor
(
r
,
(
s
->
obj
==
s
->
obj_type
?
None
:
s
->
obj
),
s
->
obj_type
);
PyObject
*
mro
,
*
res
,
*
tmp
,
*
dict
;
PyTypeObject
*
starttype
;
descrgetfunc
f
;
Py_ssize_t
i
,
n
;
starttype
=
s
->
obj_type
;
mro
=
starttype
->
tp_mro
;
if
(
mro
==
NULL
)
n
=
0
;
else
{
assert
(
PyTuple_Check
(
mro
));
n
=
PyTuple_GET_SIZE
(
mro
);
}
for
(
i
=
0
;
i
<
n
;
i
++
)
{
if
((
PyObject
*
)(
s
->
type
)
==
PyTuple_GET_ITEM
(
mro
,
i
))
break
;
}
i
++
;
res
=
NULL
;
for
(;
i
<
n
;
i
++
)
{
tmp
=
PyTuple_GET_ITEM
(
mro
,
i
);
// Pyston change:
#if 0
if (PyType_Check(tmp))
dict = ((PyTypeObject *)tmp)->tp_dict;
else if (PyClass_Check(tmp))
dict = ((PyClassObject *)tmp)->cl_dict;
else
continue;
res = PyDict_GetItem(dict, name);
#endif
res
=
tmp
->
getattr
(
attr
->
s
);
if
(
res
!=
NULL
)
{
// Pyston change:
#if 0
Py_INCREF(res);
f = Py_TYPE(res)->tp_descr_get;
if (f != NULL) {
tmp = f(res,
/* Only pass 'obj' param if
this is instance-mode sper
(See SF ID #743627)
*/
(s->obj == (PyObject *)
s->obj_type
? (PyObject *)NULL
: s->obj),
(PyObject *)starttype);
Py_DECREF(res);
res = tmp;
}
#endif
return
processDescriptor
(
res
,
(
s
->
obj
==
s
->
obj_type
?
None
:
s
->
obj
),
s
->
obj_type
);
}
}
}
Box
*
r
=
typeLookup
(
s
->
cls
,
attr
->
s
,
NULL
);
// TODO implement this
RELEASE_ASSERT
(
r
,
"should call the equivalent of objectGetattr here"
);
return
processDescriptor
(
r
,
s
,
s
->
cls
);
}
...
...
@@ -132,7 +186,8 @@ Box* superInit(Box* _self, Box* _type, Box* obj) {
}
void
setupSuper
()
{
super_cls
=
new
BoxedHeapClass
(
object_cls
,
&
BoxedSuper
::
gcHandler
,
0
,
sizeof
(
BoxedSuper
),
false
,
"super"
);
super_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
BoxedSuper
::
gcHandler
,
0
,
sizeof
(
BoxedSuper
),
false
,
"super"
);
super_cls
->
giveAttr
(
"__getattribute__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
superGetattribute
,
UNKNOWN
,
2
)));
super_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
superRepr
,
STR
,
1
)));
...
...
src/runtime/traceback.cpp
View file @
39859d79
...
...
@@ -107,8 +107,8 @@ Box* BoxedTraceback::getLines(Box* b) {
}
void
setupTraceback
()
{
traceback_cls
=
new
BoxedHeapClass
(
object_cls
,
BoxedTraceback
::
gcHandler
,
0
,
sizeof
(
BoxedTraceback
),
false
,
"traceback"
);
traceback_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
BoxedTraceback
::
gcHandler
,
0
,
sizeof
(
BoxedTraceback
),
false
,
"traceback"
);
traceback_cls
->
giveAttr
(
"getLines"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedTraceback
::
getLines
,
UNKNOWN
,
1
)));
...
...
src/runtime/tuple.cpp
View file @
39859d79
...
...
@@ -386,7 +386,8 @@ extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
void
setupTuple
()
{
tuple_iterator_cls
=
new
BoxedHeapClass
(
object_cls
,
&
tupleIteratorGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
,
"tuple"
);
tuple_iterator_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
tupleIteratorGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
,
"tuple"
);
tuple_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
tupleNew
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
CLFunction
*
getitem
=
createRTFunction
(
2
,
0
,
0
,
0
);
...
...
src/runtime/types.cpp
View file @
39859d79
...
...
@@ -21,6 +21,7 @@
#include <sstream>
#include <stdint.h>
#include "capi/typeobject.h"
#include "core/options.h"
#include "core/stats.h"
#include "core/types.h"
...
...
@@ -96,10 +97,16 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
assert(static_cast<BoxedClass*>(e)->is_pyston_class);
}
#endif
BoxedClass
*
b
=
cls
;
while
(
b
)
{
ASSERT
(
b
->
is_pyston_class
,
"%s (%s)"
,
cls
->
tp_name
,
b
->
tp_name
);
b
=
b
->
tp_base
;
if
(
!
cls
->
tp_mro
)
{
assert
(
!
list_cls
);
}
else
{
assert
(
cls
->
tp_mro
&&
"maybe we should just skip these checks if !mro"
);
assert
(
cls
->
tp_mro
->
cls
==
tuple_cls
);
for
(
auto
b
:
static_cast
<
BoxedTuple
*>
(
cls
->
tp_mro
)
->
elts
)
{
assert
(
isSubclass
(
b
->
cls
,
type_cls
));
ASSERT
(
static_cast
<
BoxedClass
*>
(
b
)
->
is_pyston_class
,
"%s (%s)"
,
cls
->
tp_name
,
static_cast
<
BoxedClass
*>
(
b
)
->
tp_name
);
}
}
#endif
...
...
@@ -405,6 +412,10 @@ extern "C" void typeGCHandler(GCVisitor* v, Box* b) {
v
->
visit
(
cls
->
tp_base
);
if
(
cls
->
tp_dict
)
v
->
visit
(
cls
->
tp_dict
);
if
(
cls
->
tp_mro
)
v
->
visit
(
cls
->
tp_mro
);
if
(
cls
->
tp_bases
)
v
->
visit
(
cls
->
tp_bases
);
if
(
cls
->
tp_flags
&
Py_TPFLAGS_HEAPTYPE
)
{
BoxedHeapClass
*
hcls
=
static_cast
<
BoxedHeapClass
*>
(
cls
);
...
...
@@ -898,6 +909,15 @@ Box* typeHash(BoxedClass* self) {
return
boxInt
(
reinterpret_cast
<
intptr_t
>
(
self
)
>>
4
);
}
Box
*
typeMro
(
BoxedClass
*
self
)
{
assert
(
isSubclass
(
self
->
cls
,
type_cls
));
Box
*
r
=
mro_external
(
self
);
if
(
!
r
)
throwCAPIException
();
return
r
;
}
Box
*
moduleRepr
(
BoxedModule
*
m
)
{
assert
(
m
->
cls
==
module_cls
);
...
...
@@ -1220,20 +1240,19 @@ void setupRuntime() {
object_cls
=
::
new
(
mem
)
BoxedClass
(
NULL
,
&
boxGCHandler
,
0
,
sizeof
(
Box
),
false
);
mem
=
gc_alloc
(
sizeof
(
BoxedHeapClass
),
gc
::
GCKind
::
PYTHON
);
type_cls
=
::
new
(
mem
)
BoxedHeapClass
(
object_cls
,
&
typeGCHandler
,
offsetof
(
BoxedClass
,
attrs
),
sizeof
(
BoxedHeapClass
),
false
);
BoxedHeapClass
(
object_cls
,
&
typeGCHandler
,
offsetof
(
BoxedClass
,
attrs
),
sizeof
(
BoxedHeapClass
),
false
,
NULL
);
PyObject_Init
(
object_cls
,
type_cls
);
PyObject_Init
(
type_cls
,
type_cls
);
none_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
none_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
,
NULL
);
None
=
new
(
none_cls
)
Box
();
assert
(
None
->
cls
);
gc
::
registerPermanentRoot
(
None
);
// You can't actually have an instance of basestring
basestring_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
basestring_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
,
NULL
);
// TODO we leak all the string data!
str_cls
=
new
BoxedHeapClass
(
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedString
),
false
);
str_cls
=
new
BoxedHeapClass
(
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedString
),
false
,
NULL
);
// Hold off on assigning names until str_cls is ready
object_cls
->
tp_name
=
"object"
;
...
...
@@ -1260,54 +1279,75 @@ void setupRuntime() {
object_cls
->
giveAttr
(
"__base__"
,
None
);
tuple_cls
=
new
BoxedHeapClass
(
object_cls
,
&
tupleGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
,
"tuple"
);
tuple_cls
=
new
BoxedHeapClass
(
object_cls
,
&
tupleGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
,
boxStrConstant
(
"tuple"
)
);
EmptyTuple
=
new
BoxedTuple
({});
gc
::
registerPermanentRoot
(
EmptyTuple
);
list_cls
=
new
BoxedHeapClass
(
object_cls
,
&
listGCHandler
,
0
,
sizeof
(
BoxedList
),
false
,
boxStrConstant
(
"list"
));
// Kind of hacky, but it's easier to manually construct the mro for a couple key classes
// than try to make the MRO construction code be safe against say, tuple_cls not having
// an mro (since the mro is stored as a tuple).
tuple_cls
->
tp_mro
=
new
BoxedTuple
({
tuple_cls
,
object_cls
});
list_cls
->
tp_mro
=
new
BoxedTuple
({
list_cls
,
object_cls
});
type_cls
->
tp_mro
=
new
BoxedTuple
({
type_cls
,
object_cls
});
object_cls
->
finishInitialization
();
type_cls
->
finishInitialization
();
basestring_cls
->
finishInitialization
();
str_cls
->
finishInitialization
();
none_cls
->
finishInitialization
();
tuple_cls
->
finishInitialization
();
list_cls
->
finishInitialization
();
module_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
offsetof
(
BoxedModule
,
attrs
),
sizeof
(
BoxedModule
),
false
,
"module"
);
module_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
offsetof
(
BoxedModule
,
attrs
),
sizeof
(
BoxedModule
),
false
,
"module"
);
// 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.
int_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedInt
),
false
,
"int"
);
bool_cls
=
new
BoxedHeapClass
(
int_cls
,
NULL
,
0
,
sizeof
(
BoxedBool
),
false
,
"bool"
);
complex_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedComplex
),
false
,
"complex"
);
long_cls
=
new
BoxedHeapClass
(
object_cls
,
&
BoxedLong
::
gchandler
,
0
,
sizeof
(
BoxedLong
),
false
,
"long"
);
float_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFloat
),
false
,
"float"
);
function_cls
=
new
BoxedHeapClass
(
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedFunction
,
attrs
),
sizeof
(
BoxedFunction
),
false
,
"function"
);
int_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedInt
),
false
,
"int"
);
bool_cls
=
BoxedHeapClass
::
create
(
type_cls
,
int_cls
,
NULL
,
0
,
sizeof
(
BoxedBool
),
false
,
"bool"
);
complex_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedComplex
),
false
,
"complex"
);
long_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
BoxedLong
::
gchandler
,
0
,
sizeof
(
BoxedLong
),
false
,
"long"
);
float_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFloat
),
false
,
"float"
);
function_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedFunction
,
attrs
),
sizeof
(
BoxedFunction
),
false
,
"function"
);
function_cls
->
tp_weaklistoffset
=
offsetof
(
BoxedFunction
,
in_weakreflist
);
builtin_function_or_method_cls
=
new
BoxedHeapClass
(
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedBuiltinFunctionOrMethod
,
attrs
),
sizeof
(
BoxedBuiltinFunctionOrMethod
),
false
,
"builtin_function_or_method"
);
builtin_function_or_method_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedBuiltinFunctionOrMethod
,
attrs
),
sizeof
(
BoxedBuiltinFunctionOrMethod
),
false
,
"builtin_function_or_method"
);
builtin_function_or_method_cls
->
tp_weaklistoffset
=
offsetof
(
BoxedBuiltinFunctionOrMethod
,
in_weakreflist
);
function_cls
->
simple_destructor
=
builtin_function_or_method_cls
->
simple_destructor
=
functionDtor
;
instancemethod_cls
=
new
BoxedHeapClass
(
object_cls
,
&
instancemethodGCHandler
,
0
,
sizeof
(
BoxedInstanceMethod
),
false
,
"instancemethod"
);
instancemethod_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
instancemethodGCHandler
,
0
,
sizeof
(
BoxedInstanceMethod
),
false
,
"instancemethod"
);
instancemethod_cls
->
tp_weaklistoffset
=
offsetof
(
BoxedInstanceMethod
,
in_weakreflist
);
list_cls
=
new
BoxedHeapClass
(
object_cls
,
&
listGCHandler
,
0
,
sizeof
(
BoxedList
),
false
,
"list"
);
slice_cls
=
new
BoxedHeapClass
(
object_cls
,
&
sliceGCHandler
,
0
,
sizeof
(
BoxedSlice
),
false
,
"slice"
);
dict_cls
=
new
BoxedHeapClass
(
object_cls
,
&
dictGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
,
"dict"
);
file_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFile
),
false
,
"file"
);
set_cls
=
new
BoxedHeapClass
(
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
,
"set"
);
frozenset_cls
=
new
BoxedHeapClass
(
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
,
"frozenset"
);
member_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
,
"member"
);
pyston_getset_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
"getset"
);
capi_getset_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
"getset"
);
closure_cls
=
new
BoxedHeapClass
(
object_cls
,
&
closureGCHandler
,
offsetof
(
BoxedClosure
,
attrs
),
sizeof
(
BoxedClosure
),
false
,
"closure"
);
property_cls
=
new
BoxedHeapClass
(
object_cls
,
&
propertyGCHandler
,
0
,
sizeof
(
BoxedProperty
),
false
,
"property"
);
staticmethod_cls
=
new
BoxedHeapClass
(
object_cls
,
&
staticmethodGCHandler
,
0
,
sizeof
(
BoxedStaticmethod
),
false
,
"staticmethod"
);
classmethod_cls
=
new
BoxedHeapClass
(
object_cls
,
&
classmethodGCHandler
,
0
,
sizeof
(
BoxedClassmethod
),
false
,
"classmethod"
);
attrwrapper_cls
=
new
BoxedHeapClass
(
object_cls
,
&
AttrWrapper
::
gcHandler
,
0
,
sizeof
(
AttrWrapper
),
false
,
"attrwrapper"
);
list_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
listGCHandler
,
0
,
sizeof
(
BoxedList
),
false
,
"list"
);
slice_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
sliceGCHandler
,
0
,
sizeof
(
BoxedSlice
),
false
,
"slice"
);
dict_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
dictGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
,
"dict"
);
file_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFile
),
false
,
"file"
);
set_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
,
"set"
);
frozenset_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
,
"frozenset"
);
member_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
,
"member"
);
pyston_getset_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
"getset"
);
capi_getset_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
"getset"
);
closure_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
closureGCHandler
,
offsetof
(
BoxedClosure
,
attrs
),
sizeof
(
BoxedClosure
),
false
,
"closure"
);
property_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
propertyGCHandler
,
0
,
sizeof
(
BoxedProperty
),
false
,
"property"
);
staticmethod_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
staticmethodGCHandler
,
0
,
sizeof
(
BoxedStaticmethod
),
false
,
"staticmethod"
);
classmethod_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
classmethodGCHandler
,
0
,
sizeof
(
BoxedClassmethod
),
false
,
"classmethod"
);
attrwrapper_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
AttrWrapper
::
gcHandler
,
0
,
sizeof
(
AttrWrapper
),
false
,
"attrwrapper"
);
// TODO: add explicit __get__ and __set__ methods to these
pyston_getset_cls
->
freeze
();
...
...
@@ -1345,6 +1385,9 @@ void setupRuntime() {
type_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
typeRepr
,
STR
,
1
)));
type_cls
->
giveAttr
(
"__hash__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
typeHash
,
BOXED_INT
,
1
)));
type_cls
->
giveAttr
(
"__module__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
typeModule
,
typeSetModule
,
NULL
));
type_cls
->
giveAttr
(
"__mro__"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedClass
,
tp_mro
)));
type_cls
->
giveAttr
(
"mro"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
typeMro
,
UNKNOWN
,
1
)));
type_cls
->
freeze
();
none_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
noneRepr
,
STR
,
1
)));
...
...
src/runtime/types.h
View file @
39859d79
...
...
@@ -192,9 +192,15 @@ public:
void
freeze
();
protected:
// These functions are not meant for external callers and will mostly just be called
// by BoxedHeapClass::create(), but setupRuntime() also needs to do some manual class
// creation due to bootstrapping issues.
void
finishInitialization
();
BoxedClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
);
DEFAULT_CLASS
(
type_cls
);
friend
void
setupRuntime
(
);
};
class
BoxedHeapClass
:
public
BoxedClass
{
...
...
@@ -207,15 +213,22 @@ public:
BoxedString
*
ht_name
;
PyObject
**
ht_slots
;
BoxedHeapClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
,
const
std
::
string
&
name
);
// These functions are the preferred way to construct new types:
static
BoxedHeapClass
*
create
(
BoxedClass
*
metatype
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
,
BoxedString
*
name
,
BoxedTuple
*
bases
);
static
BoxedHeapClass
*
create
(
BoxedClass
*
metatype
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
,
const
std
::
string
&
name
);
private:
// These functions are not meant for external callers and will mostly just be called
// by BoxedHeapClass::create(), but setupRuntime() also needs to do some manual class
// creation due to bootstrapping issues.
BoxedHeapClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
,
BoxedString
*
name
);
// This constructor is only used for bootstrapping purposes to be called for types that
// are initialized before str_cls.
BoxedHeapClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
);
friend
void
setupRuntime
();
DEFAULT_CLASS
(
type_cls
);
};
static_assert
(
sizeof
(
pyston
::
Box
)
==
sizeof
(
struct
_object
),
""
);
...
...
test/tests/multiple_inheritance.py
0 → 100644
View file @
39859d79
# Testing the basic multiple-inheritance rules and functionality:
class
C
(
object
):
n
=
1
def
c
(
self
):
print
"C.c()"
def
f
(
self
):
print
"C.f()"
,
self
.
n
class
D
(
object
):
n
=
2
def
d
(
self
):
print
"D.d()"
def
f
(
self
):
print
"D.f()"
,
self
.
n
class
E
(
C
,
D
):
pass
class
F
(
D
,
C
):
pass
class
G
(
E
,
D
):
pass
for
o
in
[
C
(),
D
(),
E
(),
F
()]:
print
type
(
o
),
type
(
o
).
mro
(),
type
(
o
).
__mro__
o
.
f
()
try
:
o
.
c
()
except
Exception
,
e
:
print
e
try
:
o
.
d
()
except
Exception
,
e
:
print
e
# Testing invalid multiple inheritance hierarchies:
# Conflicting MRO:
try
:
class
G
(
E
,
F
):
pass
except
TypeError
,
e
:
# This is silly but I think actually reasonable: the error message for this case is implementation-specific,
# since it depends on dict ordering rules (says either "for bases E, F" or "for bases F, E", depending on ordering).
# Canonicalize the error message by sorting the characters in it:
print
''
.
join
(
sorted
(
e
.
message
)).
strip
()
# Conflicting MRO:
try
:
class
H
(
C
,
F
):
pass
except
TypeError
,
e
:
print
''
.
join
(
sorted
(
e
.
message
)).
strip
()
# "instance lay-out conflict"
try
:
class
I
(
str
,
int
):
pass
except
TypeError
,
e
:
print
e
# Testing the way super() behaves with multiple inheritance:
class
S
(
C
,
D
):
n
=
3
def
c
(
self
):
print
"S.c()"
super
(
S
,
self
).
c
()
def
d
(
self
):
print
"S.d()"
super
(
S
,
self
).
d
()
def
f
(
self
):
print
"S.f()"
print
self
.
n
,
super
(
S
,
self
).
n
,
super
(
C
,
self
).
n
# TODO: Pyston doesn't support the full super.__getattribute__, so this will abort
# rather than throw an exception:
# try:
# print super(D, self).n
# except Exception as e:
# print e
super
(
S
,
self
).
f
()
super
(
C
,
self
).
f
()
s
=
S
()
s
.
c
()
s
.
d
()
s
.
f
()
for
cls
in
[
object
,
tuple
,
list
,
type
,
int
,
bool
]:
print
cls
.
__mro__
test/tests/super.py
View file @
39859d79
...
...
@@ -5,6 +5,9 @@ class B(object):
o
.
arg1
=
arg1
return
o
def
f
(
self
):
print
"B.f()"
class
C
(
B
):
def
__new__
(
cls
,
arg1
,
arg2
):
print
"C.__new__"
,
arg2
...
...
@@ -13,9 +16,14 @@ class C(B):
print
super
(
C
,
cls
),
super
(
C
,
o
)
return
o
def
f
(
self
):
print
"C.f()"
super
(
C
,
self
).
f
()
c
=
C
(
1
,
2
)
print
c
.
arg1
print
c
.
arg2
c
.
f
()
try
:
super
(
1
)
...
...
tools/tester.py
View file @
39859d79
...
...
@@ -413,16 +413,16 @@ if __name__ == "__main__":
]
tests += big_tests
LIB_DIR = os.path.join(sys.prefix, "lib/python2.7")
for t in tests:
bn = os.path.basename(t)
assert bn.endswith(".py")
module_name = bn[:-3]
try:
__import__(module_name)
if os.path.exists(os.path.join(LIB_DIR, module_name)) or
\
os.path.exists(os.path.join(LIB_DIR, module_name + ".py")) or
\
module_name in sys.builtin_module_names:
raise Exception("Error: %s hides builtin module '%s'" % (t, module_name))
except ImportError:
pass
# good
for t in TOSKIP:
assert t in ("%s/t.py" % TEST_DIR, "%s/t2.py" % TEST_DIR) or t in tests, t
...
...
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