Lots more work to speed up the solver when it's fed large initialized data structures.
Lots more work to speed up the solver when it's fed large initialized data structures.

s_let.counter:
  count the number of variables that are moved into this let
multi.__init__():
multi.free():
  compute free variables only when needed.
get_compress_key():
  used to compress the set of equations in the unifier.
  experimentally this actually slows things down, so not used.
unifier.split():
  don't cast sz.vars to a set, it already is one. (avoids a copy)
  call eq.free() to compute it on the fly
unifier.simplify():
  avoid another cast to set()
solver.__init__():
  try_unname - a flag to tell us to try to shrink the current s_let()
solver.solve():
  if try_unname is set, call do_extra_unname().
  use difference_update() to update s_let.vars directly rather than copying
solver.move_exists():
  keep a running counter of the number of variables attached to this s_let(),
    every 1000 set the try_unname() flag.
solver.do_extra_unname():
 When solving for a large data structure, the normal split/unname
  isn't called until it's all over.  Even relatively small data
  structures run into the tens of thousands of tvars. 
ftv():
  no longer needed


samrushing/irken-compiler,samrushing/irken-compiler,samrushing/irken-compiler,samrushing/irken-compiler