optimize Type::symbols()

This commit is contained in:
Folkert 2022-03-10 22:29:37 +01:00
parent 76a118db14
commit 4ce7221c39
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C

View file

@ -713,11 +713,8 @@ impl Type {
} }
} }
pub fn symbols(&self) -> ImSet<Symbol> { pub fn symbols(&self) -> Vec<Symbol> {
let mut found_symbols = ImSet::default(); symbols_help(self)
symbols_help(self, &mut found_symbols);
found_symbols
} }
/// a shallow dealias, continue until the first constructor is not an alias. /// a shallow dealias, continue until the first constructor is not an alias.
@ -934,62 +931,61 @@ impl Type {
} }
} }
fn symbols_help(tipe: &Type, accum: &mut ImSet<Symbol>) { fn symbols_help(initial: &Type) -> Vec<Symbol> {
use Type::*; use Type::*;
match tipe { let mut output = vec![];
Function(args, closure, ret) => { let mut stack = vec![initial];
symbols_help(ret, accum);
symbols_help(closure, accum);
args.iter().for_each(|arg| symbols_help(arg, accum));
}
FunctionOrTagUnion(_, _, ext) => {
symbols_help(ext, accum);
}
RecursiveTagUnion(_, tags, ext) | TagUnion(tags, ext) => {
symbols_help(ext, accum);
tags.iter()
.map(|v| v.1.iter())
.flatten()
.for_each(|arg| symbols_help(arg, accum));
}
Record(fields, ext) => { while let Some(tipe) = stack.pop() {
symbols_help(ext, accum); match tipe {
fields.values().for_each(|field| { Function(args, closure, ret) => {
use RecordField::*; stack.push(ret);
stack.push(closure);
stack.extend(args);
}
FunctionOrTagUnion(_, _, ext) => {
stack.push(ext);
}
RecursiveTagUnion(_, tags, ext) | TagUnion(tags, ext) => {
stack.push(ext);
stack.extend(tags.iter().map(|v| v.1.iter()).flatten());
}
match field { Record(fields, ext) => {
Optional(arg) => symbols_help(arg, accum), stack.push(ext);
Required(arg) => symbols_help(arg, accum), stack.extend(fields.values().map(|field| field.as_inner()));
Demanded(arg) => symbols_help(arg, accum), }
} Alias {
}); symbol: alias_symbol,
actual: actual_type,
..
} => {
output.push(*alias_symbol);
stack.push(actual_type);
}
HostExposedAlias { name, actual, .. } => {
output.push(*name);
stack.push(actual);
}
Apply(symbol, args, _) => {
output.push(*symbol);
stack.extend(args);
}
Erroneous(Problem::CyclicAlias(alias, _, _)) => {
output.push(*alias);
}
RangedNumber(typ, _) => {
stack.push(typ);
}
EmptyRec | EmptyTagUnion | ClosureTag { .. } | Erroneous(_) | Variable(_) => {}
} }
Alias {
symbol: alias_symbol,
actual: actual_type,
..
} => {
accum.insert(*alias_symbol);
symbols_help(actual_type, accum);
}
HostExposedAlias { name, actual, .. } => {
accum.insert(*name);
symbols_help(actual, accum);
}
Apply(symbol, args, _) => {
accum.insert(*symbol);
args.iter().for_each(|arg| symbols_help(arg, accum));
}
Erroneous(Problem::CyclicAlias(alias, _, _)) => {
accum.insert(*alias);
}
RangedNumber(typ, _) => {
symbols_help(typ, accum);
}
EmptyRec | EmptyTagUnion | ClosureTag { .. } | Erroneous(_) | Variable(_) => {}
} }
output.sort();
output.dedup();
output
} }
fn variables_help(tipe: &Type, accum: &mut ImSet<Variable>) { fn variables_help(tipe: &Type, accum: &mut ImSet<Variable>) {