Пример #1
0
    def _apply_field_ast(
        self,
        schema: s_schema.Schema,
        context: sd.CommandContext,
        node: qlast.DDLOperation,
        op: sd.AlterObjectProperty,
    ) -> None:
        if op.property == 'default':
            if op.new_value:
                assert isinstance(op.new_value, list)
                op.new_value = op.new_value[0]
                super()._apply_field_ast(schema, context, node, op)

        elif op.property == 'bases':
            enum_values = self.get_local_attribute_value('enum_values')
            if enum_values:
                assert isinstance(node, qlast.BasesMixin)
                node.bases = [
                    qlast.TypeName(
                        maintype=qlast.ObjectRef(name='enum'),
                        subtypes=[
                            qlast.TypeName(maintype=qlast.ObjectRef(name=v))
                            for v in enum_values
                        ])
                ]
            else:
                super()._apply_field_ast(schema, context, node, op)
        else:
            super()._apply_field_ast(schema, context, node, op)
Пример #2
0
def type_to_ql_typeref(t: s_obj.Object,
                       *,
                       _name=None,
                       ctx: context.ContextLevel) -> qlast.TypeName:
    if t.is_any():
        result = qlast.TypeName(name=_name, maintype=qlast.AnyType())
    elif t.is_anytuple():
        result = qlast.TypeName(name=_name, maintype=qlast.AnyTuple())
    elif not isinstance(t, s_abc.Collection):
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(
                                    module=t.get_name(ctx.env.schema).module,
                                    name=t.get_name(ctx.env.schema).name))
    elif isinstance(t, s_abc.Tuple) and t.named:
        result = qlast.TypeName(
            name=_name,
            maintype=qlast.ObjectRef(name=t.schema_name),
            subtypes=[
                type_to_ql_typeref(st, _name=sn, ctx=ctx)
                for sn, st in t.iter_subtypes(ctx.env.schema)
            ])
    else:
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name=t.schema_name),
                                subtypes=[
                                    type_to_ql_typeref(st, ctx=ctx)
                                    for st in t.get_subtypes(ctx.env.schema)
                                ])

    return result
Пример #3
0
    def _apply_field_ast(
        self,
        schema: s_schema.Schema,
        context: sd.CommandContext,
        node: qlast.DDLOperation,
        op: sd.AlterObjectProperty,
    ) -> None:
        if op.property == 'bases':
            explicit_bases = self.get_explicit_bases(schema, context,
                                                     op.new_value)

            if explicit_bases:
                if isinstance(node, qlast.CreateObject):
                    node.bases = [
                        qlast.TypeName(maintype=utils.name_to_ast_ref(b))
                        for b in explicit_bases
                    ]
                else:
                    node.commands.append(
                        qlast.AlterAddInherit(bases=[
                            qlast.TypeName(maintype=utils.name_to_ast_ref(b), )
                            for b in explicit_bases
                        ], ))
        else:
            super()._apply_field_ast(schema, context, node, op)
Пример #4
0
def typeref_to_ast(schema, t, *, _name=None) -> qlast.TypeName:
    if t.is_type() and t.is_any():
        result = qlast.TypeName(name=_name, maintype=qlast.AnyType())
    elif t.is_type() and t.is_anytuple():
        result = qlast.TypeName(name=_name, maintype=qlast.AnyTuple())
    elif not isinstance(t, s_abc.Collection):
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(
                                    module=t.get_name(schema).module,
                                    name=t.get_name(schema).name))
    elif isinstance(t, s_abc.Tuple) and t.named:
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name=t.schema_name),
                                subtypes=[
                                    typeref_to_ast(schema, st, _name=sn)
                                    for sn, st in t.iter_subtypes(schema)
                                ])
    else:
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name=t.schema_name),
                                subtypes=[
                                    typeref_to_ast(schema, st)
                                    for st in t.get_subtypes(schema)
                                ])

    return result
Пример #5
0
def typeref_to_ast(schema, t: so.Object) -> ql_ast.TypeName:
    if not isinstance(t, s_abc.Collection):
        if t.is_type() and t.is_any():
            ref = ql_ast.AnyType()
        elif t.is_type() and t.is_anytuple():
            ref = ql_ast.AnyTuple()
        else:
            ref = ql_ast.ObjectRef(
                module=t.get_name(schema).module,
                name=t.get_name(schema).name
            )

        result = ql_ast.TypeName(
            maintype=ref
        )
    else:
        result = ql_ast.TypeName(
            maintype=ql_ast.ObjectRef(
                name=t.schema_name
            ),
            subtypes=[
                typeref_to_ast(schema, st) for st in t.get_subtypes(schema)
            ]
        )

    return result
Пример #6
0
def typeref_to_ast(
    schema: s_schema.Schema,
    ref: Union[so.Object, so.ObjectShell],
    *,
    _name: Optional[str] = None,
) -> qlast.TypeExpr:
    from . import types as s_types

    if isinstance(ref, so.ObjectShell):
        t = ref.resolve(schema)
    else:
        t = ref

    result: qlast.TypeExpr
    components: Tuple[so.Object, ...]

    if t.is_type() and cast(s_types.Type, t).is_any(schema):
        result = qlast.TypeName(name=_name, maintype=qlast.AnyType())
    elif t.is_type() and cast(s_types.Type, t).is_anytuple(schema):
        result = qlast.TypeName(name=_name, maintype=qlast.AnyTuple())
    elif isinstance(t, s_types.Tuple) and t.is_named(schema):
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name=t.schema_name),
                                subtypes=[
                                    typeref_to_ast(schema, st, _name=sn)
                                    for sn, st in t.iter_subtypes(schema)
                                ])
    elif isinstance(t, (s_types.Array, s_types.Tuple)):
        # Here the concrete type Array is used because t.schema_name is used,
        # which is not defined for more generic collections and abcs
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name=t.schema_name),
                                subtypes=[
                                    typeref_to_ast(schema, st)
                                    for st in t.get_subtypes(schema)
                                ])
    elif t.is_type() and cast(s_types.Type, t).is_union_type(schema):
        object_set: Optional[so.ObjectSet[s_types.Type]] = \
            cast(s_types.Type, t).get_union_of(schema)
        assert object_set is not None

        component_objects = tuple(object_set.objects(schema))
        result = typeref_to_ast(schema, component_objects[0])
        for component_object in component_objects[1:]:
            result = qlast.TypeOp(
                left=result,
                op='|',
                right=typeref_to_ast(schema, component_object),
            )
    elif isinstance(t, so.QualifiedObject):
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(
                                    module=t.get_name(schema).module,
                                    name=t.get_name(schema).name))
    else:
        raise NotImplementedError(f'cannot represent {t!r} as a shell')

    return result
Пример #7
0
    def visit_ObjectField(self, node):
        fname = node.name.value

        # handle boolean ops
        if fname == 'and':
            return self._visit_list_of_inputs(node.value, 'AND')
        elif fname == 'or':
            return self._visit_list_of_inputs(node.value, 'OR')
        elif fname == 'not':
            return qlast.UnaryOp(op='NOT', operand=self.visit(node.value))

        # handle various scalar ops
        op = gt.GQL_TO_OPS_MAP.get(fname)

        if op:
            value = self.visit(node.value)
            return qlast.BinOp(left=self._context.filter, op=op, right=value)

        # we're at the beginning of a scalar op
        _, target = self._get_parent_and_current_type()

        name = self.get_path_prefix()
        name.append(qlast.Ptr(ptr=qlast.ObjectRef(name=fname)))
        name = qlast.Path(steps=name)

        ftype = target.get_field_type(fname)
        typename = ftype.name
        if typename not in {'std::str', 'std::uuid'}:
            gql_type = gt.EDB_TO_GQL_SCALARS_MAP.get(typename)
            if gql_type == graphql.GraphQLString:
                # potentially need to cast the 'name' side into a
                # <str>, so as to be compatible with the 'value'
                name = qlast.TypeCast(
                    expr=name,
                    type=qlast.TypeName(maintype=qlast.ObjectRef(name='str')),
                )

        self._context.filter = name

        value = self.visit(node.value)
        # we need to cast a target string into <uuid> or enum
        if typename == 'std::uuid' and not isinstance(value.right,
                                                      qlast.TypeCast):
            value.right = qlast.TypeCast(
                expr=value.right,
                type=qlast.TypeName(maintype=qlast.ObjectRef(name='uuid')),
            )
        elif ftype.is_enum():
            value.right = qlast.TypeCast(
                expr=value.right,
                type=qlast.TypeName(maintype=qlast.ObjectRef(name=ftype.name)),
            )

        return value
Пример #8
0
def _inject_tname(
        insert_stmt: qlast.InsertQuery, *,
        ctx: context.ContextLevel) -> None:

    for el in insert_stmt.shape:
        if isinstance(el.compexpr, qlast.InsertQuery):
            _inject_tname(el.compexpr, ctx=ctx)

    assert isinstance(insert_stmt.subject.steps[0], qlast.BaseObjectRef)
    insert_stmt.shape.append(
        qlast.ShapeElement(
            expr=qlast.Path(
                steps=[qlast.Ptr(ptr=qlast.ObjectRef(name='_tname'))],
            ),
            compexpr=qlast.Path(
                steps=[
                    qlast.Introspect(
                        type=qlast.TypeName(
                            maintype=insert_stmt.subject.steps[0],
                        ),
                    ),
                    qlast.Ptr(ptr=qlast.ObjectRef(name='name')),
                ],
            ),
        ),
    )
Пример #9
0
    def _apply_field_ast(self, schema, context, node, op):
        if op.property == 'bases':
            mcls = self.get_schema_metaclass()
            default_base = mcls.get_default_base_name()

            if not isinstance(op.new_value, so.ObjectList):
                bases = so.ObjectList.create(schema, op.new_value)
            else:
                bases = op.new_value

            base_names = [
                b for b in bases.names(schema, allow_unresolved=True)
                if b != default_base and sn.shortname_from_fullname(b) == b
            ]

            if base_names:
                if isinstance(node, qlast.CreateObject):
                    node.bases = [
                        qlast.TypeName(maintype=qlast.ObjectRef(
                            name=b.name, module=b.module)) for b in base_names
                    ]
                else:
                    node.commands.append(
                        qlast.AlterAddInherit(bases=[
                            qlast.ObjectRef(module=b.module, name=b.name)
                            for b in base_names
                        ], ))

        elif op.property == 'is_abstract':
            node.is_abstract = op.new_value
        elif op.property == 'is_final':
            node.is_final = op.new_value
        else:
            super()._apply_field_ast(schema, context, node, op)
Пример #10
0
    def _classname_from_ast(cls, schema: s_schema.Schema,
                            astnode: qlast.NamedDDL,
                            context: sd.CommandContext) -> sn.Name:
        name = super()._classname_from_ast(schema, astnode, context)

        parent_ctx = cls.get_referrer_context(context)
        if parent_ctx is not None:
            assert isinstance(parent_ctx.op, sd.ObjectCommand)
            referrer_name = parent_ctx.op.classname

            try:
                base_ref = utils.ast_to_typeref(
                    qlast.TypeName(maintype=astnode.name),
                    modaliases=context.modaliases,
                    schema=schema)
            except errors.InvalidReferenceError:
                base_name = sn.Name(name)
            else:
                base_name = base_ref.get_name(schema)

            quals = cls._classname_quals_from_ast(schema, astnode, base_name,
                                                  referrer_name, context)
            pnn = sn.get_specialized_name(base_name, referrer_name, *quals)
            name = sn.Name(name=pnn, module=referrer_name.module)

        assert isinstance(name, sn.Name)
        return name
Пример #11
0
    def _apply_field_ast(self, schema, context, node, op):
        if op.property == 'bases':
            if not isinstance(op.new_value, so.ObjectList):
                bases = so.ObjectList.create(schema, op.new_value)
            else:
                bases = op.new_value

            base_names = bases.names(schema, allow_unresolved=True)

            node.bases = [
                qlast.TypeName(
                    maintype=qlast.ObjectRef(
                        name=b.name,
                        module=b.module
                    )
                )
                for b in base_names
            ]
        elif op.property == 'ancestors':
            pass
        elif op.property == 'is_abstract':
            node.is_abstract = op.new_value
        elif op.property == 'is_final':
            node.is_final = op.new_value
        else:
            super()._apply_field_ast(schema, context, node, op)
Пример #12
0
    def _prepare_field(self, node):
        path = self._context.path[-1]
        include_base = self._context.include_base[-1]

        is_top = self._is_top_level_field(node)

        spath = self._context.path[-1]
        prevt, target = self._get_parent_and_current_type()

        # insert normal or specialized link
        steps = []
        if include_base:
            base = spath[0].type
            steps.append(qlast.TypeIndirection(
                type=qlast.TypeName(
                    maintype=qlast.ObjectRef(
                        module=base.module,
                        name=base.short_name
                    ),
                ),
            ))
        steps.append(qlast.Ptr(
            ptr=qlast.ObjectRef(
                name=node.name.value
            )
        ))

        return is_top, path, prevt, target, steps
Пример #13
0
def get_config_type_shape(
    schema: s_schema.Schema,
    stype: s_objtypes.ObjectType,
    path: List[qlast.Base],
) -> List[qlast.ShapeElement]:
    from . import objtypes as s_objtypes
    shape = []
    seen: Set[str] = set()

    stypes = [stype] + list(stype.descendants(schema))

    for t in stypes:
        t_name = t.get_name(schema)

        for unqual_pn, p in t.get_pointers(schema).items(schema):
            pn = str(unqual_pn)
            if pn in ('id', '__type__') or pn in seen:
                continue

            elem_path: List[qlast.Base] = []

            if t != stype:
                elem_path.append(
                    qlast.TypeIntersection(type=qlast.TypeName(
                        maintype=qlast.ObjectRef(
                            module=t_name.module,
                            name=t_name.name,
                        ), ), ), )

            elem_path.append(qlast.Ptr(ptr=qlast.ObjectRef(name=pn)))

            ptype = p.get_target(schema)
            assert ptype is not None

            if isinstance(ptype, s_objtypes.ObjectType):
                subshape = get_config_type_shape(schema, ptype,
                                                 path + elem_path)
                subshape.append(
                    qlast.ShapeElement(
                        expr=qlast.Path(steps=[
                            qlast.Ptr(ptr=qlast.ObjectRef(name='_tname'), ),
                        ], ),
                        compexpr=qlast.Path(steps=path + elem_path + [
                            qlast.Ptr(ptr=qlast.ObjectRef(name='__type__')),
                            qlast.Ptr(ptr=qlast.ObjectRef(name='name')),
                        ], ),
                    ), )
            else:
                subshape = []

            shape.append(
                qlast.ShapeElement(
                    expr=qlast.Path(steps=elem_path),
                    elements=subshape,
                ), )

            seen.add(pn)

    return shape
Пример #14
0
    def visit_TypeCast(self, node):
        if node.to_type.subtypes:
            typ = qlast.TypeName(
                maintype=qlast.ObjectRef(name=node.to_type.collection),
                subtypes=[
                    qlast.ObjectRef(module=stn.module, name=stn.name)
                    for stn in node.to_type.subtypes
                ])
        else:
            to_type = self.context.schema.get_by_id(node.to_type.id)
            mtn = to_type.get_name(self.context.schema)
            mt = qlast.ObjectRef(module=mtn.module, name=mtn.name)
            typ = qlast.TypeName(maintype=mt)

        result = qlast.TypeCast(expr=self.visit(node.expr), type=typ)

        return result
Пример #15
0
    def visit_Variable(self, node):
        varname = node.name.value
        var = self._context.vars[varname]

        vartype = var.defn.type
        if isinstance(vartype, gql_ast.NonNullType):
            # TODO: Add non-null validation to the produced EdgeQL?
            vartype = vartype.type

        casttype = qlast.TypeName(maintype=qlast.ObjectRef(
            name=gt.GQL_TO_EDB_SCALARS_MAP[vartype.name.value]))
        # potentially this is an array
        if self.is_list_type(vartype):
            casttype = qlast.TypeName(maintype=qlast.ObjectRef(name='array'),
                                      subtypes=[casttype])

        return qlast.TypeCast(type=casttype,
                              expr=qlast.Parameter(name=varname))
Пример #16
0
 def reduce_COLON_TypedShape(self, *kids):
     # typed shape needs to be transformed here into a different
     # expression
     shape = kids[1].val
     self.val = [
         qlast.TypeName(maintype=shape.expr.steps[0],
                        context=context.get_context(shape.expr.steps[0]))
     ]
     self.val += shape.elements
Пример #17
0
def get_params_symtable(
    params: FuncParameterList,
    schema: s_schema.Schema,
    *,
    inlined_defaults: bool,
) -> Dict[str, qlast.Expr]:

    anchors: Dict[str, qlast.Expr] = {}

    defaults_mask = qlast.TypeCast(
        expr=qlast.Parameter(name='__defaults_mask__', optional=False),
        type=qlast.TypeName(
            maintype=qlast.ObjectRef(
                module='std',
                name='bytes',
            ),
        ),
    )

    for pi, p in enumerate(params.get_in_canonical_order(schema)):
        p_shortname = p.get_parameter_name(schema)
        p_is_optional = p.get_typemod(schema) is not ft.TypeModifier.SINGLETON
        anchors[p_shortname] = qlast.TypeCast(
            expr=qlast.Parameter(
                name=p_shortname,
                optional=p_is_optional,
            ),
            type=utils.typeref_to_ast(schema, p.get_type(schema)),
        )

        p_default = p.get_default(schema)
        if p_default is None:
            continue

        if not inlined_defaults:
            continue

        anchors[p_shortname] = qlast.IfElse(
            condition=qlast.BinOp(
                left=qlast.FunctionCall(
                    func=('std', 'bytes_get_bit'),
                    args=[
                        defaults_mask,
                        qlast.IntegerConstant(value=str(pi)),
                    ]),
                op='=',
                right=qlast.IntegerConstant(value='0'),
            ),
            if_expr=anchors[p_shortname],
            else_expr=qlast._Optional(expr=p_default.qlast),
        )

    return anchors
Пример #18
0
def get_config_type_shape(schema, stype,
                          path) -> typing.List[qlast.ShapeElement]:
    shape = []
    seen = set()

    stypes = [stype] + list(stype.descendants(schema))

    for t in stypes:
        t_name = t.get_name(schema)

        for pn, p in t.get_pointers(schema).items(schema):
            if pn in ('id', '__type__') or pn in seen:
                continue

            elem_path = []

            if t is not stype:
                elem_path.append(
                    qlast.TypeIndirection(type=qlast.TypeName(
                        maintype=qlast.ObjectRef(
                            module=t_name.module,
                            name=t_name.name,
                        ), ), ), )

            elem_path.append(qlast.Ptr(ptr=qlast.ObjectRef(name=pn)))

            ptype = p.get_target(schema)

            if ptype.is_object_type():
                subshape = get_config_type_shape(schema, ptype,
                                                 path + elem_path)
                subshape.append(
                    qlast.ShapeElement(
                        expr=qlast.Path(steps=[
                            qlast.Ptr(ptr=qlast.ObjectRef(name='_tname'), ),
                        ], ),
                        compexpr=qlast.Path(steps=path + elem_path + [
                            qlast.Ptr(ptr=qlast.ObjectRef(name='__type__')),
                            qlast.Ptr(ptr=qlast.ObjectRef(name='name')),
                        ], ),
                    ), )
            else:
                subshape = []

            shape.append(
                qlast.ShapeElement(
                    expr=qlast.Path(steps=elem_path),
                    elements=subshape,
                ), )

            seen.add(pn)

    return shape
Пример #19
0
    def _apply_field_ast(
        self,
        schema: s_schema.Schema,
        context: sd.CommandContext,
        node: qlast.DDLOperation,
        op: sd.AlterObjectProperty,
    ) -> None:
        if op.property == 'bases':
            mcls = self.get_schema_metaclass()
            default_base = mcls.get_default_base_name()

            bases = op.new_value
            assert isinstance(bases, so.ObjectList)

            base_names: List[sn.SchemaName] = [
                b for b in bases.names(schema, allow_unresolved=True)
                if isinstance(b, sn.SchemaName)
                if b != default_base and sn.shortname_from_fullname(b) == b
            ]

            if base_names:
                if isinstance(node, qlast.CreateObject):
                    node.bases = [
                        qlast.TypeName(
                            maintype=qlast.ObjectRef(
                                name=b.name,
                                module=b.module
                            )
                        )
                        for b in base_names
                    ]
                else:
                    node.commands.append(
                        qlast.AlterAddInherit(
                            bases=[
                                qlast.ObjectRef(
                                    module=b.module,
                                    name=b.name
                                )
                                for b in base_names
                            ],
                        )
                    )

        elif op.property == 'is_abstract':
            node.is_abstract = op.new_value
        elif op.property == 'is_final':
            node.is_final = op.new_value
        else:
            super()._apply_field_ast(schema, context, node, op)
Пример #20
0
    def from_ast(
        cls,
        schema: s_schema.Schema,
        modaliases: Mapping[Optional[str], str],
        num: int,
        astnode: qlast.FuncParam,
    ) -> ParameterDesc:

        paramd = None
        if astnode.default is not None:
            defexpr = expr.Expression.from_ast(
                astnode.default, schema, modaliases, as_fragment=True)
            paramd = expr.Expression.compiled(
                defexpr,
                schema,
                as_fragment=True,
                options=qlcompiler.CompilerOptions(
                    modaliases=modaliases,
                )
            )

        paramt_ast = astnode.type

        if astnode.kind is ft.ParameterKind.VARIADIC:
            paramt_ast = qlast.TypeName(
                maintype=qlast.ObjectRef(
                    name='array',
                ),
                subtypes=[paramt_ast],
            )

        assert isinstance(paramt_ast, qlast.TypeName)
        paramt = utils.ast_to_type_shell(
            paramt_ast,
            modaliases=modaliases,
            schema=schema,
        )

        return cls(
            num=num,
            name=astnode.name,
            type=paramt,
            typemod=astnode.typemod,
            kind=astnode.kind,
            default=paramd
        )
Пример #21
0
    def _apply_field_ast(self, schema, context, node, op):
        if op.property == 'default':
            if op.new_value:
                op.new_value = op.new_value[0]
                super()._apply_field_ast(schema, context, node, op)

        elif op.property == 'bases':
            enum_values = self.get_attribute_value('enum_values')
            if enum_values:
                node.bases = [
                    qlast.TypeName(
                        maintype=qlast.ObjectRef(name='enum'),
                        subtypes=[
                            qlast.TypeExprLiteral(
                                val=qlast.BaseConstant.from_python(v))
                            for v in enum_values
                        ])
                ]
            else:
                super()._apply_field_ast(schema, context, node, op)
        else:
            super()._apply_field_ast(schema, context, node, op)
Пример #22
0
    def _classname_from_ast(cls, schema, astnode, context):
        name = super()._classname_from_ast(schema, astnode, context)

        parent_ctx = cls.get_referrer_context(context)
        if parent_ctx is not None:
            referrer_name = parent_ctx.op.classname

            try:
                base_ref = utils.ast_to_typeref(
                    qlast.TypeName(maintype=astnode.name),
                    modaliases=context.modaliases, schema=schema)
            except errors.InvalidReferenceError:
                base_name = sn.Name(name)
            else:
                base_name = base_ref.get_name(schema)

            quals = cls._classname_quals_from_ast(
                schema, astnode, base_name, referrer_name, context)
            pnn = sn.get_specialized_name(base_name, referrer_name, *quals)
            name = sn.Name(name=pnn, module=referrer_name.module)

        return name
Пример #23
0
    def _get_general_offset_limit(self, after, before, first, last):
        # convert any static values to corresponding qlast
        if after is not None:
            if isinstance(after, qlast.Base):
                after = qlast.TypeCast(type=qlast.TypeName(
                    maintype=qlast.ObjectRef(name='int64')),
                                       expr=after)
            else:
                after = qlast.BaseConstant.from_python(after)
        if before is not None:
            if isinstance(before, qlast.Base):
                before = qlast.TypeCast(type=qlast.TypeName(
                    maintype=qlast.ObjectRef(name='int64')),
                                        expr=before)
            else:
                before = qlast.BaseConstant.from_python(before)
        if first is not None and not isinstance(first, qlast.Base):
            first = qlast.BaseConstant.from_python(first)
        if last is not None and not isinstance(last, qlast.Base):
            last = qlast.BaseConstant.from_python(last)

        offset = limit = None
        # convert before, after, first and last into offset and limit
        if after is not None:
            # The +1 is to make 'after' into an appropriate index.
            #
            # 0--a--1--b--2--c--3-- ... we call element at
            # index 0 (or "element 0" for short), the element
            # immediately after the mark 0. So after "element
            # 0" really means after "index 1".
            offset = qlast.BinOp(left=after,
                                 op='+',
                                 right=qlast.IntegerConstant(value='1'))

        if before is not None:
            # limit = before - (after or 0)
            if after:
                limit = qlast.BinOp(left=before, op='-', right=after)
            else:
                limit = before

        if first is not None:
            if limit is None:
                limit = first
            else:
                limit = qlast.IfElse(if_expr=first,
                                     condition=qlast.BinOp(left=first,
                                                           op='<',
                                                           right=limit),
                                     else_expr=limit)

        if last is not None:
            if limit is not None:
                if offset:
                    offset = qlast.BinOp(left=offset,
                                         op='+',
                                         right=qlast.BinOp(left=limit,
                                                           op='-',
                                                           right=last))
                else:
                    offset = qlast.BinOp(left=limit, op='-', right=last)

                limit = qlast.IfElse(if_expr=last,
                                     condition=qlast.BinOp(left=last,
                                                           op='<',
                                                           right=limit),
                                     else_expr=limit)

            else:
                # FIXME: there wasn't any limit, so we can define last
                # in terms of offset alone without negative OFFSET
                # implementation
                raise g_errors.GraphQLTranslationError(
                    f'last translates to a negative OFFSET in '
                    f'EdgeQL which is currently unsupported')

        return offset, limit
Пример #24
0
def typeref_to_ast(schema: s_schema.Schema,
                   t: so.Object,
                   *,
                   _name: Optional[str] = None) -> qlast.TypeExpr:
    from . import types as s_types

    if isinstance(t, so.ObjectRef):
        # We want typenames like 'anytype` that are wrapped in an
        # ObjectRef to be unwrapped to proper types, so that we
        # can generate proper AST nodes for them (e.g. for `anytype` it
        # is `qlast.AnyType()`).
        t = t._resolve_ref(schema)

    result: qlast.TypeExpr
    components: Tuple[so.ObjectRef, ...]

    if t.is_type() and cast(s_types.Type, t).is_any():
        result = qlast.TypeName(name=_name, maintype=qlast.AnyType())
    elif t.is_type() and cast(s_types.Type, t).is_anytuple():
        result = qlast.TypeName(name=_name, maintype=qlast.AnyTuple())
    elif isinstance(t, s_types.Tuple) and t.named:
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name=t.schema_name),
                                subtypes=[
                                    typeref_to_ast(schema,
                                                   cast(so.ObjectRef, st),
                                                   _name=sn)
                                    for sn, st in t.iter_subtypes(schema)
                                ])
    elif isinstance(t, (s_types.Array, s_types.Tuple)):
        # Here the concrete type Array is used because t.schema_name is used,
        # which is not defined for more generic collections and abcs
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name=t.schema_name),
                                subtypes=[
                                    typeref_to_ast(schema, st)
                                    for st in t.get_subtypes(schema)
                                ])
    elif isinstance(t, s_types.UnionTypeRef):
        components = t.get_union_of(schema)
        result = typeref_to_ast(schema, components[0])
        for component in components[1:]:
            result = qlast.TypeOp(
                left=result,
                op='|',
                right=typeref_to_ast(schema, component),
            )
    elif t.is_type() and cast(s_types.Type, t).is_union_type(schema):
        object_set: Optional[so.ObjectSet[s_types.Type]] = \
            cast(s_types.Type, t).get_union_of(schema)
        assert object_set is not None

        components = tuple(object_set.objects(schema))
        result = typeref_to_ast(schema, components[0])
        for component in components[1:]:
            result = qlast.TypeOp(
                left=result,
                op='|',
                right=typeref_to_ast(schema, component),
            )
    else:
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(
                                    module=t.get_name(schema).module,
                                    name=t.get_name(schema).name))

    return result
Пример #25
0
def shell_to_ast(
    schema: s_schema.Schema,
    t: so.ObjectShell,
    *,
    _name: Optional[str] = None,
) -> qlast.TypeExpr:
    from . import pseudo as s_pseudo
    from . import types as s_types

    result: qlast.TypeExpr
    qlref: qlast.BaseObjectRef

    if isinstance(t, s_pseudo.PseudoTypeShell):
        if t.name == 'anytype':
            qlref = qlast.AnyType()
        elif t.name == 'anytuple':
            qlref = qlast.AnyTuple()
        else:
            raise AssertionError(f'unexpected pseudo type shell: {t.name!r}')
        result = qlast.TypeName(name=_name, maintype=qlref)
    elif isinstance(t, s_types.TupleTypeShell):
        if t.is_named():
            result = qlast.TypeName(name=_name,
                                    maintype=qlast.ObjectRef(name='tuple', ),
                                    subtypes=[
                                        shell_to_ast(schema, st, _name=sn)
                                        for sn, st in t.iter_subtypes(schema)
                                    ])
        else:
            result = qlast.TypeName(name=_name,
                                    maintype=qlast.ObjectRef(name='tuple', ),
                                    subtypes=[
                                        shell_to_ast(schema, st)
                                        for st in t.get_subtypes(schema)
                                    ])
    elif isinstance(t, s_types.ArrayTypeShell):
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name='array', ),
                                subtypes=[
                                    shell_to_ast(schema, st)
                                    for st in t.get_subtypes(schema)
                                ])
    elif isinstance(t, s_types.UnionTypeShell):
        components = t.get_components(schema)
        result = typeref_to_ast(schema, components[0])
        for component in components[1:]:
            result = qlast.TypeOp(
                left=result,
                op='|',
                right=typeref_to_ast(schema, component),
            )
    elif isinstance(t, so.ObjectShell):
        name = t.name
        if isinstance(name, sn.SchemaName):
            qlref = qlast.ObjectRef(
                module=name.module,
                name=name.name,
            )
        else:
            qlref = qlast.ObjectRef(
                module='',
                name=name,
            )
        result = qlast.TypeName(
            name=_name,
            maintype=qlref,
        )
    else:
        raise NotImplementedError(f'cannot represent {t!r} as a shell')

    return result
Пример #26
0
def typeref_to_ast(
    schema: s_schema.Schema,
    ref: Union[so.Object, so.ObjectShell],
    *,
    _name: Optional[str] = None,
    disambiguate_std: bool = False,
) -> qlast.TypeExpr:
    from . import types as s_types

    if isinstance(ref, so.ObjectShell):
        return shell_to_ast(schema, ref)
    else:
        t = ref

    result: qlast.TypeExpr
    components: Tuple[so.Object, ...]

    if t.is_type() and cast(s_types.Type, t).is_any(schema):
        result = qlast.TypeName(name=_name, maintype=qlast.AnyType())
    elif t.is_type() and cast(s_types.Type, t).is_anytuple(schema):
        result = qlast.TypeName(name=_name, maintype=qlast.AnyTuple())
    elif isinstance(t, s_types.Tuple) and t.is_named(schema):
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name=t.schema_name),
                                subtypes=[
                                    typeref_to_ast(
                                        schema,
                                        st,
                                        _name=sn,
                                        disambiguate_std=disambiguate_std)
                                    for sn, st in t.iter_subtypes(schema)
                                ])
    elif isinstance(t, (s_types.Array, s_types.Tuple)):
        # Here the concrete type Array is used because t.schema_name is used,
        # which is not defined for more generic collections and abcs
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(name=t.schema_name),
                                subtypes=[
                                    typeref_to_ast(
                                        schema,
                                        st,
                                        disambiguate_std=disambiguate_std)
                                    for st in t.get_subtypes(schema)
                                ])
    elif t.is_type() and cast(s_types.Type, t).is_union_type(schema):
        object_set: Optional[so.ObjectSet[s_types.Type]] = \
            cast(s_types.Type, t).get_union_of(schema)
        assert object_set is not None

        component_objects = tuple(object_set.objects(schema))
        result = typeref_to_ast(schema,
                                component_objects[0],
                                disambiguate_std=disambiguate_std)
        for component_object in component_objects[1:]:
            result = qlast.TypeOp(
                left=result,
                op='|',
                right=typeref_to_ast(schema,
                                     component_object,
                                     disambiguate_std=disambiguate_std),
            )
    elif isinstance(t, so.QualifiedObject):
        t_name = t.get_name(schema)
        module = t_name.module
        if disambiguate_std and module == 'std':
            # If the type is defined in 'std::', replace the module to
            # '__std__' to handle cases where 'std' name is aliased to
            # another module.
            module = '__std__'
        result = qlast.TypeName(name=_name,
                                maintype=qlast.ObjectRef(module=module,
                                                         name=t_name.name))
    else:
        raise NotImplementedError(f'cannot represent {t!r} as a shell')

    return result
Пример #27
0
 def reduce_NodeName_LANGBRACKET_SubtypeList_RANGBRACKET(self, *kids):
     self.val = qlast.TypeName(
         maintype=kids[0].val,
         subtypes=kids[2].val,
     )
Пример #28
0
 def reduce_ANYTUPLE(self, *kids):
     self.val = qlast.TypeName(maintype=qlast.AnyTuple())
Пример #29
0
 def reduce_ANYTYPE(self, *kids):
     self.val = qlast.TypeName(maintype=qlast.AnyType())
Пример #30
0
 def reduce_NodeName(self, *kids):
     self.val = qlast.TypeName(maintype=kids[0].val)