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,64 +931,63 @@ impl Type {
} }
} }
fn symbols_help(tipe: &Type, accum: &mut ImSet<Symbol>) { fn symbols_help(initial: &Type) -> Vec<Symbol> {
use Type::*; use Type::*;
let mut output = vec![];
let mut stack = vec![initial];
while let Some(tipe) = stack.pop() {
match tipe { match tipe {
Function(args, closure, ret) => { Function(args, closure, ret) => {
symbols_help(ret, accum); stack.push(ret);
symbols_help(closure, accum); stack.push(closure);
args.iter().for_each(|arg| symbols_help(arg, accum)); stack.extend(args);
} }
FunctionOrTagUnion(_, _, ext) => { FunctionOrTagUnion(_, _, ext) => {
symbols_help(ext, accum); stack.push(ext);
} }
RecursiveTagUnion(_, tags, ext) | TagUnion(tags, ext) => { RecursiveTagUnion(_, tags, ext) | TagUnion(tags, ext) => {
symbols_help(ext, accum); stack.push(ext);
tags.iter() stack.extend(tags.iter().map(|v| v.1.iter()).flatten());
.map(|v| v.1.iter())
.flatten()
.for_each(|arg| symbols_help(arg, accum));
} }
Record(fields, ext) => { Record(fields, ext) => {
symbols_help(ext, accum); stack.push(ext);
fields.values().for_each(|field| { stack.extend(fields.values().map(|field| field.as_inner()));
use RecordField::*;
match field {
Optional(arg) => symbols_help(arg, accum),
Required(arg) => symbols_help(arg, accum),
Demanded(arg) => symbols_help(arg, accum),
}
});
} }
Alias { Alias {
symbol: alias_symbol, symbol: alias_symbol,
actual: actual_type, actual: actual_type,
.. ..
} => { } => {
accum.insert(*alias_symbol); output.push(*alias_symbol);
symbols_help(actual_type, accum); stack.push(actual_type);
} }
HostExposedAlias { name, actual, .. } => { HostExposedAlias { name, actual, .. } => {
accum.insert(*name); output.push(*name);
symbols_help(actual, accum); stack.push(actual);
} }
Apply(symbol, args, _) => { Apply(symbol, args, _) => {
accum.insert(*symbol); output.push(*symbol);
args.iter().for_each(|arg| symbols_help(arg, accum)); stack.extend(args);
} }
Erroneous(Problem::CyclicAlias(alias, _, _)) => { Erroneous(Problem::CyclicAlias(alias, _, _)) => {
accum.insert(*alias); output.push(*alias);
} }
RangedNumber(typ, _) => { RangedNumber(typ, _) => {
symbols_help(typ, accum); stack.push(typ);
} }
EmptyRec | EmptyTagUnion | ClosureTag { .. } | Erroneous(_) | Variable(_) => {} 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>) {
use Type::*; use Type::*;