Пример #1
0
            def wrapper(hy_compiler, *args):

                if shadow and any(is_unpack("iterable", x) for x in args):
                    # Try a shadow function call with this name instead.
                    return Expression([Symbol("hy.pyops." + name),
                                       *args]).replace(hy_compiler.this)

                expr = hy_compiler.this
                root = unmangle(expr[0])

                if py_version_required and sys.version_info < py_version_required:
                    raise hy_compiler._syntax_error(
                        expr,
                        "`{}` requires Python {} or later".format(
                            root, ".".join(map(str, py_version_required))),
                    )

                try:
                    parse_tree = pattern.parse(args)
                except NoParseError as e:
                    raise hy_compiler._syntax_error(
                        expr[min(e.state.pos + 1,
                                 len(expr) - 1)],
                        "parse error for pattern macro '{}': {}".format(
                            root, e.msg.replace("<EOF>", "end of form")),
                    )
                return fn(hy_compiler, expr, root, *parse_tree)
Пример #2
0
    def _compile_collect(self, exprs, with_kwargs=False, dict_display=False):
        """Collect the expression contexts from a list of compiled expression.

        This returns a list of the expression contexts, and the sum of the
        Result objects passed as arguments.

        """
        compiled_exprs = []
        ret = Result()
        keywords = []

        exprs_iter = iter(exprs)
        for expr in exprs_iter:

            if is_unpack("mapping", expr):
                ret += self.compile(expr[1])
                if dict_display:
                    compiled_exprs.append(None)
                    compiled_exprs.append(ret.force_expr)
                elif with_kwargs:
                    keywords.append(
                        asty.keyword(expr, arg=None, value=ret.force_expr))

            elif with_kwargs and isinstance(expr, Keyword):
                if keyword.iskeyword(expr.name):
                    raise self._syntax_error(
                        expr,
                        "keyword argument cannot be Python reserved word")

                try:
                    value = next(exprs_iter)
                except StopIteration:
                    raise self._syntax_error(
                        expr,
                        "Keyword argument {kw} needs a value.".format(kw=expr))

                if not expr:
                    raise self._syntax_error(
                        expr, "Can't call a function with the empty keyword")

                compiled_value = self.compile(value)
                ret += compiled_value

                arg = str(expr)[1:]
                keywords.append(
                    asty.keyword(expr,
                                 arg=mangle(arg),
                                 value=compiled_value.force_expr))

            else:
                ret += self.compile(expr)
                compiled_exprs.append(ret.force_expr)

        return compiled_exprs, ret, keywords
Пример #3
0
    def compile_expression(self, expr, *, allow_annotation_expression=False):
        # Perform macro expansions
        expr = macroexpand(expr, self.module, self)
        if isinstance(expr, (Result, ast.AST)):
            # Use this as-is.
            return expr
        elif not isinstance(expr, Expression):
            # Go through compile again if we have a different type of model.
            return self.compile(expr)

        if not expr:
            raise self._syntax_error(
                expr, "empty expressions are not allowed at top level"
            )

        args = list(expr)
        root = args.pop(0)
        func = None

        if isinstance(root, Symbol) and root.startswith("."):
            # (.split "test test") -> "test test".split()
            # (.a.b.c x v1 v2) -> (.c (. x a b) v1 v2) ->  x.a.b.c(v1, v2)

            # Get the method name (the last named attribute
            # in the chain of attributes)
            attrs = [
                Symbol(a).replace(root) if a else None for a in root.split(".")[1:]
            ]
            if not all(attrs):
                raise self._syntax_error(expr, "cannot access empty attribute")
            root = attrs.pop()

            # Get the object we're calling the method on
            # (extracted with the attribute access DSL)
            # Skip past keywords and their arguments.
            try:
                kws, obj, rest = (
                    many(KEYWORD + FORM | unpack("mapping")) + FORM + many(FORM)
                ).parse(args)
            except NoParseError:
                raise self._syntax_error(expr, "attribute access requires object")
            # Reconstruct `args` to exclude `obj`.
            args = [x for p in kws for x in p] + list(rest)
            if is_unpack("iterable", obj):
                raise self._syntax_error(
                    obj, "can't call a method on an unpacking form"
                )
            func = self.compile(Expression([Symbol(".").replace(root), obj] + attrs))

            # And get the method
            func += asty.Attribute(
                root, value=func.force_expr, attr=mangle(root), ctx=ast.Load()
            )

        if is_annotate_expression(root):
            # Flatten and compile the annotation expression.
            ann_expr = Expression(root + args).replace(root)
            return self.compile_expression(ann_expr, allow_annotation_expression=True)

        if not func:
            func = self.compile(root)

        args, ret, keywords = self._compile_collect(args, with_kwargs=True)

        return (
            func + ret + asty.Call(expr, func=func.expr, args=args, keywords=keywords)
        )