# File lib/rgen/util/pattern_matcher.rb, line 204
  def match_internal(pat_element, test_element, visited, check_later)
    return true if visited[test_element]
    visited[test_element] = true
    unless pat_element.class == test_element.class
      match_failed(nil, "wrong class: #{pat_element.class} vs #{test_element.class}")
      return false 
    end
    all_structural_features(pat_element).each do |f|
      pat_values = pat_element.getGeneric(f.name)
      # nil values must be kept to support size check with Bindables

      pat_values = [ pat_values ] unless pat_values.is_a?(Array)
      test_values = test_element.getGeneric(f.name)
      test_values = [ test_values] unless test_values.is_a?(Array)
      if pat_values.size == 1 && pat_values.first.is_a?(Bindable) && pat_values.first._many?
        unless match_many_bindable(pat_values.first, test_values)
          return false
        end
      else
        unless pat_values.size == test_values.size
          match_failed(f, "wrong size #{pat_values.size} vs. #{test_values.size}")
          return false 
        end
        pat_values.each_with_index do |pv,i|
          tv = test_values[i]
          if pv.is_a?(Lazy)
            check_later << CheckLater.new(f, pv, tv)
          elsif pv.is_a?(Bindable)
            if pv._bound?
              unless pv._value == tv
                match_failed(f, "value does not match bound value #{pv._value.class}:#{pv._value.object_id} vs. #{tv.class}:#{tv.object_id}")
                return false 
              end
            else
              pv._bind(tv)
            end
          else
            if f.is_a?(RGen::ECore::EAttribute)
              unless pv == tv 
                match_failed(f, "wrong attribute value")
                return false 
              end
            else
              if pv.is_a?(Proxy)
                unless pv._target.object_id == tv.object_id
                  match_failed(f, "wrong target object")
                  return false 
                end
              else
                unless both_nil_or_match(pv, tv, visited, check_later)
                  return false 
                end
              end
            end
          end
        end
      end
    end
    true
  end