optimize: dedup consts

This commit is contained in:
2025-05-15 19:11:34 +08:00
parent 864be73e77
commit 1e50322af0
8 changed files with 51 additions and 31 deletions

View File

@@ -112,7 +112,7 @@ ir! {
With => { namespace: Box<Ir>, expr: Box<Ir> },
Assert => { assertion: Box<Ir>, expr: Box<Ir> },
ConcatStrings => { parts: Vec<Ir> },
Const => { value: i::Const },
Const => { idx: usize },
Var => { sym: usize },
#[derive(Copy)]
Thunk => { idx: usize },
@@ -127,6 +127,7 @@ pub struct DowngradeContext {
thunks: Vec<Ir>,
funcs: Vec<Func>,
consts: Vec<i::Const>,
constmap: HashMap<i::Const, usize>,
symbols: Vec<EcoString>,
symmap: HashMap<EcoString, usize>,
}
@@ -157,6 +158,16 @@ impl DowngradeContext {
LoadFunc { idx }
}
fn new_const(&mut self, cnst: i::Const) -> Const {
if let Some(&idx) = self.constmap.get(&cnst) {
Const { idx }
} else {
self.constmap.insert(cnst.clone(), self.consts.len());
self.consts.push(cnst);
Const { idx: self.consts.len() - 1 }
}
}
fn new_sym(&mut self, sym: impl Into<EcoString>) -> usize {
let sym = sym.into();
if let Some(&idx) = self.symmap.get(&sym) {
@@ -414,9 +425,7 @@ impl Downgrade for ast::Path {
let parts = self
.parts()
.map(|part| match part {
ast::InterpolPart::Literal(lit) => Const {
value: lit.to_string().into(),
}
ast::InterpolPart::Literal(lit) => ctx.new_const(lit.to_string().into())
.ir()
.ok(),
ast::InterpolPart::Interpolation(interpol) => {
@@ -444,7 +453,7 @@ impl Downgrade for ast::Str {
.normalized_parts()
.into_iter()
.map(|part| match part {
ast::InterpolPart::Literal(lit) => Const { value: lit.into() }.ir().ok(),
ast::InterpolPart::Literal(lit) => ctx.new_const(lit.into()).ir().ok(),
ast::InterpolPart::Interpolation(interpol) => {
interpol.expr().unwrap().downgrade(ctx)
}
@@ -459,17 +468,11 @@ impl Downgrade for ast::Str {
}
impl Downgrade for ast::Literal {
fn downgrade(self, _ctx: &mut DowngradeContext) -> Result<Ir> {
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
match self.kind() {
ast::LiteralKind::Integer(int) => Const {
value: int.value().unwrap().into(),
},
ast::LiteralKind::Float(float) => Const {
value: float.value().unwrap().into(),
},
ast::LiteralKind::Uri(uri) => Const {
value: uri.to_string().into(),
},
ast::LiteralKind::Integer(int) => ctx.new_const(int.value().unwrap().into()),
ast::LiteralKind::Float(float) => ctx.new_const(float.value().unwrap().into()),
ast::LiteralKind::Uri(uri) => ctx.new_const(uri.to_string().into())
}
.ir()
.ok()
@@ -519,11 +522,6 @@ impl Downgrade for ast::HasAttr {
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
let attrs = self.expr().unwrap().downgrade(ctx)?;
let path = downgrade_attrpath(self.attrpath().unwrap(), ctx)?;
if let Some(attrs) = Downcast::<Attrs>::downcast_ref(&attrs) {
if let Some(res) = attrs.has_attr(&path) {
return Const { value: res.into() }.ir().ok();
}
}
HasAttr {
lhs: attrs.boxed(),
rhs: path,
@@ -730,7 +728,7 @@ fn downgrade_attr(attr: ast::Attr, ctx: &mut DowngradeContext) -> Result<Attr> {
let parts = parts
.into_iter()
.map(|part| match part {
Literal(lit) => Const { value: lit.into() }.ir().ok(),
Literal(lit) => ctx.new_const(lit.into()).ir().ok(),
Interpolation(interpol) => interpol.expr().unwrap().downgrade(ctx),
})
.collect::<Result<Vec<_>>>()?;