/*
Processing part. Every type variable is mapped to the actual type in the resolvedTypeVariablesMap. This map is used later
on for resolving types.
434946
private void processTypeVariables(TypeVariable<?>[] variables, Type[] values) {
        for (int i = 0; i < variables.length; i++) {
            processTypeVariable(variables[i], values[i]);
        }
    }
1007025
private static Map<TypeVariable<?>, Type> mergeMaps(TypeDiscoverer<?> parent, Map<TypeVariable<?>, Type> map) {

        Map<TypeVariable<?>, Type> typeVariableMap = new HashMap<TypeVariable<?>, Type>();
        typeVariableMap.putAll(map);
        typeVariableMap.putAll(parent.getTypeVariableMap());

        return typeVariableMap;
    }
1371969
@Override
	protected Map<JvmTypeParameter, LightweightMergedBoundTypeArgument> getTypeParameterMapping() {
		if (typeParameterMapping == null) {
			typeParameterMapping = initializeTypeParameterMapping();
		}
		return typeParameterMapping;
	}
242598
public static Type resolveAt(Object o, TypeVariable<?> var) {
        Validate.notNull(var, "no variable to read");
        final GenericDeclaration genericDeclaration = var.getGenericDeclaration();
        Validate.isInstanceOf(Class.class, genericDeclaration, "%s is not declared by a Class",
            TypeUtils.toLongString(var));
        return resolveAt(o, var, TypeUtils.getTypeArguments(o.getClass(), (Class<?>) genericDeclaration));
    }
247211
private void processInjectedFields(TypeElement component) {
    getInjectedFields(component).stream().peek(this::validateField).forEach(field -> {
      String fieldName = field.getSimpleName().toString();
      addInjectedVariable(field, fieldName);
      injectedFieldsName.add(fieldName);
    });
  }
534082
private static Type[] extractTypeArgumentsFrom(final Map<TypeVariable<?>, Type> mappings, final TypeVariable<?>[] variables) {
        final Type[] result = new Type[variables.length];
        int index = 0;
        for (final TypeVariable<?> var : variables) {
            Validate.isTrue(mappings.containsKey(var), "missing argument mapping for %s", toString(var));
            result[index++] = mappings.get(var);
        }
        return result;
    }
865068
private Map<TemplateType, JSType> evaluateTypeTransformations(
      ImmutableList<TemplateType> templateTypes,
      Map<TemplateType, JSType> inferredTypes,
      FlowScope scope) {

    Map<String, JSType> typeVars = null;
    Map<TemplateType, JSType> result = null;
    TypeTransformation ttlObj = null;

    for (TemplateType type : templateTypes) {
      if (type.isTypeTransformation()) {
        // Lazy initialization when the first type transformation is found
        if (ttlObj == null) {
          ttlObj = new TypeTransformation(compiler, scope.getDeclarationScope());
          typeVars = buildTypeVariables(inferredTypes);
          result = new LinkedHashMap<>();
        }
        // Evaluate the type transformation expression using the current
        // known types for the template type variables
        JSType transformedType = ttlObj.eval(
            type.getTypeTransformation(),
            ImmutableMap.copyOf(typeVars));
        result.put(type, transformedType);
        // Add the transformed type to the type variables
        typeVars.put(type.getReferenceName(), transformedType);
      }
    }
    return result;
  }
796741
function resolveTypes(types) {

  CORE_TYPES.forEach(function(t) {
    if (!types[t]) {
      types[t] = {type:t, resolved:true};
    }
  });

  // Resolve the type structure by copying all properties and read/write functions from the parent to the child
  // (if they aren't already defined)
  // Can (and will often be) run multiple times on the same object.
  // XXX: This isn't pretty
  function resolveType(type) {

    if (typeof type !== 'object') {
      throw new Error('Type definition must be an object. Illegal value: ' + type);
    }

    var parent = types[type.type];

    while (parent && !type.resolved) {
      resolveType(parent);

      _.defaults(type, JSON.parse(JSON.stringify(parent)));
      type.write = type.write || parent.write;
      type.read = type.read || parent.read;
      type.type = parent.type; // Always switch to the parent's type.
      parent = types[type.type];
    }

  }

  Object.keys(types).forEach(function(name) {

    var type = types[name];
    resolveType(type);

    type.name = name;
  });

  Object.keys(types).forEach(function(name) {

    var type = types[name];
    // Add any missing read/write functions

    if (!type.write) {
      type.write = function(builder, value, attribute) {

        if (attribute.mask) {
          if (typeof value == 'object') {
            var mask = '';
            attribute.mask.slice().reverse().forEach(function(property) {
              mask += value[property]?'1':'0'; // XXX: Is this a problem performance-wise?
            });

            debug('Created mask for ', attribute.name, mask, value);
            value = parseInt(mask, 2);

          }
        }

        if (attribute.enum) {
          switch(typeof value) {
            case 'string':
              value = attribute.enum[value];
              break;
            case 'number':
              value = attribute.enum.get(value);
              break;
          }
          value = value.value;
        }

        builder[attribute.type](value);
      };
    }

    if (!type.read) {
      type.read = function(parser, attribute) {
        parser[attribute.type](attribute.name);

        /*parser.tap(function() {
          debug('Read attribute', attribute.name, this.vars[attribute.name]);
        });*/

        if (attribute.mask) {

          parser.tap(function() {
            var value = {};
            this.vars[attribute.name].toString(2).split('').reverse().forEach(function(bit, pos) {
              value[attribute.mask[pos]] = (bit === '1');
            });
            this.vars[attribute.name] = value;
          });
        }
      };
    }

  });

  //debug('Resolved types', types);

  return types;
}
1360791
public static Type resolve(Type type, Type declaringType, EntityType context) {
        Type resolved = unwrap(type);

        String varName = getVarName(resolved);
        if (varName != null) {
            resolved = resolveVar(resolved, varName, declaringType, context);
        } else if (!resolved.getParameters().isEmpty()) {
            resolved = resolveWithParameters(resolved, declaringType, context);
        }

        // rewrap entity type
        if (type instanceof EntityType) {
            if (!unwrap(type).equals(resolved)) {
                resolved = new EntityType(resolved, ((EntityType) type).getSuperTypes());
            } else {
                // reset to original type
                resolved = type;
            }
        }

        return resolved;
    }
1124729
Type resolveTypeVariables(final Type type) {
        if (type instanceof Class<?>) {
            // Arrays and non-generic classes have no type variables
            return type;

        } else if (type instanceof ParameterizedType) {
            // Recursively resolve parameterized types
            final ParameterizedType parameterizedType = (ParameterizedType) type;
            final Type[] typeArgs = parameterizedType.getActualTypeArguments();
            Type[] typeArgsResolved = null;
            for (int i = 0; i < typeArgs.length; i++) {
                // Recursively revolve each parameter of the type
                final Type typeArgResolved = resolveTypeVariables(typeArgs[i]);
                // Only compare typeArgs to typeArgResolved until the first difference is found
                if (typeArgsResolved == null) {
                    if (!typeArgResolved.equals(typeArgs[i])) {
                        // After the first difference is found, lazily allocate typeArgsResolved 
                        typeArgsResolved = new Type[typeArgs.length];
                        // Go back and copy all the previous args
                        System.arraycopy(typeArgs, 0, typeArgsResolved, 0, i);
                        // Insert the first different arg
                        typeArgsResolved[i] = typeArgResolved;
                    }
                } else {
                    // After the first difference is found, keep copying the resolved args into the array 
                    typeArgsResolved[i] = typeArgResolved;
                }
            }
            if (typeArgsResolved == null) {
                // There were no type parameters to resolve
                return type;
            } else {
                // Return new ParameterizedType that wraps the resolved type args
                return new ParameterizedTypeImpl((Class<?>) parameterizedType.getRawType(), typeArgsResolved,
                        parameterizedType.getOwnerType());
            }

        } else if (type instanceof TypeVariable<?>) {
            // Look up concrete type for type variable
            final TypeVariable<?> typeVariable = (TypeVariable<?>) type;
            for (int i = 0; i < typeVariables.length; i++) {
                if (typeVariables[i].getName().equals(typeVariable.getName())) {
                    return resolvedTypeArguments[i];
                }
            }
            // Could not resolve type variable
            return type;

        } else if (type instanceof GenericArrayType) {
            // Count the array dimensions, and resolve the innermost type of the array
            int numArrayDims = 0;
            Type t = type;
            while (t instanceof GenericArrayType) {
                numArrayDims++;
                t = ((GenericArrayType) t).getGenericComponentType();
            }
            final Type innermostType = t;
            final Type innermostTypeResolved = resolveTypeVariables(innermostType);
            if (!(innermostTypeResolved instanceof Class<?>)) {
                throw new IllegalArgumentException("Could not resolve generic array type " + type);
            }
            final Class<?> innermostTypeResolvedClass = (Class<?>) innermostTypeResolved;

            // Build an array to hold the size of each dimension, filled with zeroes
            final int[] dims = (int[]) Array.newInstance(int.class, numArrayDims);

            // Build a zero-sized array of the required number of dimensions, using the resolved innermost class 
            final Object arrayInstance = Array.newInstance(innermostTypeResolvedClass, dims);

            // Get the class of this array instance -- this is the resolved array type
            return arrayInstance.getClass();

        } else if (type instanceof WildcardType) {
            // TODO: Support WildcardType
            throw ClassGraphException.newClassGraphException("WildcardType not yet supported: " + type);

        } else {
            throw ClassGraphException.newClassGraphException("Got unexpected type: " + type);
        }
    }
1100608
private static Type materializeTypeVariable(ArrayList<Type> typeHierarchy, TypeVariable<?> typeVar) {
		TypeVariable<?> inTypeTypeVar = typeVar;
		// iterate thru hierarchy from top to bottom until type variable gets a class assigned
		for (int i = typeHierarchy.size() - 1; i >= 0; i--) {
			Type curT = typeHierarchy.get(i);

			// parameterized type
			if (curT instanceof ParameterizedType) {
				Class<?> rawType = ((Class<?>) ((ParameterizedType) curT).getRawType());

				for (int paramIndex = 0; paramIndex < rawType.getTypeParameters().length; paramIndex++) {

					TypeVariable<?> curVarOfCurT = rawType.getTypeParameters()[paramIndex];

					// check if variable names match
					if (sameTypeVars(curVarOfCurT, inTypeTypeVar)) {
						Type curVarType = ((ParameterizedType) curT).getActualTypeArguments()[paramIndex];

						// another type variable level
						if (curVarType instanceof TypeVariable<?>) {
							inTypeTypeVar = (TypeVariable<?>) curVarType;
						}
						// class
						else {
							return curVarType;
						}
					}
				}
			}
		}
		// can not be materialized, most likely due to type erasure
		// return the type variable of the deepest level
		return inTypeTypeVar;
	}
473203
public void resolveVariablesWith(Map<String, INDArray> arrays) {
        for (Map.Entry<String,INDArray> e : arrays.entrySet()) {
            SDVariable varForName = getVariable(e.getKey());
            if (varForName == null) {
                throw new ND4JIllegalStateException("No variable name found for " + e.getKey());
            }

            Variable v = variables.get(e.getKey());
            if(varForName.getVariableType() == VariableType.PLACEHOLDER){
                //Check shape:
                long[] shape = varForName.placeholderShape();
                long[] newShape = e.getValue().shape();
                Preconditions.checkState(shape.length == newShape.length, "Placeholder shape not compatible (mismatched rank): placeholder \"%s\" " +
                        "shape %s, got incompatible shape %s", e.getKey(), shape, newShape);
            }
        }


        for (val entry : arrays.entrySet()) {
            if (!variables.get(entry.getKey()).getVariable().isPlaceHolder()) {
                throw new ND4JIllegalStateException("Illegal variable " + entry.getKey() + " passed in. Variable found not to be a place holder variable");
            }

            val specifiedShape = getOriginalShapeForPlaceHolder(entry.getKey());
            //whole shape was specified: validate whether the input array shape is equal
            if (!Shape.isPlaceholderShape(specifiedShape)) {
                if (!Shape.shapeEquals(specifiedShape, entry.getValue().shape())) {
                    throw new ND4JIllegalStateException("Place holder shape specified was " + Arrays.toString(specifiedShape) + " but array shape was " + Arrays.toString(entry.getValue().shape()));
                }
            }

            associateArrayWithVariable(entry.getValue(), getVariable(entry.getKey()));
            setArrayForVariable(entry.getKey(), entry.getValue());
        }

        //declare resolved
        resolvedVariables = true;
    }
701184
private void reusePreviouslyUsedVariableMap(SortedSet<Assignment> varsToRename) {
    // If prevUsedRenameMap had duplicate values then this pass would be
    // non-deterministic.
    // In such a case, the following will throw an IllegalArgumentException.
    checkNotNull(prevUsedRenameMap.getNewNameToOriginalNameMap());
    for (Assignment a : varsToRename) {
      String prevNewName = prevUsedRenameMap.lookupNewName(a.oldName);
      if (prevNewName == null || reservedNames.contains(prevNewName)) {
        continue;
      }

      if (a.isLocal
          || (!externNames.contains(a.oldName)
              && prevNewName.startsWith(prefix))) {
        reservedNames.add(prevNewName);
        finalizeNameAssignment(a, prevNewName);
      }
    }
  }
818447
private Type resolveType(Type beanType, Type beanType2, Type type) {
        if (type instanceof ParameterizedType) {
            if (beanType instanceof ParameterizedType) {
                return resolveParameterizedType((ParameterizedType) beanType, (ParameterizedType) type);
            }
            if (beanType instanceof Class<?>) {
                return resolveType(((Class<?>) beanType).getGenericSuperclass(), beanType2, type);
            }
        }

        if (type instanceof TypeVariable<?>) {
            if (beanType instanceof ParameterizedType) {
                return resolveTypeParameter((ParameterizedType) beanType, beanType2, (TypeVariable<?>) type);
            }
            if (beanType instanceof Class<?>) {
                return resolveType(((Class<?>) beanType).getGenericSuperclass(), beanType2, type);
            }
        }
        return type;
    }
672754
private function processDeferredIdentificationVariables()
    {
        foreach ($this->deferredIdentificationVariables as $deferredItem) {
            $identVariable = $deferredItem['expression'];

            // Check if IdentificationVariable exists in queryComponents
            if ( ! isset($this->queryComponents[$identVariable])) {
                $this->semanticalError(
                    "'$identVariable' is not defined.", $deferredItem['token']
                );
            }

            $qComp = $this->queryComponents[$identVariable];

            // Check if queryComponent points to an AbstractSchemaName or a ResultVariable
            if ( ! isset($qComp['metadata'])) {
                $this->semanticalError(
                    "'$identVariable' does not point to a Class.", $deferredItem['token']
                );
            }

            // Validate if identification variable nesting level is lower or equal than the current one
            if ($qComp['nestingLevel'] > $deferredItem['nestingLevel']) {
                $this->semanticalError(
                    "'$identVariable' is used outside the scope of its declaration.", $deferredItem['token']
                );
            }
        }
    }
970704
static void buildTypeVariableMap(final Type[] types, final Map<TypeVariable<?>, Type> map) {
        for (Type type : types) {
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                buildTypeVariableMap(parameterizedType, map);
                Type rawType = parameterizedType.getRawType();
                if (rawType instanceof Class)
                    buildTypeVariableMap(((Class<?>) rawType).getGenericInterfaces(), map);
            } else if (type instanceof Class) {
                buildTypeVariableMap(((Class<?>) type).getGenericInterfaces(), map);
            }
        }
    }
767045
protected Map<JvmIdentifiableElement, ResolvedTypes> prepare(ResolvedTypes resolvedTypes, IFeatureScopeSession featureScopeSession) {
		Map<JvmIdentifiableElement, ResolvedTypes> resolvedTypesByContext = Maps.newHashMapWithExpectedSize(3); 
		JvmType root = getRootJvmType();
		rootedInstances.add(root);
		recordExpressions(root);
		doPrepare(resolvedTypes, featureScopeSession, root, resolvedTypesByContext);
		return resolvedTypesByContext;
	}