fn shape()

in antlir/bzl/shape2/bzl2ir.rs [166:292]


fn shape(builder: &mut GlobalsBuilder) {
    fn shape(kwargs: DictOf<'v, &str, Value<'v>>) -> anyhow::Result<TypeId> {
        let mut reg = get_type_registry(eval)?.try_borrow_mut()?;
        let fields = kwargs
            .to_dict()
            .into_iter()
            .filter(|(key, _)| *key != "__I_AM_TARGET__")
            .map(|(key, val)| val.try_to_field(&reg).map(|f| (key.into(), f)))
            .collect::<Result<_>>()?;
        let s = ir::Struct {
            fields,
            docstring: None,
            name: None,
        };
        let ty = ir::Type::Complex(ir::ComplexType::Struct(s));
        Ok(reg.add(ty))
    }

    fn list(ty: Value<'v>) -> anyhow::Result<StarlarkType> {
        let reg = get_type_registry(eval)?.try_borrow()?;
        ty.try_to_type(&reg)
            .map(|ty| ir::Type::List { item_type: ty })
            .map(Rc::new)
            .map(StarlarkType)
    }

    fn r#enum(args: Value<'v>) -> anyhow::Result<TypeId> {
        let mut reg = get_type_registry(eval)?.try_borrow_mut()?;
        let options = args
            .iterate_collect(heap)
            .context("while collecting enum variants")?
            .into_iter()
            .map(|v| String::unpack_param(v).map(|s| s.into()))
            .collect::<Result<_>>()?;
        let enm = ir::Enum {
            options,
            docstring: None,
            name: None,
        };
        let ty = ir::Type::Complex(ir::ComplexType::Enum(enm));
        Ok(reg.add(ty))
    }

    fn field(
        ty: Value<'v>,
        optional @ false: bool,
        default: Option<Value<'v>>,
    ) -> anyhow::Result<StarlarkField> {
        let reg = get_type_registry(eval)?.try_borrow()?;
        ty.try_to_type(&reg)
            .and_then(|ty| {
                Ok(ir::Field {
                    ty,
                    required: !optional,
                    default_value: default
                        .map(|d| {
                            d.to_json().and_then(|s| {
                                serde_json::from_str(&s).context("parsing result of to_json")
                            })
                        })
                        .transpose()?,
                })
            })
            .map(StarlarkField)
    }

    fn new(
        _shape: Value<'v>,
        kwargs: DictOf<'v, StringValue<'v>, Value<'v>>,
    ) -> anyhow::Result<StructGen<'v, Value<'v>>> {
        // no need to type-check, since it will already be done at buck parse
        // time, and will also be done when loading the json
        Ok(StructGen::new(kwargs.to_dict()))
    }

    fn dict(key_type: Value<'v>, value_type: Value<'v>) -> anyhow::Result<StarlarkType> {
        let reg = get_type_registry(eval)?.try_borrow()?;
        let key_type = key_type
            .try_to_type(&reg)
            .context("dict key must be a type")?;
        let value_type = value_type
            .try_to_type(&reg)
            .context("dict value must be a type")?;
        Ok(StarlarkType(Rc::new(ir::Type::Map {
            key_type,
            value_type,
        })))
    }

    fn tuple(args: Value<'v>) -> anyhow::Result<StarlarkType> {
        let reg = get_type_registry(eval)?.try_borrow()?;
        let item_types = args
            .iterate_collect(heap)?
            .into_iter()
            .enumerate()
            .map(|(i, v)| {
                v.try_to_type(&reg)
                    .with_context(|| format!("tuple item at {} is not a type", i))
            })
            .collect::<Result<_>>()?;
        Ok(StarlarkType(Rc::new(ir::Type::Tuple { item_types })))
    }

    fn union(args: Value<'v>) -> anyhow::Result<TypeId> {
        let mut reg = get_type_registry(eval)?.try_borrow_mut()?;
        let types = args
            .iterate_collect(heap)?
            .into_iter()
            .enumerate()
            .map(|(i, v)| {
                v.try_to_type(&reg)
                    .with_context(|| format!("union item at {} is not a type", i))
            })
            .collect::<Result<_>>()?;
        let u = ir::Union {
            types,
            docstring: None,
            name: None,
        };
        let ty = ir::Type::Complex(ir::ComplexType::Union(u));
        Ok(reg.add(ty))
    }

    fn path() -> anyhow::Result<StarlarkField> {
        Err(anyhow!("shape.path is no longer a callable function"))
    }
}