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))
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
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