Esempio n. 1
0
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
Esempio n. 2
0
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)
Esempio n. 3
0
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)
Esempio n. 4
0
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)
Esempio n. 5
0
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)