Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
4ca6c9db
Kaydet (Commit)
4ca6c9db
authored
Agu 29, 1994
tarafından
Guido van Rossum
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
* Python/compile.c (com_argdefs, com_arglist): avoid referencing
CHILD(n,i) for i >= NCH(n)
üst
3a241818
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
303 additions
and
156 deletions
+303
-156
compile.c
Python/compile.c
+303
-156
No files found.
Python/compile.c
Dosyayı görüntüle @
4ca6c9db
/***********************************************************
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993
, 1994
by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
Amsterdam, The Netherlands.
All Rights Reserved
All Rights Reserved
...
@@ -127,16 +127,16 @@ typeobject Codetype = {
...
@@ -127,16 +127,16 @@ typeobject Codetype = {
"code"
,
"code"
,
sizeof
(
codeobject
),
sizeof
(
codeobject
),
0
,
0
,
code_dealloc
,
/*tp_dealloc*/
(
destructor
)
code_dealloc
,
/*tp_dealloc*/
0
,
/*tp_print*/
0
,
/*tp_print*/
code_getattr
,
/*tp_getattr*/
(
getattrfunc
)
code_getattr
,
/*tp_getattr*/
0
,
/*tp_setattr*/
0
,
/*tp_setattr*/
code_compare
,
/*tp_compare*/
(
cmpfunc
)
code_compare
,
/*tp_compare*/
code_repr
,
/*tp_repr*/
(
reprfunc
)
code_repr
,
/*tp_repr*/
0
,
/*tp_as_number*/
0
,
/*tp_as_number*/
0
,
/*tp_as_sequence*/
0
,
/*tp_as_sequence*/
0
,
/*tp_as_mapping*/
0
,
/*tp_as_mapping*/
code_hash
,
/*tp_hash*/
(
hashfunc
)
code_hash
,
/*tp_hash*/
};
};
codeobject
*
codeobject
*
...
@@ -151,16 +151,37 @@ newcodeobject(code, consts, names, filename, name)
...
@@ -151,16 +151,37 @@ newcodeobject(code, consts, names, filename, name)
int
i
;
int
i
;
/* Check argument types */
/* Check argument types */
if
(
code
==
NULL
||
!
is_stringobject
(
code
)
||
if
(
code
==
NULL
||
!
is_stringobject
(
code
)
||
consts
==
NULL
||
!
is_listobject
(
consts
)
||
consts
==
NULL
||
names
==
NULL
||
!
is_listobject
(
names
)
||
names
==
NULL
||
name
==
NULL
||
!
(
is_stringobject
(
name
)
||
name
==
None
))
{
name
==
NULL
||
!
(
is_stringobject
(
name
)
||
name
==
None
))
{
err_badcall
();
err_badcall
();
return
NULL
;
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
))
{
err_badcall
();
return
NULL
;
}
else
{
INCREF
(
consts
);
INCREF
(
names
);
}
/* Make sure the list of names contains only strings */
/* Make sure the list of names contains only strings */
for
(
i
=
get
list
size
(
names
);
--
i
>=
0
;
)
{
for
(
i
=
get
tuple
size
(
names
);
--
i
>=
0
;
)
{
object
*
v
=
get
list
item
(
names
,
i
);
object
*
v
=
get
tuple
item
(
names
,
i
);
if
(
v
==
NULL
||
!
is_stringobject
(
v
))
{
if
(
v
==
NULL
||
!
is_stringobject
(
v
))
{
DECREF
(
consts
);
DECREF
(
names
);
err_badcall
();
err_badcall
();
return
NULL
;
return
NULL
;
}
}
...
@@ -169,15 +190,17 @@ newcodeobject(code, consts, names, filename, name)
...
@@ -169,15 +190,17 @@ newcodeobject(code, consts, names, filename, name)
if
(
co
!=
NULL
)
{
if
(
co
!=
NULL
)
{
INCREF
(
code
);
INCREF
(
code
);
co
->
co_code
=
(
stringobject
*
)
code
;
co
->
co_code
=
(
stringobject
*
)
code
;
INCREF
(
consts
);
co
->
co_consts
=
consts
;
co
->
co_consts
=
consts
;
INCREF
(
names
);
co
->
co_names
=
names
;
co
->
co_names
=
names
;
INCREF
(
filename
);
INCREF
(
filename
);
co
->
co_filename
=
filename
;
co
->
co_filename
=
filename
;
INCREF
(
name
);
INCREF
(
name
);
co
->
co_name
=
name
;
co
->
co_name
=
name
;
}
}
else
{
DECREF
(
consts
);
DECREF
(
names
);
}
return
co
;
return
co
;
}
}
...
@@ -194,6 +217,7 @@ struct compiling {
...
@@ -194,6 +217,7 @@ struct compiling {
int
c_nexti
;
/* index into c_code */
int
c_nexti
;
/* index into c_code */
int
c_errors
;
/* counts errors occurred */
int
c_errors
;
/* counts errors occurred */
int
c_infunction
;
/* set when compiling a function */
int
c_infunction
;
/* set when compiling a function */
int
c_interactive
;
/* generating code for interactive command */
int
c_loops
;
/* counts nested loops */
int
c_loops
;
/* counts nested loops */
int
c_begin
;
/* begin of current loop, for 'continue' */
int
c_begin
;
/* begin of current loop, for 'continue' */
int
c_block
[
MAXBLOCKS
];
/* stack of block types */
int
c_block
[
MAXBLOCKS
];
/* stack of block types */
...
@@ -249,6 +273,7 @@ static int com_addconst PROTO((struct compiling *, object *));
...
@@ -249,6 +273,7 @@ static int com_addconst PROTO((struct compiling *, object *));
static
int
com_addname
PROTO
((
struct
compiling
*
,
object
*
));
static
int
com_addname
PROTO
((
struct
compiling
*
,
object
*
));
static
void
com_addopname
PROTO
((
struct
compiling
*
,
int
,
node
*
));
static
void
com_addopname
PROTO
((
struct
compiling
*
,
int
,
node
*
));
static
void
com_list
PROTO
((
struct
compiling
*
,
node
*
,
int
));
static
void
com_list
PROTO
((
struct
compiling
*
,
node
*
,
int
));
static
int
com_argdefs
PROTO
((
struct
compiling
*
,
node
*
,
int
*
));
static
int
static
int
com_init
(
c
,
filename
)
com_init
(
c
,
filename
)
...
@@ -266,6 +291,7 @@ com_init(c, filename)
...
@@ -266,6 +291,7 @@ com_init(c, filename)
c
->
c_nexti
=
0
;
c
->
c_nexti
=
0
;
c
->
c_errors
=
0
;
c
->
c_errors
=
0
;
c
->
c_infunction
=
0
;
c
->
c_infunction
=
0
;
c
->
c_interactive
=
0
;
c
->
c_loops
=
0
;
c
->
c_loops
=
0
;
c
->
c_begin
=
0
;
c
->
c_begin
=
0
;
c
->
c_nblocks
=
0
;
c
->
c_nblocks
=
0
;
...
@@ -462,20 +488,19 @@ static object *
...
@@ -462,20 +488,19 @@ static object *
parsenumber
(
s
)
parsenumber
(
s
)
char
*
s
;
char
*
s
;
{
{
extern
long
strtol
PROTO
((
const
char
*
,
char
**
,
int
));
extern
long
my
strtol
PROTO
((
const
char
*
,
char
**
,
int
));
extern
unsigned
long
strtoul
PROTO
((
const
char
*
,
char
**
,
int
));
extern
unsigned
long
my
strtoul
PROTO
((
const
char
*
,
char
**
,
int
));
extern
double
strtod
PROTO
((
const
char
*
,
char
*
*
));
extern
double
atof
PROTO
((
const
char
*
));
char
*
end
;
char
*
end
;
long
x
;
long
x
;
double
xx
;
errno
=
0
;
errno
=
0
;
end
=
s
+
strlen
(
s
)
-
1
;
end
=
s
+
strlen
(
s
)
-
1
;
if
(
*
end
==
'l'
||
*
end
==
'L'
)
if
(
*
end
==
'l'
||
*
end
==
'L'
)
return
long_scan
(
s
,
0
);
return
long_scan
(
s
,
0
);
if
(
s
[
0
]
==
'0'
)
if
(
s
[
0
]
==
'0'
)
x
=
(
long
)
strtoul
(
s
,
&
end
,
0
);
x
=
(
long
)
my
strtoul
(
s
,
&
end
,
0
);
else
else
x
=
strtol
(
s
,
&
end
,
0
);
x
=
my
strtol
(
s
,
&
end
,
0
);
if
(
*
end
==
'\0'
)
{
if
(
*
end
==
'\0'
)
{
if
(
errno
!=
0
)
{
if
(
errno
!=
0
)
{
err_setstr
(
OverflowError
,
err_setstr
(
OverflowError
,
...
@@ -484,22 +509,8 @@ parsenumber(s)
...
@@ -484,22 +509,8 @@ parsenumber(s)
}
}
return
newintobject
(
x
);
return
newintobject
(
x
);
}
}
errno
=
0
;
/* XXX Huge floats may silently fail */
xx
=
strtod
(
s
,
&
end
);
return
newfloatobject
(
atof
(
s
));
if
(
*
end
==
'\0'
)
{
#ifndef BROKEN_STRTOD
/* Some strtod() versions (e.g., in older SunOS systems)
set errno incorrectly; better to ignore overflows
than not to be able to use float literals at all! */
if
(
errno
!=
0
)
{
err_setstr
(
OverflowError
,
"float literal too large"
);
return
NULL
;
}
#endif
return
newfloatobject
(
xx
);
}
err_setstr
(
SystemError
,
"bad number syntax?!?!"
);
return
NULL
;
}
}
static
object
*
static
object
*
...
@@ -510,6 +521,7 @@ parsestr(s)
...
@@ -510,6 +521,7 @@ parsestr(s)
int
len
;
int
len
;
char
*
buf
;
char
*
buf
;
char
*
p
;
char
*
p
;
char
*
end
;
int
c
;
int
c
;
int
quote
=
*
s
;
int
quote
=
*
s
;
if
(
quote
!=
'\''
&&
quote
!=
'\"'
)
{
if
(
quote
!=
'\''
&&
quote
!=
'\"'
)
{
...
@@ -522,11 +534,20 @@ parsestr(s)
...
@@ -522,11 +534,20 @@ parsestr(s)
err_badcall
();
err_badcall
();
return
NULL
;
return
NULL
;
}
}
if
(
len
>=
4
&&
s
[
0
]
==
quote
&&
s
[
1
]
==
quote
)
{
s
+=
2
;
len
-=
2
;
if
(
s
[
--
len
]
!=
quote
||
s
[
--
len
]
!=
quote
)
{
err_badcall
();
return
NULL
;
}
}
if
(
strchr
(
s
,
'\\'
)
==
NULL
)
if
(
strchr
(
s
,
'\\'
)
==
NULL
)
return
newsizedstringobject
(
s
,
len
);
return
newsizedstringobject
(
s
,
len
);
v
=
newsizedstringobject
((
char
*
)
NULL
,
len
);
v
=
newsizedstringobject
((
char
*
)
NULL
,
len
);
p
=
buf
=
getstringvalue
(
v
);
p
=
buf
=
getstringvalue
(
v
);
while
(
*
s
!=
'\0'
&&
*
s
!=
quote
)
{
end
=
s
+
len
;
while
(
s
<
end
)
{
if
(
*
s
!=
'\\'
)
{
if
(
*
s
!=
'\\'
)
{
*
p
++
=
*
s
++
;
*
p
++
=
*
s
++
;
continue
;
continue
;
...
@@ -534,6 +555,7 @@ parsestr(s)
...
@@ -534,6 +555,7 @@ parsestr(s)
s
++
;
s
++
;
switch
(
*
s
++
)
{
switch
(
*
s
++
)
{
/* XXX This assumes ASCII! */
/* XXX This assumes ASCII! */
case
'\n'
:
break
;
case
'\\'
:
*
p
++
=
'\\'
;
break
;
case
'\\'
:
*
p
++
=
'\\'
;
break
;
case
'\''
:
*
p
++
=
'\''
;
break
;
case
'\''
:
*
p
++
=
'\''
;
break
;
case
'\"'
:
*
p
++
=
'\"'
;
break
;
case
'\"'
:
*
p
++
=
'\"'
;
break
;
...
@@ -649,7 +671,14 @@ com_atom(c, n)
...
@@ -649,7 +671,14 @@ com_atom(c, n)
com_addoparg
(
c
,
LOAD_CONST
,
i
);
com_addoparg
(
c
,
LOAD_CONST
,
i
);
break
;
break
;
case
STRING
:
case
STRING
:
if
((
v
=
parsestr
(
STR
(
ch
)))
==
NULL
)
{
if
((
v
=
parsestr
(
STR
(
ch
)))
!=
NULL
)
{
/* String literal concatenation */
for
(
i
=
1
;
i
<
NCH
(
n
)
&&
v
!=
NULL
;
i
++
)
{
joinstring_decref
(
&
v
,
parsestr
(
STR
(
CHILD
(
n
,
i
))));
}
}
if
(
v
==
NULL
)
{
c
->
c_errors
++
;
c
->
c_errors
++
;
i
=
255
;
i
=
255
;
}
}
...
@@ -1098,6 +1127,8 @@ com_test(c, n)
...
@@ -1098,6 +1127,8 @@ com_test(c, n)
if
(
NCH
(
n
)
==
1
&&
TYPE
(
CHILD
(
n
,
0
))
==
lambdef
)
{
if
(
NCH
(
n
)
==
1
&&
TYPE
(
CHILD
(
n
,
0
))
==
lambdef
)
{
object
*
v
;
object
*
v
;
int
i
;
int
i
;
int
argcount
;
int
ndefs
=
com_argdefs
(
c
,
CHILD
(
n
,
0
),
&
argcount
);
v
=
(
object
*
)
compile
(
CHILD
(
n
,
0
),
c
->
c_filename
);
v
=
(
object
*
)
compile
(
CHILD
(
n
,
0
),
c
->
c_filename
);
if
(
v
==
NULL
)
{
if
(
v
==
NULL
)
{
c
->
c_errors
++
;
c
->
c_errors
++
;
...
@@ -1109,6 +1140,8 @@ com_test(c, n)
...
@@ -1109,6 +1140,8 @@ com_test(c, n)
}
}
com_addoparg
(
c
,
LOAD_CONST
,
i
);
com_addoparg
(
c
,
LOAD_CONST
,
i
);
com_addbyte
(
c
,
BUILD_FUNCTION
);
com_addbyte
(
c
,
BUILD_FUNCTION
);
if
(
ndefs
>
0
)
com_addoparg
(
c
,
SET_FUNC_ARGS
,
argcount
);
}
}
else
{
else
{
int
anchor
=
0
;
int
anchor
=
0
;
...
@@ -1355,7 +1388,10 @@ com_expr_stmt(c, n)
...
@@ -1355,7 +1388,10 @@ com_expr_stmt(c, n)
REQ
(
n
,
expr_stmt
);
/* testlist ('=' testlist)* */
REQ
(
n
,
expr_stmt
);
/* testlist ('=' testlist)* */
com_node
(
c
,
CHILD
(
n
,
NCH
(
n
)
-
1
));
com_node
(
c
,
CHILD
(
n
,
NCH
(
n
)
-
1
));
if
(
NCH
(
n
)
==
1
)
{
if
(
NCH
(
n
)
==
1
)
{
com_addbyte
(
c
,
PRINT_EXPR
);
if
(
c
->
c_interactive
)
com_addbyte
(
c
,
PRINT_EXPR
);
else
com_addbyte
(
c
,
POP_TOP
);
}
}
else
{
else
{
int
i
;
int
i
;
...
@@ -1625,25 +1661,7 @@ com_for_stmt(c, n)
...
@@ -1625,25 +1661,7 @@ com_for_stmt(c, n)
com_backpatch
(
c
,
break_anchor
);
com_backpatch
(
c
,
break_anchor
);
}
}
/* Although 'execpt' and 'finally' clauses can be combined
/* Code generated for "try: S finally: Sf" is as follows:
syntactically, they are compiled separately. In fact,
try: S
except E1: S1
except E2: S2
...
finally: Sf
is equivalent to
try:
try: S
except E1: S1
except E2: S2
...
finally: Sf
meaning that the 'finally' clause is entered even if things
go wrong again in an exception handler. Note that this is
not the case for exception handlers: at most one is entered.
Code generated for "try: S finally: Sf" is as follows:
SETUP_FINALLY L
SETUP_FINALLY L
<code for S>
<code for S>
...
@@ -1710,86 +1728,97 @@ com_for_stmt(c, n)
...
@@ -1710,86 +1728,97 @@ com_for_stmt(c, n)
*/
*/
static
void
static
void
com_try_
stm
t
(
c
,
n
)
com_try_
excep
t
(
c
,
n
)
struct
compiling
*
c
;
struct
compiling
*
c
;
node
*
n
;
node
*
n
;
{
{
int
finally_anchor
=
0
;
int
except_anchor
=
0
;
int
except_anchor
=
0
;
REQ
(
n
,
try_stmt
);
int
end_anchor
=
0
;
/* 'try' ':' suite (except_clause ':' suite)*
int
else_anchor
=
0
;
| 'try' ':' 'finally' ':' suite */
int
i
;
node
*
ch
;
/* XXX This can be simplified because except and finally can
com_addfwref
(
c
,
SETUP_EXCEPT
,
&
except_anchor
);
no longer be mixed in a single try statement */
block_push
(
c
,
SETUP_EXCEPT
);
if
(
NCH
(
n
)
>
3
&&
TYPE
(
CHILD
(
n
,
NCH
(
n
)
-
3
))
!=
except_clause
)
{
/* Have a 'finally' clause */
com_addfwref
(
c
,
SETUP_FINALLY
,
&
finally_anchor
);
block_push
(
c
,
SETUP_FINALLY
);
}
if
(
NCH
(
n
)
>
3
&&
TYPE
(
CHILD
(
n
,
3
))
==
except_clause
)
{
/* Have an 'except' clause */
com_addfwref
(
c
,
SETUP_EXCEPT
,
&
except_anchor
);
block_push
(
c
,
SETUP_EXCEPT
);
}
com_node
(
c
,
CHILD
(
n
,
2
));
com_node
(
c
,
CHILD
(
n
,
2
));
if
(
except_anchor
)
{
com_addbyte
(
c
,
POP_BLOCK
);
int
end_anchor
=
0
;
block_pop
(
c
,
SETUP_EXCEPT
)
;
int
i
;
com_addfwref
(
c
,
JUMP_FORWARD
,
&
else_anchor
)
;
node
*
ch
;
com_backpatch
(
c
,
except_anchor
)
;
com_addbyte
(
c
,
POP_BLOCK
)
;
for
(
i
=
3
;
block_pop
(
c
,
SETUP_EXCEPT
)
;
i
<
NCH
(
n
)
&&
TYPE
(
ch
=
CHILD
(
n
,
i
))
==
except_clause
;
com_addfwref
(
c
,
JUMP_FORWARD
,
&
end_anchor
);
i
+=
3
)
{
com_backpatch
(
c
,
except_anchor
);
/* except_clause: 'except' [expr [',' expr]] */
for
(
i
=
3
;
if
(
except_anchor
==
0
)
{
i
<
NCH
(
n
)
&&
TYPE
(
ch
=
CHILD
(
n
,
i
))
==
except_clause
;
err_setstr
(
SyntaxError
,
i
+=
3
)
{
"default 'except:' must be last"
);
/* except_clause: 'except' [expr [',' expr]] */
c
->
c_errors
++
;
if
(
except_anchor
==
0
)
{
break
;
err_setstr
(
SyntaxError
,
}
"default 'except:' must be last"
)
;
except_anchor
=
0
;
c
->
c_errors
++
;
com_addoparg
(
c
,
SET_LINENO
,
ch
->
n_lineno
)
;
break
;
if
(
NCH
(
ch
)
>
1
)
{
}
com_addbyte
(
c
,
DUP_TOP
);
except_anchor
=
0
;
com_node
(
c
,
CHILD
(
ch
,
1
))
;
com_addoparg
(
c
,
SET_LINENO
,
ch
->
n_lineno
);
com_addoparg
(
c
,
COMPARE_OP
,
EXC_MATCH
);
if
(
NCH
(
ch
)
>
1
)
{
com_addfwref
(
c
,
JUMP_IF_FALSE
,
&
except_anchor
);
com_addbyte
(
c
,
DU
P_TOP
);
com_addbyte
(
c
,
PO
P_TOP
);
com_node
(
c
,
CHILD
(
ch
,
1
));
}
com_addoparg
(
c
,
COMPARE_OP
,
EXC_MATCH
);
com_addbyte
(
c
,
POP_TOP
);
com_addfwref
(
c
,
JUMP_IF_FALSE
,
&
except_anchor
);
if
(
NCH
(
ch
)
>
3
)
com_addbyte
(
c
,
POP_TOP
);
com_assign
(
c
,
CHILD
(
ch
,
3
),
1
/*assigning*/
);
}
else
com_addbyte
(
c
,
POP_TOP
);
com_addbyte
(
c
,
POP_TOP
);
if
(
NCH
(
ch
)
>
3
)
com_addbyte
(
c
,
POP_TOP
);
com_assign
(
c
,
CHILD
(
ch
,
3
),
1
/*assigning*/
);
com_node
(
c
,
CHILD
(
n
,
i
+
2
));
else
com_addfwref
(
c
,
JUMP_FORWARD
,
&
end_anchor
);
com_addbyte
(
c
,
POP_TOP
);
if
(
except_anchor
)
{
com_backpatch
(
c
,
except_anchor
);
com_addbyte
(
c
,
POP_TOP
);
com_addbyte
(
c
,
POP_TOP
);
com_node
(
c
,
CHILD
(
n
,
i
+
2
));
com_addfwref
(
c
,
JUMP_FORWARD
,
&
end_anchor
);
if
(
except_anchor
)
{
com_backpatch
(
c
,
except_anchor
);
com_addbyte
(
c
,
POP_TOP
);
}
}
}
com_addbyte
(
c
,
END_FINALLY
);
com_backpatch
(
c
,
end_anchor
);
}
if
(
finally_anchor
)
{
node
*
ch
;
com_addbyte
(
c
,
POP_BLOCK
);
block_pop
(
c
,
SETUP_FINALLY
);
block_push
(
c
,
END_FINALLY
);
com_addoparg
(
c
,
LOAD_CONST
,
com_addconst
(
c
,
None
));
com_backpatch
(
c
,
finally_anchor
);
ch
=
CHILD
(
n
,
NCH
(
n
)
-
1
);
com_addoparg
(
c
,
SET_LINENO
,
ch
->
n_lineno
);
com_node
(
c
,
ch
);
com_addbyte
(
c
,
END_FINALLY
);
block_pop
(
c
,
END_FINALLY
);
}
}
com_addbyte
(
c
,
END_FINALLY
);
com_backpatch
(
c
,
else_anchor
);
if
(
i
<
NCH
(
n
))
com_node
(
c
,
CHILD
(
n
,
i
+
2
));
com_backpatch
(
c
,
end_anchor
);
}
static
void
com_try_finally
(
c
,
n
)
struct
compiling
*
c
;
node
*
n
;
{
int
finally_anchor
=
0
;
node
*
ch
;
com_addfwref
(
c
,
SETUP_FINALLY
,
&
finally_anchor
);
block_push
(
c
,
SETUP_FINALLY
);
com_node
(
c
,
CHILD
(
n
,
2
));
com_addbyte
(
c
,
POP_BLOCK
);
block_pop
(
c
,
SETUP_FINALLY
);
block_push
(
c
,
END_FINALLY
);
com_addoparg
(
c
,
LOAD_CONST
,
com_addconst
(
c
,
None
));
com_backpatch
(
c
,
finally_anchor
);
ch
=
CHILD
(
n
,
NCH
(
n
)
-
1
);
com_addoparg
(
c
,
SET_LINENO
,
ch
->
n_lineno
);
com_node
(
c
,
ch
);
com_addbyte
(
c
,
END_FINALLY
);
block_pop
(
c
,
END_FINALLY
);
}
static
void
com_try_stmt
(
c
,
n
)
struct
compiling
*
c
;
node
*
n
;
{
REQ
(
n
,
try_stmt
);
/* 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
| 'try' ':' suite 'finally' ':' suite */
if
(
TYPE
(
CHILD
(
n
,
3
))
!=
except_clause
)
com_try_finally
(
c
,
n
);
else
com_try_except
(
c
,
n
);
}
}
static
void
static
void
...
@@ -1830,6 +1859,72 @@ com_continue_stmt(c, n)
...
@@ -1830,6 +1859,72 @@ com_continue_stmt(c, n)
XXX if we could pop the exception still on the stack */
XXX if we could pop the exception still on the stack */
}
}
static
int
com_argdefs
(
c
,
n
,
argcount_return
)
struct
compiling
*
c
;
node
*
n
;
int
*
argcount_return
;
{
int
i
,
nch
,
nargs
,
ndefs
,
star
;
if
(
TYPE
(
n
)
==
lambdef
)
{
/* lambdef: 'lambda' [varargslist] ':' test */
n
=
CHILD
(
n
,
1
);
}
else
{
REQ
(
n
,
funcdef
);
/* funcdef: 'def' NAME parameters ... */
n
=
CHILD
(
n
,
2
);
REQ
(
n
,
parameters
);
/* parameters: '(' [varargslist] ')' */
n
=
CHILD
(
n
,
1
);
}
if
(
TYPE
(
n
)
!=
varargslist
)
return
-
1
;
/* varargslist:
(fpdef ['=' test] ',')* '*' NAME |
fpdef ['=' test] (',' fpdef ['=' test])* [','] */
nch
=
NCH
(
n
);
if
(
nch
>=
2
&&
TYPE
(
CHILD
(
n
,
nch
-
2
))
==
STAR
)
{
star
=
1
;
nch
-=
2
;
}
else
star
=
0
;
nargs
=
0
;
ndefs
=
0
;
for
(
i
=
0
;
i
<
nch
;
i
++
)
{
int
t
;
nargs
++
;
i
++
;
if
(
i
>=
nch
)
break
;
t
=
TYPE
(
CHILD
(
n
,
i
));
if
(
t
==
EQUAL
)
{
i
++
;
ndefs
++
;
com_node
(
c
,
CHILD
(
n
,
i
));
i
++
;
if
(
i
>=
nch
)
break
;
t
=
TYPE
(
CHILD
(
n
,
i
));
}
else
{
/* Treat "(a=1, b)" as "(a=1, b=None)" */
if
(
ndefs
)
{
com_addoparg
(
c
,
LOAD_CONST
,
com_addconst
(
c
,
None
));
ndefs
++
;
}
}
if
(
t
!=
COMMA
)
break
;
}
if
(
star
)
nargs
^=
0x4000
;
*
argcount_return
=
nargs
;
if
(
ndefs
>
0
)
com_addoparg
(
c
,
BUILD_TUPLE
,
ndefs
);
return
ndefs
;
}
static
void
static
void
com_funcdef
(
c
,
n
)
com_funcdef
(
c
,
n
)
struct
compiling
*
c
;
struct
compiling
*
c
;
...
@@ -1842,8 +1937,12 @@ com_funcdef(c, n)
...
@@ -1842,8 +1937,12 @@ com_funcdef(c, n)
c
->
c_errors
++
;
c
->
c_errors
++
;
else
{
else
{
int
i
=
com_addconst
(
c
,
v
);
int
i
=
com_addconst
(
c
,
v
);
int
argcount
;
int
ndefs
=
com_argdefs
(
c
,
n
,
&
argcount
);
com_addoparg
(
c
,
LOAD_CONST
,
i
);
com_addoparg
(
c
,
LOAD_CONST
,
i
);
com_addbyte
(
c
,
BUILD_FUNCTION
);
com_addbyte
(
c
,
BUILD_FUNCTION
);
if
(
ndefs
>
0
)
com_addoparg
(
c
,
SET_FUNC_ARGS
,
argcount
);
com_addopname
(
c
,
STORE_NAME
,
CHILD
(
n
,
1
));
com_addopname
(
c
,
STORE_NAME
,
CHILD
(
n
,
1
));
DECREF
(
v
);
DECREF
(
v
);
}
}
...
@@ -2082,25 +2181,52 @@ com_arglist(c, n)
...
@@ -2082,25 +2181,52 @@ com_arglist(c, n)
struct
compiling
*
c
;
struct
compiling
*
c
;
node
*
n
;
node
*
n
;
{
{
int
i
,
nargs
,
op
;
int
nch
,
op
,
nargs
,
i
,
t
;
REQ
(
n
,
varargslist
);
REQ
(
n
,
varargslist
);
/* varargslist:
/* varargslist:
(fpdef ',')* '*' NAME | fpdef (',' fpdef)* [','] */
(fpdef ['=' test] ',')* '*' NAME |
op
=
UNPACK_ARG
;
fpdef ['=' test] (',' fpdef ['=' test])* [','] */
nargs
=
(
NCH
(
n
)
+
1
)
/
2
;
nch
=
NCH
(
n
);
for
(
i
=
0
;
i
<
NCH
(
n
);
i
+=
2
)
{
if
(
nch
>=
2
&&
TYPE
(
CHILD
(
n
,
nch
-
2
))
==
STAR
)
{
int
t
=
TYPE
(
CHILD
(
n
,
i
));
op
=
UNPACK_VARARG
;
if
(
t
==
STAR
)
{
nch
-=
2
;
op
=
UNPACK_VARARG
;
}
nargs
=
i
/
2
;
else
op
=
UNPACK_ARG
;
nargs
=
0
;
for
(
i
=
0
;
i
<
nch
;
i
++
)
{
nargs
++
;
i
++
;
if
(
i
>=
nch
)
break
;
break
;
t
=
TYPE
(
CHILD
(
n
,
i
));
if
(
t
==
EQUAL
)
{
i
+=
2
;
if
(
i
>=
nch
)
break
;
t
=
TYPE
(
CHILD
(
n
,
i
));
}
}
if
(
t
!=
COMMA
)
break
;
}
}
com_addoparg
(
c
,
op
,
nargs
);
com_addoparg
(
c
,
op
,
nargs
);
for
(
i
=
0
;
i
<
2
*
nargs
;
i
+=
2
)
for
(
i
=
0
;
i
<
nch
;
i
++
)
{
com_fpdef
(
c
,
CHILD
(
n
,
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
)
break
;
t
=
TYPE
(
CHILD
(
n
,
i
));
}
if
(
t
!=
COMMA
)
break
;
}
if
(
op
==
UNPACK_VARARG
)
if
(
op
==
UNPACK_VARARG
)
com_addopname
(
c
,
STORE_NAME
,
CHILD
(
n
,
2
*
nargs
+
1
));
com_addopname
(
c
,
STORE_NAME
,
CHILD
(
n
,
nch
+
1
));
}
}
static
void
static
void
...
@@ -2175,11 +2301,13 @@ compile_node(c, n)
...
@@ -2175,11 +2301,13 @@ compile_node(c, n)
case
single_input
:
/* One interactive command */
case
single_input
:
/* One interactive command */
/* NEWLINE | simple_stmt | compound_stmt NEWLINE */
/* NEWLINE | simple_stmt | compound_stmt NEWLINE */
c
->
c_interactive
++
;
n
=
CHILD
(
n
,
0
);
n
=
CHILD
(
n
,
0
);
if
(
TYPE
(
n
)
!=
NEWLINE
)
if
(
TYPE
(
n
)
!=
NEWLINE
)
com_node
(
c
,
n
);
com_node
(
c
,
n
);
com_addoparg
(
c
,
LOAD_CONST
,
com_addconst
(
c
,
None
));
com_addoparg
(
c
,
LOAD_CONST
,
com_addconst
(
c
,
None
));
com_addbyte
(
c
,
RETURN_VALUE
);
com_addbyte
(
c
,
RETURN_VALUE
);
c
->
c_interactive
--
;
break
;
break
;
case
file_input
:
/* A whole file, or built-in function exec() */
case
file_input
:
/* A whole file, or built-in function exec() */
...
@@ -2222,23 +2350,21 @@ compile_node(c, n)
...
@@ -2222,23 +2350,21 @@ compile_node(c, n)
instructions that refer to local variables with LOAD_FAST etc.
instructions that refer to local variables with LOAD_FAST etc.
The latter instructions are much faster because they don't need to
The latter instructions are much faster because they don't need to
look up the variable name in a dictionary.
look up the variable name in a dictionary.
To find all local variables, we check all STORE_NAME and IMPORT_FROM
To find all local variables, we check all STORE_NAME, IMPORT_FROM and
instructions. This yields all local variables, including arguments,
DELETE_NAME instructions. This yields all local variables, including
function definitions, class definitions and import statements.
arguments, function definitions, class definitions and import
(We don't check DELETE_NAME instructions, since if there's no
statements.
STORE_NAME the DELETE_NAME will surely fail.)
All remaining LOAD_NAME instructions must refer to non-local (global
There is one problem: 'from foo import *' introduces local variables
or builtin) variables, so are replaced by LOAD_GLOBAL.
that we can't know while compiling. If this is the case, wo don't
optimize at all (this rarely happens, since this form of import
There are two problems: 'from foo import *' and 'exec' may introduce
statement is mostly used at the module level).
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
Note that, because of this optimization, code like the following
rare, & this form of import statement is mostly used at the module
won't work:
level).
eval('x = 1')
print x
NB: this modifies the string object co->co_code!
NB: this modifies the string object co->co_code!
*/
*/
...
@@ -2300,7 +2426,7 @@ optimize(c)
...
@@ -2300,7 +2426,7 @@ optimize(c)
}
}
}
}
if
(
nlocals
==
0
||
dictlookup
(
locals
,
"*"
)
!=
NULL
)
{
if
(
dictlookup
(
locals
,
"*"
)
!=
NULL
)
{
/* Don't optimize anything */
/* Don't optimize anything */
goto
end
;
goto
end
;
}
}
...
@@ -2315,7 +2441,26 @@ optimize(c)
...
@@ -2315,7 +2441,26 @@ optimize(c)
if
(
HAS_ARG
(
opcode
))
if
(
HAS_ARG
(
opcode
))
oparg
=
NEXTARG
();
oparg
=
NEXTARG
();
if
(
opcode
==
RESERVE_FAST
)
{
if
(
opcode
==
RESERVE_FAST
)
{
int
i
=
com_addconst
(
c
,
locals
);
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
[
1
]
=
i
&
0xff
;
cur_instr
[
2
]
=
(
i
>>
8
)
&
0xff
;
cur_instr
[
2
]
=
(
i
>>
8
)
&
0xff
;
fast_reserved
=
1
;
fast_reserved
=
1
;
...
@@ -2332,6 +2477,8 @@ optimize(c)
...
@@ -2332,6 +2477,8 @@ optimize(c)
v
=
dict2lookup
(
locals
,
name
);
v
=
dict2lookup
(
locals
,
name
);
if
(
v
==
NULL
)
{
if
(
v
==
NULL
)
{
err_clear
();
err_clear
();
if
(
opcode
==
LOAD_NAME
)
cur_instr
[
0
]
=
LOAD_GLOBAL
;
continue
;
continue
;
}
}
i
=
getintvalue
(
v
);
i
=
getintvalue
(
v
);
...
...
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