13
13
14
14
from hy .lex import mangle , unmangle
15
15
16
- import hy .macros
17
- from hy ._compat import (
18
- str_type , bytes_type , long_type , PY3 , PY35 , raise_empty )
19
- from hy .macros import requiref , macroexpand , tag_macroexpand
16
+ from hy ._compat import (str_type , string_types , bytes_type , long_type , PY3 ,
17
+ PY35 , raise_empty )
18
+ from hy .macros import requiref , load_macros , macroexpand , tag_macroexpand
20
19
import hy .importer
21
20
22
21
import traceback
23
22
import importlib
23
+ import inspect
24
+ import pkgutil
25
+ import types
24
26
import ast
25
27
import sys
26
28
import copy
@@ -283,28 +285,45 @@ def is_unpack(kind, x):
283
285
284
286
285
287
class HyASTCompiler (object ):
288
+ """A Hy-to-Python AST compiler"""
286
289
287
- def __init__ (self , module_name ):
290
+ def __init__ (self , module ):
291
+ """
292
+ Parameters
293
+ ----------
294
+ module: str or types.ModuleType
295
+ Module in which the Hy tree is evaluated.
296
+ """
288
297
self .anon_var_count = 0
289
298
self .imports = defaultdict (set )
290
- self .module_name = module_name
291
299
self .temp_if = None
300
+
301
+ if not inspect .ismodule (module ):
302
+ module = importlib .import_module (module )
303
+
304
+ self .module = module
305
+ self .module_name = module .__name__
306
+
292
307
self .can_use_stdlib = (
293
- not module_name .startswith ("hy.core" )
294
- or module_name == "hy.core.macros" )
308
+ not self .module_name .startswith ("hy.core" )
309
+ or self .module_name == "hy.core.macros" )
310
+
311
+ # Load stdlib macros into the module namespace.
312
+ load_macros (self .module )
313
+
295
314
# Everything in core needs to be explicit (except for
296
315
# the core macros, which are built with the core functions).
297
316
if self .can_use_stdlib and not _stdlib :
298
317
# Populate _stdlib.
299
318
import hy .core
300
- for module in hy .core .STDLIB :
301
- mod = importlib .import_module (module )
302
- for e in map (ast_str , mod . EXPORTS ):
319
+ for stdlib_module in hy .core .STDLIB :
320
+ mod = importlib .import_module (stdlib_module )
321
+ for e in map (ast_str , getattr ( mod , ' EXPORTS' , []) ):
303
322
if getattr (mod , e ) is not getattr (builtins , e , '' ):
304
323
# Don't bother putting a name in _stdlib if it
305
324
# points to a builtin with the same name. This
306
325
# prevents pointless imports.
307
- _stdlib [e ] = module
326
+ _stdlib [e ] = stdlib_module
308
327
309
328
def get_anon_var (self ):
310
329
self .anon_var_count += 1
@@ -1098,11 +1117,6 @@ def compile_unary_operator(self, expr, root, arg):
1098
1117
brackets (SYM , sym (":as" ), _symn ) |
1099
1118
brackets (SYM , brackets (many (_symn + maybe (sym (":as" ) + _symn )))))])
1100
1119
def compile_import_or_require (self , expr , root , entries ):
1101
- """
1102
- TODO for `require`: keep track of what we've imported in this run and
1103
- then "unimport" it after we've completed `thing' so that we don't
1104
- pollute other envs.
1105
- """
1106
1120
ret = Result ()
1107
1121
1108
1122
for entry in entries :
@@ -1128,8 +1142,9 @@ def compile_import_or_require(self, expr, root, entries):
1128
1142
else :
1129
1143
assignments = [(k , v or k ) for k , v in kids ]
1130
1144
1145
+ ast_module = ast_str (module , piecewise = True )
1146
+
1131
1147
if root == "import" :
1132
- ast_module = ast_str (module , piecewise = True )
1133
1148
module = ast_module .lstrip ("." )
1134
1149
level = len (ast_module ) - len (module )
1135
1150
if assignments == "ALL" and prefix == "" :
@@ -1150,10 +1165,23 @@ def compile_import_or_require(self, expr, root, entries):
1150
1165
for k , v in assignments ]
1151
1166
ret += node (
1152
1167
expr , module = module or None , names = names , level = level )
1153
- else : # root == "require"
1154
- importlib .import_module (module )
1155
- requiref (module , self .module_name ,
1156
- assignments = assignments , prefix = prefix )
1168
+
1169
+ elif requiref (ast_module , self .module , assignments = assignments ,
1170
+ prefix = prefix ):
1171
+ # Actually calling `require` is necessary for macro expansions
1172
+ # occurring during compilation.
1173
+ self .imports ['hy.macros' ].update (['requiref' ])
1174
+ # The `require` we're creating in AST is the same as above, but used at
1175
+ # run-time (e.g. when modules are loaded via bytecode).
1176
+ ret += self .compile (HyExpression ([
1177
+ HySymbol ('requiref' ),
1178
+ HyString (ast_module ),
1179
+ HySymbol ('None' ),
1180
+ HyKeyword ('assignments' ),
1181
+ (HyString ("ALL" ) if assignments == "ALL" else
1182
+ [[HyString (k ), HyString (v )] for k , v in assignments ]),
1183
+ HyKeyword ('prefix' ),
1184
+ HyString (prefix )]).replace (expr ))
1157
1185
1158
1186
return ret
1159
1187
@@ -1484,7 +1512,8 @@ def compile_class_expression(self, expr, root, name, rest):
1484
1512
[x for pair in attrs [0 ] for x in pair ]).replace (attrs )))
1485
1513
1486
1514
for e in body :
1487
- e = self .compile (self ._rewire_init (macroexpand (e , self )))
1515
+ e = self .compile (self ._rewire_init (
1516
+ macroexpand (e , self .module , self )))
1488
1517
bodyr += e + e .expr_as_stmt ()
1489
1518
1490
1519
return bases + asty .ClassDef (
@@ -1520,28 +1549,24 @@ def compile_dispatch_tag_macro(self, expr, root, tag, arg):
1520
1549
return self .compile (tag_macroexpand (
1521
1550
HyString (mangle (tag )).replace (tag ),
1522
1551
arg ,
1523
- self ))
1524
-
1525
- _namespaces = {}
1552
+ self .module ))
1526
1553
1527
1554
@special (["eval-and-compile" , "eval-when-compile" ], [many (FORM )])
1528
1555
def compile_eval_and_compile (self , expr , root , body ):
1529
1556
new_expr = HyExpression ([HySymbol ("do" ).replace (expr [0 ])]).replace (expr )
1530
- if self .module_name not in self ._namespaces :
1531
- # Initialize a compile-time namespace for this module.
1532
- self ._namespaces [self .module_name ] = {
1533
- 'hy' : hy , '__name__' : self .module_name }
1557
+
1534
1558
hy .importer .hy_eval (new_expr + body ,
1535
- self ._namespaces [self .module_name ],
1536
- self .module_name )
1559
+ self .module .__dict__ ,
1560
+ self .module )
1561
+
1537
1562
return (self ._compile_branch (body )
1538
1563
if ast_str (root ) == "eval_and_compile"
1539
1564
else Result ())
1540
1565
1541
1566
@builds_model (HyExpression )
1542
1567
def compile_expression (self , expr ):
1543
1568
# Perform macro expansions
1544
- expr = macroexpand (expr , self )
1569
+ expr = macroexpand (expr , self . module , self )
1545
1570
if not isinstance (expr , HyExpression ):
1546
1571
# Go through compile again if the type changed.
1547
1572
return self .compile (expr )
@@ -1699,20 +1724,41 @@ def compile_dict(self, m):
1699
1724
return ret + asty .Dict (m , keys = keyvalues [::2 ], values = keyvalues [1 ::2 ])
1700
1725
1701
1726
1702
- def hy_compile (tree , module_name , root = ast .Module , get_expr = False ):
1727
+ def hy_compile (tree , module , root = ast .Module , get_expr = False ):
1703
1728
"""
1704
- Compile a HyObject tree into a Python AST Module.
1729
+ Compile a Hy tree into a Python AST tree.
1730
+
1731
+ Parameters
1732
+ ----------
1733
+ module: str or types.ModuleType
1734
+ Module, or name of the module, in which the Hy tree is evaluated.
1705
1735
1706
- If `get_expr` is True, return a tuple (module, last_expression), where
1707
- `last_expression` is the.
1736
+ root: ast object, optional (ast.Module)
1737
+ Root object for the Python AST tree.
1738
+
1739
+ get_expr: bool, optional (False)
1740
+ If true, return a tuple with `(root_obj, last_expression)`.
1741
+
1742
+ Returns
1743
+ -------
1744
+ out : A Python AST tree
1708
1745
"""
1709
1746
1747
+ if isinstance (module , string_types ):
1748
+ if module .startswith ('<' ) and module .endswith ('>' ):
1749
+ module = types .ModuleType (module )
1750
+ else :
1751
+ module = importlib .import_module (ast_str (module , piecewise = True ))
1752
+ if not inspect .ismodule (module ):
1753
+ raise TypeError ('Invalid module type: {}' .format (type (module )))
1754
+
1755
+
1710
1756
tree = wrap_value (tree )
1711
1757
if not isinstance (tree , HyObject ):
1712
1758
raise HyCompileError ("`tree` must be a HyObject or capable of "
1713
1759
"being promoted to one" )
1714
1760
1715
- compiler = HyASTCompiler (module_name )
1761
+ compiler = HyASTCompiler (module )
1716
1762
result = compiler .compile (tree )
1717
1763
expr = result .force_expr
1718
1764
0 commit comments