147 lines
4.5 KiB
Rust
147 lines
4.5 KiB
Rust
use rnix::ast;
|
|
|
|
use super::*;
|
|
|
|
pub fn downgrade_param(param: ast::Param, ctx: &mut DowngradeContext) -> Result<Param> {
|
|
match param {
|
|
ast::Param::IdentParam(ident) => Ok(Param::Ident(ident.to_string().into())),
|
|
ast::Param::Pattern(pattern) => downgrade_pattern(pattern, ctx),
|
|
}
|
|
}
|
|
|
|
pub fn downgrade_pattern(pattern: ast::Pattern, ctx: &mut DowngradeContext) -> Result<Param> {
|
|
let formals = pattern
|
|
.pat_entries()
|
|
.map(|entry| {
|
|
let ident = entry.ident().unwrap().to_string().into();
|
|
if entry.default().is_none() {
|
|
Ok((ident, None))
|
|
} else {
|
|
entry
|
|
.default()
|
|
.unwrap()
|
|
.downgrade(ctx)
|
|
.map(|ok| (ident, Some(ctx.new_thunk(ok))))
|
|
}
|
|
})
|
|
.collect::<Result<Vec<_>>>()?;
|
|
let ellipsis = pattern.ellipsis_token().is_some();
|
|
let alias = pattern
|
|
.pat_bind()
|
|
.map(|alias| alias.ident().unwrap().to_string().into());
|
|
Ok(Param::Formals {
|
|
formals,
|
|
ellipsis,
|
|
alias,
|
|
})
|
|
}
|
|
|
|
pub fn downgrade_attrs(has_entry: impl ast::HasEntry, ctx: &mut DowngradeContext) -> Result<Attrs> {
|
|
let entires = has_entry.entries();
|
|
let mut attrs = Attrs {
|
|
stcs: HashMap::new(),
|
|
dyns: Vec::new(),
|
|
};
|
|
|
|
for entry in entires {
|
|
match entry {
|
|
ast::Entry::Inherit(inherit) => downgrade_inherit(inherit, &mut attrs.stcs, ctx)?,
|
|
ast::Entry::AttrpathValue(value) => downgrade_attrpathvalue(value, &mut attrs, ctx)?,
|
|
}
|
|
}
|
|
|
|
Ok(attrs)
|
|
}
|
|
|
|
pub fn downgrade_inherit(
|
|
inherit: ast::Inherit,
|
|
stcs: &mut HashMap<String, Ir>,
|
|
ctx: &mut DowngradeContext,
|
|
) -> Result<()> {
|
|
let from = if let Some(from) = inherit.from() {
|
|
let from = from.expr().unwrap().downgrade(ctx)?;
|
|
Some(ctx.new_thunk(from))
|
|
} else {
|
|
None
|
|
};
|
|
for attr in inherit.attrs() {
|
|
let ident = match downgrade_attr(attr, ctx)? {
|
|
Attr::Str(ident) => ident,
|
|
_ => {
|
|
return Err(Error::DowngradeError(
|
|
"dynamic attributes not allowed in inherit".to_string(),
|
|
));
|
|
}
|
|
};
|
|
let expr = from.map_or_else(
|
|
|| Var { sym: ident.clone() }.ir().ok(),
|
|
|from| {
|
|
Ok(Select {
|
|
expr: from.ir().boxed(),
|
|
attrpath: vec![Attr::Str(ident.clone())],
|
|
default: None,
|
|
}
|
|
.ir())
|
|
},
|
|
)?;
|
|
// TODO: Error Handling
|
|
assert!(stcs.insert(ident, expr).is_none());
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn downgrade_attr(attr: ast::Attr, ctx: &mut DowngradeContext) -> Result<Attr> {
|
|
use ast::Attr::*;
|
|
use ast::InterpolPart::*;
|
|
match attr {
|
|
Ident(ident) => Ok(Attr::Str(ident.to_string().into())),
|
|
Str(string) => {
|
|
let parts = string.normalized_parts();
|
|
if parts.is_empty() {
|
|
Ok(Attr::Str("".into()))
|
|
} else if parts.len() == 1 {
|
|
match parts.into_iter().next().unwrap() {
|
|
Literal(ident) => Ok(Attr::Str(ident.into())),
|
|
Interpolation(interpol) => {
|
|
Ok(Attr::Dynamic(interpol.expr().unwrap().downgrade(ctx)?))
|
|
}
|
|
}
|
|
} else {
|
|
let parts = parts
|
|
.into_iter()
|
|
.map(|part| match part {
|
|
Literal(lit) => self::Str { val: lit.into() }.ir().ok(),
|
|
Interpolation(interpol) => interpol.expr().unwrap().downgrade(ctx),
|
|
})
|
|
.collect::<Result<Vec<_>>>()?;
|
|
Ok(Attr::Strs(ConcatStrings { parts }))
|
|
}
|
|
}
|
|
Dynamic(dynamic) => Ok(Attr::Dynamic(dynamic.expr().unwrap().downgrade(ctx)?)),
|
|
}
|
|
}
|
|
|
|
pub fn downgrade_attrpath(
|
|
attrpath: ast::Attrpath,
|
|
ctx: &mut DowngradeContext,
|
|
) -> Result<Vec<Attr>> {
|
|
attrpath
|
|
.attrs()
|
|
.map(|attr| downgrade_attr(attr, ctx))
|
|
.collect::<Result<Vec<_>>>()
|
|
}
|
|
|
|
pub fn downgrade_attrpathvalue(
|
|
value: ast::AttrpathValue,
|
|
attrs: &mut Attrs,
|
|
ctx: &mut DowngradeContext,
|
|
) -> Result<()> {
|
|
let path = downgrade_attrpath(value.attrpath().unwrap(), ctx)?;
|
|
let value = value.value().unwrap().downgrade(ctx)?;
|
|
let value = match value {
|
|
x @ Ir::Const(_) => x,
|
|
x => ctx.new_thunk(x).ir(),
|
|
};
|
|
attrs.insert(path, value, ctx)
|
|
}
|