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)
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
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)
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
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
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
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
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')), ], ), ), )
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)
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
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)
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
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
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
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))
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
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
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
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)
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 )
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)
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
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
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
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
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
def reduce_NodeName_LANGBRACKET_SubtypeList_RANGBRACKET(self, *kids): self.val = qlast.TypeName( maintype=kids[0].val, subtypes=kids[2].val, )
def reduce_ANYTUPLE(self, *kids): self.val = qlast.TypeName(maintype=qlast.AnyTuple())
def reduce_ANYTYPE(self, *kids): self.val = qlast.TypeName(maintype=qlast.AnyType())
def reduce_NodeName(self, *kids): self.val = qlast.TypeName(maintype=kids[0].val)