Ejemplo n.º 1
0
def compile_IfElseExpr(expr: irast.Base, *,
                       ctx: context.CompilerContextLevel) -> pgast.Base:
    with ctx.new() as subctx:
        return pgast.CaseExpr(args=[
            pgast.CaseWhen(expr=dispatch.compile(expr.condition, ctx=subctx),
                           result=dispatch.compile(expr.if_expr, ctx=subctx))
        ],
                              defresult=dispatch.compile(expr.else_expr,
                                                         ctx=subctx))
Ejemplo n.º 2
0
def compile_IndexIndirection(expr: irast.Base, *,
                             ctx: context.CompilerContextLevel) -> pgast.Base:
    # Handle Expr[Index], where Expr may be std::str or array<T>.
    # For strings we translate this into substr calls, whereas
    # for arrays the native slice syntax is used.
    is_string = False
    arg_type = _infer_type(expr.expr, ctx=ctx)

    with ctx.new() as subctx:
        subctx.expr_exposed = False
        subj = dispatch.compile(expr.expr, ctx=subctx)
        index = dispatch.compile(expr.index, ctx=subctx)

    if isinstance(arg_type, s_scalars.ScalarType):
        b = arg_type.get_topmost_concrete_base()
        is_string = b.name == 'std::str'

    one = pgast.Constant(val=1)
    zero = pgast.Constant(val=0)

    when_cond = astutils.new_binop(lexpr=index, rexpr=zero, op=ast.ops.LT)

    index_plus_one = astutils.new_binop(lexpr=index, op=ast.ops.ADD, rexpr=one)

    if is_string:
        upper_bound = pgast.FuncCall(name=('char_length', ), args=[subj])
    else:
        upper_bound = pgast.FuncCall(name=('array_upper', ), args=[subj, one])

    neg_off = astutils.new_binop(lexpr=upper_bound,
                                 rexpr=index_plus_one,
                                 op=ast.ops.ADD)

    when_expr = pgast.CaseWhen(expr=when_cond, result=neg_off)

    index = pgast.CaseExpr(args=[when_expr], defresult=index_plus_one)

    if is_string:
        index = pgast.TypeCast(arg=index,
                               type_name=pgast.TypeName(name=('int', )))
        result = pgast.FuncCall(name=('substr', ), args=[subj, index, one])
    else:
        indirection = pgast.Indices(ridx=index)
        result = pgast.Indirection(arg=subj, indirection=[indirection])

    return result
Ejemplo n.º 3
0
def compile_SliceIndirection(expr: irast.Base, *,
                             ctx: context.CompilerContextLevel) -> pgast.Base:
    # Handle Expr[Start:End], where Expr may be std::str or array<T>.
    # For strings we translate this into substr calls, whereas
    # for arrays the native slice syntax is used.
    with ctx.new() as subctx:
        subctx.expr_exposed = False
        subj = dispatch.compile(expr.expr, ctx=subctx)
        start = dispatch.compile(expr.start, ctx=subctx)
        stop = dispatch.compile(expr.stop, ctx=subctx)

    one = pgast.Constant(val=1)
    zero = pgast.Constant(val=0)

    is_string = False
    arg_type = _infer_type(expr.expr, ctx=ctx)

    if isinstance(arg_type, s_scalars.ScalarType):
        b = arg_type.get_topmost_concrete_base()
        is_string = b.name == 'std::str'

    if is_string:
        upper_bound = pgast.FuncCall(name=('char_length', ), args=[subj])
    else:
        upper_bound = pgast.FuncCall(name=('array_upper', ), args=[subj, one])

    if astutils.is_null_const(start):
        lower = one
    else:
        lower = start

        when_cond = astutils.new_binop(lexpr=lower, rexpr=zero, op=ast.ops.LT)
        lower_plus_one = astutils.new_binop(lexpr=lower,
                                            rexpr=one,
                                            op=ast.ops.ADD)

        neg_off = astutils.new_binop(lexpr=upper_bound,
                                     rexpr=lower_plus_one,
                                     op=ast.ops.ADD)

        when_expr = pgast.CaseWhen(expr=when_cond, result=neg_off)
        lower = pgast.CaseExpr(args=[when_expr], defresult=lower_plus_one)

    if astutils.is_null_const(stop):
        upper = upper_bound
    else:
        upper = stop

        when_cond = astutils.new_binop(lexpr=upper, rexpr=zero, op=ast.ops.LT)

        neg_off = astutils.new_binop(lexpr=upper_bound,
                                     rexpr=upper,
                                     op=ast.ops.ADD)

        when_expr = pgast.CaseWhen(expr=when_cond, result=neg_off)
        upper = pgast.CaseExpr(args=[when_expr], defresult=upper)

    if is_string:
        lower = pgast.TypeCast(arg=lower,
                               type_name=pgast.TypeName(name=('int', )))

        args = [subj, lower]

        if upper is not upper_bound:
            for_length = astutils.new_binop(lexpr=upper,
                                            op=ast.ops.SUB,
                                            rexpr=lower)
            for_length = astutils.new_binop(lexpr=for_length,
                                            op=ast.ops.ADD,
                                            rexpr=one)

            for_length = pgast.TypeCast(
                arg=for_length, type_name=pgast.TypeName(name=('int', )))
            args.append(for_length)

        result = pgast.FuncCall(name=('substr', ), args=args)

    else:
        indirection = pgast.Indices(lidx=lower, ridx=upper)
        result = pgast.Indirection(arg=subj, indirection=[indirection])

    return result