示例#1
0
def _find_cast(orig_stype: s_types.Type, new_stype: s_types.Type, *,
               srcctx: Optional[parsing.ParserContext],
               ctx: context.ContextLevel) -> Optional[s_casts.Cast]:

    casts = ctx.env.schema.get_casts_to_type(new_stype)
    if not casts and isinstance(new_stype, s_types.InheritingType):
        ancestors = new_stype.get_ancestors(ctx.env.schema)
        for t in ancestors.objects(ctx.env.schema):
            casts = ctx.env.schema.get_casts_to_type(t)
            if casts:
                break
        else:
            return None

    args = [
        (orig_stype, irast.EmptySet()),
        (new_stype, irast.EmptySet()),
    ]

    matched = polyres.find_callable((CastCallableWrapper(c) for c in casts),
                                    args=args,
                                    kwargs={},
                                    ctx=ctx)

    if len(matched) == 1:
        return cast(CastCallableWrapper, matched[0].func)._cast
    elif len(matched) > 1:
        raise errors.QueryError(
            f'cannot unambiguously cast '
            f'{orig_stype.get_displayname(ctx.env.schema)!r} '
            f'to {new_stype.get_displayname(ctx.env.schema)!r}',
            context=srcctx)
    else:
        return None
示例#2
0
def new_empty_set(*, stype: typing.Optional[s_types.Type]=None, alias: str,
                  ctx: context.ContextLevel,
                  srcctx: typing.Optional[
                      parsing.ParserContext]=None) -> irast.Set:
    if stype is None:
        stype = s_pseudo.Any.create()
        ctx.env.type_origins[stype] = srcctx

    typeref = irtyputils.type_to_typeref(ctx.env.schema, stype)
    path_id = pathctx.get_expression_path_id(stype, alias, ctx=ctx)
    ir_set = irast.EmptySet(path_id=path_id, typeref=typeref)
    ctx.env.set_types[ir_set] = stype
    return ir_set
示例#3
0
def new_empty_set(*,
                  stype: typing.Optional[s_types.Type] = None,
                  alias: str,
                  ctx: context.ContextLevel) -> irast.Set:
    if stype is None:
        path_id_scls = s_pseudo.Any.create()
    else:
        path_id_scls = stype

    path_id = pathctx.get_expression_path_id(path_id_scls, alias, ctx=ctx)
    ir_set = irast.EmptySet(path_id=path_id)
    ctx.env.set_types[ir_set] = stype
    return ir_set
示例#4
0
文件: setgen.py 项目: signupsi/edgedb
def new_empty_set(*, stype: Optional[s_types.Type]=None, alias: str,
                  ctx: context.ContextLevel,
                  srcctx: Optional[
                      parsing.ParserContext]=None) -> irast.Set:
    if stype is None:
        stype = s_pseudo.PseudoType.get(ctx.env.schema, 'anytype')
        if srcctx is not None:
            ctx.env.type_origins[stype] = srcctx

    typeref = typegen.type_to_typeref(stype, env=ctx.env)
    path_id = pathctx.get_expression_path_id(stype, alias, ctx=ctx)
    ir_set = irast.EmptySet(path_id=path_id, typeref=typeref)
    ctx.env.set_types[ir_set] = stype
    return ir_set
示例#5
0
def find_callable_typemods(
        candidates: Sequence[s_func.CallableLike], *, num_args: int,
        kwargs_names: AbstractSet[str],
        ctx: context.ContextLevel) -> Dict[Union[int, str], ft.TypeModifier]:
    """Find the type modifiers for a callable.

    We do this early, before we've compiled/checked the arguments,
    so that we can compile the arguments with the proper fences.
    """

    typ = s_pseudo.PseudoType.get(ctx.env.schema, 'anytype')
    dummy = irast.EmptySet()  # type: ignore
    args = [(typ, dummy)] * num_args
    kwargs = {k: (typ, dummy) for k in kwargs_names}
    options = find_callable(candidates,
                            basic_matching_only=True,
                            args=args,
                            kwargs=kwargs,
                            ctx=ctx)

    # No options means an error is going to happen later, but for now,
    # just return some placeholders so that we can make it to the
    # error later.
    if not options:
        return {k: _SINGLETON for k in set(range(num_args)) | kwargs_names}

    fts: Dict[Union[int, str], ft.TypeModifier] = {}
    for choice in options:
        for barg in choice.args:
            if not barg.param or barg.arg_id is None:
                continue
            ft = barg.param.get_typemod(ctx.env.schema)
            if barg.arg_id in fts and fts[barg.arg_id] != ft:
                if ft == _SET_OF or fts[barg.arg_id] == _SET_OF:
                    raise errors.QueryError(
                        f'argument could be SET OF or not in call to '
                        f'{candidates[0].get_verbosename(ctx.env.schema)}: '
                        f'seems like a stdlib bug!')
                else:
                    # If there is a mix between OPTIONAL and SINGLETON
                    # arguments in possible call sites, we just call it
                    # optional. Generated code quality will be a little
                    # worse but still correct.
                    fts[barg.arg_id] = _OPTIONAL
            else:
                fts[barg.arg_id] = ft

    return fts
示例#6
0
def _find_cast(
        orig_stype: s_types.Type,
        new_stype: s_types.Type, *,
        srcctx: Optional[parsing.ParserContext],
        ctx: context.ContextLevel) -> Optional[s_casts.Cast]:

    # Don't try to pick up casts when there is a direct subtyping
    # relationship.
    if (orig_stype.issubclass(ctx.env.schema, new_stype)
            or new_stype.issubclass(ctx.env.schema, orig_stype)):
        return None

    casts = ctx.env.schema.get_casts_to_type(new_stype)
    if not casts and isinstance(new_stype, s_types.InheritingType):
        ancestors = new_stype.get_ancestors(ctx.env.schema)
        for t in ancestors.objects(ctx.env.schema):
            casts = ctx.env.schema.get_casts_to_type(t)
            if casts:
                break
        else:
            return None

    dummy_set = irast.EmptySet()  # type: ignore
    args = [
        (orig_stype, dummy_set),
        (new_stype, dummy_set),
    ]

    matched = polyres.find_callable(
        (CastCallableWrapper(c) for c in casts), args=args, kwargs={}, ctx=ctx)

    if len(matched) == 1:
        return cast(CastCallableWrapper, matched[0].func)._cast
    elif len(matched) > 1:
        raise errors.QueryError(
            f'cannot unambiguously cast '
            f'{orig_stype.get_displayname(ctx.env.schema)!r} '
            f'to {new_stype.get_displayname(ctx.env.schema)!r}',
            context=srcctx)
    else:
        return None