From e344ac1fd62d13e05d575622b44e2028bb830498 Mon Sep 17 00:00:00 2001 From: Kodi Arfer Date: Thu, 24 May 2018 17:51:21 -0700 Subject: [PATCH] Fix the management of _stdlib _stdlib is a global variable, so core modules could use it, contrary to our intention, so long as they happened to be compiled after a non-core module. I've added a compiler attribute to track whether we can use _stdlib. This fix exposed some cases where hy.core.shadow tried to use a core function, so I fixed those. I've also added an `if not _stdlib` to `load_stdlib` so that we only bother to actually load _stdlib once. --- hy/compiler.py | 27 ++++++++++++++++----------- hy/core/shadow.hy | 14 ++++++++------ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/hy/compiler.py b/hy/compiler.py index e69fe9b78..4b109fb2d 100755 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -52,14 +52,15 @@ def compile_time_ns(module_name): def load_stdlib(): import hy.core - for module in hy.core.STDLIB: - mod = importlib.import_module(module) - for e in map(ast_str, mod.EXPORTS): - if getattr(mod, e) is not getattr(builtins, e, ''): - # Don't bother putting a name in _stdlib if it - # points to a builtin with the same name. This - # prevents pointless imports. - _stdlib[e] = module + if not _stdlib: + for module in hy.core.STDLIB: + mod = importlib.import_module(module) + for e in map(ast_str, mod.EXPORTS): + if getattr(mod, e) is not getattr(builtins, e, ''): + # Don't bother putting a name in _stdlib if it + # points to a builtin with the same name. This + # prevents pointless imports. + _stdlib[e] = module def ast_str(x, piecewise=False): @@ -355,8 +356,12 @@ def __init__(self, module_name): self.imports = defaultdict(set) self.module_name = module_name self.temp_if = None - if not module_name.startswith("hy.core"): - # everything in core needs to be explicit. + self.can_use_stdlib = ( + not module_name.startswith("hy.core") + or module_name == "hy.core.macros") + # Everything in core needs to be explicit (except for + # the core macros, which are built with the core functions). + if self.can_use_stdlib: load_stdlib() def get_anon_var(self): @@ -1698,7 +1703,7 @@ def compile_symbol(self, symbol): attr=ast_str(local), ctx=ast.Load()) - if ast_str(symbol) in _stdlib: + if self.can_use_stdlib and ast_str(symbol) in _stdlib: self.imports[_stdlib[ast_str(symbol)]].add(ast_str(symbol)) return asty.Name(symbol, id=ast_str(symbol), ctx=ast.Load()) diff --git a/hy/core/shadow.hy b/hy/core/shadow.hy index 65acb46b0..c69f344cd 100644 --- a/hy/core/shadow.hy +++ b/hy/core/shadow.hy @@ -5,8 +5,10 @@ ;;;; Hy shadow functions (import operator) -(import [hy._compat [PY35]]) +(import [hy._compat [PY3 PY35]]) +(if PY3 + (import [functools [reduce]])) (defn + [&rest args] "Shadowed `+` operator adds `args`." @@ -14,7 +16,7 @@ (= (len args) 0) 0 (= (len args) 1) - (+ (first args)) + (+ (get args 0)) ; else (reduce operator.add args))) @@ -30,7 +32,7 @@ (= (len args) 0) 1 (= (len args) 1) - (first args) + (get args 0) ; else (reduce operator.mul args))) @@ -81,7 +83,7 @@ (= (len args) 0) 0 (= (len args) 1) - (first args) + (get args 0) ; else (reduce operator.or_ args))) @@ -130,7 +132,7 @@ (= (len args) 0) True (= (len args) 1) - (first args) + (get args 0) ; else (reduce (fn [x y] (and x y)) args))) @@ -140,7 +142,7 @@ (= (len args) 0) None (= (len args) 1) - (first args) + (get args 0) ; else (reduce (fn [x y] (or x y)) args)))