def compile_Indirection(expr: qlast.Base, *, ctx: context.ContextLevel) -> irast.Base: node = dispatch.compile(expr.arg, ctx=ctx) int_type = schemactx.get_schema_type('std::int64', ctx=ctx) for indirection_el in expr.indirection: if isinstance(indirection_el, qlast.Index): idx = dispatch.compile(indirection_el.index, ctx=ctx) node = irast.IndexIndirection(expr=node, index=idx) elif isinstance(indirection_el, qlast.Slice): if indirection_el.start: start = dispatch.compile(indirection_el.start, ctx=ctx) else: start = irast.Constant(value=None, type=int_type) if indirection_el.stop: stop = dispatch.compile(indirection_el.stop, ctx=ctx) else: stop = irast.Constant(value=None, type=int_type) node = irast.SliceIndirection(expr=node, start=start, stop=stop) else: raise ValueError('unexpected indirection node: ' '{!r}'.format(indirection_el)) return node
def try_fold_comparison_binop( op: ast.ops.Operator, left: irast.Set, right: irast.Set, *, ctx: context.ContextLevel) -> typing.Optional[irast.Set]: """Try folding a comparison expr into a constant.""" left = left.expr right = right.expr if op == ast.ops.EQ: value = left.value == right.value elif op == ast.ops.NE: value = left.value != right.value elif op == ast.ops.GT: value = left.value > right.value elif op == ast.ops.GE: value = left.value >= right.value elif op == ast.ops.LT: value = left.value < right.value elif op == ast.ops.LE: value = left.value <= right.value else: value = None if value is not None: return setgen.ensure_set(irast.Constant( value=value, type=ctx.schema.get('std::bool')), ctx=ctx)
def compile_UnaryOp(expr: qlast.Base, *, ctx: context.ContextLevel) -> irast.Set: if expr.op == qlast.DISTINCT: return compile_distinct_op(expr, ctx=ctx) operand = dispatch.compile(expr.operand, ctx=ctx) if astutils.is_exists_expr_set(operand): operand.expr.negated = not operand.expr.negated return operand unop = irast.UnaryOp(expr=operand, op=expr.op) result_type = irutils.infer_type(unop, ctx.schema) real_t = ctx.schema.get('std::anyreal') if (isinstance(operand.expr, irast.Constant) and result_type.issubclass(real_t)): # Fold the operation to constant if possible if expr.op == ast.ops.UMINUS: return setgen.ensure_set(irast.Constant(value=-operand.expr.value, type=result_type), ctx=ctx) elif expr.op == ast.ops.UPLUS: return operand return setgen.generated_set(unop, ctx=ctx)
def try_fold_arithmetic_binop( op: ast.ops.Operator, left: irast.Set, right: irast.Set, *, ctx: context.ContextLevel) -> typing.Optional[irast.Set]: """Try folding an arithmetic expr into a constant.""" schema = ctx.schema real_t = schema.get('std::anyreal') float_t = schema.get('std::anyfloat') int_t = schema.get('std::anyint') left_type = irutils.infer_type(left, schema) right_type = irutils.infer_type(right, schema) if not left_type.issubclass(real_t) or not right_type.issubclass(real_t): return result_type = left_type if right_type.issubclass(float_t): result_type = right_type left = left.expr right = right.expr if op == ast.ops.ADD: value = left.value + right.value elif op == ast.ops.SUB: value = left.value - right.value elif op == ast.ops.MUL: value = left.value * right.value elif op == ast.ops.DIV: if left_type.issubclass(int_t) and right_type.issubclass(int_t): value = left.value // right.value else: value = left.value / right.value elif op == ast.ops.POW: value = left.value**right.value elif op == ast.ops.MOD: value = left.value % right.value else: value = None if value is not None: return setgen.ensure_set(irast.Constant(value=value, type=result_type), ctx=ctx)
def compile_Constant(expr: qlast.Base, *, ctx: context.ContextLevel) -> irast.Base: ct = s_basetypes.normalize_type(expr.value.__class__, ctx.schema) return setgen.generated_set(irast.Constant(value=expr.value, type=ct), ctx=ctx)