Exemple #1
0
def compile_BinOp(
        expr: qlast.Base, *, ctx: context.ContextLevel) -> irast.Set:
    try_folding = True

    if isinstance(expr.op, ast.ops.TypeCheckOperator):
        op_node = compile_type_check_op(expr, ctx=ctx)
    elif isinstance(expr.op, qlast.SetOperator):
        op_node = compile_set_op(expr, ctx=ctx)
        try_folding = False
    elif isinstance(expr.op, qlast.EquivalenceOperator):
        op_node = compile_equivalence_op(expr, ctx=ctx)
    elif isinstance(expr.op, ast.ops.MembershipOperator):
        op_node = compile_membership_op(expr, ctx=ctx)
        try_folding = False
    else:
        left = dispatch.compile(expr.left, ctx=ctx)
        right = dispatch.compile(expr.right, ctx=ctx)
        op_node = irast.BinOp(left=left, right=right, op=expr.op)

    if try_folding:
        folded = try_fold_binop(op_node, ctx=ctx)
        if folded is not None:
            return folded

    return setgen.ensure_set(op_node, ctx=ctx)
Exemple #2
0
def extend_irbinop(binop, *exprs, op=ast.ops.AND):
    exprs = list(exprs)
    binop = binop or exprs.pop(0)

    for expr in exprs:
        if expr is not binop:
            binop = irast.BinOp(left=binop, right=expr, op=op)

    return binop
Exemple #3
0
def compile_membership_op(expr: qlast.BinOp, *,
                          ctx: context.ContextLevel) -> irast.Base:
    left = dispatch.compile(expr.left, ctx=ctx)
    with ctx.newscope(fenced=True) as scopectx:
        # [NOT] IN is an aggregate, so we need to put a scope fence.
        right = setgen.scoped_set(dispatch.compile(expr.right, ctx=scopectx),
                                  ctx=scopectx)

    op_node = irast.BinOp(left=left, right=right, op=expr.op)
    return setgen.generated_set(op_node, ctx=ctx)
Exemple #4
0
def try_fold_binop(binop: irast.BinOp, *,
                   ctx: context.ContextLevel) -> typing.Optional[irast.Set]:
    """Try folding a binary operator expression."""
    schema = ctx.schema
    real_t = schema.get('std::anyreal')

    result_type = irutils.infer_type(binop, schema)
    folded = None

    left = binop.left
    right = binop.right
    op = binop.op

    if (isinstance(left.expr, irast.Constant)
            and isinstance(right.expr, irast.Constant)):
        # Left and right nodes are constants.
        if isinstance(op, ast.ops.ComparisonOperator):
            folded = try_fold_comparison_binop(op, left, right, ctx=ctx)

        elif result_type.issubclass(real_t):
            folded = try_fold_arithmetic_binop(op, left, right, ctx=ctx)

    elif op in {ast.ops.ADD, ast.ops.MUL}:
        # Let's check if we have (CONST + (OTHER_CONST + X))
        # tree, which can be optimized to ((CONST + OTHER_CONST) + X)

        my_const = left
        other_binop = right
        if isinstance(right.expr, irast.Constant):
            my_const, other_binop = other_binop, my_const

        if (isinstance(my_const.expr, irast.Constant)
                and isinstance(other_binop.expr, irast.BinOp)
                and other_binop.expr.op == op):

            other_const = other_binop.expr.left
            other_binop_node = other_binop.expr.right
            if isinstance(other_binop_node.expr, irast.Constant):
                other_binop_node, other_const = \
                    other_const, other_binop_node

            if isinstance(other_const.expr, irast.Constant):
                new_const = try_fold_arithmetic_binop(op,
                                                      other_const,
                                                      my_const,
                                                      ctx=ctx)

                if new_const is not None:
                    folded_binop = irast.BinOp(left=new_const,
                                               right=other_binop_node,
                                               op=op)
                    folded = setgen.ensure_set(folded_binop, ctx=ctx)

    return folded
Exemple #5
0
def compile_type_check_op(expr: qlast.BinOp, *,
                          ctx: context.ContextLevel) -> irast.BinOp:
    # <Expr> IS <Type>
    left = dispatch.compile(expr.left, ctx=ctx)
    with ctx.new() as subctx:
        subctx.path_as_type = True
        right = dispatch.compile(expr.right, ctx=subctx)

    ltype = irutils.infer_type(left, ctx.schema)
    left = setgen.ptr_step_set(left,
                               source=ltype,
                               ptr_name=('std', '__type__'),
                               direction=s_pointers.PointerDirection.Outbound,
                               source_context=expr.context,
                               ctx=ctx)

    pathctx.register_set_in_scope(left, ctx=ctx)

    right = typegen.process_type_ref_expr(right)

    return irast.BinOp(left=left, right=right, op=expr.op)