/// <summary> /// Modifie la valeur d'un élément d'une collection. /// L'élément est désigné par les paramètres d'indexation. /// </summary> /// <param name="var"></param> /// <param name="indexingParameters"></param> void SetElementValue(object val, object newValue, Context context) { dynamic newValueDynamic = newValue; dynamic index; // TODO : support des arrays multi-dimensionels. if (IndexingParameters.Count > 1) { for (int i = 0; i <= IndexingParameters.Count - 1; i++) { List <IGettable> parameters = IndexingParameters[i]; if (parameters.Count == 0) { throw new Exception("Expected indexing parameter"); } // On laisse faire le runtime pour la résolution dynamique =D dynamic tmp = val; index = IndexingParameters[0][0].GetValue(context); val = tmp[index]; } dynamic enumValFinal = val; index = IndexingParameters.Last().First().GetValue(context); enumValFinal[index] = newValueDynamic; } else if (IndexingParameters.Count == 1) { dynamic enumValFinal = val; index = IndexingParameters.First().First().GetValue(context); enumValFinal[index] = newValueDynamic; } }
/// <summary> /// Retourne la valeur de cette expression, si celle ci n'est liée à aucun objet. /// (i.e si elle est de la forme : /// machin() ou machin MAIS PAS truc.machin /// </summary> /// <returns></returns> public object GetObjectUnboundValue(Context context) { switch (this.SubExpType) { // Groupe d'expression. // -------------------------------------------------------------- case ExpTypes.ExpressionGroup: return(Group.GetValue(context)); // Expression constante d'un objet // -------------------------------------------------------------- case ExpTypes.ConstantObject: // Objet constant : 0, "jiji", 0.0, true, etc... if (constantValueCache == null) { constantValueCache = Parsing.ParseBasicType(this.Name); } return(constantValueCache); // Expression constante d'un type. // -------------------------------------------------------------- case ExpTypes.ConstantTypeName: if (constantValueCache == null) { constantValueCache = new InternalTypeRepresentation( ReflectionUtils.FindType( context, null, Name, GenericParameters, IndexingParameters, false)); } return(constantValueCache); // Expression "new" // -------------------------------------------------------------- case ExpTypes.NewObject: // Si le Type de l'instance n'est pas encore connu, if (findTypeResultCache == null) { findTypeResultCache = ReflectionUtils.FindType( context, null, Name, GenericParameters, IndexingParameters, false); } // Raccourci pour faire moins moche var result = findTypeResultCache; // C'est s'il n'y a pas de paramètres. int paramsCount = Parameters == null ? 0 : Parameters.Count; // Le nombre de paramètres d'index est donné par le nombre d'éléments // de la dernière liste de la liste de paramètres d'indexation. int indexingParametersCount = IndexingParameters.Count == 0 ? 0 : IndexingParameters.Last().Count; object[] args = new object[indexingParametersCount + paramsCount]; int j = 0; // On ajoute les paramètres de taille d'array if (IndexingParameters.Count != 0) { foreach (IGettable gettable in IndexingParameters.Last()) { args[j] = gettable.GetValue(context); j++; } } // On ajoute les paramètres du constructeur. if (Parameters != null) { foreach (IGettable obj in Parameters) { args[j] = obj.GetValue(context); j++; } } // Note : les paramètres génériques sont inclus dans le type. return(Activator.CreateInstance(findTypeResultCache, args)); // Expression "new" // -------------------------------------------------------------- case ExpTypes.Variable: // C'est une variable locale ou globale, non associée à un objet. object val; if (context.LocalVariables.ContainsKey(Name)) { val = context.LocalVariables[Name].Value; } else if (context.GlobalContext.Variables.ContainsKey(Name)) { val = context.GlobalContext.Variables[Name].Value; } else { Type t = ReflectionUtils.FindType(context, null, Name, GenericParameters, IndexingParameters, false); if (t == null) { throw new InterpreterException(String.Format("Impossible de trouver la variable locale ou globale '{0}'.", Name)); } val = new InternalTypeRepresentation(t); } // On regarde s'il y a des paramètres d'indexation : if (IndexingParameters.Count == 0) { return(val); } else { // On parcours les indexers. // TODO : support des arrays multi-dimensionels. for (int i = 0; i < IndexingParameters.Count; i++) { List <IGettable> parameters = IndexingParameters[i]; if (parameters.Count == 0) { throw new Exception("Expected indexing parameter"); } // On laisse faire le runtime pour la résolution dynamique =D dynamic tmp = val; dynamic index = IndexingParameters[0][0].GetValue(context); val = tmp[index]; } return(val); } case ExpTypes.Method: // C'est une méthode locale ou globale, non associée à un objet. // Cela appellera la méthode. Function func; if (context.LocalVariables.ContainsKey(Name)) { if (context.LocalVariables[Name].Value is Function) { func = (Function)context.LocalVariables[Name].Value; } else { throw new InterpreterException(String.Format("Impossible de trouver la fonction locale ou globale {0}.", Name)); } } else { throw new InterpreterException(String.Format("Impossible de trouver la fonction locale ou globale {0}.", Name)); } // Obtient les valeurs des paramètres. object[] parameterValues = new object[Parameters.Count]; for (int i = 0; i < Parameters.Count; i++) { parameterValues[i] = Parameters[i].GetValue(context); } return(func.Call(parameterValues, context)); } throw new Exception(); }