Ejemplo n.º 1
0
def macroexpand_1(tree, module_name):
    """Expand the toplevel macro from `tree` once, in the context of
    `module_name`."""
    if isinstance(tree, HyExpression):
        if tree == []:
            return tree

        fn = tree[0]
        if fn in ("quote", "quasiquote"):
            return tree
        ntree = HyExpression(tree[:])
        ntree.replace(tree)

        if isinstance(fn, HyString):
            m = _hy_macros[module_name].get(fn)
            if m is None:
                m = _hy_macros[None].get(fn)
            if m is not None:
                try:
                    obj = wrap_value(m(*ntree[1:]))

                except HyTypeError as e:
                    if e.expression is None:
                        e.expression = tree
                    raise
                except Exception as e:
                    msg = "expanding `" + str(tree[0]) + "': " + repr(e)
                    raise HyMacroExpansionError(tree, msg)
                replace_hy_obj(obj, tree)
                return obj

        return ntree
    return tree
Ejemplo n.º 2
0
def hy_eval(hytree, namespace, module_name):
    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

    if not isinstance(namespace, dict):
        raise HyTypeError(foo, "Globals must be a dictionary")

    # Two-step eval: eval() the body of the exec call
    eval(ast_compile(_ast, "<eval_body>", "exec"), namespace)

    # Then eval the expression context and return that
    return eval(ast_compile(expr, "<eval>", "eval"), namespace)
Ejemplo n.º 3
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
Ejemplo n.º 4
0
def macroexpand_1(tree, module_name):
    """Expand the toplevel macro from `tree` once, in the context of
    `module_name`."""
    if isinstance(tree, HyExpression):
        if tree == []:
            return tree

        fn = tree[0]
        if fn in ("quote", "quasiquote"):
            return tree
        ntree = HyExpression(tree[:])
        ntree.replace(tree)

        if isinstance(fn, HyString):
            m = _hy_macros[module_name].get(fn)
            if m is None:
                m = _hy_macros[None].get(fn)
            if m is not None:
                try:
                    obj = wrap_value(m(*ntree[1:]))

                except HyTypeError as e:
                    if e.expression is None:
                        e.expression = tree
                    raise
                except Exception as e:
                    msg = "expanding `" + str(tree[0]) + "': " + repr(e)
                    raise HyMacroExpansionError(tree, msg)
                replace_hy_obj(obj, tree)
                return obj

        return ntree
    return tree
Ejemplo n.º 5
0
def hy_eval(hytree, namespace, module_name, ast_callback=None):
    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

    if ast_callback:
        ast_callback(_ast, expr)

    if not isinstance(namespace, dict):
        raise HyTypeError(foo, "Globals must be a dictionary")

    # Two-step eval: eval() the body of the exec call
    eval(ast_compile(_ast, "<eval_body>", "exec"), namespace)

    # Then eval the expression context and return that
    return eval(ast_compile(expr, "<eval>", "eval"), namespace)
Ejemplo n.º 6
0
    def replace(self, other):
        if self.car is not None:
            replace_hy_obj(self.car, other)
        if self.cdr is not None:
            replace_hy_obj(self.cdr, other)

        HyObject.replace(self, other)
Ejemplo n.º 7
0
def hy_eval(hytree, namespace=None, module_name=None, ast_callback=None):
    """``eval`` evaluates a quoted expression and returns the value. The optional
    second and third arguments specify the dictionary of globals to use and the
    module name. The globals dictionary defaults to ``(local)`` and the module
    name defaults to the name of the current module.

       => (eval '(print "Hello World"))
       "Hello World"

    If you want to evaluate a string, use ``read-str`` to convert it to a
    form first:

       => (eval (read-str "(+ 1 1)"))
       2"""
    if namespace is None:
        frame = inspect.stack()[1][0]
        namespace = inspect.getargvalues(frame).locals
    if module_name is None:
        m = inspect.getmodule(inspect.stack()[1][0])
        module_name = '__eval__' if m is None else m.__name__

    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

    if ast_callback:
        ast_callback(_ast, expr)

    if not isinstance(namespace, dict):
        raise HyTypeError(foo, "Globals must be a dictionary")

    # Two-step eval: eval() the body of the exec call
    eval(ast_compile(_ast, "<eval_body>", "exec"), namespace)

    # Then eval the expression context and return that
    return eval(ast_compile(expr, "<eval>", "eval"), namespace)
Ejemplo n.º 8
0
Archivo: importer.py Proyecto: waigx/hy
def hy_eval(hytree, namespace=None, module_name=None, ast_callback=None):
    """``eval`` evaluates a quoted expression and returns the value. The optional
    second and third arguments specify the dictionary of globals to use and the
    module name. The globals dictionary defaults to ``(local)`` and the module
    name defaults to the name of the current module.

       => (eval '(print "Hello World"))
       "Hello World"

    If you want to evaluate a string, use ``read-str`` to convert it to a
    form first:

       => (eval (read-str "(+ 1 1)"))
       2"""
    if namespace is None:
        frame = inspect.stack()[1][0]
        namespace = inspect.getargvalues(frame).locals
    if module_name is None:
        m = inspect.getmodule(inspect.stack()[1][0])
        module_name = '__eval__' if m is None else m.__name__

    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

    if ast_callback:
        ast_callback(_ast, expr)

    if not isinstance(namespace, dict):
        raise HyTypeError(foo, "Globals must be a dictionary")

    # Two-step eval: eval() the body of the exec call
    eval(ast_compile(_ast, "<eval_body>", "exec"), namespace)

    # Then eval the expression context and return that
    return eval(ast_compile(expr, "<eval>", "eval"), namespace)
Ejemplo n.º 9
0
def macroexpand_1(tree, compiler):
    """Expand the toplevel macro from `tree` once, in the context of
    `module_name`."""
    if isinstance(tree, HyExpression):
        if tree == []:
            return tree

        fn = tree[0]
        if fn in ("quote", "quasiquote"):
            return tree
        ntree = HyExpression(tree[:])
        ntree.replace(tree)

        opts = {}

        if isinstance(fn, HySymbol):
            fn = mangle(str_type(fn))
            m = _hy_macros[compiler.module_name].get(fn)
            if m is None:
                m = _hy_macros[None].get(fn)
            if m is not None:
                if m._hy_macro_pass_compiler:
                    opts['compiler'] = compiler

                try:
                    m_copy = make_empty_fn_copy(m)
                    m_copy(compiler.module_name, *ntree[1:], **opts)
                except TypeError as e:
                    msg = "expanding `" + str(tree[0]) + "': "
                    msg += str(e).replace("<lambda>()", "", 1).strip()
                    raise HyMacroExpansionError(tree, msg)

                try:
                    obj = m(compiler.module_name, *ntree[1:], **opts)
                except HyTypeError as e:
                    if e.expression is None:
                        e.expression = tree
                    raise
                except Exception as e:
                    msg = "expanding `" + str(tree[0]) + "': " + repr(e)
                    raise HyMacroExpansionError(tree, msg)
                replace_hy_obj(obj, tree)
                return obj
        return ntree
    return tree
Ejemplo n.º 10
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)
Ejemplo n.º 11
0
def macroexpand(tree, compiler, once=False):
    """Expand the toplevel macros for the `tree`.

    Load the macros from the given `compiler.module_name`, then expand the
    (top-level) macros in `tree` until we no longer can.

    """
    load_macros(compiler.module_name)
    while True:

        if not isinstance(tree, HyExpression) or tree == []:
            break

        fn = tree[0]
        if fn in ("quote", "quasiquote") or not isinstance(fn, HySymbol):
            break

        fn = mangle(fn)
        m = _hy_macros[compiler.module_name].get(fn) or _hy_macros[None].get(
            fn)
        if not m:
            break

        opts = {}
        if m._hy_macro_pass_compiler:
            opts['compiler'] = compiler

        try:
            m_copy = make_empty_fn_copy(m)
            m_copy(compiler.module_name, *tree[1:], **opts)
        except TypeError as e:
            msg = "expanding `" + str(tree[0]) + "': "
            msg += str(e).replace("<lambda>()", "", 1).strip()
            raise HyMacroExpansionError(tree, msg)

        try:
            obj = m(compiler.module_name, *tree[1:], **opts)
        except HyTypeError as e:
            if e.expression is None:
                e.expression = tree
            raise
        except Exception as e:
            msg = "expanding `" + str(tree[0]) + "': " + repr(e)
            raise HyMacroExpansionError(tree, msg)
        tree = replace_hy_obj(obj, tree)

        if once:
            break

    tree = wrap_value(tree)
    return tree
Ejemplo n.º 12
0
def hy_eval(hytree, namespace, module_name):
    foo = HyObject()
    foo.start_line = 0
    foo.end_line = 0
    foo.start_column = 0
    foo.end_column = 0
    replace_hy_obj(hytree, foo)
    _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

    # Two-step eval: eval() the body of the exec call
    eval(ast_compile(_ast, "<eval_body>", "exec"), namespace)

    # Then eval the expression context and return that
    return eval(ast_compile(expr, "<eval>", "eval"), namespace)
Ejemplo n.º 13
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)
Ejemplo n.º 14
0
Archivo: macros.py Proyecto: 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)
Ejemplo n.º 15
0
def hy_eval(hytree, namespace, module_name):
    foo = HyObject()
    foo.start_line = 0
    foo.end_line = 0
    foo.start_column = 0
    foo.end_column = 0
    replace_hy_obj(hytree, foo)
    _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

    # Two-step eval: eval() the body of the exec call
    eval(ast_compile(_ast, "<eval_body>", "exec"), namespace)

    # Then eval the expression context and return that
    return eval(ast_compile(expr, "<eval>", "eval"), namespace)
Ejemplo n.º 16
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)
Ejemplo n.º 17
0
Archivo: macros.py Proyecto: kartikm/hy
def macroexpand(tree, compiler, once=False):
    """Expand the toplevel macros for the `tree`.

    Load the macros from the given `module_name`, then expand the (top-level)
    macros in `tree` until we no longer can.

    """
    load_macros(compiler.module_name)
    while True:

        if not isinstance(tree, HyExpression) or tree == []:
            break

        fn = tree[0]
        if fn in ("quote", "quasiquote") or not isinstance(fn, HySymbol):
            break

        fn = mangle(fn)
        m = _hy_macros[compiler.module_name].get(fn) or _hy_macros[None].get(fn)
        if not m:
            break

        opts = {}
        if m._hy_macro_pass_compiler:
            opts['compiler'] = compiler

        try:
            m_copy = make_empty_fn_copy(m)
            m_copy(compiler.module_name, *tree[1:], **opts)
        except TypeError as e:
            msg = "expanding `" + str(tree[0]) + "': "
            msg += str(e).replace("<lambda>()", "", 1).strip()
            raise HyMacroExpansionError(tree, msg)

        try:
            obj = m(compiler.module_name, *tree[1:], **opts)
        except HyTypeError as e:
            if e.expression is None:
                e.expression = tree
            raise
        except Exception as e:
            msg = "expanding `" + str(tree[0]) + "': " + repr(e)
            raise HyMacroExpansionError(tree, msg)
        tree = replace_hy_obj(obj, tree)

        if once:
            break

    tree = wrap_value(tree)
    return tree
Ejemplo n.º 18
0
Archivo: macros.py Proyecto: Tritlo/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)
Ejemplo n.º 19
0
Archivo: macros.py Proyecto: kartikm/hy
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)
Ejemplo n.º 20
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)
Ejemplo n.º 21
0
Archivo: macros.py Proyecto: hylang/hy
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("`{0}' is not a defined tag macro.".format(tag),
                          None, tag, None)

    expr = tag_macro(tree)

    if isinstance(expr, HyExpression):
        expr.module = inspect.getmodule(tag_macro)

    return replace_hy_obj(expr, tree)
Ejemplo n.º 22
0
def macroexpand(tree, module, compiler=None, once=False):
    """Expand the toplevel macros for the given Hy AST tree.

    Load the macros from the given `module`, then expand the (top-level) macros
    in `tree` until we no longer can.

    `HyExpression` resulting from macro expansions are assigned the module in
    which the macro function is defined (determined using `inspect.getmodule`).
    If the resulting `HyExpression` is itself macro expanded, then the
    namespace of the assigned module is checked first for a macro corresponding
    to the expression's head/car symbol.  If the head/car symbol of such a
    `HyExpression` is not found among the macros of its assigned module's
    namespace, the outer-most namespace--e.g.  the one given by the `module`
    parameter--is used as a fallback.

    Parameters
    ----------
    tree: HyObject or list
        Hy AST tree.

    module: str or types.ModuleType
        Module used to determine the local namespace for macros.

    compiler: HyASTCompiler, optional
        The compiler object passed to expanded macros.

    once: boolean, optional
        Only expand the first macro in `tree`.

    Returns
    ------
    out: HyObject
        Returns a mutated tree with macros expanded.
    """
    if not inspect.ismodule(module):
        module = importlib.import_module(module)

    assert not compiler or compiler.module == module

    while isinstance(tree, HyExpression) and tree:

        fn = tree[0]
        if fn in ("quote", "quasiquote") or not isinstance(fn, HySymbol):
            break

        fn = mangle(fn)
        expr_modules = (
            ([] if not hasattr(tree, 'module') else [tree.module]) + [module])

        # Choose the first namespace with the macro.
        m = next((mod.__macros__[fn]
                  for mod in expr_modules if fn in mod.__macros__), None)
        if not m:
            break

        opts = {}
        if m._hy_macro_pass_compiler:
            if compiler is None:
                from hy.compiler import HyASTCompiler
                compiler = HyASTCompiler(module)
            opts['compiler'] = compiler

        with macro_exceptions(module, tree, compiler):
            obj = m(module.__name__, *tree[1:], **opts)

            if isinstance(obj, HyExpression):
                obj.module = inspect.getmodule(m)

            tree = replace_hy_obj(obj, tree)

        if once:
            break

    tree = wrap_value(tree)
    return tree
Ejemplo n.º 23
0
def test_replace_tuple():
    """ Test replacing tuples."""
    replaced = replace_hy_obj((0, ), HyInteger(13))
    assert type(replaced) == HyList
    assert type(replaced[0]) == HyInteger
    assert replaced == HyList([HyInteger(0)])
Ejemplo n.º 24
0
def test_replace_string_type():
    """Test replacing python string"""
    replaced = replace_hy_obj("foo", HyString("bar"))
    assert replaced == HyString("foo")
Ejemplo n.º 25
0
def test_replace_int():
    """ Test replacing integers."""
    replaced = replace_hy_obj(0, HyInteger(13))
    assert replaced == HyInteger(0)
Ejemplo n.º 26
0
def test_replace_tuple():
    replaced = replace_hy_obj((0, ), Integer(13))
    assert type(replaced) == List
    assert type(replaced[0]) == Integer
    assert replaced == List([Integer(0)])
Ejemplo n.º 27
0
    def replace(self, other):
        for x in self:
            replace_hy_obj(x, other)

        HyObject.replace(self, other)
        return self
Ejemplo n.º 28
0
def macroexpand(tree, module, compiler=None, once=False, result_ok=True):
    """Expand the toplevel macros for the given Hy AST tree.

    Load the macros from the given `module`, then expand the (top-level) macros
    in `tree` until we no longer can.

    `Expression` resulting from macro expansions are assigned the module in
    which the macro function is defined (determined using `inspect.getmodule`).
    If the resulting `Expression` is itself macro expanded, then the namespace
    of the assigned module is checked first for a macro corresponding to the
    expression's head/car symbol.  If the head/car symbol of such a `Expression`
    is not found among the macros of its assigned module's namespace, the
    outer-most namespace--e.g.  the one given by the `module` parameter--is used
    as a fallback.

    Args:
        tree (Union[Object, list]): Hy AST tree.
        module (Union[str, ModuleType]): Module used to determine the local
            namespace for macros.
        compiler (Optional[HyASTCompiler] ): The compiler object passed to
            expanded macros. Defaults to None
        once (bool): Only expand the first macro in `tree`. Defaults to False
        result_ok (bool): Whether or not it's okay to return a compiler `Result` instance.
            Defaults to True.

    Returns:
        Union[Object, Result]: A mutated tree with macros expanded.
    """
    if not inspect.ismodule(module):
        module = importlib.import_module(module)

    assert not compiler or compiler.module == module

    while isinstance(tree, Expression) and tree:

        fn = tree[0]
        if fn in ("quote", "quasiquote") or not isinstance(fn, Symbol):
            break

        fn = mangle(fn)
        expr_modules = ([] if not hasattr(tree, "module") else [tree.module
                                                                ]) + [module]
        expr_modules.append(builtins)

        # Choose the first namespace with the macro.
        m = next(
            (mod.__macros__[fn]
             for mod in expr_modules if fn in getattr(mod, "__macros__", ())),
            None,
        )
        if not m:
            break

        with MacroExceptions(module, tree, compiler):
            if compiler:
                compiler.this = tree
            obj = m(compiler, *tree[1:])
            if isinstance(obj, (hy.compiler.Result, AST)):
                return obj if result_ok else tree

            if isinstance(obj, Expression):
                obj.module = inspect.getmodule(m)

            tree = replace_hy_obj(obj, tree)

        if once:
            break

    tree = as_model(tree)
    return tree
Ejemplo n.º 29
0
def test_replace_int():
    replaced = replace_hy_obj(0, Integer(13))
    assert replaced == Integer(0)
Ejemplo n.º 30
0
def test_replace_string_type():
    """Test replacing python string"""
    replaced = replace_hy_obj(str_type("foo"), HyString("bar"))
    assert replaced == HyString("foo")
Ejemplo n.º 31
0
def test_replace_str():
    replaced = replace_hy_obj("foo", String("bar"))
    assert replaced == String("foo")
Ejemplo n.º 32
0
def test_replace_long_type():
    """ Test replacing integers."""
    replaced = replace_hy_obj(long_type(0), HyInteger(13))
    assert replaced == HyInteger(0)
Ejemplo n.º 33
0
def test_replace_long_type():
    """ Test replacing integers."""
    replaced = replace_hy_obj(long_type(0), HyInteger(13))
    assert replaced == HyInteger(0)
Ejemplo n.º 34
0
def test_replace_tuple():
    """ Test replacing tuples."""
    replaced = replace_hy_obj((long_type(0), ), HyInteger(13))
    assert type(replaced) == HyList
    assert type(replaced[0]) == HyInteger
    assert replaced == HyList([HyInteger(0)])
Ejemplo n.º 35
0
Archivo: macros.py Proyecto: hylang/hy
def macroexpand(tree, module, compiler=None, once=False):
    """Expand the toplevel macros for the given Hy AST tree.

    Load the macros from the given `module`, then expand the (top-level) macros
    in `tree` until we no longer can.

    `HyExpression` resulting from macro expansions are assigned the module in
    which the macro function is defined (determined using `inspect.getmodule`).
    If the resulting `HyExpression` is itself macro expanded, then the
    namespace of the assigned module is checked first for a macro corresponding
    to the expression's head/car symbol.  If the head/car symbol of such a
    `HyExpression` is not found among the macros of its assigned module's
    namespace, the outer-most namespace--e.g.  the one given by the `module`
    parameter--is used as a fallback.

    Parameters
    ----------
    tree: HyObject or list
        Hy AST tree.

    module: str or types.ModuleType
        Module used to determine the local namespace for macros.

    compiler: HyASTCompiler, optional
        The compiler object passed to expanded macros.

    once: boolean, optional
        Only expand the first macro in `tree`.

    Returns
    ------
    out: HyObject
        Returns a mutated tree with macros expanded.
    """
    if not inspect.ismodule(module):
        module = importlib.import_module(module)

    assert not compiler or compiler.module == module

    while True:

        if not isinstance(tree, HyExpression) or tree == []:
            break

        fn = tree[0]
        if fn in ("quote", "quasiquote") or not isinstance(fn, HySymbol):
            break

        fn = mangle(fn)
        expr_modules = (([] if not hasattr(tree, 'module') else [tree.module])
            + [module])

        # Choose the first namespace with the macro.
        m = next((mod.__macros__[fn]
                  for mod in expr_modules
                  if fn in mod.__macros__),
                 None)
        if not m:
            break

        opts = {}
        if m._hy_macro_pass_compiler:
            if compiler is None:
                from hy.compiler import HyASTCompiler
                compiler = HyASTCompiler(module)
            opts['compiler'] = compiler

        with macro_exceptions(module, tree, compiler):
            obj = m(module.__name__, *tree[1:], **opts)

            if isinstance(obj, HyExpression):
                obj.module = inspect.getmodule(m)

            tree = replace_hy_obj(obj, tree)

        if once:
            break

    tree = wrap_value(tree)
    return tree