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
873bdc18
Commit
873bdc18
authored
Feb 17, 2000
by
Jeremy Hylton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
satisfy the tabnanny
fix broken references to filename var in generateXXX methods
parent
1e862e8a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
398 additions
and
394 deletions
+398
-394
Lib/compiler/pycodegen.py
Lib/compiler/pycodegen.py
+199
-197
Tools/compiler/compiler/pycodegen.py
Tools/compiler/compiler/pycodegen.py
+199
-197
No files found.
Lib/compiler/pycodegen.py
View file @
873bdc18
...
@@ -80,7 +80,7 @@ class ASTVisitor:
...
@@ -80,7 +80,7 @@ class ASTVisitor:
VERBOSE
=
0
VERBOSE
=
0
def
__init__
(
self
):
def
__init__
(
self
):
self
.
node
=
None
self
.
node
=
None
def
preorder
(
self
,
tree
,
visitor
):
def
preorder
(
self
,
tree
,
visitor
):
"""Do preorder walk of tree using visitor"""
"""Do preorder walk of tree using visitor"""
...
@@ -163,27 +163,26 @@ class CodeGenerator:
...
@@ -163,27 +163,26 @@ class CodeGenerator:
# XXX should clean up initialization and generateXXX funcs
# XXX should clean up initialization and generateXXX funcs
def
__init__
(
self
,
filename
=
"<?>"
):
def
__init__
(
self
,
filename
=
"<?>"
):
self
.
filename
=
filename
self
.
filename
=
filename
self
.
code
=
PyAssembler
()
self
.
code
=
PyAssembler
()
self
.
code
.
setFlags
(
0
)
self
.
code
.
setFlags
(
0
)
self
.
locals
=
misc
.
Stack
()
self
.
locals
=
misc
.
Stack
()
self
.
loops
=
misc
.
Stack
()
self
.
loops
=
misc
.
Stack
()
self
.
namespace
=
0
self
.
namespace
=
0
self
.
curStack
=
0
self
.
curStack
=
0
self
.
maxStack
=
0
self
.
maxStack
=
0
def
emit
(
self
,
*
args
):
def
emit
(
self
,
*
args
):
# XXX could just use self.emit = self.code.emit
# XXX could just use self.emit = self.code.emit
apply
(
self
.
code
.
emit
,
args
)
apply
(
self
.
code
.
emit
,
args
)
def
_generateFunctionOrLambdaCode
(
self
,
func
):
def
_generateFunctionOrLambdaCode
(
self
,
func
):
self
.
name
=
func
.
name
self
.
name
=
func
.
name
self
.
filename
=
filename
# keep a lookout for 'def foo((x,y)):'
# keep a lookout for 'def foo((x,y)):'
args
,
hasTupleArg
=
self
.
generateArglist
(
func
.
argnames
)
args
,
hasTupleArg
=
self
.
generateArglist
(
func
.
argnames
)
self
.
code
=
PyAssembler
(
args
=
args
,
name
=
func
.
name
,
self
.
code
=
PyAssembler
(
args
=
args
,
name
=
func
.
name
,
filename
=
filename
)
filename
=
self
.
filename
)
self
.
namespace
=
self
.
OPTIMIZED
self
.
namespace
=
self
.
OPTIMIZED
if
func
.
varargs
:
if
func
.
varargs
:
self
.
code
.
setVarArgs
()
self
.
code
.
setVarArgs
()
...
@@ -191,8 +190,8 @@ class CodeGenerator:
...
@@ -191,8 +190,8 @@ class CodeGenerator:
self
.
code
.
setKWArgs
()
self
.
code
.
setKWArgs
()
lnf
=
walk
(
func
.
code
,
LocalNameFinder
(
args
),
0
)
lnf
=
walk
(
func
.
code
,
LocalNameFinder
(
args
),
0
)
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
emit
(
'SET_LINENO'
,
func
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
func
.
lineno
)
if
hasTupleArg
:
if
hasTupleArg
:
self
.
generateArgUnpack
(
func
.
argnames
)
self
.
generateArgUnpack
(
func
.
argnames
)
walk
(
func
.
code
,
self
)
walk
(
func
.
code
,
self
)
...
@@ -239,7 +238,7 @@ class CodeGenerator:
...
@@ -239,7 +238,7 @@ class CodeGenerator:
def
generateClassCode
(
self
,
klass
):
def
generateClassCode
(
self
,
klass
):
self
.
code
=
PyAssembler
(
name
=
klass
.
name
,
self
.
code
=
PyAssembler
(
name
=
klass
.
name
,
filename
=
filename
)
filename
=
self
.
filename
)
self
.
emit
(
'SET_LINENO'
,
klass
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
klass
.
lineno
)
lnf
=
walk
(
klass
.
code
,
LocalNameFinder
(),
0
)
lnf
=
walk
(
klass
.
code
,
LocalNameFinder
(),
0
)
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
locals
.
push
(
lnf
.
getLocals
())
...
@@ -254,7 +253,7 @@ class CodeGenerator:
...
@@ -254,7 +253,7 @@ class CodeGenerator:
return
self
.
code
.
makeCodeObject
()
return
self
.
code
.
makeCodeObject
()
def
isLocalName
(
self
,
name
):
def
isLocalName
(
self
,
name
):
return
self
.
locals
.
top
().
has_elt
(
name
)
return
self
.
locals
.
top
().
has_elt
(
name
)
def
_nameOp
(
self
,
prefix
,
name
):
def
_nameOp
(
self
,
prefix
,
name
):
if
self
.
isLocalName
(
name
):
if
self
.
isLocalName
(
name
):
...
@@ -290,8 +289,8 @@ class CodeGenerator:
...
@@ -290,8 +289,8 @@ class CodeGenerator:
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
def
visitModule
(
self
,
node
):
def
visitModule
(
self
,
node
):
lnf
=
walk
(
node
.
node
,
LocalNameFinder
(),
0
)
lnf
=
walk
(
node
.
node
,
LocalNameFinder
(),
0
)
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
visit
(
node
.
node
)
self
.
visit
(
node
.
node
)
self
.
emit
(
'LOAD_CONST'
,
None
)
self
.
emit
(
'LOAD_CONST'
,
None
)
self
.
emit
(
'RETURN_VALUE'
)
self
.
emit
(
'RETURN_VALUE'
)
...
@@ -353,15 +352,15 @@ class CodeGenerator:
...
@@ -353,15 +352,15 @@ class CodeGenerator:
kw
=
0
kw
=
0
if
hasattr
(
node
,
'lineno'
):
if
hasattr
(
node
,
'lineno'
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
visit
(
node
.
node
)
self
.
visit
(
node
.
node
)
for
arg
in
node
.
args
:
for
arg
in
node
.
args
:
self
.
visit
(
arg
)
self
.
visit
(
arg
)
if
isinstance
(
arg
,
ast
.
Keyword
):
if
isinstance
(
arg
,
ast
.
Keyword
):
kw
=
kw
+
1
kw
=
kw
+
1
else
:
else
:
pos
=
pos
+
1
pos
=
pos
+
1
self
.
emit
(
'CALL_FUNCTION'
,
kw
<<
8
|
pos
)
self
.
emit
(
'CALL_FUNCTION'
,
kw
<<
8
|
pos
)
return
1
return
1
def
visitKeyword
(
self
,
node
):
def
visitKeyword
(
self
,
node
):
self
.
emit
(
'LOAD_CONST'
,
node
.
name
)
self
.
emit
(
'LOAD_CONST'
,
node
.
name
)
...
@@ -369,24 +368,24 @@ class CodeGenerator:
...
@@ -369,24 +368,24 @@ class CodeGenerator:
return
1
return
1
def
visitIf
(
self
,
node
):
def
visitIf
(
self
,
node
):
after
=
StackRef
()
after
=
StackRef
()
for
test
,
suite
in
node
.
tests
:
for
test
,
suite
in
node
.
tests
:
if
hasattr
(
test
,
'lineno'
):
if
hasattr
(
test
,
'lineno'
):
self
.
emit
(
'SET_LINENO'
,
test
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
test
.
lineno
)
else
:
else
:
print
"warning"
,
"no line number"
print
"warning"
,
"no line number"
self
.
visit
(
test
)
self
.
visit
(
test
)
dest
=
StackRef
()
dest
=
StackRef
()
self
.
emit
(
'JUMP_IF_FALSE'
,
dest
)
self
.
emit
(
'JUMP_IF_FALSE'
,
dest
)
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
self
.
visit
(
suite
)
self
.
visit
(
suite
)
self
.
emit
(
'JUMP_FORWARD'
,
after
)
self
.
emit
(
'JUMP_FORWARD'
,
after
)
dest
.
bind
(
self
.
code
.
getCurInst
())
dest
.
bind
(
self
.
code
.
getCurInst
())
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
if
node
.
else_
:
if
node
.
else_
:
self
.
visit
(
node
.
else_
)
self
.
visit
(
node
.
else_
)
after
.
bind
(
self
.
code
.
getCurInst
())
after
.
bind
(
self
.
code
.
getCurInst
())
return
1
return
1
def
startLoop
(
self
):
def
startLoop
(
self
):
l
=
Loop
()
l
=
Loop
()
...
@@ -516,64 +515,64 @@ class CodeGenerator:
...
@@ -516,64 +515,64 @@ class CodeGenerator:
return
1
return
1
def
visitCompare
(
self
,
node
):
def
visitCompare
(
self
,
node
):
"""Comment from compile.c follows:
"""Comment from compile.c follows:
The following code is generated for all but the last
The following code is generated for all but the last
comparison in a chain:
comparison in a chain:
label: on stack: opcode:
jump to:
label: on stack: opcode:
jump to:
a
<code to load b>
a
<code to load b>
a, b
DUP_TOP
a, b
DUP_TOP
a, b, b
ROT_THREE
a, b, b
ROT_THREE
b, a, b
COMPARE_OP
b, a, b
COMPARE_OP
b, 0-or-1 JUMP_IF_FALSE
L1
b, 0-or-1 JUMP_IF_FALSE
L1
b, 1
POP_TOP
b, 1
POP_TOP
b
b
We are now ready to repeat this sequence for the next
We are now ready to repeat this sequence for the next
comparison in the chain.
comparison in the chain.
For the last we generate:
For the last we generate:
b
<code to load c>
b
<code to load c>
b, c
COMPARE_OP
b, c
COMPARE_OP
0-or-1
0-or-1
If there were any jumps to L1 (i.e., there was more than one
If there were any jumps to L1 (i.e., there was more than one
comparison), we generate:
comparison), we generate:
0-or-1 JUMP_FORWARD
L2
0-or-1 JUMP_FORWARD
L2
L1: b, 0
ROT_TWO
L1: b, 0
ROT_TWO
0, b
POP_TOP
0, b
POP_TOP
0
0
L2:
0-or-1
L2:
0-or-1
"""
"""
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
# if refs are never emitted, subsequent bind call has no effect
# if refs are never emitted, subsequent bind call has no effect
l1
=
StackRef
()
l1
=
StackRef
()
l2
=
StackRef
()
l2
=
StackRef
()
for
op
,
code
in
node
.
ops
[:
-
1
]:
for
op
,
code
in
node
.
ops
[:
-
1
]:
# emit every comparison except the last
# emit every comparison except the last
self
.
visit
(
code
)
self
.
visit
(
code
)
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'ROT_THREE'
)
self
.
emit
(
'ROT_THREE'
)
self
.
emit
(
'COMPARE_OP'
,
op
)
self
.
emit
(
'COMPARE_OP'
,
op
)
# dupTop and compareOp cancel stack effect
# dupTop and compareOp cancel stack effect
self
.
emit
(
'JUMP_IF_FALSE'
,
l1
)
self
.
emit
(
'JUMP_IF_FALSE'
,
l1
)
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
if
node
.
ops
:
if
node
.
ops
:
# emit the last comparison
# emit the last comparison
op
,
code
=
node
.
ops
[
-
1
]
op
,
code
=
node
.
ops
[
-
1
]
self
.
visit
(
code
)
self
.
visit
(
code
)
self
.
emit
(
'COMPARE_OP'
,
op
)
self
.
emit
(
'COMPARE_OP'
,
op
)
if
len
(
node
.
ops
)
>
1
:
if
len
(
node
.
ops
)
>
1
:
self
.
emit
(
'JUMP_FORWARD'
,
l2
)
self
.
emit
(
'JUMP_FORWARD'
,
l2
)
l1
.
bind
(
self
.
code
.
getCurInst
())
l1
.
bind
(
self
.
code
.
getCurInst
())
self
.
emit
(
'ROT_TWO'
)
self
.
emit
(
'ROT_TWO'
)
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
l2
.
bind
(
self
.
code
.
getCurInst
())
l2
.
bind
(
self
.
code
.
getCurInst
())
return
1
return
1
def
visitGetattr
(
self
,
node
):
def
visitGetattr
(
self
,
node
):
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
...
@@ -590,7 +589,7 @@ class CodeGenerator:
...
@@ -590,7 +589,7 @@ class CodeGenerator:
self
.
emit
(
'BINARY_SUBSCR'
)
self
.
emit
(
'BINARY_SUBSCR'
)
elif
node
.
flags
==
'OP_ASSIGN'
:
elif
node
.
flags
==
'OP_ASSIGN'
:
self
.
emit
(
'STORE_SUBSCR'
)
self
.
emit
(
'STORE_SUBSCR'
)
elif
node
.
flags
==
'OP_DELETE'
:
elif
node
.
flags
==
'OP_DELETE'
:
self
.
emit
(
'DELETE_SUBSCR'
)
self
.
emit
(
'DELETE_SUBSCR'
)
return
1
return
1
...
@@ -624,11 +623,11 @@ class CodeGenerator:
...
@@ -624,11 +623,11 @@ class CodeGenerator:
def
visitAssign
(
self
,
node
):
def
visitAssign
(
self
,
node
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
dups
=
len
(
node
.
nodes
)
-
1
dups
=
len
(
node
.
nodes
)
-
1
for
i
in
range
(
len
(
node
.
nodes
)):
for
i
in
range
(
len
(
node
.
nodes
)):
elt
=
node
.
nodes
[
i
]
elt
=
node
.
nodes
[
i
]
if
i
<
dups
:
if
i
<
dups
:
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'DUP_TOP'
)
if
isinstance
(
elt
,
ast
.
Node
):
if
isinstance
(
elt
,
ast
.
Node
):
self
.
visit
(
elt
)
self
.
visit
(
elt
)
return
1
return
1
...
@@ -659,10 +658,10 @@ class CodeGenerator:
...
@@ -659,10 +658,10 @@ class CodeGenerator:
visitAssList
=
visitAssTuple
visitAssList
=
visitAssTuple
def
binaryOp
(
self
,
node
,
op
):
def
binaryOp
(
self
,
node
,
op
):
self
.
visit
(
node
.
left
)
self
.
visit
(
node
.
left
)
self
.
visit
(
node
.
right
)
self
.
visit
(
node
.
right
)
self
.
emit
(
op
)
self
.
emit
(
op
)
return
1
return
1
def
unaryOp
(
self
,
node
,
op
):
def
unaryOp
(
self
,
node
,
op
):
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
...
@@ -670,28 +669,28 @@ class CodeGenerator:
...
@@ -670,28 +669,28 @@ class CodeGenerator:
return
1
return
1
def
visitAdd
(
self
,
node
):
def
visitAdd
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_ADD'
)
return
self
.
binaryOp
(
node
,
'BINARY_ADD'
)
def
visitSub
(
self
,
node
):
def
visitSub
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_SUBTRACT'
)
return
self
.
binaryOp
(
node
,
'BINARY_SUBTRACT'
)
def
visitMul
(
self
,
node
):
def
visitMul
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_MULTIPLY'
)
return
self
.
binaryOp
(
node
,
'BINARY_MULTIPLY'
)
def
visitDiv
(
self
,
node
):
def
visitDiv
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_DIVIDE'
)
return
self
.
binaryOp
(
node
,
'BINARY_DIVIDE'
)
def
visitMod
(
self
,
node
):
def
visitMod
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_MODULO'
)
return
self
.
binaryOp
(
node
,
'BINARY_MODULO'
)
def
visitPower
(
self
,
node
):
def
visitPower
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_POWER'
)
return
self
.
binaryOp
(
node
,
'BINARY_POWER'
)
def
visitLeftShift
(
self
,
node
):
def
visitLeftShift
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_LSHIFT'
)
return
self
.
binaryOp
(
node
,
'BINARY_LSHIFT'
)
def
visitRightShift
(
self
,
node
):
def
visitRightShift
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_RSHIFT'
)
return
self
.
binaryOp
(
node
,
'BINARY_RSHIFT'
)
def
visitInvert
(
self
,
node
):
def
visitInvert
(
self
,
node
):
return
self
.
unaryOp
(
node
,
'UNARY_INVERT'
)
return
self
.
unaryOp
(
node
,
'UNARY_INVERT'
)
...
@@ -712,20 +711,20 @@ class CodeGenerator:
...
@@ -712,20 +711,20 @@ class CodeGenerator:
return
self
.
unaryOp
(
node
,
'UNARY_CONVERT'
)
return
self
.
unaryOp
(
node
,
'UNARY_CONVERT'
)
def
bitOp
(
self
,
nodes
,
op
):
def
bitOp
(
self
,
nodes
,
op
):
self
.
visit
(
nodes
[
0
])
self
.
visit
(
nodes
[
0
])
for
node
in
nodes
[
1
:]:
for
node
in
nodes
[
1
:]:
self
.
visit
(
node
)
self
.
visit
(
node
)
self
.
emit
(
op
)
self
.
emit
(
op
)
return
1
return
1
def
visitBitand
(
self
,
node
):
def
visitBitand
(
self
,
node
):
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_AND'
)
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_AND'
)
def
visitBitor
(
self
,
node
):
def
visitBitor
(
self
,
node
):
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_OR'
)
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_OR'
)
def
visitBitxor
(
self
,
node
):
def
visitBitxor
(
self
,
node
):
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_XOR'
)
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_XOR'
)
def
visitTest
(
self
,
node
,
jump
):
def
visitTest
(
self
,
node
,
jump
):
end
=
StackRef
()
end
=
StackRef
()
...
@@ -738,22 +737,22 @@ class CodeGenerator:
...
@@ -738,22 +737,22 @@ class CodeGenerator:
return
1
return
1
def
visitAssert
(
self
,
node
):
def
visitAssert
(
self
,
node
):
# XXX __debug__ and AssertionError appear to be special cases
# XXX __debug__ and AssertionError appear to be special cases
# -- they are always loaded as globals even if there are local
# -- they are always loaded as globals even if there are local
# names. I guess this is a sort of renaming op.
# names. I guess this is a sort of renaming op.
skip
=
StackRef
()
skip
=
StackRef
()
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'LOAD_GLOBAL'
,
'__debug__'
)
self
.
emit
(
'LOAD_GLOBAL'
,
'__debug__'
)
self
.
emit
(
'JUMP_IF_FALSE'
,
skip
)
self
.
emit
(
'JUMP_IF_FALSE'
,
skip
)
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
self
.
visit
(
node
.
test
)
self
.
visit
(
node
.
test
)
self
.
emit
(
'JUMP_IF_TRUE'
,
skip
)
self
.
emit
(
'JUMP_IF_TRUE'
,
skip
)
self
.
emit
(
'LOAD_GLOBAL'
,
'AssertionError'
)
self
.
emit
(
'LOAD_GLOBAL'
,
'AssertionError'
)
self
.
visit
(
node
.
fail
)
self
.
visit
(
node
.
fail
)
self
.
emit
(
'RAISE_VARARGS'
,
2
)
self
.
emit
(
'RAISE_VARARGS'
,
2
)
skip
.
bind
(
self
.
code
.
getCurInst
())
skip
.
bind
(
self
.
code
.
getCurInst
())
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
return
1
return
1
def
visitAnd
(
self
,
node
):
def
visitAnd
(
self
,
node
):
return
self
.
visitTest
(
node
,
'JUMP_IF_FALSE'
)
return
self
.
visitTest
(
node
,
'JUMP_IF_FALSE'
)
...
@@ -765,12 +764,12 @@ class CodeGenerator:
...
@@ -765,12 +764,12 @@ class CodeGenerator:
self
.
loadName
(
node
.
name
)
self
.
loadName
(
node
.
name
)
def
visitConst
(
self
,
node
):
def
visitConst
(
self
,
node
):
self
.
emit
(
'LOAD_CONST'
,
node
.
value
)
self
.
emit
(
'LOAD_CONST'
,
node
.
value
)
return
1
return
1
def
visitEllipsis
(
self
,
node
):
def
visitEllipsis
(
self
,
node
):
self
.
emit
(
'LOAD_CONST'
,
Ellipsis
)
self
.
emit
(
'LOAD_CONST'
,
Ellipsis
)
return
1
return
1
def
visitTuple
(
self
,
node
):
def
visitTuple
(
self
,
node
):
for
elt
in
node
.
nodes
:
for
elt
in
node
.
nodes
:
...
@@ -785,76 +784,76 @@ class CodeGenerator:
...
@@ -785,76 +784,76 @@ class CodeGenerator:
return
1
return
1
def
visitDict
(
self
,
node
):
def
visitDict
(
self
,
node
):
self
.
emit
(
'BUILD_MAP'
,
0
)
self
.
emit
(
'BUILD_MAP'
,
0
)
for
k
,
v
in
node
.
items
:
for
k
,
v
in
node
.
items
:
# XXX need to add set lineno when there aren't constants
# XXX need to add set lineno when there aren't constants
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'DUP_TOP'
)
self
.
visit
(
v
)
self
.
visit
(
v
)
self
.
emit
(
'ROT_TWO'
)
self
.
emit
(
'ROT_TWO'
)
self
.
visit
(
k
)
self
.
visit
(
k
)
self
.
emit
(
'STORE_SUBSCR'
)
self
.
emit
(
'STORE_SUBSCR'
)
return
1
return
1
def
visitReturn
(
self
,
node
):
def
visitReturn
(
self
,
node
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
visit
(
node
.
value
)
self
.
visit
(
node
.
value
)
self
.
emit
(
'RETURN_VALUE'
)
self
.
emit
(
'RETURN_VALUE'
)
return
1
return
1
def
visitRaise
(
self
,
node
):
def
visitRaise
(
self
,
node
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
n
=
0
n
=
0
if
node
.
expr1
:
if
node
.
expr1
:
self
.
visit
(
node
.
expr1
)
self
.
visit
(
node
.
expr1
)
n
=
n
+
1
n
=
n
+
1
if
node
.
expr2
:
if
node
.
expr2
:
self
.
visit
(
node
.
expr2
)
self
.
visit
(
node
.
expr2
)
n
=
n
+
1
n
=
n
+
1
if
node
.
expr3
:
if
node
.
expr3
:
self
.
visit
(
node
.
expr3
)
self
.
visit
(
node
.
expr3
)
n
=
n
+
1
n
=
n
+
1
self
.
emit
(
'RAISE_VARARGS'
,
n
)
self
.
emit
(
'RAISE_VARARGS'
,
n
)
return
1
return
1
def
visitPrint
(
self
,
node
):
def
visitPrint
(
self
,
node
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
for
child
in
node
.
nodes
:
for
child
in
node
.
nodes
:
self
.
visit
(
child
)
self
.
visit
(
child
)
self
.
emit
(
'PRINT_ITEM'
)
self
.
emit
(
'PRINT_ITEM'
)
return
1
return
1
def
visitPrintnl
(
self
,
node
):
def
visitPrintnl
(
self
,
node
):
self
.
visitPrint
(
node
)
self
.
visitPrint
(
node
)
self
.
emit
(
'PRINT_NEWLINE'
)
self
.
emit
(
'PRINT_NEWLINE'
)
return
1
return
1
def
visitExec
(
self
,
node
):
def
visitExec
(
self
,
node
):
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
if
node
.
locals
is
None
:
if
node
.
locals
is
None
:
self
.
emit
(
'LOAD_CONST'
,
None
)
self
.
emit
(
'LOAD_CONST'
,
None
)
else
:
else
:
self
.
visit
(
node
.
locals
)
self
.
visit
(
node
.
locals
)
if
node
.
globals
is
None
:
if
node
.
globals
is
None
:
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'DUP_TOP'
)
else
:
else
:
self
.
visit
(
node
.
globals
)
self
.
visit
(
node
.
globals
)
self
.
emit
(
'EXEC_STMT'
)
self
.
emit
(
'EXEC_STMT'
)
class
LocalNameFinder
:
class
LocalNameFinder
:
def
__init__
(
self
,
names
=
()):
def
__init__
(
self
,
names
=
()):
self
.
names
=
misc
.
Set
()
self
.
names
=
misc
.
Set
()
self
.
globals
=
misc
.
Set
()
self
.
globals
=
misc
.
Set
()
for
name
in
names
:
for
name
in
names
:
self
.
names
.
add
(
name
)
self
.
names
.
add
(
name
)
def
getLocals
(
self
):
def
getLocals
(
self
):
for
elt
in
self
.
globals
.
items
():
for
elt
in
self
.
globals
.
items
():
if
self
.
names
.
has_elt
(
elt
):
if
self
.
names
.
has_elt
(
elt
):
self
.
names
.
remove
(
elt
)
self
.
names
.
remove
(
elt
)
return
self
.
names
return
self
.
names
def
visitDict
(
self
,
node
):
def
visitDict
(
self
,
node
):
return
1
return
1
def
visitGlobal
(
self
,
node
):
def
visitGlobal
(
self
,
node
):
for
name
in
node
.
names
:
for
name
in
node
.
names
:
...
@@ -863,25 +862,25 @@ class LocalNameFinder:
...
@@ -863,25 +862,25 @@ class LocalNameFinder:
def
visitFunction
(
self
,
node
):
def
visitFunction
(
self
,
node
):
self
.
names
.
add
(
node
.
name
)
self
.
names
.
add
(
node
.
name
)
return
1
return
1
def
visitLambda
(
self
,
node
):
def
visitLambda
(
self
,
node
):
return
1
return
1
def
visitImport
(
self
,
node
):
def
visitImport
(
self
,
node
):
for
name
in
node
.
names
:
for
name
in
node
.
names
:
self
.
names
.
add
(
name
)
self
.
names
.
add
(
name
)
def
visitFrom
(
self
,
node
):
def
visitFrom
(
self
,
node
):
for
name
in
node
.
names
:
for
name
in
node
.
names
:
self
.
names
.
add
(
name
)
self
.
names
.
add
(
name
)
def
visitClassdef
(
self
,
node
):
def
visitClassdef
(
self
,
node
):
self
.
names
.
add
(
node
.
name
)
self
.
names
.
add
(
node
.
name
)
return
1
return
1
def
visitAssName
(
self
,
node
):
def
visitAssName
(
self
,
node
):
self
.
names
.
add
(
node
.
name
)
self
.
names
.
add
(
node
.
name
)
class
Loop
:
class
Loop
:
def
__init__
(
self
):
def
__init__
(
self
):
...
@@ -926,7 +925,13 @@ class CompiledModule:
...
@@ -926,7 +925,13 @@ class CompiledModule:
mtime
=
os
.
stat
(
self
.
filename
)[
stat
.
ST_MTIME
]
mtime
=
os
.
stat
(
self
.
filename
)[
stat
.
ST_MTIME
]
mtime
=
struct
.
pack
(
'i'
,
mtime
)
mtime
=
struct
.
pack
(
'i'
,
mtime
)
return
magic
+
mtime
return
magic
+
mtime
def
compile
(
filename
):
buf
=
open
(
filename
).
read
()
mod
=
CompiledModule
(
buf
,
filename
)
mod
.
compile
()
mod
.
dump
(
filename
+
'c'
)
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
import
getopt
import
getopt
...
@@ -945,7 +950,4 @@ if __name__ == "__main__":
...
@@ -945,7 +950,4 @@ if __name__ == "__main__":
for
filename
in
args
:
for
filename
in
args
:
if
VERBOSE
:
if
VERBOSE
:
print
filename
print
filename
buf
=
open
(
filename
).
read
()
compile
(
filename
)
mod
=
CompiledModule
(
buf
,
filename
)
mod
.
compile
()
mod
.
dump
(
filename
+
'c'
)
Tools/compiler/compiler/pycodegen.py
View file @
873bdc18
...
@@ -80,7 +80,7 @@ class ASTVisitor:
...
@@ -80,7 +80,7 @@ class ASTVisitor:
VERBOSE
=
0
VERBOSE
=
0
def
__init__
(
self
):
def
__init__
(
self
):
self
.
node
=
None
self
.
node
=
None
def
preorder
(
self
,
tree
,
visitor
):
def
preorder
(
self
,
tree
,
visitor
):
"""Do preorder walk of tree using visitor"""
"""Do preorder walk of tree using visitor"""
...
@@ -163,27 +163,26 @@ class CodeGenerator:
...
@@ -163,27 +163,26 @@ class CodeGenerator:
# XXX should clean up initialization and generateXXX funcs
# XXX should clean up initialization and generateXXX funcs
def
__init__
(
self
,
filename
=
"<?>"
):
def
__init__
(
self
,
filename
=
"<?>"
):
self
.
filename
=
filename
self
.
filename
=
filename
self
.
code
=
PyAssembler
()
self
.
code
=
PyAssembler
()
self
.
code
.
setFlags
(
0
)
self
.
code
.
setFlags
(
0
)
self
.
locals
=
misc
.
Stack
()
self
.
locals
=
misc
.
Stack
()
self
.
loops
=
misc
.
Stack
()
self
.
loops
=
misc
.
Stack
()
self
.
namespace
=
0
self
.
namespace
=
0
self
.
curStack
=
0
self
.
curStack
=
0
self
.
maxStack
=
0
self
.
maxStack
=
0
def
emit
(
self
,
*
args
):
def
emit
(
self
,
*
args
):
# XXX could just use self.emit = self.code.emit
# XXX could just use self.emit = self.code.emit
apply
(
self
.
code
.
emit
,
args
)
apply
(
self
.
code
.
emit
,
args
)
def
_generateFunctionOrLambdaCode
(
self
,
func
):
def
_generateFunctionOrLambdaCode
(
self
,
func
):
self
.
name
=
func
.
name
self
.
name
=
func
.
name
self
.
filename
=
filename
# keep a lookout for 'def foo((x,y)):'
# keep a lookout for 'def foo((x,y)):'
args
,
hasTupleArg
=
self
.
generateArglist
(
func
.
argnames
)
args
,
hasTupleArg
=
self
.
generateArglist
(
func
.
argnames
)
self
.
code
=
PyAssembler
(
args
=
args
,
name
=
func
.
name
,
self
.
code
=
PyAssembler
(
args
=
args
,
name
=
func
.
name
,
filename
=
filename
)
filename
=
self
.
filename
)
self
.
namespace
=
self
.
OPTIMIZED
self
.
namespace
=
self
.
OPTIMIZED
if
func
.
varargs
:
if
func
.
varargs
:
self
.
code
.
setVarArgs
()
self
.
code
.
setVarArgs
()
...
@@ -191,8 +190,8 @@ class CodeGenerator:
...
@@ -191,8 +190,8 @@ class CodeGenerator:
self
.
code
.
setKWArgs
()
self
.
code
.
setKWArgs
()
lnf
=
walk
(
func
.
code
,
LocalNameFinder
(
args
),
0
)
lnf
=
walk
(
func
.
code
,
LocalNameFinder
(
args
),
0
)
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
emit
(
'SET_LINENO'
,
func
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
func
.
lineno
)
if
hasTupleArg
:
if
hasTupleArg
:
self
.
generateArgUnpack
(
func
.
argnames
)
self
.
generateArgUnpack
(
func
.
argnames
)
walk
(
func
.
code
,
self
)
walk
(
func
.
code
,
self
)
...
@@ -239,7 +238,7 @@ class CodeGenerator:
...
@@ -239,7 +238,7 @@ class CodeGenerator:
def
generateClassCode
(
self
,
klass
):
def
generateClassCode
(
self
,
klass
):
self
.
code
=
PyAssembler
(
name
=
klass
.
name
,
self
.
code
=
PyAssembler
(
name
=
klass
.
name
,
filename
=
filename
)
filename
=
self
.
filename
)
self
.
emit
(
'SET_LINENO'
,
klass
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
klass
.
lineno
)
lnf
=
walk
(
klass
.
code
,
LocalNameFinder
(),
0
)
lnf
=
walk
(
klass
.
code
,
LocalNameFinder
(),
0
)
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
locals
.
push
(
lnf
.
getLocals
())
...
@@ -254,7 +253,7 @@ class CodeGenerator:
...
@@ -254,7 +253,7 @@ class CodeGenerator:
return
self
.
code
.
makeCodeObject
()
return
self
.
code
.
makeCodeObject
()
def
isLocalName
(
self
,
name
):
def
isLocalName
(
self
,
name
):
return
self
.
locals
.
top
().
has_elt
(
name
)
return
self
.
locals
.
top
().
has_elt
(
name
)
def
_nameOp
(
self
,
prefix
,
name
):
def
_nameOp
(
self
,
prefix
,
name
):
if
self
.
isLocalName
(
name
):
if
self
.
isLocalName
(
name
):
...
@@ -290,8 +289,8 @@ class CodeGenerator:
...
@@ -290,8 +289,8 @@ class CodeGenerator:
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
def
visitModule
(
self
,
node
):
def
visitModule
(
self
,
node
):
lnf
=
walk
(
node
.
node
,
LocalNameFinder
(),
0
)
lnf
=
walk
(
node
.
node
,
LocalNameFinder
(),
0
)
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
locals
.
push
(
lnf
.
getLocals
())
self
.
visit
(
node
.
node
)
self
.
visit
(
node
.
node
)
self
.
emit
(
'LOAD_CONST'
,
None
)
self
.
emit
(
'LOAD_CONST'
,
None
)
self
.
emit
(
'RETURN_VALUE'
)
self
.
emit
(
'RETURN_VALUE'
)
...
@@ -353,15 +352,15 @@ class CodeGenerator:
...
@@ -353,15 +352,15 @@ class CodeGenerator:
kw
=
0
kw
=
0
if
hasattr
(
node
,
'lineno'
):
if
hasattr
(
node
,
'lineno'
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
visit
(
node
.
node
)
self
.
visit
(
node
.
node
)
for
arg
in
node
.
args
:
for
arg
in
node
.
args
:
self
.
visit
(
arg
)
self
.
visit
(
arg
)
if
isinstance
(
arg
,
ast
.
Keyword
):
if
isinstance
(
arg
,
ast
.
Keyword
):
kw
=
kw
+
1
kw
=
kw
+
1
else
:
else
:
pos
=
pos
+
1
pos
=
pos
+
1
self
.
emit
(
'CALL_FUNCTION'
,
kw
<<
8
|
pos
)
self
.
emit
(
'CALL_FUNCTION'
,
kw
<<
8
|
pos
)
return
1
return
1
def
visitKeyword
(
self
,
node
):
def
visitKeyword
(
self
,
node
):
self
.
emit
(
'LOAD_CONST'
,
node
.
name
)
self
.
emit
(
'LOAD_CONST'
,
node
.
name
)
...
@@ -369,24 +368,24 @@ class CodeGenerator:
...
@@ -369,24 +368,24 @@ class CodeGenerator:
return
1
return
1
def
visitIf
(
self
,
node
):
def
visitIf
(
self
,
node
):
after
=
StackRef
()
after
=
StackRef
()
for
test
,
suite
in
node
.
tests
:
for
test
,
suite
in
node
.
tests
:
if
hasattr
(
test
,
'lineno'
):
if
hasattr
(
test
,
'lineno'
):
self
.
emit
(
'SET_LINENO'
,
test
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
test
.
lineno
)
else
:
else
:
print
"warning"
,
"no line number"
print
"warning"
,
"no line number"
self
.
visit
(
test
)
self
.
visit
(
test
)
dest
=
StackRef
()
dest
=
StackRef
()
self
.
emit
(
'JUMP_IF_FALSE'
,
dest
)
self
.
emit
(
'JUMP_IF_FALSE'
,
dest
)
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
self
.
visit
(
suite
)
self
.
visit
(
suite
)
self
.
emit
(
'JUMP_FORWARD'
,
after
)
self
.
emit
(
'JUMP_FORWARD'
,
after
)
dest
.
bind
(
self
.
code
.
getCurInst
())
dest
.
bind
(
self
.
code
.
getCurInst
())
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
if
node
.
else_
:
if
node
.
else_
:
self
.
visit
(
node
.
else_
)
self
.
visit
(
node
.
else_
)
after
.
bind
(
self
.
code
.
getCurInst
())
after
.
bind
(
self
.
code
.
getCurInst
())
return
1
return
1
def
startLoop
(
self
):
def
startLoop
(
self
):
l
=
Loop
()
l
=
Loop
()
...
@@ -516,64 +515,64 @@ class CodeGenerator:
...
@@ -516,64 +515,64 @@ class CodeGenerator:
return
1
return
1
def
visitCompare
(
self
,
node
):
def
visitCompare
(
self
,
node
):
"""Comment from compile.c follows:
"""Comment from compile.c follows:
The following code is generated for all but the last
The following code is generated for all but the last
comparison in a chain:
comparison in a chain:
label: on stack: opcode:
jump to:
label: on stack: opcode:
jump to:
a
<code to load b>
a
<code to load b>
a, b
DUP_TOP
a, b
DUP_TOP
a, b, b
ROT_THREE
a, b, b
ROT_THREE
b, a, b
COMPARE_OP
b, a, b
COMPARE_OP
b, 0-or-1 JUMP_IF_FALSE
L1
b, 0-or-1 JUMP_IF_FALSE
L1
b, 1
POP_TOP
b, 1
POP_TOP
b
b
We are now ready to repeat this sequence for the next
We are now ready to repeat this sequence for the next
comparison in the chain.
comparison in the chain.
For the last we generate:
For the last we generate:
b
<code to load c>
b
<code to load c>
b, c
COMPARE_OP
b, c
COMPARE_OP
0-or-1
0-or-1
If there were any jumps to L1 (i.e., there was more than one
If there were any jumps to L1 (i.e., there was more than one
comparison), we generate:
comparison), we generate:
0-or-1 JUMP_FORWARD
L2
0-or-1 JUMP_FORWARD
L2
L1: b, 0
ROT_TWO
L1: b, 0
ROT_TWO
0, b
POP_TOP
0, b
POP_TOP
0
0
L2:
0-or-1
L2:
0-or-1
"""
"""
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
# if refs are never emitted, subsequent bind call has no effect
# if refs are never emitted, subsequent bind call has no effect
l1
=
StackRef
()
l1
=
StackRef
()
l2
=
StackRef
()
l2
=
StackRef
()
for
op
,
code
in
node
.
ops
[:
-
1
]:
for
op
,
code
in
node
.
ops
[:
-
1
]:
# emit every comparison except the last
# emit every comparison except the last
self
.
visit
(
code
)
self
.
visit
(
code
)
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'ROT_THREE'
)
self
.
emit
(
'ROT_THREE'
)
self
.
emit
(
'COMPARE_OP'
,
op
)
self
.
emit
(
'COMPARE_OP'
,
op
)
# dupTop and compareOp cancel stack effect
# dupTop and compareOp cancel stack effect
self
.
emit
(
'JUMP_IF_FALSE'
,
l1
)
self
.
emit
(
'JUMP_IF_FALSE'
,
l1
)
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
if
node
.
ops
:
if
node
.
ops
:
# emit the last comparison
# emit the last comparison
op
,
code
=
node
.
ops
[
-
1
]
op
,
code
=
node
.
ops
[
-
1
]
self
.
visit
(
code
)
self
.
visit
(
code
)
self
.
emit
(
'COMPARE_OP'
,
op
)
self
.
emit
(
'COMPARE_OP'
,
op
)
if
len
(
node
.
ops
)
>
1
:
if
len
(
node
.
ops
)
>
1
:
self
.
emit
(
'JUMP_FORWARD'
,
l2
)
self
.
emit
(
'JUMP_FORWARD'
,
l2
)
l1
.
bind
(
self
.
code
.
getCurInst
())
l1
.
bind
(
self
.
code
.
getCurInst
())
self
.
emit
(
'ROT_TWO'
)
self
.
emit
(
'ROT_TWO'
)
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
l2
.
bind
(
self
.
code
.
getCurInst
())
l2
.
bind
(
self
.
code
.
getCurInst
())
return
1
return
1
def
visitGetattr
(
self
,
node
):
def
visitGetattr
(
self
,
node
):
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
...
@@ -590,7 +589,7 @@ class CodeGenerator:
...
@@ -590,7 +589,7 @@ class CodeGenerator:
self
.
emit
(
'BINARY_SUBSCR'
)
self
.
emit
(
'BINARY_SUBSCR'
)
elif
node
.
flags
==
'OP_ASSIGN'
:
elif
node
.
flags
==
'OP_ASSIGN'
:
self
.
emit
(
'STORE_SUBSCR'
)
self
.
emit
(
'STORE_SUBSCR'
)
elif
node
.
flags
==
'OP_DELETE'
:
elif
node
.
flags
==
'OP_DELETE'
:
self
.
emit
(
'DELETE_SUBSCR'
)
self
.
emit
(
'DELETE_SUBSCR'
)
return
1
return
1
...
@@ -624,11 +623,11 @@ class CodeGenerator:
...
@@ -624,11 +623,11 @@ class CodeGenerator:
def
visitAssign
(
self
,
node
):
def
visitAssign
(
self
,
node
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
dups
=
len
(
node
.
nodes
)
-
1
dups
=
len
(
node
.
nodes
)
-
1
for
i
in
range
(
len
(
node
.
nodes
)):
for
i
in
range
(
len
(
node
.
nodes
)):
elt
=
node
.
nodes
[
i
]
elt
=
node
.
nodes
[
i
]
if
i
<
dups
:
if
i
<
dups
:
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'DUP_TOP'
)
if
isinstance
(
elt
,
ast
.
Node
):
if
isinstance
(
elt
,
ast
.
Node
):
self
.
visit
(
elt
)
self
.
visit
(
elt
)
return
1
return
1
...
@@ -659,10 +658,10 @@ class CodeGenerator:
...
@@ -659,10 +658,10 @@ class CodeGenerator:
visitAssList
=
visitAssTuple
visitAssList
=
visitAssTuple
def
binaryOp
(
self
,
node
,
op
):
def
binaryOp
(
self
,
node
,
op
):
self
.
visit
(
node
.
left
)
self
.
visit
(
node
.
left
)
self
.
visit
(
node
.
right
)
self
.
visit
(
node
.
right
)
self
.
emit
(
op
)
self
.
emit
(
op
)
return
1
return
1
def
unaryOp
(
self
,
node
,
op
):
def
unaryOp
(
self
,
node
,
op
):
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
...
@@ -670,28 +669,28 @@ class CodeGenerator:
...
@@ -670,28 +669,28 @@ class CodeGenerator:
return
1
return
1
def
visitAdd
(
self
,
node
):
def
visitAdd
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_ADD'
)
return
self
.
binaryOp
(
node
,
'BINARY_ADD'
)
def
visitSub
(
self
,
node
):
def
visitSub
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_SUBTRACT'
)
return
self
.
binaryOp
(
node
,
'BINARY_SUBTRACT'
)
def
visitMul
(
self
,
node
):
def
visitMul
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_MULTIPLY'
)
return
self
.
binaryOp
(
node
,
'BINARY_MULTIPLY'
)
def
visitDiv
(
self
,
node
):
def
visitDiv
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_DIVIDE'
)
return
self
.
binaryOp
(
node
,
'BINARY_DIVIDE'
)
def
visitMod
(
self
,
node
):
def
visitMod
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_MODULO'
)
return
self
.
binaryOp
(
node
,
'BINARY_MODULO'
)
def
visitPower
(
self
,
node
):
def
visitPower
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_POWER'
)
return
self
.
binaryOp
(
node
,
'BINARY_POWER'
)
def
visitLeftShift
(
self
,
node
):
def
visitLeftShift
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_LSHIFT'
)
return
self
.
binaryOp
(
node
,
'BINARY_LSHIFT'
)
def
visitRightShift
(
self
,
node
):
def
visitRightShift
(
self
,
node
):
return
self
.
binaryOp
(
node
,
'BINARY_RSHIFT'
)
return
self
.
binaryOp
(
node
,
'BINARY_RSHIFT'
)
def
visitInvert
(
self
,
node
):
def
visitInvert
(
self
,
node
):
return
self
.
unaryOp
(
node
,
'UNARY_INVERT'
)
return
self
.
unaryOp
(
node
,
'UNARY_INVERT'
)
...
@@ -712,20 +711,20 @@ class CodeGenerator:
...
@@ -712,20 +711,20 @@ class CodeGenerator:
return
self
.
unaryOp
(
node
,
'UNARY_CONVERT'
)
return
self
.
unaryOp
(
node
,
'UNARY_CONVERT'
)
def
bitOp
(
self
,
nodes
,
op
):
def
bitOp
(
self
,
nodes
,
op
):
self
.
visit
(
nodes
[
0
])
self
.
visit
(
nodes
[
0
])
for
node
in
nodes
[
1
:]:
for
node
in
nodes
[
1
:]:
self
.
visit
(
node
)
self
.
visit
(
node
)
self
.
emit
(
op
)
self
.
emit
(
op
)
return
1
return
1
def
visitBitand
(
self
,
node
):
def
visitBitand
(
self
,
node
):
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_AND'
)
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_AND'
)
def
visitBitor
(
self
,
node
):
def
visitBitor
(
self
,
node
):
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_OR'
)
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_OR'
)
def
visitBitxor
(
self
,
node
):
def
visitBitxor
(
self
,
node
):
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_XOR'
)
return
self
.
bitOp
(
node
.
nodes
,
'BINARY_XOR'
)
def
visitTest
(
self
,
node
,
jump
):
def
visitTest
(
self
,
node
,
jump
):
end
=
StackRef
()
end
=
StackRef
()
...
@@ -738,22 +737,22 @@ class CodeGenerator:
...
@@ -738,22 +737,22 @@ class CodeGenerator:
return
1
return
1
def
visitAssert
(
self
,
node
):
def
visitAssert
(
self
,
node
):
# XXX __debug__ and AssertionError appear to be special cases
# XXX __debug__ and AssertionError appear to be special cases
# -- they are always loaded as globals even if there are local
# -- they are always loaded as globals even if there are local
# names. I guess this is a sort of renaming op.
# names. I guess this is a sort of renaming op.
skip
=
StackRef
()
skip
=
StackRef
()
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'LOAD_GLOBAL'
,
'__debug__'
)
self
.
emit
(
'LOAD_GLOBAL'
,
'__debug__'
)
self
.
emit
(
'JUMP_IF_FALSE'
,
skip
)
self
.
emit
(
'JUMP_IF_FALSE'
,
skip
)
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
self
.
visit
(
node
.
test
)
self
.
visit
(
node
.
test
)
self
.
emit
(
'JUMP_IF_TRUE'
,
skip
)
self
.
emit
(
'JUMP_IF_TRUE'
,
skip
)
self
.
emit
(
'LOAD_GLOBAL'
,
'AssertionError'
)
self
.
emit
(
'LOAD_GLOBAL'
,
'AssertionError'
)
self
.
visit
(
node
.
fail
)
self
.
visit
(
node
.
fail
)
self
.
emit
(
'RAISE_VARARGS'
,
2
)
self
.
emit
(
'RAISE_VARARGS'
,
2
)
skip
.
bind
(
self
.
code
.
getCurInst
())
skip
.
bind
(
self
.
code
.
getCurInst
())
self
.
emit
(
'POP_TOP'
)
self
.
emit
(
'POP_TOP'
)
return
1
return
1
def
visitAnd
(
self
,
node
):
def
visitAnd
(
self
,
node
):
return
self
.
visitTest
(
node
,
'JUMP_IF_FALSE'
)
return
self
.
visitTest
(
node
,
'JUMP_IF_FALSE'
)
...
@@ -765,12 +764,12 @@ class CodeGenerator:
...
@@ -765,12 +764,12 @@ class CodeGenerator:
self
.
loadName
(
node
.
name
)
self
.
loadName
(
node
.
name
)
def
visitConst
(
self
,
node
):
def
visitConst
(
self
,
node
):
self
.
emit
(
'LOAD_CONST'
,
node
.
value
)
self
.
emit
(
'LOAD_CONST'
,
node
.
value
)
return
1
return
1
def
visitEllipsis
(
self
,
node
):
def
visitEllipsis
(
self
,
node
):
self
.
emit
(
'LOAD_CONST'
,
Ellipsis
)
self
.
emit
(
'LOAD_CONST'
,
Ellipsis
)
return
1
return
1
def
visitTuple
(
self
,
node
):
def
visitTuple
(
self
,
node
):
for
elt
in
node
.
nodes
:
for
elt
in
node
.
nodes
:
...
@@ -785,76 +784,76 @@ class CodeGenerator:
...
@@ -785,76 +784,76 @@ class CodeGenerator:
return
1
return
1
def
visitDict
(
self
,
node
):
def
visitDict
(
self
,
node
):
self
.
emit
(
'BUILD_MAP'
,
0
)
self
.
emit
(
'BUILD_MAP'
,
0
)
for
k
,
v
in
node
.
items
:
for
k
,
v
in
node
.
items
:
# XXX need to add set lineno when there aren't constants
# XXX need to add set lineno when there aren't constants
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'DUP_TOP'
)
self
.
visit
(
v
)
self
.
visit
(
v
)
self
.
emit
(
'ROT_TWO'
)
self
.
emit
(
'ROT_TWO'
)
self
.
visit
(
k
)
self
.
visit
(
k
)
self
.
emit
(
'STORE_SUBSCR'
)
self
.
emit
(
'STORE_SUBSCR'
)
return
1
return
1
def
visitReturn
(
self
,
node
):
def
visitReturn
(
self
,
node
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
visit
(
node
.
value
)
self
.
visit
(
node
.
value
)
self
.
emit
(
'RETURN_VALUE'
)
self
.
emit
(
'RETURN_VALUE'
)
return
1
return
1
def
visitRaise
(
self
,
node
):
def
visitRaise
(
self
,
node
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
n
=
0
n
=
0
if
node
.
expr1
:
if
node
.
expr1
:
self
.
visit
(
node
.
expr1
)
self
.
visit
(
node
.
expr1
)
n
=
n
+
1
n
=
n
+
1
if
node
.
expr2
:
if
node
.
expr2
:
self
.
visit
(
node
.
expr2
)
self
.
visit
(
node
.
expr2
)
n
=
n
+
1
n
=
n
+
1
if
node
.
expr3
:
if
node
.
expr3
:
self
.
visit
(
node
.
expr3
)
self
.
visit
(
node
.
expr3
)
n
=
n
+
1
n
=
n
+
1
self
.
emit
(
'RAISE_VARARGS'
,
n
)
self
.
emit
(
'RAISE_VARARGS'
,
n
)
return
1
return
1
def
visitPrint
(
self
,
node
):
def
visitPrint
(
self
,
node
):
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
self
.
emit
(
'SET_LINENO'
,
node
.
lineno
)
for
child
in
node
.
nodes
:
for
child
in
node
.
nodes
:
self
.
visit
(
child
)
self
.
visit
(
child
)
self
.
emit
(
'PRINT_ITEM'
)
self
.
emit
(
'PRINT_ITEM'
)
return
1
return
1
def
visitPrintnl
(
self
,
node
):
def
visitPrintnl
(
self
,
node
):
self
.
visitPrint
(
node
)
self
.
visitPrint
(
node
)
self
.
emit
(
'PRINT_NEWLINE'
)
self
.
emit
(
'PRINT_NEWLINE'
)
return
1
return
1
def
visitExec
(
self
,
node
):
def
visitExec
(
self
,
node
):
self
.
visit
(
node
.
expr
)
self
.
visit
(
node
.
expr
)
if
node
.
locals
is
None
:
if
node
.
locals
is
None
:
self
.
emit
(
'LOAD_CONST'
,
None
)
self
.
emit
(
'LOAD_CONST'
,
None
)
else
:
else
:
self
.
visit
(
node
.
locals
)
self
.
visit
(
node
.
locals
)
if
node
.
globals
is
None
:
if
node
.
globals
is
None
:
self
.
emit
(
'DUP_TOP'
)
self
.
emit
(
'DUP_TOP'
)
else
:
else
:
self
.
visit
(
node
.
globals
)
self
.
visit
(
node
.
globals
)
self
.
emit
(
'EXEC_STMT'
)
self
.
emit
(
'EXEC_STMT'
)
class
LocalNameFinder
:
class
LocalNameFinder
:
def
__init__
(
self
,
names
=
()):
def
__init__
(
self
,
names
=
()):
self
.
names
=
misc
.
Set
()
self
.
names
=
misc
.
Set
()
self
.
globals
=
misc
.
Set
()
self
.
globals
=
misc
.
Set
()
for
name
in
names
:
for
name
in
names
:
self
.
names
.
add
(
name
)
self
.
names
.
add
(
name
)
def
getLocals
(
self
):
def
getLocals
(
self
):
for
elt
in
self
.
globals
.
items
():
for
elt
in
self
.
globals
.
items
():
if
self
.
names
.
has_elt
(
elt
):
if
self
.
names
.
has_elt
(
elt
):
self
.
names
.
remove
(
elt
)
self
.
names
.
remove
(
elt
)
return
self
.
names
return
self
.
names
def
visitDict
(
self
,
node
):
def
visitDict
(
self
,
node
):
return
1
return
1
def
visitGlobal
(
self
,
node
):
def
visitGlobal
(
self
,
node
):
for
name
in
node
.
names
:
for
name
in
node
.
names
:
...
@@ -863,25 +862,25 @@ class LocalNameFinder:
...
@@ -863,25 +862,25 @@ class LocalNameFinder:
def
visitFunction
(
self
,
node
):
def
visitFunction
(
self
,
node
):
self
.
names
.
add
(
node
.
name
)
self
.
names
.
add
(
node
.
name
)
return
1
return
1
def
visitLambda
(
self
,
node
):
def
visitLambda
(
self
,
node
):
return
1
return
1
def
visitImport
(
self
,
node
):
def
visitImport
(
self
,
node
):
for
name
in
node
.
names
:
for
name
in
node
.
names
:
self
.
names
.
add
(
name
)
self
.
names
.
add
(
name
)
def
visitFrom
(
self
,
node
):
def
visitFrom
(
self
,
node
):
for
name
in
node
.
names
:
for
name
in
node
.
names
:
self
.
names
.
add
(
name
)
self
.
names
.
add
(
name
)
def
visitClassdef
(
self
,
node
):
def
visitClassdef
(
self
,
node
):
self
.
names
.
add
(
node
.
name
)
self
.
names
.
add
(
node
.
name
)
return
1
return
1
def
visitAssName
(
self
,
node
):
def
visitAssName
(
self
,
node
):
self
.
names
.
add
(
node
.
name
)
self
.
names
.
add
(
node
.
name
)
class
Loop
:
class
Loop
:
def
__init__
(
self
):
def
__init__
(
self
):
...
@@ -926,7 +925,13 @@ class CompiledModule:
...
@@ -926,7 +925,13 @@ class CompiledModule:
mtime
=
os
.
stat
(
self
.
filename
)[
stat
.
ST_MTIME
]
mtime
=
os
.
stat
(
self
.
filename
)[
stat
.
ST_MTIME
]
mtime
=
struct
.
pack
(
'i'
,
mtime
)
mtime
=
struct
.
pack
(
'i'
,
mtime
)
return
magic
+
mtime
return
magic
+
mtime
def
compile
(
filename
):
buf
=
open
(
filename
).
read
()
mod
=
CompiledModule
(
buf
,
filename
)
mod
.
compile
()
mod
.
dump
(
filename
+
'c'
)
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
import
getopt
import
getopt
...
@@ -945,7 +950,4 @@ if __name__ == "__main__":
...
@@ -945,7 +950,4 @@ if __name__ == "__main__":
for
filename
in
args
:
for
filename
in
args
:
if
VERBOSE
:
if
VERBOSE
:
print
filename
print
filename
buf
=
open
(
filename
).
read
()
compile
(
filename
)
mod
=
CompiledModule
(
buf
,
filename
)
mod
.
compile
()
mod
.
dump
(
filename
+
'c'
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment