def __compile_code(self, code_string): hytree = hy.lex.tokenize(code_string) module_name = '__main__' foo = HyObject() foo.start_line = 0 foo.end_line = 0 foo.start_column = 0 foo.end_column = 0 replace_hy_obj(hytree, foo) if not isinstance(module_name, string_types): raise HyTypeError(foo, "Module name must be a string") _ast, expr = hy_compile(hytree, module_name, get_expr=True) # Spoof the positions in the generated ast... for node in ast.walk(_ast): node.lineno = 1 node.col_offset = 1 for node in ast.walk(expr): node.lineno = 1 node.col_offset = 1 return _ast, expr
def tag_macroexpand(tag, tree, compiler): """Expand the tag macro "tag" with argument `tree`.""" load_macros(compiler.module_name) tag_macro = _hy_tag[compiler.module_name].get(tag) if tag_macro is None: try: tag_macro = _hy_tag[None][tag] except KeyError: raise HyTypeError(tag, "`{0}' is not a defined tag macro.".format(tag)) expr = tag_macro(tree) return replace_hy_obj(expr, tree)
def sharp_macroexpand(char, tree, compiler): """Expand the sharp macro "char" with argument `tree`.""" load_macros(compiler.module_name) sharp_macro = _hy_sharp[compiler.module_name].get(char) if sharp_macro is None: try: sharp_macro = _hy_sharp[None][char] except KeyError: raise HyTypeError( char, "`{0}' is not a defined sharp macro.".format(char)) expr = sharp_macro(tree) return replace_hy_obj(wrap_value(expr), tree)
def reader_macroexpand(char, tree, module_name): """Expand the reader macro "char" with argument `tree`.""" load_macros(module_name) reader_macro = _hy_reader[module_name].get(char) if reader_macro is None: try: reader_macro = _hy_reader[None][char] except KeyError: raise HyTypeError( char, "`{0}' is not a defined reader macro.".format(char)) expr = reader_macro(tree) return replace_hy_obj(wrap_value(expr), tree)
def reader_macroexpand(char, tree, module_name): """Expand the reader macro "char" with argument `tree`.""" load_macros(module_name) if char not in _hy_reader[module_name]: raise HyTypeError( char, "`{0}' is not a reader macro in module '{1}'".format( char, module_name, ), ) expr = _hy_reader[module_name][char](tree) return _wrap_value(expr).replace(tree)
def tag_macroexpand(tag, tree, module): """Expand the tag macro `tag` with argument `tree`.""" if not inspect.ismodule(module): module = importlib.import_module(module) expr_modules = (([] if not hasattr(tree, 'module') else [tree.module]) + [module]) # Choose the first namespace with the macro. tag_macro = next((mod.__tags__[tag] for mod in expr_modules if tag in mod.__tags__), None) if tag_macro is None: raise HyTypeError(tag, "'{0}' is not a defined tag macro.".format(tag)) expr = tag_macro(tree) if isinstance(expr, HyExpression): expr.module = inspect.getmodule(tag_macro) return replace_hy_obj(expr, tree)
def require(source_module, target_module, assignments, prefix=""): """Load macros from one module into the namespace of another. This function is called from the `require` special form in the compiler. Parameters ---------- source_module: str or types.ModuleType The module from which macros are to be imported. target_module: str, types.ModuleType or None The module into which the macros will be loaded. If `None`, then the caller's namespace. The latter is useful during evaluation of generated AST/bytecode. assignments: str or list of tuples of strs The string "ALL" or a list of macro name and alias pairs. prefix: str, optional ("") If nonempty, its value is prepended to the name of each imported macro. This allows one to emulate namespaced macros, like "mymacromodule.mymacro", which looks like an attribute of a module. Returns ------- out: boolean Whether or not macros and tags were actually transferred. """ if target_module is None: parent_frame = inspect.stack()[1][0] target_namespace = parent_frame.f_globals target_module = target_namespace.get('__name__', None) elif isinstance(target_module, str): target_module = importlib.import_module(target_module) target_namespace = target_module.__dict__ elif inspect.ismodule(target_module): target_namespace = target_module.__dict__ else: raise HyTypeError( '`target_module` is not a recognized type: {}'.format( type(target_module))) # Let's do a quick check to make sure the source module isn't actually # the module being compiled (e.g. when `runpy` executes a module's code # in `__main__`). # We use the module's underlying filename for this (when they exist), since # it's the most "fixed" attribute. if _same_modules(source_module, target_module): return False if not inspect.ismodule(source_module): try: source_module = importlib.import_module(source_module) except ImportError as e: reraise(HyRequireError, HyRequireError(e.args[0]), None) source_macros = source_module.__dict__.setdefault('__macros__', {}) source_tags = source_module.__dict__.setdefault('__tags__', {}) if len(source_module.__macros__) + len(source_module.__tags__) == 0: if assignments != "ALL": raise HyRequireError( 'The module {} has no macros or tags'.format(source_module)) else: return False target_macros = target_namespace.setdefault('__macros__', {}) target_tags = target_namespace.setdefault('__tags__', {}) if prefix: prefix += "." if assignments == "ALL": name_assigns = [ (k, k) for k in tuple(source_macros.keys()) + tuple(source_tags.keys()) ] else: name_assigns = assignments for name, alias in name_assigns: _name = mangle(name) alias = mangle(prefix + alias) if _name in source_module.__macros__: target_macros[alias] = source_macros[_name] elif _name in source_module.__tags__: target_tags[alias] = source_tags[_name] else: raise HyRequireError('Could not require name {} from {}'.format( _name, source_module)) return True
def require(source_module, target_module, assignments, prefix=""): """Load macros from one module into the namespace of another. This function is called from the `require` special form in the compiler. Parameters ---------- source_module: str or types.ModuleType The module from which macros are to be imported. target_module: str, types.ModuleType or None The module into which the macros will be loaded. If `None`, then the caller's namespace. The latter is useful during evaluation of generated AST/bytecode. assignments: str or list of tuples of strs The string "ALL" or a list of macro name and alias pairs. prefix: str, optional ("") If nonempty, its value is prepended to the name of each imported macro. This allows one to emulate namespaced macros, like "mymacromodule.mymacro", which looks like an attribute of a module. Returns ------- out: boolean Whether or not macros were actually transferred. """ if target_module is None: parent_frame = inspect.stack()[1][0] target_namespace = parent_frame.f_globals target_module = target_namespace.get('__name__', None) elif isinstance(target_module, str): target_module = importlib.import_module(target_module) target_namespace = target_module.__dict__ elif inspect.ismodule(target_module): target_namespace = target_module.__dict__ else: raise HyTypeError( '`target_module` is not a recognized type: {}'.format( type(target_module))) # Let's do a quick check to make sure the source module isn't actually # the module being compiled (e.g. when `runpy` executes a module's code # in `__main__`). # We use the module's underlying filename for this (when they exist), since # it's the most "fixed" attribute. if _same_modules(source_module, target_module): return False if not inspect.ismodule(source_module): try: if source_module.startswith("."): source_dirs = source_module.split(".") target_dirs = (getattr(target_module, "__name__", target_module).split(".")) while (len(source_dirs) > 1 and source_dirs[0] == "" and target_dirs): source_dirs.pop(0) target_dirs.pop() package = ".".join(target_dirs + source_dirs[:-1]) else: package = None source_module = importlib.import_module(source_module, package) except ImportError as e: raise HyRequireError(e.args[0]).with_traceback(None) source_macros = source_module.__dict__.setdefault('__macros__', {}) if not source_module.__macros__: if assignments != "ALL": for name, alias in assignments: try: require(f"{source_module.__name__}.{mangle(name)}", target_module, "ALL", prefix=alias) except HyRequireError as e: raise HyRequireError(f"Cannot import name '{name}'" f" from '{source_module.__name__}'" f" ({source_module.__file__})") return True else: return False target_macros = target_namespace.setdefault('__macros__', {}) if prefix: prefix += "." if assignments == "ALL": name_assigns = [(k, k) for k in source_macros.keys()] else: name_assigns = assignments for name, alias in name_assigns: _name = mangle(name) alias = mangle('#' + prefix + unmangle(alias)[1:] if unmangle(alias). startswith('#') else prefix + alias) if _name in source_module.__macros__: target_macros[alias] = source_macros[_name] else: raise HyRequireError('Could not require name {} from {}'.format( _name, source_module)) return True