Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9dca364

Browse files
committed
API change:
compile() becomes replacement for builtin compile() compileFile() generates a .pyc from a .py both are exported in __init__ compiler.parse() gets optional second argument to specify compilation mode, e.g. single, eval, exec Add AbstractCompileMode as parent class and Module, Expression, and Interactive as concrete subclasses. Each corresponds to a compilation mode. THe AbstractCompileMode instances in turn delegate to CodeGeneration subclasses specialized for their particular functions -- ModuleCodeGenerator, ExpressionCodeGeneration, InteractiveCodeGenerator.
1 parent c8ed18a commit 9dca364

6 files changed

Lines changed: 218 additions & 20 deletions

File tree

Lib/compiler/__init__.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
There are several functions defined at the top level that are imported
44
from modules contained in the package.
55
6-
parse(buf) -> AST
6+
parse(buf, mode="exec") -> AST
77
Converts a string containing Python source code to an abstract
88
syntax tree (AST). The AST is defined in compiler.ast.
99
@@ -14,11 +14,14 @@
1414
Does a pre-order walk over the ast using the visitor instance.
1515
See compiler.visitor for details.
1616
17-
compile(filename)
17+
compile(source, filename, mode, flags=None, dont_inherit=None)
18+
Returns a code object. A replacement for the builtin compile() function.
19+
20+
compileFile(filename)
1821
Generates a .pyc file by compilining filename.
1922
"""
2023

2124
from transformer import parse, parseFile
2225
from visitor import walk
23-
from pycodegen import compile
26+
from pycodegen import compile, compileFile
2427

Lib/compiler/pycodegen.py

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __init__(self):
4141
self.__super_init(self)
4242
self.loop = None
4343

44-
def compile(filename, display=0):
44+
def compileFile(filename, display=0):
4545
f = open(filename)
4646
buf = f.read()
4747
f.close()
@@ -55,16 +55,68 @@ def compile(filename, display=0):
5555
mod.dump(f)
5656
f.close()
5757

58-
class Module:
58+
def compile(source, filename, mode, flags=None, dont_inherit=None):
59+
"""Replacement for builtin compile() function"""
60+
if flags is not None or dont_inherit is not None:
61+
raise RuntimeError, "not implemented yet"
62+
63+
if mode == "single":
64+
gen = Interactive(source, filename)
65+
elif mode == "exec":
66+
gen = Module(source, filename)
67+
elif mode == "eval":
68+
gen = Expression(source, filename)
69+
else:
70+
raise ValueError("compile() 3rd arg must be 'exec' or "
71+
"'eval' or 'single'")
72+
gen.compile()
73+
return gen.code
74+
75+
class AbstractCompileMode:
76+
77+
mode = None # defined by subclass
78+
5979
def __init__(self, source, filename):
60-
self.filename = os.path.abspath(filename)
6180
self.source = source
81+
self.filename = filename
6282
self.code = None
6383

64-
def compile(self, display=0):
65-
tree = parse(self.source)
84+
def _get_tree(self):
85+
tree = parse(self.source, self.mode)
6686
misc.set_filename(self.filename, tree)
6787
syntax.check(tree)
88+
return tree
89+
90+
def compile(self):
91+
pass # implemented by subclass
92+
93+
def getCode(self):
94+
return self.code
95+
96+
class Expression(AbstractCompileMode):
97+
98+
mode = "eval"
99+
100+
def compile(self):
101+
tree = self._get_tree()
102+
gen = ExpressionCodeGenerator(tree)
103+
self.code = gen.getCode()
104+
105+
class Interactive(AbstractCompileMode):
106+
107+
mode = "single"
108+
109+
def compile(self):
110+
tree = self._get_tree()
111+
gen = InteractiveCodeGenerator(tree)
112+
self.code = gen.getCode()
113+
114+
class Module(AbstractCompileMode):
115+
116+
mode = "exec"
117+
118+
def compile(self, display=0):
119+
tree = self._get_tree()
68120
gen = ModuleCodeGenerator(tree)
69121
if display:
70122
import pprint
@@ -1097,6 +1149,44 @@ def __init__(self, tree):
10971149
def get_module(self):
10981150
return self
10991151

1152+
class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1153+
__super_init = CodeGenerator.__init__
1154+
1155+
scopes = None
1156+
futures = ()
1157+
1158+
def __init__(self, tree):
1159+
self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1160+
self.__super_init()
1161+
self.set_lineno(tree)
1162+
walk(tree, self)
1163+
self.emit('RETURN_VALUE')
1164+
1165+
def get_module(self):
1166+
return self
1167+
1168+
class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1169+
1170+
__super_init = CodeGenerator.__init__
1171+
1172+
scopes = None
1173+
futures = ()
1174+
1175+
def __init__(self, tree):
1176+
self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1177+
self.__super_init()
1178+
self.set_lineno(tree)
1179+
walk(tree, self)
1180+
self.emit('RETURN_VALUE')
1181+
1182+
def get_module(self):
1183+
return self
1184+
def visitDiscard(self, node):
1185+
# XXX Discard means it's an expression. Perhaps this is a bad
1186+
# name.
1187+
self.visit(node.expr)
1188+
self.emit('PRINT_EXPR')
1189+
11001190
class AbstractFunctionCode:
11011191
optimized = 1
11021192
lambdaCount = 0

Lib/compiler/transformer.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,14 @@ def parseFile(path):
4242
f.close()
4343
return parse(src)
4444

45-
def parse(buf):
46-
return Transformer().parsesuite(buf)
45+
def parse(buf, mode="exec"):
46+
if mode == "exec" or mode == "single":
47+
return Transformer().parsesuite(buf)
48+
elif mode == "eval":
49+
return Transformer().parseexpr(buf)
50+
else:
51+
raise ValueError("compile() arg 3 must be"
52+
" 'exec' or 'eval' or 'single'")
4753

4854
def asList(nodes):
4955
l = []

Tools/compiler/compiler/__init__.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
There are several functions defined at the top level that are imported
44
from modules contained in the package.
55
6-
parse(buf) -> AST
6+
parse(buf, mode="exec") -> AST
77
Converts a string containing Python source code to an abstract
88
syntax tree (AST). The AST is defined in compiler.ast.
99
@@ -14,11 +14,14 @@
1414
Does a pre-order walk over the ast using the visitor instance.
1515
See compiler.visitor for details.
1616
17-
compile(filename)
17+
compile(source, filename, mode, flags=None, dont_inherit=None)
18+
Returns a code object. A replacement for the builtin compile() function.
19+
20+
compileFile(filename)
1821
Generates a .pyc file by compilining filename.
1922
"""
2023

2124
from transformer import parse, parseFile
2225
from visitor import walk
23-
from pycodegen import compile
26+
from pycodegen import compile, compileFile
2427

Tools/compiler/compiler/pycodegen.py

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __init__(self):
4141
self.__super_init(self)
4242
self.loop = None
4343

44-
def compile(filename, display=0):
44+
def compileFile(filename, display=0):
4545
f = open(filename)
4646
buf = f.read()
4747
f.close()
@@ -55,16 +55,68 @@ def compile(filename, display=0):
5555
mod.dump(f)
5656
f.close()
5757

58-
class Module:
58+
def compile(source, filename, mode, flags=None, dont_inherit=None):
59+
"""Replacement for builtin compile() function"""
60+
if flags is not None or dont_inherit is not None:
61+
raise RuntimeError, "not implemented yet"
62+
63+
if mode == "single":
64+
gen = Interactive(source, filename)
65+
elif mode == "exec":
66+
gen = Module(source, filename)
67+
elif mode == "eval":
68+
gen = Expression(source, filename)
69+
else:
70+
raise ValueError("compile() 3rd arg must be 'exec' or "
71+
"'eval' or 'single'")
72+
gen.compile()
73+
return gen.code
74+
75+
class AbstractCompileMode:
76+
77+
mode = None # defined by subclass
78+
5979
def __init__(self, source, filename):
60-
self.filename = os.path.abspath(filename)
6180
self.source = source
81+
self.filename = filename
6282
self.code = None
6383

64-
def compile(self, display=0):
65-
tree = parse(self.source)
84+
def _get_tree(self):
85+
tree = parse(self.source, self.mode)
6686
misc.set_filename(self.filename, tree)
6787
syntax.check(tree)
88+
return tree
89+
90+
def compile(self):
91+
pass # implemented by subclass
92+
93+
def getCode(self):
94+
return self.code
95+
96+
class Expression(AbstractCompileMode):
97+
98+
mode = "eval"
99+
100+
def compile(self):
101+
tree = self._get_tree()
102+
gen = ExpressionCodeGenerator(tree)
103+
self.code = gen.getCode()
104+
105+
class Interactive(AbstractCompileMode):
106+
107+
mode = "single"
108+
109+
def compile(self):
110+
tree = self._get_tree()
111+
gen = InteractiveCodeGenerator(tree)
112+
self.code = gen.getCode()
113+
114+
class Module(AbstractCompileMode):
115+
116+
mode = "exec"
117+
118+
def compile(self, display=0):
119+
tree = self._get_tree()
68120
gen = ModuleCodeGenerator(tree)
69121
if display:
70122
import pprint
@@ -1097,6 +1149,44 @@ def __init__(self, tree):
10971149
def get_module(self):
10981150
return self
10991151

1152+
class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1153+
__super_init = CodeGenerator.__init__
1154+
1155+
scopes = None
1156+
futures = ()
1157+
1158+
def __init__(self, tree):
1159+
self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1160+
self.__super_init()
1161+
self.set_lineno(tree)
1162+
walk(tree, self)
1163+
self.emit('RETURN_VALUE')
1164+
1165+
def get_module(self):
1166+
return self
1167+
1168+
class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1169+
1170+
__super_init = CodeGenerator.__init__
1171+
1172+
scopes = None
1173+
futures = ()
1174+
1175+
def __init__(self, tree):
1176+
self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1177+
self.__super_init()
1178+
self.set_lineno(tree)
1179+
walk(tree, self)
1180+
self.emit('RETURN_VALUE')
1181+
1182+
def get_module(self):
1183+
return self
1184+
def visitDiscard(self, node):
1185+
# XXX Discard means it's an expression. Perhaps this is a bad
1186+
# name.
1187+
self.visit(node.expr)
1188+
self.emit('PRINT_EXPR')
1189+
11001190
class AbstractFunctionCode:
11011191
optimized = 1
11021192
lambdaCount = 0

Tools/compiler/compiler/transformer.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,14 @@ def parseFile(path):
4242
f.close()
4343
return parse(src)
4444

45-
def parse(buf):
46-
return Transformer().parsesuite(buf)
45+
def parse(buf, mode="exec"):
46+
if mode == "exec" or mode == "single":
47+
return Transformer().parsesuite(buf)
48+
elif mode == "eval":
49+
return Transformer().parseexpr(buf)
50+
else:
51+
raise ValueError("compile() arg 3 must be"
52+
" 'exec' or 'eval' or 'single'")
4753

4854
def asList(nodes):
4955
l = []

0 commit comments

Comments
 (0)