feat: a lot
This commit is contained in:
@@ -256,40 +256,6 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
|
||||
let param = downgrade_param(self.param().unwrap(), ctx)?;
|
||||
let mut body = self.body().unwrap().downgrade(ctx)?;
|
||||
|
||||
// Desugar pattern matching in function arguments into a `let` expression.
|
||||
// For example, `({ a, b ? 2 }): a + b` is desugared into:
|
||||
// `arg: let a = arg.a; b = arg.b or 2; in a + b`
|
||||
if let Param::Formals { formals, alias, .. } = ¶m {
|
||||
// `Arg` represents the raw argument (the attribute set) passed to the function.
|
||||
let arg = ctx.new_expr(Hir::Arg(Arg));
|
||||
let mut bindings: HashMap<_, _> = formals
|
||||
.iter()
|
||||
.map(|&(ref k, default)| {
|
||||
// For each formal parameter, create a `Select` expression to extract it from the argument set.
|
||||
(
|
||||
k.clone(),
|
||||
ctx.new_expr(
|
||||
Select {
|
||||
expr: arg,
|
||||
attrpath: vec![Attr::Str(k.clone())],
|
||||
default,
|
||||
}
|
||||
.to_hir(),
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
// If there's an alias (`... }@alias`), bind the alias name to the raw argument set.
|
||||
if let Some(alias) = alias {
|
||||
bindings.insert(
|
||||
alias.clone(),
|
||||
ctx.new_expr(Var { sym: alias.clone() }.to_hir()),
|
||||
);
|
||||
}
|
||||
// Wrap the original function body in the new `let` expression.
|
||||
let let_ = Let { bindings, body };
|
||||
body = ctx.new_expr(let_.to_hir());
|
||||
}
|
||||
let ident;
|
||||
let required;
|
||||
let allowed;
|
||||
@@ -304,22 +270,55 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
|
||||
ellipsis,
|
||||
alias,
|
||||
} => {
|
||||
ident = alias;
|
||||
ident = alias.clone();
|
||||
required = Some(
|
||||
formals
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|(_, default)| default.is_none())
|
||||
.map(|(k, _)| k)
|
||||
.map(|(k, _)| k.clone())
|
||||
.collect(),
|
||||
);
|
||||
allowed = if ellipsis {
|
||||
None
|
||||
} else {
|
||||
Some(formals.into_iter().map(|(k, _)| k).collect())
|
||||
Some(formals.iter().map(|(k, _)| k.clone()).collect())
|
||||
};
|
||||
|
||||
// Desugar pattern matching in function arguments into a `let` expression.
|
||||
// For example, `({ a, b ? 2 }): a + b` is desugared into:
|
||||
// `arg: let a = arg.a; b = arg.b or 2; in a + b`
|
||||
let mut bindings: HashMap<_, _> = formals
|
||||
.into_iter()
|
||||
.map(|(k, default)| {
|
||||
// For each formal parameter, create a `Select` expression to extract it from the argument set.
|
||||
// `Arg` represents the raw argument (the attribute set) passed to the function.
|
||||
let arg = ctx.new_expr(Hir::Arg(Arg));
|
||||
(
|
||||
k.clone(),
|
||||
ctx.new_expr(
|
||||
Select {
|
||||
expr: arg,
|
||||
attrpath: vec![Attr::Str(k.clone())],
|
||||
default,
|
||||
}
|
||||
.to_hir(),
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
// If there's an alias (`... }@alias`), bind the alias name to the raw argument set.
|
||||
if let Some(alias) = alias {
|
||||
bindings.insert(
|
||||
alias.clone(),
|
||||
ctx.new_expr(Var { sym: alias.clone() }.to_hir()),
|
||||
);
|
||||
}
|
||||
// Wrap the original function body in the new `let` expression.
|
||||
let let_ = Let { bindings, body };
|
||||
body = ctx.new_expr(let_.to_hir());
|
||||
}
|
||||
}
|
||||
|
||||
let param = ir::Param {
|
||||
ident,
|
||||
required,
|
||||
|
||||
@@ -40,7 +40,7 @@ pub trait DowngradeContext {
|
||||
fn with_expr<T>(&self, id: ExprId, f: impl FnOnce(&Hir, &Self) -> T) -> T;
|
||||
|
||||
/// Provides temporary mutable access to an expression.
|
||||
fn with_expr_mut<T>(&mut self, id: ExprId, f: impl FnOnce(&mut Hir, &mut Self) -> T) -> T;
|
||||
fn with_expr_mut<T>(&mut self, id: &ExprId, f: impl FnOnce(&mut Hir, &mut Self) -> T) -> T;
|
||||
}
|
||||
|
||||
ir! {
|
||||
@@ -123,7 +123,7 @@ impl Attrs for AttrSet {
|
||||
match attr {
|
||||
Attr::Str(ident) => {
|
||||
// If the next attribute is a static string.
|
||||
if let Some(&id) = self.stcs.get(&ident) {
|
||||
if let Some(id) = self.stcs.get(&ident) {
|
||||
// If a sub-attrset already exists, recurse into it.
|
||||
ctx.with_expr_mut(id, |expr, ctx| {
|
||||
expr.as_mut()
|
||||
@@ -186,7 +186,7 @@ impl Attrs for AttrSet {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
enum Param {
|
||||
/// A simple parameter, e.g., `x: ...`.
|
||||
Ident(String),
|
||||
|
||||
@@ -125,13 +125,13 @@ pub fn downgrade_inherit(
|
||||
));
|
||||
}
|
||||
};
|
||||
let expr = from.map_or_else(
|
||||
let expr = from.as_ref().map_or_else(
|
||||
// If `from` is None, `inherit foo;` becomes `foo = foo;`.
|
||||
|| Var { sym: ident.clone() }.to_hir(),
|
||||
// If `from` is Some, `inherit (from) foo;` becomes `foo = from.foo;`.
|
||||
|expr| {
|
||||
Select {
|
||||
expr,
|
||||
expr: unsafe { expr.clone() },
|
||||
attrpath: vec![Attr::Str(ident.clone())],
|
||||
default: None,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user