Example #1
0
    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
Example #2
0
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)
Example #3
0
File: macros.py Project: munk/hy
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)
Example #4
0
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)
Example #5
0
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)
Example #6
0
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)
Example #7
0
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
Example #8
0
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