Beispiel #1
0
def compile_to_ir(expr,
                  schema,
                  *,
                  anchors=None,
                  path_prefix_anchor=None,
                  security_context=None,
                  modaliases=None,
                  implicit_id_in_shapes=False,
                  implicit_tid_in_shapes=False):
    """Compile given EdgeQL statement into EdgeDB IR."""

    if debug.flags.edgeql_compile:
        debug.header('EdgeQL TEXT')
        debug.print(expr)

    tree = ql_parser.parse(expr, modaliases)

    return compile_ast_to_ir(tree,
                             schema,
                             anchors=anchors,
                             path_prefix_anchor=path_prefix_anchor,
                             security_context=security_context,
                             modaliases=modaliases,
                             implicit_id_in_shapes=implicit_id_in_shapes,
                             implicit_tid_in_shapes=implicit_tid_in_shapes)
Beispiel #2
0
def compile_func_to_ir(func,
                       schema,
                       *,
                       anchors=None,
                       security_context=None,
                       modaliases=None,
                       implicit_id_in_shapes=False,
                       implicit_tid_in_shapes=False):
    """Compile an EdgeQL function into EdgeDB IR."""

    if debug.flags.edgeql_compile:
        debug.header('EdgeQL Function')
        debug.print(func.get_code(schema))

    trees = ql_parser.parse_block(func.get_code(schema) + ';')
    if len(trees) != 1:
        raise errors.InvalidFunctionDefinitionError(
            'functions can only contain one statement')

    tree = trees[0]
    if modaliases:
        ql_parser.append_module_aliases(tree, modaliases)

    param_anchors, param_aliases = get_param_anchors_for_callable(
        func.get_params(schema), schema)

    if anchors is None:
        anchors = {}

    anchors.update(param_anchors)
    tree.aliases.extend(param_aliases)

    ir = compile_ast_to_ir(
        tree,
        schema,
        anchors=anchors,
        func_params=func.get_params(schema),
        security_context=security_context,
        modaliases=modaliases,
        implicit_id_in_shapes=implicit_id_in_shapes,
        implicit_tid_in_shapes=implicit_tid_in_shapes,
        # the body of a session_only function can contain calls to
        # other session_only functions
        session_mode=func.get_session_only(schema))

    return ir
Beispiel #3
0
def compile_func_to_ir(func,
                       schema,
                       *,
                       anchors=None,
                       security_context=None,
                       modaliases=None,
                       implicit_id_in_shapes=False,
                       implicit_tid_in_shapes=False):
    """Compile an EdgeQL function into EdgeDB IR."""

    if debug.flags.edgeql_compile:
        debug.header('EdgeQL Function')
        debug.print(func.get_code(schema))

    trees = ql_parser.parse_block(func.get_code(schema) + ';')
    if len(trees) != 1:
        raise errors.InvalidFunctionDefinitionError(
            'functions can only contain one statement')

    tree = trees[0]
    if modaliases:
        ql_parser.append_module_aliases(tree, modaliases)

    param_anchors, param_aliases = get_param_anchors_for_callable(
        func.get_params(schema),
        schema,
        inlined_defaults=func.has_inlined_defaults(schema))

    if anchors is None:
        anchors = {}

    anchors.update(param_anchors)
    tree.aliases.extend(param_aliases)

    ir = compile_ast_to_ir(
        tree,
        schema,
        anchors=anchors,
        func_params=func.get_params(schema),
        security_context=security_context,
        modaliases=modaliases,
        implicit_id_in_shapes=implicit_id_in_shapes,
        implicit_tid_in_shapes=implicit_tid_in_shapes,
        # the body of a session_only function can contain calls to
        # other session_only functions
        session_mode=func.get_session_only(schema))

    return_type = func.get_return_type(schema)
    if (not ir.stype.issubclass(schema, return_type)
            and not ir.stype.implicitly_castable_to(return_type, schema)):
        raise errors.InvalidFunctionDefinitionError(
            f'return type mismatch in function declared to return '
            f'{return_type.get_verbosename(schema)}',
            details=f'Actual return type is '
            f'{ir.stype.get_verbosename(schema)}',
            context=tree.context,
        )

    return_typemod = func.get_return_typemod(schema)
    if (return_typemod is not qltypes.TypeModifier.SET_OF
            and ir.cardinality is qltypes.Cardinality.MANY):
        raise errors.InvalidFunctionDefinitionError(
            f'return cardinality mismatch in function declared to return '
            f'a singleton',
            details=f'Function may return a set with more than one element.',
            context=tree.context,
        )

    return ir
def compile_func_to_ir(func, schema, *,
                       anchors=None,
                       security_context=None,
                       modaliases=None,
                       implicit_id_in_shapes=False,
                       implicit_tid_in_shapes=False):
    """Compile an EdgeQL function into EdgeDB IR."""

    if debug.flags.edgeql_compile:
        debug.header('EdgeQL Function')
        debug.print(func.get_code(schema))

    trees = ql_parser.parse_block(func.get_code(schema) + ';')
    if len(trees) != 1:
        raise errors.InvalidFunctionDefinitionError(
            'functions can only contain one statement')

    tree = trees[0]
    if modaliases:
        ql_parser.append_module_aliases(tree, modaliases)

    if anchors is None:
        anchors = {}

    anchors['__defaults_mask__'] = irast.Parameter(
        name='__defaults_mask__',
        typeref=irtyputils.type_to_typeref(schema, schema.get('std::bytes')))

    func_params = func.get_params(schema)
    pg_params = s_func.PgParams.from_params(schema, func_params)
    for pi, p in enumerate(pg_params.params):
        p_shortname = p.get_shortname(schema)
        anchors[p_shortname] = irast.Parameter(
            name=p_shortname,
            typeref=irtyputils.type_to_typeref(schema, p.get_type(schema)))

        if p.get_default(schema) is None:
            continue

        tree.aliases.append(
            qlast.AliasedExpr(
                alias=p_shortname,
                expr=qlast.IfElse(
                    condition=qlast.BinOp(
                        left=qlast.FunctionCall(
                            func=('std', 'bytes_get_bit'),
                            args=[
                                qlast.FuncArg(
                                    arg=qlast.Path(steps=[
                                        qlast.ObjectRef(
                                            name='__defaults_mask__')
                                    ])),
                                qlast.FuncArg(
                                    arg=qlast.IntegerConstant(value=str(pi)))
                            ]),
                        right=qlast.IntegerConstant(value='0'),
                        op='='),
                    if_expr=qlast.Path(
                        steps=[qlast.ObjectRef(name=p_shortname)]),
                    else_expr=qlast._Optional(expr=p.get_ql_default(schema)))))

    ir = compile_ast_to_ir(
        tree, schema, anchors=anchors, func=func,
        security_context=security_context, modaliases=modaliases,
        implicit_id_in_shapes=implicit_id_in_shapes,
        implicit_tid_in_shapes=implicit_tid_in_shapes)

    return ir
Beispiel #5
0
def compile_func_to_ir(
    func: s_func.Function,
    schema: s_schema.Schema,
) -> irast.Statement:
    """Compile an EdgeQL function into EdgeDB IR.

    Args:
        func:
            A function object.

        schema:
            A schema instance where the function is defined.

    Returns:
        An instance of :class:`ir.ast.Statement` representing the
        function body.
    """
    if debug.flags.edgeql_compile:
        debug.header('EdgeQL Function')
        debug.print(func.get_code(schema))

    code = func.get_code(schema)
    assert code is not None
    trees = ql_parser.parse_block(code + ';')
    if len(trees) != 1:
        raise errors.InvalidFunctionDefinitionError(
            'functions can only contain one statement')

    tree = trees[0]

    param_anchors, param_aliases = get_param_anchors_for_callable(
        func.get_params(schema),
        schema,
        inlined_defaults=func.has_inlined_defaults(schema))

    tree.aliases.extend(param_aliases)

    ir = compile_ast_to_ir(
        tree,
        schema,
        anchors=param_anchors,  # type: ignore
        # (typing#273)
        func_params=func.get_params(schema),
        # the body of a session_only function can contain calls to
        # other session_only functions
        session_mode=func.get_session_only(schema),
    )

    assert isinstance(ir, irast.Statement)

    return_type = func.get_return_type(schema)
    if (not ir.stype.issubclass(schema, return_type)
            and not ir.stype.implicitly_castable_to(return_type, schema)):
        raise errors.InvalidFunctionDefinitionError(
            f'return type mismatch in function declared to return '
            f'{return_type.get_verbosename(schema)}',
            details=f'Actual return type is '
            f'{ir.stype.get_verbosename(schema)}',
            context=tree.context,
        )

    return_typemod = func.get_return_typemod(schema)
    if (return_typemod is not qltypes.TypeModifier.SET_OF
            and ir.cardinality is qltypes.Cardinality.MANY):
        raise errors.InvalidFunctionDefinitionError(
            f'return cardinality mismatch in function declared to return '
            f'a singleton',
            details=f'Function may return a set with more than one element.',
            context=tree.context,
        )

    return ir