Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
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
Kirill Smelkov
cpython
Commits
3b7073d2
Commit
3b7073d2
authored
Jul 18, 1995
by
Guido van Rossum
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
keyword arguments and faster calls
parent
baea1c3b
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
771 additions
and
594 deletions
+771
-594
Python/bltinmodule.c
Python/bltinmodule.c
+10
-6
Python/ceval.c
Python/ceval.c
+459
-364
Python/compile.c
Python/compile.c
+280
-206
Python/import.c
Python/import.c
+2
-2
Python/marshal.c
Python/marshal.c
+13
-3
Python/pythonrun.c
Python/pythonrun.c
+3
-10
Python/traceback.c
Python/traceback.c
+4
-3
No files found.
Python/bltinmodule.c
View file @
3b7073d2
...
...
@@ -80,15 +80,20 @@ builtin_apply(self, args)
object
*
self
;
object
*
args
;
{
object
*
func
,
*
alist
;
object
*
func
,
*
alist
,
*
kwdict
=
NULL
;
if
(
!
newgetargs
(
args
,
"O
O:apply"
,
&
func
,
&
alis
t
))
if
(
!
newgetargs
(
args
,
"O
|OO:apply"
,
&
func
,
&
alist
,
&
kwdic
t
))
return
NULL
;
if
(
!
is_tupleobject
(
alist
))
{
if
(
alist
!=
NULL
&&
!
is_tupleobject
(
alist
))
{
err_setstr
(
TypeError
,
"apply() 2nd argument must be tuple"
);
return
NULL
;
}
return
call_object
(
func
,
alist
);
if
(
kwdict
!=
NULL
&&
!
is_dictobject
(
kwdict
))
{
err_setstr
(
TypeError
,
"apply() 3rd argument must be dictionary"
);
return
NULL
;
}
return
PyEval_CallObjectWithKeywords
(
func
,
alist
,
kwdict
);
}
static
object
*
...
...
@@ -373,8 +378,7 @@ builtin_eval(self, args)
return
NULL
;
}
if
(
is_codeobject
(
cmd
))
return
eval_code
((
codeobject
*
)
cmd
,
globals
,
locals
,
(
object
*
)
NULL
,
(
object
*
)
NULL
);
return
eval_code
((
codeobject
*
)
cmd
,
globals
,
locals
);
if
(
!
is_stringobject
(
cmd
))
{
err_setstr
(
TypeError
,
"eval() argument 1 must be string or code object"
);
...
...
Python/ceval.c
View file @
3b7073d2
...
...
@@ -24,6 +24,16 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Execute compiled code */
/* XXX TO DO:
XXX how to pass arguments to call_trace?
XXX access stuff can probably dereference NULL locals?
XXX need to extend apply() to be able to pass keyword args
XXX need to be able to call built-in functions with keyword args
XXX speed up searching for keywords by using a dictionary
XXX unknown keyword shouldn't raise KeyError?
XXX document it!
*/
#include "allobjects.h"
#include "import.h"
...
...
@@ -58,6 +68,12 @@ extern int suppress_print; /* Declared in pythonrun.c, set in pythonmain.c */
/* Forward declarations */
static
object
*
eval_code2
PROTO
((
codeobject
*
,
object
*
,
object
*
,
object
**
,
int
,
object
**
,
int
,
object
**
,
int
,
object
*
));
#ifdef LLTRACE
static
int
prtrace
PROTO
((
object
*
,
char
*
));
#endif
...
...
@@ -78,8 +94,8 @@ static object *rshift PROTO((object *, object *));
static
object
*
and
PROTO
((
object
*
,
object
*
));
static
object
*
xor
PROTO
((
object
*
,
object
*
));
static
object
*
or
PROTO
((
object
*
,
object
*
));
static
object
*
call_builtin
PROTO
((
object
*
,
object
*
));
static
object
*
call_function
PROTO
((
object
*
,
object
*
));
static
object
*
call_builtin
PROTO
((
object
*
,
object
*
,
object
*
));
static
object
*
call_function
PROTO
((
object
*
,
object
*
,
object
*
));
static
object
*
apply_subscript
PROTO
((
object
*
,
object
*
));
static
object
*
loop_subscript
PROTO
((
object
*
,
object
*
));
static
int
slice_index
PROTO
((
object
*
,
int
,
int
*
));
...
...
@@ -259,15 +275,38 @@ enum why_code {
};
/*
Interpreter main loop
*/
/*
Backward compatible interface
*/
object
*
eval_code
(
co
,
globals
,
locals
,
owner
,
arg
)
eval_code
(
co
,
globals
,
locals
)
codeobject
*
co
;
object
*
globals
;
object
*
locals
;
{
return
eval_code2
(
co
,
globals
,
locals
,
(
object
**
)
NULL
,
0
,
(
object
**
)
NULL
,
0
,
(
object
**
)
NULL
,
0
,
(
object
*
)
NULL
);
}
/* Interpreter main loop */
static
object
*
eval_code2
(
co
,
globals
,
locals
,
args
,
argcount
,
kws
,
kwcount
,
defs
,
defcount
,
owner
)
codeobject
*
co
;
object
*
globals
;
object
*
locals
;
object
**
args
;
int
argcount
;
object
**
kws
;
/* length: 2*kwcount */
int
kwcount
;
object
**
defs
;
int
defcount
;
object
*
owner
;
object
*
arg
;
{
register
unsigned
char
*
next_instr
;
register
int
opcode
;
/* Current opcode */
...
...
@@ -281,15 +320,14 @@ eval_code(co, globals, locals, owner, arg)
register
object
*
u
;
register
object
*
t
;
register
frameobject
*
f
;
/* Current frame */
register
listobject
*
fastlocals
=
NULL
;
object
*
retval
;
/* Return value iff why == WHY_RETURN */
int
needmerge
=
0
;
/* Set if need to merge locals back at end */
register
object
**
fastlocals
;
object
*
retval
;
/* Return value */
int
defmode
=
0
;
/* Default access mode for new variables */
#ifdef LLTRACE
int
lltrace
;
#endif
#if defined(
DEBUG ) || defined( LLTRACE
)
/* Make it easier to find out where we are with
dbx
*/
#if defined(
DEBUG) || defined(LLTRACE
)
/* Make it easier to find out where we are with
a debugger
*/
char
*
filename
=
getstringvalue
(
co
->
co_filename
);
#endif
...
...
@@ -324,8 +362,14 @@ eval_code(co, globals, locals, owner, arg)
#define POP() BASIC_POP()
#endif
if
(
globals
==
NULL
||
locals
==
NULL
)
{
err_setstr
(
SystemError
,
"eval_code: NULL globals or locals"
);
/* Local variable macros */
#define GETLOCAL(i) (fastlocals[i])
#define SETLOCAL(i, value) do { XDECREF(GETLOCAL(i)); \
GETLOCAL(i) = value; } while (0)
if
(
globals
==
NULL
)
{
err_setstr
(
SystemError
,
"eval_code2: NULL globals"
);
return
NULL
;
}
...
...
@@ -346,6 +390,110 @@ eval_code(co, globals, locals, owner, arg)
current_frame
=
f
;
if
(
co
->
co_nlocals
>
0
)
fastlocals
=
((
listobject
*
)
f
->
f_fastlocals
)
->
ob_item
;
if
(
co
->
co_argcount
>
0
||
co
->
co_flags
&
(
CO_VARARGS
|
CO_VARKEYWORDS
))
{
int
i
;
int
n
=
argcount
;
object
*
kwdict
=
NULL
;
if
(
co
->
co_flags
&
CO_VARKEYWORDS
)
{
kwdict
=
newmappingobject
();
if
(
kwdict
==
NULL
)
goto
fail
;
}
if
(
argcount
>
co
->
co_argcount
)
{
if
(
!
(
co
->
co_flags
&
CO_VARARGS
))
{
err_setstr
(
TypeError
,
"too many arguments"
);
goto
fail
;
}
n
=
co
->
co_argcount
;
}
for
(
i
=
0
;
i
<
n
;
i
++
)
{
x
=
args
[
i
];
INCREF
(
x
);
SETLOCAL
(
i
,
x
);
}
if
(
co
->
co_flags
&
CO_VARARGS
)
{
u
=
newtupleobject
(
argcount
-
n
);
for
(
i
=
n
;
i
<
argcount
;
i
++
)
{
x
=
args
[
i
];
INCREF
(
x
);
SETTUPLEITEM
(
u
,
i
-
n
,
x
);
}
SETLOCAL
(
co
->
co_argcount
,
u
);
}
for
(
i
=
0
;
i
<
kwcount
;
i
++
)
{
object
*
keyword
=
kws
[
2
*
i
];
object
*
value
=
kws
[
2
*
i
+
1
];
int
j
;
/* XXX slow -- speed up using dictionary? */
for
(
j
=
0
;
j
<
co
->
co_argcount
;
j
++
)
{
object
*
nm
=
GETTUPLEITEM
(
co
->
co_varnames
,
j
);
if
(
cmpobject
(
keyword
,
nm
)
==
0
)
break
;
}
if
(
j
>=
co
->
co_argcount
)
{
if
(
kwdict
==
NULL
)
{
err_setval
(
KeyError
/*XXX*/
,
keyword
);
goto
fail
;
}
mappinginsert
(
kwdict
,
keyword
,
value
);
}
else
{
if
(
GETLOCAL
(
j
)
!=
NULL
)
{
err_setstr
(
TypeError
,
"keyword parameter redefined"
);
goto
fail
;
}
INCREF
(
value
);
SETLOCAL
(
j
,
value
);
}
}
if
(
argcount
<
co
->
co_argcount
)
{
int
m
=
co
->
co_argcount
-
defcount
;
for
(
i
=
argcount
;
i
<
m
;
i
++
)
{
if
(
GETLOCAL
(
i
)
==
NULL
)
{
err_setstr
(
TypeError
,
"not enough arguments"
);
goto
fail
;
}
}
if
(
n
>
m
)
i
=
n
-
m
;
else
i
=
0
;
for
(;
i
<
defcount
;
i
++
)
{
if
(
GETLOCAL
(
m
+
i
)
==
NULL
)
{
object
*
def
=
defs
[
i
];
INCREF
(
def
);
SETLOCAL
(
m
+
i
,
def
);
}
}
}
if
(
kwdict
!=
NULL
)
{
i
=
co
->
co_argcount
;
if
(
co
->
co_flags
&
CO_VARARGS
)
i
++
;
SETLOCAL
(
i
,
kwdict
);
}
if
(
0
)
{
fail:
XDECREF
(
kwdict
);
goto
fail2
;
}
}
else
{
if
(
argcount
>
0
||
kwcount
>
0
)
{
err_setstr
(
TypeError
,
"no arguments expected"
);
fail2:
current_frame
=
f
->
f_back
;
DECREF
(
f
);
return
NULL
;
}
}
if
(
sys_trace
!=
NULL
)
{
/* sys_trace, if defined, is a function that will
be called on *every* entry to a code block.
...
...
@@ -359,7 +507,8 @@ eval_code(co, globals, locals, owner, arg)
depends on the situation. The global trace function
(sys.trace) is also called whenever an exception
is detected. */
if
(
call_trace
(
&
sys_trace
,
&
f
->
f_trace
,
f
,
"call"
,
arg
))
{
if
(
call_trace
(
&
sys_trace
,
&
f
->
f_trace
,
f
,
"call"
,
None
/*XXX how to compute arguments now?*/
))
{
/* Trace function raised an error */
current_frame
=
f
->
f_back
;
DECREF
(
f
);
...
...
@@ -370,7 +519,8 @@ eval_code(co, globals, locals, owner, arg)
if
(
sys_profile
!=
NULL
)
{
/* Similar for sys_profile, except it needn't return
itself and isn't called for "line" events */
if
(
call_trace
(
&
sys_profile
,
(
object
**
)
0
,
f
,
"call"
,
arg
))
{
if
(
call_trace
(
&
sys_profile
,
(
object
**
)
0
,
f
,
"call"
,
None
/*XXX*/
))
{
current_frame
=
f
->
f_back
;
DECREF
(
f
);
return
NULL
;
...
...
@@ -380,11 +530,6 @@ eval_code(co, globals, locals, owner, arg)
next_instr
=
GETUSTRINGVALUE
(
f
->
f_code
->
co_code
);
stack_pointer
=
f
->
f_valuestack
;
if
(
arg
!=
NULL
)
{
INCREF
(
arg
);
PUSH
(
arg
);
}
why
=
WHY_NOT
;
err
=
0
;
x
=
None
;
/* Not a reference, just anything non-NULL */
...
...
@@ -523,14 +668,6 @@ eval_code(co, globals, locals, owner, arg)
PUSH
(
x
);
break
;
case
UNARY_CALL
:
v
=
POP
();
f
->
f_lasti
=
INSTR_OFFSET
()
-
1
;
/* For tracing */
x
=
call_object
(
v
,
(
object
*
)
NULL
);
DECREF
(
v
);
PUSH
(
x
);
break
;
case
UNARY_INVERT
:
v
=
POP
();
x
=
invert
(
v
);
...
...
@@ -592,16 +729,6 @@ eval_code(co, globals, locals, owner, arg)
PUSH
(
x
);
break
;
case
BINARY_CALL
:
w
=
POP
();
v
=
POP
();
f
->
f_lasti
=
INSTR_OFFSET
()
-
1
;
/* For tracing */
x
=
call_object
(
v
,
w
);
DECREF
(
v
);
DECREF
(
w
);
PUSH
(
x
);
break
;
case
BINARY_LSHIFT
:
w
=
POP
();
v
=
POP
();
...
...
@@ -776,9 +903,6 @@ eval_code(co, globals, locals, owner, arg)
why
=
WHY_BREAK
;
break
;
case
RAISE_EXCEPTION
:
oparg
=
2
;
/* Fallthrough */
case
RAISE_VARARGS
:
u
=
v
=
w
=
NULL
;
switch
(
oparg
)
{
...
...
@@ -788,10 +912,7 @@ eval_code(co, globals, locals, owner, arg)
DECREF
(
u
);
u
=
NULL
;
}
else
if
(
strcmp
(
u
->
ob_type
->
tp_name
,
"traceback"
)
!=
0
)
{
/* XXX traceback.h needs to define
is_traceback() */
else
if
(
!
PyTraceback_Check
(
u
))
{
err_setstr
(
TypeError
,
"raise 3rd arg must be traceback or None"
);
goto
raise_error
;
...
...
@@ -814,8 +935,8 @@ eval_code(co, globals, locals, owner, arg)
}
/* A tuple is equivalent to its first element here */
while
(
is_tupleobject
(
w
)
&&
gettuplesize
(
w
)
>
0
)
{
object
*
t
=
w
;
w
=
GETTUPLEITEM
(
t
,
0
);
t
=
w
;
w
=
GETTUPLEITEM
(
w
,
0
);
INCREF
(
w
);
DECREF
(
t
);
}
...
...
@@ -861,9 +982,12 @@ eval_code(co, globals, locals, owner, arg)
break
;
case
LOAD_LOCALS
:
v
=
f
->
f_locals
;
INCREF
(
v
);
PUSH
(
v
);
if
((
x
=
f
->
f_locals
)
==
NULL
)
{
err_setstr
(
SystemError
,
"no locals"
);
break
;
}
INCREF
(
x
);
PUSH
(
x
);
break
;
case
RETURN_VALUE
:
...
...
@@ -871,12 +995,6 @@ eval_code(co, globals, locals, owner, arg)
why
=
WHY_RETURN
;
break
;
case
LOAD_GLOBALS
:
v
=
f
->
f_locals
;
INCREF
(
v
);
PUSH
(
v
);
break
;
case
EXEC_STMT
:
w
=
POP
();
v
=
POP
();
...
...
@@ -887,21 +1005,6 @@ eval_code(co, globals, locals, owner, arg)
DECREF
(
w
);
break
;
case
BUILD_FUNCTION
:
v
=
POP
();
x
=
newfuncobject
(
v
,
f
->
f_globals
);
DECREF
(
v
);
PUSH
(
x
);
break
;
case
SET_FUNC_ARGS
:
v
=
POP
();
/* The function */
w
=
POP
();
/* The argument list */
err
=
setfuncargstuff
(
v
,
oparg
,
w
);
PUSH
(
v
);
DECREF
(
w
);
break
;
case
POP_BLOCK
:
{
block
*
b
=
pop_block
(
f
);
...
...
@@ -947,14 +1050,18 @@ eval_code(co, globals, locals, owner, arg)
case
STORE_NAME
:
w
=
GETNAMEV
(
oparg
);
v
=
POP
();
u
=
dict2lookup
(
f
->
f_locals
,
w
);
if
((
x
=
f
->
f_locals
)
==
NULL
)
{
err_setstr
(
SystemError
,
"no locals"
);
break
;
}
u
=
dict2lookup
(
x
,
w
);
if
(
u
==
NULL
)
{
if
(
defmode
!=
0
)
{
if
(
v
!=
None
)
u
=
(
object
*
)
v
->
ob_type
;
else
u
=
NULL
;
x
=
newaccessobject
(
v
,
f
->
f_locals
,
x
=
newaccessobject
(
v
,
x
,
(
typeobject
*
)
u
,
defmode
);
DECREF
(
v
);
...
...
@@ -964,23 +1071,27 @@ eval_code(co, globals, locals, owner, arg)
}
}
else
if
(
is_accessobject
(
u
))
{
err
=
setaccessvalue
(
u
,
f
->
f_locals
,
v
);
err
=
setaccessvalue
(
u
,
x
,
v
);
DECREF
(
v
);
break
;
}
err
=
dict2insert
(
f
->
f_locals
,
w
,
v
);
err
=
dict2insert
(
x
,
w
,
v
);
DECREF
(
v
);
break
;
case
DELETE_NAME
:
w
=
GETNAMEV
(
oparg
);
u
=
dict2lookup
(
f
->
f_locals
,
w
);
if
((
x
=
f
->
f_locals
)
==
NULL
)
{
err_setstr
(
SystemError
,
"no locals"
);
break
;
}
u
=
dict2lookup
(
x
,
w
);
if
(
u
!=
NULL
&&
is_accessobject
(
u
))
{
err
=
setaccessvalue
(
u
,
f
->
f_locals
,
err
=
setaccessvalue
(
u
,
x
,
(
object
*
)
NULL
);
break
;
}
if
((
err
=
dict2remove
(
f
->
f_locals
,
w
))
!=
0
)
if
((
err
=
dict2remove
(
x
,
w
))
!=
0
)
err_setval
(
NameError
,
w
);
break
;
...
...
@@ -988,74 +1099,6 @@ eval_code(co, globals, locals, owner, arg)
default:
switch
(
opcode
)
{
#endif
case
UNPACK_VARARG
:
if
(
EMPTY
())
{
err_setstr
(
TypeError
,
"no argument list"
);
why
=
WHY_EXCEPTION
;
break
;
}
v
=
POP
();
if
(
!
is_tupleobject
(
v
))
{
err_setstr
(
TypeError
,
"bad argument list"
);
why
=
WHY_EXCEPTION
;
}
else
if
(
gettuplesize
(
v
)
<
oparg
)
{
err_setstr
(
TypeError
,
"not enough arguments"
);
why
=
WHY_EXCEPTION
;
}
else
if
(
oparg
==
0
)
{
PUSH
(
v
);
break
;
}
else
{
x
=
gettupleslice
(
v
,
oparg
,
gettuplesize
(
v
));
if
(
x
!=
NULL
)
{
PUSH
(
x
);
if
(
!
CHECK_STACK
(
oparg
))
{
x
=
NULL
;
break
;
}
for
(;
--
oparg
>=
0
;
)
{
w
=
GETTUPLEITEM
(
v
,
oparg
);
INCREF
(
w
);
PUSH
(
w
);
}
}
}
DECREF
(
v
);
break
;
case
UNPACK_ARG
:
{
int
n
;
if
(
EMPTY
())
{
err_setstr
(
TypeError
,
"no argument list"
);
why
=
WHY_EXCEPTION
;
break
;
}
v
=
POP
();
if
(
!
is_tupleobject
(
v
))
{
err_setstr
(
TypeError
,
"bad argument list"
);
why
=
WHY_EXCEPTION
;
DECREF
(
v
);
break
;
}
n
=
gettuplesize
(
v
);
if
(
n
!=
oparg
)
{
err_setstr
(
TypeError
,
"arg count mismatch"
);
why
=
WHY_EXCEPTION
;
DECREF
(
v
);
break
;
}
PUSH
(
v
);
}
/* Fall through */
case
UNPACK_TUPLE
:
v
=
POP
();
if
(
!
is_tupleobject
(
v
))
{
...
...
@@ -1125,24 +1168,29 @@ eval_code(co, globals, locals, owner, arg)
case
STORE_GLOBAL
:
w
=
GETNAMEV
(
oparg
);
v
=
POP
();
if
(
f
->
f_locals
!=
NULL
)
{
u
=
dict2lookup
(
f
->
f_locals
,
w
);
if
(
u
!=
NULL
&&
is_accessobject
(
u
))
{
err
=
setaccessvalue
(
u
,
f
->
f_globals
,
v
);
err
=
setaccessvalue
(
u
,
f
->
f_globals
,
v
);
DECREF
(
v
);
break
;
}
}
err
=
dict2insert
(
f
->
f_globals
,
w
,
v
);
DECREF
(
v
);
break
;
case
DELETE_GLOBAL
:
w
=
GETNAMEV
(
oparg
);
if
(
f
->
f_locals
!=
NULL
)
{
u
=
dict2lookup
(
f
->
f_locals
,
w
);
if
(
u
!=
NULL
&&
is_accessobject
(
u
))
{
err
=
setaccessvalue
(
u
,
f
->
f_globals
,
(
object
*
)
NULL
);
break
;
}
}
if
((
err
=
dict2remove
(
f
->
f_globals
,
w
))
!=
0
)
err_setval
(
NameError
,
w
);
break
;
...
...
@@ -1155,7 +1203,11 @@ eval_code(co, globals, locals, owner, arg)
case
LOAD_NAME
:
w
=
GETNAMEV
(
oparg
);
x
=
dict2lookup
(
f
->
f_locals
,
w
);
if
((
x
=
f
->
f_locals
)
==
NULL
)
{
err_setstr
(
SystemError
,
"no locals"
);
break
;
}
x
=
dict2lookup
(
x
,
w
);
if
(
x
==
NULL
)
{
err_clear
();
x
=
dict2lookup
(
f
->
f_globals
,
w
);
...
...
@@ -1199,9 +1251,14 @@ eval_code(co, globals, locals, owner, arg)
PUSH
(
x
);
break
;
#if 0
case LOAD_LOCAL:
w = GETNAMEV(oparg);
x
=
dict2lookup
(
f
->
f_locals
,
w
);
if ((x = f->f_locals) == NULL) {
err_setstr(SystemError, "no locals");
break;
}
x = dict2lookup(x, w);
if (x == NULL) {
err_setval(NameError, w);
break;
...
...
@@ -1215,29 +1272,14 @@ eval_code(co, globals, locals, owner, arg)
INCREF(x);
PUSH(x);
break;
case
RESERVE_FAST
:
x
=
GETCONST
(
oparg
);
if
(
x
==
None
)
break
;
if
(
x
==
NULL
||
!
is_tupleobject
(
x
))
{
err_setstr
(
SystemError
,
"bad RESERVE_FAST"
);
x
=
NULL
;
break
;
}
XDECREF
(
f
->
f_fastlocals
);
XDECREF
(
f
->
f_localmap
);
INCREF
(
x
);
f
->
f_localmap
=
x
;
f
->
f_fastlocals
=
x
=
newlistobject
(
gettuplesize
(
x
));
fastlocals
=
(
listobject
*
)
x
;
break
;
#endif
case
LOAD_FAST
:
x
=
GETL
ISTITEM
(
fastlocals
,
oparg
);
x
=
GETL
OCAL
(
oparg
);
if
(
x
==
NULL
)
{
err_setval
(
NameError
,
gettupleitem
(
f
->
f_localmap
,
oparg
));
gettupleitem
(
co
->
co_varnames
,
oparg
));
break
;
}
if
(
is_accessobject
(
x
))
{
...
...
@@ -1252,30 +1294,29 @@ eval_code(co, globals, locals, owner, arg)
case
STORE_FAST
:
v
=
POP
();
w
=
GETL
ISTITEM
(
fastlocals
,
oparg
);
w
=
GETL
OCAL
(
oparg
);
if
(
w
!=
NULL
&&
is_accessobject
(
w
))
{
err
=
setaccessvalue
(
w
,
f
->
f_locals
,
v
);
DECREF
(
v
);
break
;
}
GETLISTITEM
(
fastlocals
,
oparg
)
=
v
;
XDECREF
(
w
);
SETLOCAL
(
oparg
,
v
);
break
;
case
DELETE_FAST
:
x
=
GETL
ISTITEM
(
fastlocals
,
oparg
);
x
=
GETL
OCAL
(
oparg
);
if
(
x
==
NULL
)
{
err_setval
(
NameError
,
gettupleitem
(
f
->
f_localmap
,
oparg
));
gettupleitem
(
co
->
co_varnames
,
oparg
));
break
;
}
if
(
x
!=
NULL
&&
is_accessobject
(
x
))
{
if
(
is_accessobject
(
x
))
{
err
=
setaccessvalue
(
x
,
f
->
f_locals
,
(
object
*
)
NULL
);
break
;
}
GETLISTITEM
(
fastlocals
,
oparg
)
=
NULL
;
DECREF
(
x
);
SETLOCAL
(
oparg
,
NULL
);
break
;
case
BUILD_TUPLE
:
...
...
@@ -1343,7 +1384,11 @@ eval_code(co, globals, locals, owner, arg)
break
;
}
}
w
=
mkvalue
(
"(OOOO)"
,
w
,
f
->
f_globals
,
f
->
f_locals
,
u
);
w
=
mkvalue
(
"(OOOO)"
,
w
,
f
->
f_globals
,
f
->
f_locals
==
NULL
?
None
:
f
->
f_locals
,
u
);
DECREF
(
u
);
if
(
w
==
NULL
)
{
x
=
NULL
;
...
...
@@ -1358,7 +1403,11 @@ eval_code(co, globals, locals, owner, arg)
w
=
GETNAMEV
(
oparg
);
v
=
TOP
();
fast_2_locals
(
f
);
err
=
import_from
(
f
->
f_locals
,
v
,
w
);
if
((
x
=
f
->
f_locals
)
==
NULL
)
{
err_setstr
(
SystemError
,
"no locals"
);
break
;
}
err
=
import_from
(
x
,
v
,
w
);
locals_2_fast
(
f
,
0
);
break
;
...
...
@@ -1447,12 +1496,6 @@ eval_code(co, globals, locals, owner, arg)
case
CALL_FUNCTION
:
{
/* XXX To do:
- fill in default arguments here
- proper handling of keyword parameters
- change eval_code interface to take an
array of arguments instead of a tuple
*/
int
na
=
oparg
&
0xff
;
int
nk
=
(
oparg
>>
8
)
&
0xff
;
int
n
=
na
+
2
*
nk
;
...
...
@@ -1460,75 +1503,120 @@ eval_code(co, globals, locals, owner, arg)
object
*
func
=
*
pfunc
;
object
*
self
=
NULL
;
object
*
class
=
NULL
;
object
*
args
;
f
->
f_lasti
=
INSTR_OFFSET
()
-
3
;
/* For tracing */
INCREF
(
func
);
if
(
is_instancemethodobject
(
func
))
{
self
=
instancemethodgetself
(
func
);
if
(
self
!=
NULL
)
{
class
=
instancemethodgetclass
(
func
);
DECREF
(
func
);
func
=
instancemethodgetfunc
(
func
);
INCREF
(
func
);
if
(
self
!=
NULL
)
{
INCREF
(
self
);
DECREF
(
*
pfunc
);
*
pfunc
=
self
;
na
++
;
n
++
;
}
else
{
/* Unbound methods must be
called with an instance of
the class (or a derived
class) as first argument */
if
(
na
>
0
&&
(
self
=
stack_pointer
[
-
n
])
!=
NULL
&&
is_instanceobject
(
self
)
&&
issubclass
(
(
object
*
)
(((
instanceobject
*
)
self
)
->
in_class
),
class
))
/* Handy-dandy */
;
else
{
err_setstr
(
TypeError
,
"unbound method must be called with class instance 1st argument"
);
return
NULL
;
}
}
args
=
newtupleobject
(
n
);
}
else
INCREF
(
func
);
if
(
is_funcobject
(
func
))
{
object
*
co
=
getfunccode
(
func
);
object
*
globals
=
getfuncglobals
(
func
);
object
*
argdefs
=
PyFunction_GetDefaults
(
func
);
object
**
d
;
int
nd
;
if
(
argdefs
!=
NULL
)
{
d
=
&
GETTUPLEITEM
(
argdefs
,
0
);
nd
=
((
tupleobject
*
)
argdefs
)
->
ob_size
;
}
else
{
d
=
NULL
;
nd
=
0
;
}
x
=
eval_code2
(
(
codeobject
*
)
co
,
globals
,
(
object
*
)
NULL
,
stack_pointer
-
n
,
na
,
stack_pointer
-
2
*
nk
,
nk
,
d
,
nd
,
class
);
}
else
{
object
*
args
=
newtupleobject
(
na
);
object
*
kwdict
=
NULL
;
if
(
args
==
NULL
)
x
=
NULL
;
else
if
(
nk
>
0
)
{
err_setstr
(
SystemError
,
"calling built-in with keywords not yet implemented"
);
x
=
NULL
;
}
else
{
while
(
--
n
>=
0
)
{
while
(
--
na
>=
0
)
{
w
=
POP
();
SETTUPLEITEM
(
args
,
n
,
w
);
SETTUPLEITEM
(
args
,
na
,
w
);
}
if
(
self
==
NULL
)
POP
();
if
(
is_funcobject
(
func
))
{
int
argcount
;
object
*
argdefs
=
getfuncargstuff
(
func
,
&
argcount
);
if
(
argdefs
==
NULL
)
{
/* Fast path */
object
*
co
,
*
loc
,
*
glob
;
co
=
getfunccode
(
func
);
loc
=
newdictobject
();
if
(
loc
==
NULL
)
{
x
=
NULL
;
DECREF
(
func
);
break
;
}
glob
=
getfuncglobals
(
func
);
INCREF
(
glob
);
x
=
eval_code
(
(
codeobject
*
)
co
,
glob
,
loc
,
class
,
args
);
DECREF
(
glob
);
DECREF
(
loc
);
x
=
call_object
(
func
,
args
);
DECREF
(
args
);
}
}
DECREF
(
func
);
while
(
stack_pointer
>
pfunc
)
{
w
=
POP
();
DECREF
(
w
);
}
PUSH
(
x
);
break
;
}
case
MAKE_FUNCTION
:
v
=
POP
();
/* code object */
x
=
newfuncobject
(
v
,
f
->
f_globals
);
DECREF
(
v
);
/* XXX Maybe this should be a separate opcode? */
if
(
x
!=
NULL
&&
oparg
>
0
)
{
v
=
newtupleobject
(
oparg
);
if
(
v
==
NULL
)
{
DECREF
(
x
);
x
=
NULL
;
break
;
}
x
=
call_object
(
func
,
args
);
DECREF
(
args
);
PUSH
(
x
);
while
(
--
oparg
>=
0
)
{
w
=
POP
(
);
SETTUPLEITEM
(
v
,
oparg
,
w
);
}
DECREF
(
func
);
break
;
err
=
PyFunction_SetDefaults
(
x
,
v
);
DECREF
(
v
)
;
}
PUSH
(
x
);
break
;
default:
fprintf
(
stderr
,
"XXX lineno: %d, opcode: %d
\n
"
,
f
->
f_lineno
,
opcode
);
err_setstr
(
SystemError
,
"
eval_code:
unknown opcode"
);
err_setstr
(
SystemError
,
"unknown opcode"
);
why
=
WHY_EXCEPTION
;
break
;
...
...
@@ -1543,8 +1631,15 @@ eval_code(co, globals, locals, owner, arg)
/* Quickly continue if no error occurred */
if
(
why
==
WHY_NOT
)
{
if
(
err
==
0
&&
x
!=
NULL
)
if
(
err
==
0
&&
x
!=
NULL
)
{
#ifdef CHECKEXC
if
(
err_occurred
())
fprintf
(
stderr
,
"XXX undetected error
\n
"
);
else
#endif
continue
;
/* Normal, fast path */
}
why
=
WHY_EXCEPTION
;
x
=
None
;
err
=
0
;
...
...
@@ -1561,8 +1656,12 @@ eval_code(co, globals, locals, owner, arg)
}
}
else
{
if
(
err_occurred
())
fatal
(
"XXX undetected error"
);
if
(
err_occurred
())
{
fprintf
(
stderr
,
"XXX undetected error (why=%d)
\n
"
,
why
);
why
=
WHY_EXCEPTION
;
}
}
#endif
...
...
@@ -1676,9 +1775,6 @@ eval_code(co, globals, locals, owner, arg)
current_frame
=
f
->
f_back
;
DECREF
(
f
);
if
(
needmerge
)
locals_2_fast
(
current_frame
,
1
);
return
retval
;
}
...
...
@@ -2134,38 +2230,66 @@ not(v)
}
/* External interface to call any callable object. The arg may be NULL. */
/* External interface to call any callable object.
The arg must be a tuple or NULL. */
object
*
call_object
(
func
,
arg
)
object
*
func
;
object
*
arg
;
{
binaryfunc
call
;
return
PyEval_CallObjectWithKeywords
(
func
,
arg
,
(
object
*
)
NULL
);
}
object
*
PyEval_CallObjectWithKeywords
(
func
,
arg
,
kw
)
object
*
func
;
object
*
arg
;
object
*
kw
;
{
ternaryfunc
call
;
object
*
result
;
if
(
arg
==
NULL
)
arg
=
newtupleobject
(
0
);
else
if
(
!
is_tupleobject
(
arg
))
{
err_setstr
(
TypeError
,
"argument list must be a tuple"
);
return
NULL
;
}
else
INCREF
(
arg
);
if
(
call
=
func
->
ob_type
->
tp_call
)
result
=
(
*
call
)(
func
,
arg
);
result
=
(
*
call
)(
func
,
arg
,
kw
);
else
if
(
is_instancemethodobject
(
func
)
||
is_funcobject
(
func
))
result
=
call_function
(
func
,
arg
);
result
=
call_function
(
func
,
arg
,
kw
);
else
result
=
call_builtin
(
func
,
arg
);
result
=
call_builtin
(
func
,
arg
,
kw
);
DECREF
(
arg
);
if
(
result
==
NULL
&&
!
err_occurred
())
fatal
(
"null result without error in call_object"
);
err_setstr
(
SystemError
,
"NULL result without error in call_object"
);
return
result
;
}
static
object
*
call_builtin
(
func
,
arg
)
call_builtin
(
func
,
arg
,
kw
)
object
*
func
;
object
*
arg
;
object
*
kw
;
{
if
(
kw
!=
NULL
)
{
err_setstr
(
SystemError
,
"calling built-in with keywords not yet implemented"
);
return
NULL
;
}
if
(
is_methodobject
(
func
))
{
method
meth
=
getmethod
(
func
);
object
*
self
=
getself
(
func
);
if
(
!
getvarargs
(
func
)
&&
arg
!=
NULL
&&
is_tupleobject
(
arg
)
)
{
if
(
!
getvarargs
(
func
))
{
int
size
=
gettuplesize
(
arg
);
if
(
size
==
1
)
arg
=
GETTUPLEITEM
(
arg
,
0
);
...
...
@@ -2181,7 +2305,8 @@ call_builtin(func, arg)
object
*
res
,
*
call
=
getattr
(
func
,
"__call__"
);
if
(
call
==
NULL
)
{
err_clear
();
err_setstr
(
AttributeError
,
"no __call__ method defined"
);
err_setstr
(
AttributeError
,
"no __call__ method defined"
);
return
NULL
;
}
res
=
call_object
(
call
,
arg
);
...
...
@@ -2193,16 +2318,21 @@ call_builtin(func, arg)
}
static
object
*
call_function
(
func
,
arg
)
call_function
(
func
,
arg
,
kw
)
object
*
func
;
object
*
arg
;
object
*
kw
;
{
object
*
newarg
=
NULL
;
object
*
newlocals
,
*
newglobals
;
object
*
class
=
NULL
;
object
*
co
,
*
v
;
object
*
class
=
NULL
;
/* == owner */
object
*
argdefs
;
int
argcount
;
object
**
d
,
**
k
;
int
nk
,
nd
;
object
*
result
;
if
(
kw
!=
NULL
&&
!
is_dictobject
(
kw
))
{
err_badcall
();
return
NULL
;
}
if
(
is_instancemethodobject
(
func
))
{
object
*
self
=
instancemethodgetself
(
func
);
...
...
@@ -2211,49 +2341,37 @@ call_function(func, arg)
if
(
self
==
NULL
)
{
/* Unbound methods must be called with an instance of
the class (or a derived class) as first argument */
if
(
arg
!=
NULL
&&
is_tupleobject
(
arg
)
&&
gettuplesize
(
arg
)
>=
1
)
{
if
(
gettuplesize
(
arg
)
>=
1
)
{
self
=
GETTUPLEITEM
(
arg
,
0
);
if
(
self
!=
NULL
&&
is_instanceobject
(
self
)
&&
issubclass
((
object
*
)
(((
instanceobject
*
)
self
)
->
in_class
),
class
))
/*
self = self
*/
;
/*
Handy-dandy
*/
;
else
self
=
NULL
;
}
if
(
self
==
NULL
)
{
err_setstr
(
TypeError
,
"unbound method must be called with class instance argument"
);
"unbound method must be called with class instance
1st
argument"
);
return
NULL
;
}
INCREF
(
arg
);
}
else
{
if
(
arg
==
NULL
)
argcount
=
0
;
else
if
(
is_tupleobject
(
arg
))
argcount
=
gettuplesize
(
arg
);
else
argcount
=
1
;
newarg
=
newtupleobject
(
argcount
+
1
);
int
argcount
=
gettuplesize
(
arg
);
object
*
newarg
=
newtupleobject
(
argcount
+
1
);
int
i
;
if
(
newarg
==
NULL
)
return
NULL
;
INCREF
(
self
);
SETTUPLEITEM
(
newarg
,
0
,
self
);
if
(
arg
!=
NULL
&&
!
is_tupleobject
(
arg
))
{
INCREF
(
arg
);
SETTUPLEITEM
(
newarg
,
1
,
arg
);
}
else
{
int
i
;
object
*
v
;
for
(
i
=
0
;
i
<
argcount
;
i
++
)
{
v
=
GETTUPLEITEM
(
arg
,
i
);
object
*
v
=
GETTUPLEITEM
(
arg
,
i
);
XINCREF
(
v
);
SETTUPLEITEM
(
newarg
,
i
+
1
,
v
);
}
}
arg
=
newarg
;
}
}
...
...
@@ -2262,65 +2380,51 @@ call_function(func, arg)
err_setstr
(
TypeError
,
"call of non-function"
);
return
NULL
;
}
}
argdefs
=
getfuncargstuff
(
func
,
&
argcount
);
if
(
argdefs
!=
NULL
&&
arg
!=
NULL
&&
is_tupleobject
(
arg
))
{
int
actualcount
,
j
;
/* Process default arguments */
if
(
argcount
&
0x4000
)
argcount
^=
0x4000
;
actualcount
=
gettuplesize
(
arg
);
j
=
gettuplesize
(
argdefs
)
-
(
argcount
-
actualcount
);
if
(
actualcount
<
argcount
&&
j
>=
0
)
{
int
i
;
object
*
v
;
if
(
newarg
==
NULL
)
INCREF
(
arg
);
newarg
=
newtupleobject
(
argcount
);
if
(
newarg
==
NULL
)
{
DECREF
(
arg
);
return
NULL
;
}
for
(
i
=
0
;
i
<
actualcount
;
i
++
)
{
v
=
GETTUPLEITEM
(
arg
,
i
);
XINCREF
(
v
);
SETTUPLEITEM
(
newarg
,
i
,
v
);
}
for
(;
i
<
argcount
;
i
++
,
j
++
)
{
v
=
GETTUPLEITEM
(
argdefs
,
j
);
XINCREF
(
v
);
SETTUPLEITEM
(
newarg
,
i
,
v
);
}
DECREF
(
arg
);
arg
=
newarg
;
argdefs
=
PyFunction_GetDefaults
(
func
);
if
(
argdefs
!=
NULL
&&
is_tupleobject
(
argdefs
))
{
d
=
&
GETTUPLEITEM
((
tupleobject
*
)
argdefs
,
0
);
nd
=
gettuplesize
(
argdefs
);
}
else
{
d
=
NULL
;
nd
=
0
;
}
co
=
getfunccode
(
func
);
if
(
co
==
NULL
)
{
XDECREF
(
newarg
);
if
(
kw
!=
NULL
)
{
int
pos
,
i
;
nk
=
getmappingsize
(
kw
);
k
=
NEW
(
object
*
,
2
*
nk
);
if
(
k
==
NULL
)
{
err_nomem
();
DECREF
(
arg
);
return
NULL
;
}
if
(
!
is_codeobject
(
co
))
fatal
(
"XXX Bad code"
);
newlocals
=
newdictobject
();
if
(
newlocals
==
NULL
)
{
XDECREF
(
newarg
);
return
NULL
;
pos
=
i
=
0
;
while
(
mappinggetnext
(
kw
,
&
pos
,
&
k
[
i
],
&
k
[
i
+
1
]))
i
+=
2
;
nk
=
i
/
2
;
/* XXX This is broken if the caller deletes dict items! */
}
else
{
k
=
NULL
;
nk
=
0
;
}
newglobals
=
getfuncglobals
(
func
);
INCREF
(
newglobals
);
v
=
eval_code
((
codeobject
*
)
co
,
newglobals
,
newlocals
,
class
,
arg
);
DECREF
(
newlocals
);
DECREF
(
newglobal
s
);
result
=
eval_code2
(
(
codeobject
*
)
getfunccode
(
func
),
getfuncglobals
(
func
),
(
object
*
)
NULL
,
&
GETTUPLEITEM
(
arg
,
0
),
gettuplesize
(
arg
),
k
,
nk
,
d
,
nd
,
clas
s
);
XDECREF
(
newarg
);
DECREF
(
arg
);
XDEL
(
k
);
return
v
;
return
result
;
}
static
object
*
...
...
@@ -2690,21 +2794,9 @@ access_statement(name, vmode, f)
int
mode
=
getintvalue
(
vmode
);
object
*
value
,
*
ac
;
typeobject
*
type
;
int
fastind
,
ret
;
fastind
=
-
1
;
if
(
f
->
f_localmap
==
NULL
)
int
ret
;
fast_2_locals
(
f
);
value
=
dict2lookup
(
f
->
f_locals
,
name
);
else
{
object
*
map
=
f
->
f_localmap
;
value
=
NULL
;
for
(
fastind
=
gettuplesize
(
map
);
--
fastind
>=
0
;
)
{
object
*
fname
=
GETTUPLEITEM
(
map
,
fastind
);
if
(
cmpobject
(
name
,
fname
)
==
0
)
{
value
=
getlistitem
(
f
->
f_fastlocals
,
fastind
);
break
;
}
}
}
if
(
value
&&
is_accessobject
(
value
))
{
err_setstr
(
AccessError
,
"can't override access"
);
return
-
1
;
...
...
@@ -2717,12 +2809,9 @@ access_statement(name, vmode, f)
ac
=
newaccessobject
(
value
,
f
->
f_locals
,
type
,
mode
);
if
(
ac
==
NULL
)
return
-
1
;
if
(
fastind
>=
0
)
ret
=
setlistitem
(
f
->
f_fastlocals
,
fastind
,
ac
);
else
{
ret
=
dict2insert
(
f
->
f_locals
,
name
,
ac
);
ret
=
mappinginsert
(
f
->
f_locals
,
name
,
ac
);
DECREF
(
ac
);
}
locals_2_fast
(
f
,
0
);
return
ret
;
}
...
...
@@ -2735,6 +2824,7 @@ exec_statement(prog, globals, locals)
char
*
s
;
int
n
;
object
*
v
;
int
plain
=
0
;
if
(
is_tupleobject
(
prog
)
&&
globals
==
None
&&
locals
==
None
&&
((
n
=
gettuplesize
(
prog
))
==
2
||
n
==
3
))
{
...
...
@@ -2746,8 +2836,10 @@ exec_statement(prog, globals, locals)
}
if
(
globals
==
None
)
{
globals
=
getglobals
();
if
(
locals
==
None
)
if
(
locals
==
None
)
{
locals
=
getlocals
();
plain
=
1
;
}
}
else
if
(
locals
==
None
)
locals
=
globals
;
...
...
@@ -2766,8 +2858,7 @@ exec_statement(prog, globals, locals)
if
(
dictlookup
(
globals
,
"__builtins__"
)
==
NULL
)
dictinsert
(
globals
,
"__builtins__"
,
current_frame
->
f_builtins
);
if
(
is_codeobject
(
prog
))
{
if
(
eval_code
((
codeobject
*
)
prog
,
globals
,
locals
,
(
object
*
)
NULL
,
(
object
*
)
NULL
)
==
NULL
)
if
(
eval_code
((
codeobject
*
)
prog
,
globals
,
locals
)
==
NULL
)
return
-
1
;
return
0
;
}
...
...
@@ -2783,13 +2874,16 @@ exec_statement(prog, globals, locals)
err_setstr
(
ValueError
,
"embedded '
\\
0' in exec string"
);
return
-
1
;
}
if
((
v
=
run_string
(
s
,
file_input
,
globals
,
locals
))
==
NULL
)
v
=
run_string
(
s
,
file_input
,
globals
,
locals
);
if
(
v
==
NULL
)
return
-
1
;
DECREF
(
v
);
if
(
plain
)
locals_2_fast
(
current_frame
,
0
);
return
0
;
}
/* Hack for
Ken Manheimer
*/
/* Hack for
newimp.py
*/
static
object
*
find_from_args
(
f
,
nexti
)
frameobject
*
f
;
...
...
@@ -2812,7 +2906,8 @@ find_from_args(f, nexti)
return
NULL
;
do
{
oparg
=
(
next_instr
+=
2
,
(
next_instr
[
-
1
]
<<
8
)
+
next_instr
[
-
2
]);
oparg
=
(
next_instr
[
1
]
<<
8
)
+
next_instr
[
0
];
next_instr
+=
2
;
name
=
Getnamev
(
f
,
oparg
);
if
(
addlistitem
(
list
,
name
)
<
0
)
{
DECREF
(
list
);
...
...
Python/compile.c
View file @
3b7073d2
...
...
@@ -25,8 +25,14 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Compile an expression node to intermediate code */
/* XXX TO DO:
XXX Compute maximum needed stack sizes while compiling
XXX Compute maximum needed stack sizes while compiling;
XXX then frame object can be one malloc and no stack checks are needed
XXX add __doc__ attribute == co_doc to code object attributes
XXX don't execute doc string
XXX Generate simple jump for break/return outside 'try...finally'
XXX get rid of SET_LINENO instructions, use JAR's table trick
XXX (need an option to put them back in, for debugger!)
XXX other JAR tricks?
*/
#include "allobjects.h"
...
...
@@ -44,9 +50,13 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define OFF(x) offsetof(codeobject, x)
static
struct
memberlist
code_memberlist
[]
=
{
{
"co_argcount"
,
T_INT
,
OFF
(
co_argcount
),
READONLY
},
{
"co_nlocals"
,
T_INT
,
OFF
(
co_nlocals
),
READONLY
},
{
"co_flags"
,
T_INT
,
OFF
(
co_flags
),
READONLY
},
{
"co_code"
,
T_OBJECT
,
OFF
(
co_code
),
READONLY
},
{
"co_consts"
,
T_OBJECT
,
OFF
(
co_consts
),
READONLY
},
{
"co_names"
,
T_OBJECT
,
OFF
(
co_names
),
READONLY
},
{
"co_varnames"
,
T_OBJECT
,
OFF
(
co_varnames
),
READONLY
},
{
"co_filename"
,
T_OBJECT
,
OFF
(
co_filename
),
READONLY
},
{
"co_name"
,
T_OBJECT
,
OFF
(
co_name
),
READONLY
},
{
NULL
}
/* Sentinel */
...
...
@@ -69,6 +79,7 @@ code_dealloc(co)
XDECREF
(
co
->
co_names
);
XDECREF
(
co
->
co_filename
);
XDECREF
(
co
->
co_name
);
XDECREF
(
co
->
co_varnames
);
DEL
(
co
);
}
...
...
@@ -97,11 +108,19 @@ code_compare(co, cp)
codeobject
*
co
,
*
cp
;
{
int
cmp
;
cmp
=
cp
->
co_argcount
-
cp
->
co_argcount
;
if
(
cmp
)
return
cmp
;
cmp
=
cp
->
co_nlocals
-
cp
->
co_nlocals
;
if
(
cmp
)
return
cmp
;
cmp
=
cp
->
co_flags
-
cp
->
co_flags
;
if
(
cmp
)
return
cmp
;
cmp
=
cmpobject
((
object
*
)
co
->
co_code
,
(
object
*
)
cp
->
co_code
);
if
(
cmp
)
return
cmp
;
cmp
=
cmpobject
(
co
->
co_consts
,
cp
->
co_consts
);
if
(
cmp
)
return
cmp
;
cmp
=
cmpobject
(
co
->
co_names
,
cp
->
co_names
);
if
(
cmp
)
return
cmp
;
cmp
=
cmpobject
(
co
->
co_varnames
,
cp
->
co_varnames
);
return
cmp
;
}
...
...
@@ -109,14 +128,17 @@ static long
code_hash
(
co
)
codeobject
*
co
;
{
long
h
,
h1
,
h2
,
h3
;
long
h
,
h1
,
h2
,
h3
,
h4
;
h1
=
hashobject
((
object
*
)
co
->
co_code
);
if
(
h1
==
-
1
)
return
-
1
;
h2
=
hashobject
(
co
->
co_consts
);
if
(
h2
==
-
1
)
return
-
1
;
h3
=
hashobject
(
co
->
co_names
);
if
(
h3
==
-
1
)
return
-
1
;
h
=
h1
^
h2
^
h3
;
h4
=
hashobject
(
co
->
co_varnames
);
if
(
h4
==
-
1
)
return
-
1
;
h
=
h1
^
h2
^
h3
^
h4
^
co
->
co_argcount
^
co
->
co_nlocals
^
co
->
co_flags
;
if
(
h
==
-
1
)
h
=
-
2
;
return
h
;
}
...
...
@@ -140,67 +162,64 @@ typeobject Codetype = {
};
codeobject
*
newcodeobject
(
code
,
consts
,
names
,
filename
,
name
)
newcodeobject
(
argcount
,
nlocals
,
flags
,
code
,
consts
,
names
,
varnames
,
filename
,
name
)
int
argcount
;
int
nlocals
;
int
flags
;
object
*
code
;
object
*
consts
;
object
*
names
;
object
*
varnames
;
object
*
filename
;
object
*
name
;
{
codeobject
*
co
;
int
i
;
/* Check argument types */
if
(
code
==
NULL
||
!
is_stringobject
(
code
)
||
consts
==
NULL
||
names
==
NULL
||
name
==
NULL
||
!
(
is_stringobject
(
name
)
||
name
==
None
))
{
if
(
argcount
<
0
||
nlocals
<
0
||
code
==
NULL
||
!
is_stringobject
(
code
)
||
consts
==
NULL
||
!
is_tupleobject
(
consts
)
||
names
==
NULL
||
!
is_tupleobject
(
names
)
||
varnames
==
NULL
||
!
is_tupleobject
(
varnames
)
||
name
==
NULL
||
!
is_stringobject
(
name
)
||
filename
==
NULL
||
!
is_stringobject
(
filename
))
{
err_badcall
();
return
NULL
;
}
/* Allow two lists instead of two tuples */
if
(
is_listobject
(
consts
)
&&
is_listobject
(
names
))
{
consts
=
listtuple
(
consts
);
if
(
consts
==
NULL
)
return
NULL
;
names
=
listtuple
(
names
);
if
(
names
==
NULL
)
{
DECREF
(
consts
);
return
NULL
;
}
}
else
if
(
!
is_tupleobject
(
consts
)
&&
!
is_tupleobject
(
names
))
{
/* Make sure names and varnames are all strings */
for
(
i
=
gettuplesize
(
names
);
--
i
>=
0
;
)
{
object
*
v
=
gettupleitem
(
names
,
i
);
if
(
v
==
NULL
||
!
is_stringobject
(
v
))
{
err_badcall
();
return
NULL
;
}
else
{
INCREF
(
consts
);
INCREF
(
names
);
}
/* Make sure the list of names contains only strings */
for
(
i
=
gettuplesize
(
names
);
--
i
>=
0
;
)
{
object
*
v
=
gettupleitem
(
names
,
i
);
for
(
i
=
gettuplesize
(
varnames
);
--
i
>=
0
;
)
{
object
*
v
=
gettupleitem
(
varnames
,
i
);
if
(
v
==
NULL
||
!
is_stringobject
(
v
))
{
DECREF
(
consts
);
DECREF
(
names
);
err_badcall
();
return
NULL
;
}
}
co
=
NEWOBJ
(
codeobject
,
&
Codetype
);
if
(
co
!=
NULL
)
{
co
->
co_argcount
=
argcount
;
co
->
co_nlocals
=
nlocals
;
co
->
co_flags
=
flags
;
INCREF
(
code
);
co
->
co_code
=
(
stringobject
*
)
code
;
INCREF
(
consts
);
co
->
co_consts
=
consts
;
INCREF
(
names
);
co
->
co_names
=
names
;
INCREF
(
varnames
);
co
->
co_varnames
=
varnames
;
INCREF
(
filename
);
co
->
co_filename
=
filename
;
INCREF
(
name
);
co
->
co_name
=
name
;
}
else
{
DECREF
(
consts
);
DECREF
(
names
);
}
return
co
;
}
...
...
@@ -213,7 +232,12 @@ struct compiling {
object
*
c_code
;
/* string */
object
*
c_consts
;
/* list of objects */
object
*
c_names
;
/* list of strings (names) */
object
*
c_globals
;
/* dictionary */
object
*
c_globals
;
/* dictionary (value=None) */
object
*
c_locals
;
/* dictionary (value=localID) */
object
*
c_varnames
;
/* list (inverse of c_locals) */
int
c_nlocals
;
/* index of next local */
int
c_argcount
;
/* number of top-level arguments */
int
c_flags
;
/* same as co_flags */
int
c_nexti
;
/* index into c_code */
int
c_errors
;
/* counts errors occurred */
int
c_infunction
;
/* set when compiling a function */
...
...
@@ -257,7 +281,7 @@ block_pop(c, type)
}
/* Prototypes */
/* Prototype
forward declaration
s */
static
int
com_init
PROTO
((
struct
compiling
*
,
char
*
));
static
void
com_free
PROTO
((
struct
compiling
*
));
...
...
@@ -273,7 +297,8 @@ static int com_addconst PROTO((struct compiling *, object *));
static
int
com_addname
PROTO
((
struct
compiling
*
,
object
*
));
static
void
com_addopname
PROTO
((
struct
compiling
*
,
int
,
node
*
));
static
void
com_list
PROTO
((
struct
compiling
*
,
node
*
,
int
));
static
int
com_argdefs
PROTO
((
struct
compiling
*
,
node
*
,
int
*
));
static
int
com_argdefs
PROTO
((
struct
compiling
*
,
node
*
));
static
int
com_newlocal
PROTO
((
struct
compiling
*
,
char
*
));
static
int
com_init
(
c
,
filename
)
...
...
@@ -288,6 +313,13 @@ com_init(c, filename)
goto
fail_1
;
if
((
c
->
c_globals
=
newdictobject
())
==
NULL
)
goto
fail_0
;
if
((
c
->
c_locals
=
newdictobject
())
==
NULL
)
goto
fail_00
;
if
((
c
->
c_varnames
=
newlistobject
(
0
))
==
NULL
)
goto
fail_000
;
c
->
c_nlocals
=
0
;
c
->
c_argcount
=
0
;
c
->
c_flags
=
0
;
c
->
c_nexti
=
0
;
c
->
c_errors
=
0
;
c
->
c_infunction
=
0
;
...
...
@@ -299,6 +331,10 @@ com_init(c, filename)
c
->
c_name
=
"?"
;
return
1
;
fail_000:
DECREF
(
c
->
c_locals
);
fail_00:
DECREF
(
c
->
c_globals
);
fail_0:
DECREF
(
c
->
c_names
);
fail_1:
...
...
@@ -317,6 +353,8 @@ com_free(c)
XDECREF
(
c
->
c_consts
);
XDECREF
(
c
->
c_names
);
XDECREF
(
c
->
c_globals
);
XDECREF
(
c
->
c_locals
);
XDECREF
(
c
->
c_varnames
);
}
static
void
...
...
@@ -333,6 +371,7 @@ com_addbyte(c, byte)
int
byte
;
{
int
len
;
/*fprintf(stderr, "%3d: %3d\n", c->c_nexti, byte);*/
if
(
byte
<
0
||
byte
>
255
)
{
/*
fprintf(stderr, "XXX compiling bad byte: %d\n", byte);
...
...
@@ -1221,8 +1260,7 @@ com_test(c, n)
if
(
NCH
(
n
)
==
1
&&
TYPE
(
CHILD
(
n
,
0
))
==
lambdef
)
{
object
*
v
;
int
i
;
int
argcount
;
int
ndefs
=
com_argdefs
(
c
,
CHILD
(
n
,
0
),
&
argcount
);
int
ndefs
=
com_argdefs
(
c
,
CHILD
(
n
,
0
));
v
=
(
object
*
)
compile
(
CHILD
(
n
,
0
),
c
->
c_filename
);
if
(
v
==
NULL
)
{
c
->
c_errors
++
;
...
...
@@ -1233,9 +1271,7 @@ com_test(c, n)
DECREF
(
v
);
}
com_addoparg
(
c
,
LOAD_CONST
,
i
);
com_addbyte
(
c
,
BUILD_FUNCTION
);
if
(
ndefs
>
0
)
com_addoparg
(
c
,
SET_FUNC_ARGS
,
argcount
);
com_addoparg
(
c
,
MAKE_FUNCTION
,
ndefs
);
}
else
{
int
anchor
=
0
;
...
...
@@ -1537,16 +1573,12 @@ com_raise_stmt(c, n)
{
REQ
(
n
,
raise_stmt
);
/* 'raise' test [',' test [',' test]] */
com_node
(
c
,
CHILD
(
n
,
1
));
if
(
NCH
(
n
)
>
3
)
if
(
NCH
(
n
)
>
3
)
{
com_node
(
c
,
CHILD
(
n
,
3
));
else
com_addoparg
(
c
,
LOAD_CONST
,
com_addconst
(
c
,
None
));
if
(
NCH
(
n
)
>
5
)
{
if
(
NCH
(
n
)
>
5
)
com_node
(
c
,
CHILD
(
n
,
5
));
com_addoparg
(
c
,
RAISE_VARARGS
,
3
);
}
else
com_addbyte
(
c
,
RAISE_EXCEPTION
);
com_addoparg
(
c
,
RAISE_VARARGS
,
NCH
(
n
)
/
2
);
}
static
void
...
...
@@ -1585,9 +1617,67 @@ com_global_stmt(c, n)
REQ
(
n
,
global_stmt
);
/* 'global' NAME (',' NAME)* */
for
(
i
=
1
;
i
<
NCH
(
n
);
i
+=
2
)
{
if
(
dictinsert
(
c
->
c_globals
,
STR
(
CHILD
(
n
,
i
)),
None
)
!=
0
)
char
*
s
=
STR
(
CHILD
(
n
,
i
));
if
(
dictlookup
(
c
->
c_locals
,
s
)
!=
NULL
)
{
err_setstr
(
SyntaxError
,
"name is local and global"
);
c
->
c_errors
++
;
}
else
if
(
dictinsert
(
c
->
c_globals
,
s
,
None
)
!=
0
)
c
->
c_errors
++
;
}
}
static
int
com_newlocal_o
(
c
,
nameval
)
struct
compiling
*
c
;
object
*
nameval
;
{
int
i
;
object
*
ival
;
if
(
getlistsize
(
c
->
c_varnames
)
!=
c
->
c_nlocals
)
{
/* This is usually caused by an error on a previous call */
if
(
c
->
c_errors
==
0
)
{
err_setstr
(
SystemError
,
"mixed up var name/index"
);
c
->
c_errors
++
;
}
return
0
;
}
ival
=
newintobject
(
i
=
c
->
c_nlocals
++
);
if
(
ival
==
NULL
)
c
->
c_errors
++
;
else
if
(
mappinginsert
(
c
->
c_locals
,
nameval
,
ival
)
!=
0
)
c
->
c_errors
++
;
else
if
(
addlistitem
(
c
->
c_varnames
,
nameval
)
!=
0
)
c
->
c_errors
++
;
XDECREF
(
ival
);
return
i
;
}
static
int
com_addlocal_o
(
c
,
nameval
)
struct
compiling
*
c
;
object
*
nameval
;
{
object
*
ival
=
mappinglookup
(
c
->
c_locals
,
nameval
);
if
(
ival
!=
NULL
)
return
getintvalue
(
ival
);
return
com_newlocal_o
(
c
,
nameval
);
}
static
int
com_newlocal
(
c
,
name
)
struct
compiling
*
c
;
char
*
name
;
{
object
*
nameval
=
newstringobject
(
name
);
int
i
;
if
(
nameval
==
NULL
)
{
c
->
c_errors
++
;
return
0
;
}
i
=
com_newlocal_o
(
c
,
nameval
);
DECREF
(
nameval
);
return
i
;
}
#define strequ(a, b) (strcmp((a), (b)) == 0)
...
...
@@ -2019,12 +2109,11 @@ com_continue_stmt(c, n)
}
static
int
com_argdefs
(
c
,
n
,
argcount_return
)
com_argdefs
(
c
,
n
)
struct
compiling
*
c
;
node
*
n
;
int
*
argcount_return
;
{
int
i
,
nch
,
nargs
,
ndefs
,
star
;
int
i
,
nch
,
nargs
,
ndefs
;
if
(
TYPE
(
n
)
==
lambdef
)
{
/* lambdef: 'lambda' [varargslist] ':' test */
n
=
CHILD
(
n
,
1
);
...
...
@@ -2036,14 +2125,13 @@ com_argdefs(c, n, argcount_return)
n
=
CHILD
(
n
,
1
);
}
if
(
TYPE
(
n
)
!=
varargslist
)
return
-
1
;
return
0
;
/* varargslist:
(fpdef ['=' test] ',')* '*'
NAME
....... |
(fpdef ['=' test] ',')* '*' ....... |
fpdef ['=' test] (',' fpdef ['=' test])* [','] */
nch
=
NCH
(
n
);
nargs
=
0
;
ndefs
=
0
;
star
=
0
;
for
(
i
=
0
;
i
<
nch
;
i
++
)
{
int
t
;
if
(
TYPE
(
CHILD
(
n
,
i
))
==
STAR
)
...
...
@@ -2073,11 +2161,6 @@ com_argdefs(c, n, argcount_return)
if
(
t
!=
COMMA
)
break
;
}
if
(
star
)
nargs
^=
0x4000
;
*
argcount_return
=
nargs
;
if
(
ndefs
>
0
)
com_addoparg
(
c
,
BUILD_TUPLE
,
ndefs
);
return
ndefs
;
}
...
...
@@ -2093,12 +2176,9 @@ com_funcdef(c, n)
c
->
c_errors
++
;
else
{
int
i
=
com_addconst
(
c
,
v
);
int
argcount
;
int
ndefs
=
com_argdefs
(
c
,
n
,
&
argcount
);
int
ndefs
=
com_argdefs
(
c
,
n
);
com_addoparg
(
c
,
LOAD_CONST
,
i
);
com_addbyte
(
c
,
BUILD_FUNCTION
);
if
(
ndefs
>
0
)
com_addoparg
(
c
,
SET_FUNC_ARGS
,
argcount
);
com_addoparg
(
c
,
MAKE_FUNCTION
,
ndefs
);
com_addopname
(
c
,
STORE_NAME
,
CHILD
(
n
,
1
));
DECREF
(
v
);
}
...
...
@@ -2145,8 +2225,8 @@ com_classdef(c, n)
else
{
i
=
com_addconst
(
c
,
v
);
com_addoparg
(
c
,
LOAD_CONST
,
i
);
com_add
byte
(
c
,
BUILD_FUNCTION
);
com_add
byte
(
c
,
UNARY_CALL
);
com_add
oparg
(
c
,
MAKE_FUNCTION
,
0
);
com_add
oparg
(
c
,
CALL_FUNCTION
,
0
);
com_addbyte
(
c
,
BUILD_CLASS
);
com_addopname
(
c
,
STORE_NAME
,
CHILD
(
n
,
1
));
DECREF
(
v
);
...
...
@@ -2312,7 +2392,7 @@ com_fpdef(c, n)
if
(
TYPE
(
CHILD
(
n
,
0
))
==
LPAR
)
com_fplist
(
c
,
CHILD
(
n
,
1
));
else
com_addop
name
(
c
,
STORE_NAME
,
CHILD
(
n
,
0
));
com_addop
arg
(
c
,
STORE_FAST
,
com_newlocal
(
c
,
STR
(
CHILD
(
n
,
0
))
));
}
static
void
...
...
@@ -2337,53 +2417,87 @@ com_arglist(c, n)
struct
compiling
*
c
;
node
*
n
;
{
int
nch
,
op
,
nargs
,
i
,
t
;
int
nch
,
i
;
int
complex
=
0
;
REQ
(
n
,
varargslist
);
/* varargslist:
(fpdef ['=' test] ',')* '*' NAME ..... |
fpdef ['=' test] (',' fpdef ['=' test])* [','] */
(fpdef ['=' test] ',')* (fpdef ['=' test] | '*' .....) */
nch
=
NCH
(
n
);
op
=
UNPACK_ARG
;
nargs
=
0
;
/* Enter all arguments in table of locals */
for
(
i
=
0
;
i
<
nch
;
i
++
)
{
if
(
TYPE
(
CHILD
(
n
,
i
))
==
STAR
)
{
nch
=
i
;
if
(
TYPE
(
CHILD
(
n
,
i
+
1
))
!=
STAR
)
op
=
UNPACK_VARARG
;
node
*
ch
=
CHILD
(
n
,
i
);
node
*
fp
;
char
*
name
;
if
(
TYPE
(
ch
)
==
STAR
)
break
;
REQ
(
ch
,
fpdef
);
/* fpdef: NAME | '(' fplist ')' */
fp
=
CHILD
(
ch
,
0
);
if
(
TYPE
(
fp
)
==
NAME
)
name
=
STR
(
fp
);
else
{
name
=
""
;
complex
=
1
;
}
nargs
++
;
i
++
;
if
(
i
>=
nch
)
com_newlocal
(
c
,
name
)
;
c
->
c_argcount
++
;
if
(
++
i
>=
nch
)
break
;
t
=
TYPE
(
CHILD
(
n
,
i
)
);
if
(
t
==
EQUAL
)
{
ch
=
CHILD
(
n
,
i
);
if
(
TYPE
(
ch
)
==
EQUAL
)
i
+=
2
;
if
(
i
>=
nch
)
break
;
t
=
TYPE
(
CHILD
(
n
,
i
));
else
REQ
(
ch
,
COMMA
);
}
if
(
t
!=
COMMA
)
break
;
/* Handle *arguments */
if
(
i
<
nch
)
{
node
*
ch
;
ch
=
CHILD
(
n
,
i
);
REQ
(
ch
,
STAR
);
ch
=
CHILD
(
n
,
i
+
1
);
if
(
TYPE
(
ch
)
==
NAME
)
{
c
->
c_flags
|=
CO_VARARGS
;
i
+=
3
;
com_newlocal
(
c
,
STR
(
ch
));
}
com_addoparg
(
c
,
op
,
nargs
);
}
/* Handle **keywords */
if
(
i
<
nch
)
{
node
*
ch
;
ch
=
CHILD
(
n
,
i
);
REQ
(
ch
,
STAR
);
ch
=
CHILD
(
n
,
i
+
1
);
REQ
(
ch
,
STAR
);
ch
=
CHILD
(
n
,
i
+
2
);
REQ
(
ch
,
NAME
);
c
->
c_flags
|=
CO_VARKEYWORDS
;
com_newlocal
(
c
,
STR
(
ch
));
}
if
(
complex
)
{
/* Generate code for complex arguments only after
having counted the simple arguments */
int
ilocal
=
0
;
for
(
i
=
0
;
i
<
nch
;
i
++
)
{
com_fpdef
(
c
,
CHILD
(
n
,
i
));
i
++
;
if
(
i
>=
nch
)
break
;
t
=
TYPE
(
CHILD
(
n
,
i
));
if
(
t
==
EQUAL
)
{
i
+=
2
;
if
(
i
>=
nch
)
node
*
ch
=
CHILD
(
n
,
i
);
node
*
fp
;
char
*
name
;
if
(
TYPE
(
ch
)
==
STAR
)
break
;
t
=
TYPE
(
CHILD
(
n
,
i
));
REQ
(
ch
,
fpdef
);
/* fpdef: NAME | '(' fplist ')' */
fp
=
CHILD
(
ch
,
0
);
if
(
TYPE
(
fp
)
!=
NAME
)
{
com_addoparg
(
c
,
LOAD_FAST
,
ilocal
);
com_fpdef
(
c
,
ch
);
}
if
(
t
!=
COMMA
)
ilocal
++
;
if
(
++
i
>=
nch
)
break
;
ch
=
CHILD
(
n
,
i
);
if
(
TYPE
(
ch
)
==
EQUAL
)
i
+=
2
;
else
REQ
(
ch
,
COMMA
);
}
}
if
(
op
==
UNPACK_VARARG
)
com_addopname
(
c
,
STORE_NAME
,
CHILD
(
n
,
nch
+
1
));
}
static
void
...
...
@@ -2424,12 +2538,11 @@ compile_funcdef(c, n)
(
void
)
com_addconst
(
c
,
doc
);
DECREF
(
doc
);
}
com_addoparg
(
c
,
RESERVE_FAST
,
com_addconst
(
c
,
None
));
/* Patched! */
else
(
void
)
com_addconst
(
c
,
None
);
/* No docstring */
ch
=
CHILD
(
n
,
2
);
/* parameters: '(' [varargslist] ')' */
ch
=
CHILD
(
ch
,
1
);
/* ')' | varargslist */
if
(
TYPE
(
ch
)
==
RPAR
)
com_addoparg
(
c
,
UNPACK_ARG
,
0
);
else
if
(
TYPE
(
ch
)
==
varargslist
)
com_arglist
(
c
,
ch
);
c
->
c_infunction
=
1
;
com_node
(
c
,
CHILD
(
n
,
4
));
...
...
@@ -2444,21 +2557,18 @@ compile_lambdef(c, n)
node
*
n
;
{
node
*
ch
;
REQ
(
n
,
lambdef
);
/* lambdef: 'lambda' [
parameters
] ':' test */
REQ
(
n
,
lambdef
);
/* lambdef: 'lambda' [
varargslist
] ':' test */
c
->
c_name
=
"<lambda>"
;
ch
=
CHILD
(
n
,
1
);
(
void
)
com_addconst
(
c
,
None
);
if
(
TYPE
(
ch
)
==
COLON
)
{
com_addoparg
(
c
,
UNPACK_ARG
,
0
);
com_node
(
c
,
CHILD
(
n
,
2
));
}
else
{
com_addoparg
(
c
,
RESERVE_FAST
,
com_addconst
(
c
,
None
));
(
void
)
com_addconst
(
c
,
None
);
/* No docstring */
if
(
TYPE
(
ch
)
==
varargslist
)
{
com_arglist
(
c
,
ch
);
c
om_node
(
c
,
CHILD
(
n
,
3
)
);
c
h
=
CHILD
(
n
,
3
);
}
else
ch
=
CHILD
(
n
,
2
);
com_node
(
c
,
ch
);
com_addbyte
(
c
,
RETURN_VALUE
);
}
...
...
@@ -2544,34 +2654,31 @@ compile_node(c, n)
The latter instructions are much faster because they don't need to
look up the variable name in a dictionary.
To find all local variables, we check all STORE_NAME, IMPORT_FROM and
DELETE_NAME instructions. This yields all local variables, including
arguments, function definitions, class definitions and import
statements.
To find all local variables, we check all STORE_NAME, IMPORT_FROM
and DELETE_NAME instructions. This yields all local variables,
function definitions, class definitions and import statements.
Argument names have already been entered into the list by the
special processing for the argument list.
All remaining LOAD_NAME instructions must refer to non-local (global
or builtin) variables, so are replaced by LOAD_GLOBAL.
There are two problems: 'from foo import *' and 'exec' may introduce
local variables that we can't know while compiling. If this is the
case, we
don't optimize at all (this rarely happens, since exec is
rare, & this form of import statement is mostly used at the module
l
evel)
.
case, we
can still optimize bona fide locals (since those
statements will be surrounded by fast_2_locals() and
l
ocals_2_fast()), but we can't change LOAD_NAME to LOAD_GLOBAL
.
NB: this modifies the string object co->co_code!
*/
NB: this modifies the string object c->c_code! */
static
void
optimize
(
c
)
struct
compiling
*
c
;
{
unsigned
char
*
next_instr
,
*
cur_instr
;
object
*
locals
;
int
nlocals
;
int
opcode
;
int
oparg
;
object
*
name
;
int
fast_reserved
;
object
*
error_type
,
*
error_value
,
*
error_traceback
;
#define NEXTOP() (*next_instr++)
...
...
@@ -2579,53 +2686,33 @@ optimize(c)
#define GETITEM(v, i) (getlistitem((v), (i)))
#define GETNAMEOBJ(i) (GETITEM(c->c_names, (i)))
locals
=
newdictobject
();
if
(
locals
==
NULL
)
{
c
->
c_errors
++
;
return
;
}
nlocals
=
0
;
err_fetch
(
&
error_type
,
&
error_value
,
&
error_traceback
);
c
->
c_flags
|=
CO_OPTIMIZED
;
next_instr
=
(
unsigned
char
*
)
getstringvalue
(
c
->
c_code
);
for
(;;)
{
opcode
=
NEXTOP
();
if
(
opcode
==
STOP_CODE
)
break
;
if
(
opcode
==
EXEC_STMT
)
goto
end
;
/* Don't optimize if exec present */
if
(
HAS_ARG
(
opcode
))
oparg
=
NEXTARG
();
if
(
opcode
==
STORE_NAME
||
opcode
==
DELETE_NAME
||
opcode
==
IMPORT_FROM
)
{
object
*
v
;
name
=
GETNAMEOBJ
(
oparg
);
if
(
dict2lookup
(
locals
,
name
)
!=
NULL
)
continue
;
err_clear
();
v
=
newintobject
(
nlocals
);
if
(
v
==
NULL
)
{
c
->
c_errors
++
;
goto
err
;
}
nlocals
++
;
if
(
dict2insert
(
locals
,
name
,
v
)
!=
0
)
{
DECREF
(
v
);
c
->
c_errors
++
;
goto
err
;
}
DECREF
(
v
);
switch
(
opcode
)
{
case
STORE_NAME
:
case
DELETE_NAME
:
case
IMPORT_FROM
:
com_addlocal_o
(
c
,
GETNAMEOBJ
(
oparg
));
break
;
case
EXEC_STMT
:
c
->
c_flags
&=
~
CO_OPTIMIZED
;
break
;
}
}
if
(
dictlookup
(
locals
,
"*"
)
!=
NULL
)
{
/* Don't optimize anything */
goto
end
;
}
if
(
dictlookup
(
c
->
c_locals
,
"*"
)
!=
NULL
)
c
->
c_flags
&=
~
CO_OPTIMIZED
;
next_instr
=
(
unsigned
char
*
)
getstringvalue
(
c
->
c_code
);
fast_reserved
=
0
;
for
(;;)
{
cur_instr
=
next_instr
;
opcode
=
NEXTOP
();
...
...
@@ -2633,45 +2720,17 @@ optimize(c)
break
;
if
(
HAS_ARG
(
opcode
))
oparg
=
NEXTARG
();
if
(
opcode
==
RESERVE_FAST
)
{
int
i
;
object
*
localmap
=
newtupleobject
(
nlocals
);
int
pos
;
object
*
key
,
*
value
;
if
(
localmap
==
NULL
)
{
/* XXX mask error */
err_clear
();
continue
;
}
pos
=
0
;
while
(
mappinggetnext
(
locals
,
&
pos
,
&
key
,
&
value
))
{
int
j
;
if
(
!
is_intobject
(
value
))
continue
;
j
=
getintvalue
(
value
);
if
(
0
<=
j
&&
j
<
nlocals
)
{
INCREF
(
key
);
settupleitem
(
localmap
,
j
,
key
);
}
}
i
=
com_addconst
(
c
,
localmap
);
cur_instr
[
1
]
=
i
&
0xff
;
cur_instr
[
2
]
=
(
i
>>
8
)
&
0xff
;
fast_reserved
=
1
;
DECREF
(
localmap
);
continue
;
}
if
(
!
fast_reserved
)
continue
;
if
(
opcode
==
LOAD_NAME
||
opcode
==
STORE_NAME
||
opcode
==
DELETE_NAME
)
{
object
*
v
;
int
i
;
name
=
GETNAMEOBJ
(
oparg
);
v
=
dict2lookup
(
locals
,
name
);
v
=
dict2lookup
(
c
->
c_
locals
,
name
);
if
(
v
==
NULL
)
{
err_clear
();
if
(
opcode
==
LOAD_NAME
)
if
(
opcode
==
LOAD_NAME
&&
(
c
->
c_flags
&
CO_OPTIMIZED
))
cur_instr
[
0
]
=
LOAD_GLOBAL
;
continue
;
}
...
...
@@ -2686,10 +2745,8 @@ optimize(c)
}
}
end:
if
(
c
->
c_errors
==
0
)
err_restore
(
error_type
,
error_value
,
error_traceback
);
err:
DECREF
(
locals
);
}
codeobject
*
...
...
@@ -2703,18 +2760,35 @@ compile(n, filename)
return
NULL
;
compile_node
(
&
sc
,
n
);
com_done
(
&
sc
);
if
((
TYPE
(
n
)
==
funcdef
||
TYPE
(
n
)
==
lambdef
)
&&
sc
.
c_errors
==
0
)
if
((
TYPE
(
n
)
==
funcdef
||
TYPE
(
n
)
==
lambdef
)
&&
sc
.
c_errors
==
0
)
{
optimize
(
&
sc
);
sc
.
c_flags
|=
CO_NEWLOCALS
;
}
else
if
(
TYPE
(
n
)
==
classdef
)
sc
.
c_flags
|=
CO_NEWLOCALS
;
co
=
NULL
;
if
(
sc
.
c_errors
==
0
)
{
object
*
v
,
*
w
;
v
=
newstringobject
(
sc
.
c_filename
);
w
=
newstringobject
(
sc
.
c_name
);
if
(
v
!=
NULL
&&
w
!=
NULL
)
co
=
newcodeobject
(
sc
.
c_code
,
sc
.
c_consts
,
sc
.
c_names
,
v
,
w
);
XDECREF
(
v
);
XDECREF
(
w
);
object
*
consts
,
*
names
,
*
varnames
,
*
filename
,
*
name
;
consts
=
listtuple
(
sc
.
c_consts
);
names
=
listtuple
(
sc
.
c_names
);
varnames
=
listtuple
(
sc
.
c_varnames
);
filename
=
newstringobject
(
sc
.
c_filename
);
name
=
newstringobject
(
sc
.
c_name
);
if
(
!
err_occurred
())
co
=
newcodeobject
(
sc
.
c_argcount
,
sc
.
c_nlocals
,
sc
.
c_flags
,
sc
.
c_code
,
consts
,
names
,
varnames
,
filename
,
name
);
XDECREF
(
consts
);
XDECREF
(
names
);
XDECREF
(
varnames
);
XDECREF
(
filename
);
XDECREF
(
name
);
}
com_free
(
&
sc
);
return
co
;
...
...
Python/import.c
View file @
3b7073d2
...
...
@@ -54,7 +54,7 @@ extern long getmtime(); /* In getmtime.c */
Apple MPW compiler swaps their values, botching string constants */
/* XXX Perhaps the magic number should be frozen and a version field
added to the .pyc file header? */
#define MAGIC (
0x4127L
| ((long)'\r'<<16) | ((long)'\n'<<24))
#define MAGIC (
11913
| ((long)'\r'<<16) | ((long)'\n'<<24))
object
*
import_modules
;
/* This becomes sys.modules */
...
...
@@ -159,7 +159,7 @@ exec_code_module(name, co)
if
(
dictinsert
(
d
,
"__builtins__"
,
getbuiltins
())
!=
0
)
return
NULL
;
}
v
=
eval_code
((
codeobject
*
)
co
,
d
,
d
,
d
,
(
object
*
)
NULL
);
v
=
eval_code
((
codeobject
*
)
co
,
d
,
d
);
/* XXX owner? */
if
(
v
==
NULL
)
return
NULL
;
DECREF
(
v
);
...
...
Python/marshal.c
View file @
3b7073d2
...
...
@@ -44,7 +44,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define TYPE_TUPLE '('
#define TYPE_LIST '['
#define TYPE_DICT '{'
#define TYPE_CODE '
C
'
#define TYPE_CODE '
c
'
#define TYPE_UNKNOWN '?'
typedef
struct
{
...
...
@@ -187,9 +187,13 @@ w_object(v, p)
else
if
(
is_codeobject
(
v
))
{
codeobject
*
co
=
(
codeobject
*
)
v
;
w_byte
(
TYPE_CODE
,
p
);
w_short
(
co
->
co_argcount
,
p
);
w_short
(
co
->
co_nlocals
,
p
);
w_short
(
co
->
co_flags
,
p
);
w_object
((
object
*
)
co
->
co_code
,
p
);
w_object
(
co
->
co_consts
,
p
);
w_object
(
co
->
co_names
,
p
);
w_object
(
co
->
co_varnames
,
p
);
w_object
(
co
->
co_filename
,
p
);
w_object
(
co
->
co_name
,
p
);
}
...
...
@@ -374,14 +378,20 @@ r_object(p)
case
TYPE_CODE
:
{
int
argcount
=
r_short
(
p
);
int
nlocals
=
r_short
(
p
);
int
flags
=
r_short
(
p
);
object
*
code
=
r_object
(
p
);
object
*
consts
=
r_object
(
p
);
object
*
names
=
r_object
(
p
);
object
*
varnames
=
r_object
(
p
);
object
*
filename
=
r_object
(
p
);
object
*
name
=
r_object
(
p
);
if
(
!
err_occurred
())
{
v
=
(
object
*
)
newcodeobject
(
code
,
consts
,
names
,
filename
,
name
);
v
=
(
object
*
)
newcodeobject
(
argcount
,
nlocals
,
flags
,
code
,
consts
,
names
,
varnames
,
filename
,
name
);
}
else
v
=
NULL
;
...
...
Python/pythonrun.c
View file @
3b7073d2
...
...
@@ -430,7 +430,7 @@ run_node(n, filename, globals, locals)
freetree
(
n
);
if
(
co
==
NULL
)
return
NULL
;
v
=
eval_code
(
co
,
globals
,
locals
,
(
object
*
)
NULL
,
(
object
*
)
NULL
);
v
=
eval_code
(
co
,
globals
,
locals
);
DECREF
(
co
);
return
v
;
}
...
...
@@ -462,7 +462,7 @@ run_pyc_file(fp, filename, globals, locals)
return
NULL
;
}
co
=
(
codeobject
*
)
v
;
v
=
eval_code
(
co
,
globals
,
locals
,
(
object
*
)
NULL
,
(
object
*
)
NULL
);
v
=
eval_code
(
co
,
globals
,
locals
);
DECREF
(
co
);
return
v
;
}
...
...
@@ -603,16 +603,9 @@ cleanup()
object
*
exitfunc
=
sysget
(
"exitfunc"
);
if
(
exitfunc
)
{
object
*
arg
;
object
*
res
;
sysset
(
"exitfunc"
,
(
object
*
)
NULL
);
arg
=
newtupleobject
(
0
);
if
(
arg
==
NULL
)
res
=
NULL
;
else
{
res
=
call_object
(
exitfunc
,
arg
);
DECREF
(
arg
);
}
res
=
call_object
(
exitfunc
,
(
object
*
)
NULL
);
if
(
res
==
NULL
)
{
fprintf
(
stderr
,
"Error in sys.exitfunc:
\n
"
);
print_error
();
...
...
Python/traceback.c
View file @
3b7073d2
...
...
@@ -68,7 +68,10 @@ tb_dealloc(tb)
DEL
(
tb
);
}
static
typeobject
Tracebacktype
=
{
#define Tracebacktype PyTraceback_Type
#define is_tracebackobject PyTraceback_Check
typeobject
Tracebacktype
=
{
OB_HEAD_INIT
(
&
Typetype
)
0
,
"traceback"
,
...
...
@@ -85,8 +88,6 @@ static typeobject Tracebacktype = {
0
,
/*tp_as_mapping*/
};
#define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
static
tracebackobject
*
newtracebackobject
(
next
,
frame
,
lasti
,
lineno
)
tracebackobject
*
next
;
...
...
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