def pre_cond?(blk, slf, inst, bind, *args)
      states = [[0, 0]] # [position in @arg, position in args]
      preds = []
      until states.empty?
        formal, actual = states.pop
        if formal == @args.size && actual == args.size then # Matched all actuals, no formals left over
	  check_arg_preds(bind, preds) if preds.size > 0
          @args.each_with_index {|a,i| args[i] = block_wrap(slf, inst, a, bind, &args[i]) if a.is_a? MethodType }
          if @block then
            if @block.is_a? OptionalType
              blk = block_wrap(slf, inst, @block.type.instantiate(inst), bind, &blk) if blk
            else
              next unless blk
              blk = block_wrap(slf, inst, @block, bind, &blk)
            end
          elsif blk then
            next
          end
          return [true, args, blk, bind]
        end
        next if formal >= @args.size # Too many actuals to match
        t = @args[formal]
        if t.instance_of? AnnotatedArgType then
	        bind.local_variable_set(t.name.to_sym,args[actual])
	        t = t.type
        end
        case t
        when OptionalType
          t = t.type.instantiate(inst)
          if actual == args.size
            states << [formal+1, actual] # skip to allow extra formal optionals at end
          elsif t.is_a? MethodType
            if args[actual].is_a? Proc
              args[actual] = block_wrap(slf, inst, t, bind, &args[actual])
              states << [formal+1, actual+1]
            elsif args[actual].nil?
              states << [formal+1, actual+1] # match
              states << [formal+1, actual] # skip
            else
              states << [formal+1, actual]
            end
          elsif t.member?(args[actual], vars_wild: true)
            states << [formal+1, actual+1] # match
            states << [formal+1, actual] # skip
          else
            states << [formal+1, actual]  # types don't match; must skip this formal
          end
        when VarargType
          t = t.type.instantiate(inst)
          if actual == args.size
            states << [formal+1, actual] # skip to allow empty vararg at end
          elsif t.member?(args[actual], vars_wild: true)
            states << [formal, actual+1] # match, more varargs coming
            states << [formal+1, actual+1] # match, no more varargs
            states << [formal+1, actual] # skip over even though matches
          else
            states << [formal+1, actual] # doesn't match, must skip
          end
        when DependentArgType
	  bind.local_variable_set(t.name.to_sym,args[actual])
          preds.push(t)
          t = t.type.instantiate(inst)
          the_actual = nil
          if actual == args.size
            next unless t.instance_of? FiniteHashType
            if t.member?({}, vars_wild: true) # try matching against the empty hash
              states << [formal+1, actual]
            end
          elsif t.member?(args[actual], vars_wild: true)
            states << [formal+1, actual+1] # match
            # no else case; if there is no match, this is a dead end
          end
        else
          t = NominalType.new 'Proc' if t.instance_of? MethodType
          t = t.instantiate(inst)
          the_actual = nil
          if actual == args.size
            next unless t.instance_of? FiniteHashType
            if t.member?({}, vars_wild: true) # try matching against the empty hash
              states << [formal+1, actual]
            end
          elsif t.member?(args[actual], vars_wild: true)
            states << [formal+1, actual+1] # match
            # no else case; if there is no match, this is a dead end
          end
        end
      end
      return [false, args, blk, bind]
    end
def pre_cond?(blk, slf, inst, bind, *args)
      states = [[0, 0]] # [position in @arg, position in args]
      preds = []
      until states.empty?
        formal, actual = states.pop
        if formal == @args.size && actual == args.size then # Matched all actuals, no formals left over
	  check_arg_preds(bind, preds) if preds.size > 0
          @args.each_with_index {|a,i| args[i] = block_wrap(slf, inst, a, bind, &args[i]) if a.is_a? MethodType }
          if @block then
            if @block.is_a? OptionalType
              blk = block_wrap(slf, inst, @block.type.instantiate(inst), bind, &blk) if blk
            else
              next unless blk
              blk = block_wrap(slf, inst, @block, bind, &blk)
            end
          elsif blk then
            next
          end
          return [true, args, blk, bind]
        end
        next if formal >= @args.size # Too many actuals to match
        t = @args[formal]
        if t.instance_of? AnnotatedArgType then
	        bind.local_variable_set(t.name.to_sym,args[actual])
	        t = t.type
        end
        case t
        when OptionalType
          t = t.type.instantiate(inst)
          if actual == args.size
            states << [formal+1, actual] # skip to allow extra formal optionals at end
          elsif t.is_a? MethodType
            if args[actual].is_a? Proc
              args[actual] = block_wrap(slf, inst, t, bind, &args[actual])
              states << [formal+1, actual+1]
            elsif args[actual].nil?
              states << [formal+1, actual+1] # match
              states << [formal+1, actual] # skip
            else
              states << [formal+1, actual]
            end
          elsif t.member?(args[actual], vars_wild: true)
            states << [formal+1, actual+1] # match
            states << [formal+1, actual] # skip
          else
            states << [formal+1, actual]  # types don't match; must skip this formal
          end
        when VarargType
          t = t.type.instantiate(inst)
          if actual == args.size
            states << [formal+1, actual] # skip to allow empty vararg at end
          elsif t.member?(args[actual], vars_wild: true)
            states << [formal, actual+1] # match, more varargs coming
            states << [formal+1, actual+1] # match, no more varargs
            states << [formal+1, actual] # skip over even though matches
          else
            states << [formal+1, actual] # doesn't match, must skip
          end
        when DependentArgType
	  bind.local_variable_set(t.name.to_sym,args[actual])
          preds.push(t)
          t = t.type.instantiate(inst)
          the_actual = nil
          if actual == args.size
            next unless t.instance_of? FiniteHashType
            if t.member?({}, vars_wild: true) # try matching against the empty hash
              states << [formal+1, actual]
            end
          elsif t.member?(args[actual], vars_wild: true)
            states << [formal+1, actual+1] # match
            # no else case; if there is no match, this is a dead end
          end
        else
          t = NominalType.new 'Proc' if t.instance_of? MethodType
          t = t.instantiate(inst)
          the_actual = nil
          if actual == args.size
            next unless t.instance_of? FiniteHashType
            if t.member?({}, vars_wild: true) # try matching against the empty hash
              states << [formal+1, actual]
            end
          elsif t.member?(args[actual], vars_wild: true)
            states << [formal+1, actual+1] # match
            # no else case; if there is no match, this is a dead end
          end
        end
      end
      return [false, args, blk, bind]
    end
Create a new MethodType

 [+args+] List of types of the arguments of the procedure (use [] for no args).
 [+block+] The type of the block passed to this method, if it takes one.
 [+ret+] The type that the procedure returns.
 TODO: Check blk
 Very similar to Typecheck.check_arg_types