/// <summary> /// Vérifie que la classe passée en paramètre respecte les conditions pour être marquée sérializable /// (si elle l'est). /// </summary> void PerformSerializableChecking(Language.ClassDeclaration decl, Semantic.TypeTable types) { Language.ClankType type = types.Types[decl.Name]; if (!type.SupportSerialization) { return; } bool hasError = false; string error = "La classe '" + decl.Name + "' est marquée serializable mais contient des variables non serializables : "; // Vérifie que les types des variables d'instances sont tous "serializable". foreach (var kvp in type.InstanceVariables) { string name = kvp.Key; Language.Variable variable = kvp.Value; // Si la variable a des paramètres génériqu if (variable.Type.BaseType.HasGenericParameterTypeMembers()) { /*if(!variable.Type.BaseType.SupportSerializationAsGeneric) * { * hasError = true; * error += variable.ToString() + " ne supporte pas la sérialisation en tant que param générique, "; * }*/ // On ne peut pas check maintenant, il faut connaître les params génériques. } else if (!(variable.Type.BaseType is Language.GenericParameterType)) { List <string> dummy; if (!variable.Type.DoesSupportSerialization(out dummy)) { hasError = true; error += variable.ToString() + "ne supporte pas la sérialisation, "; } } } if (hasError) { error = error.TrimEnd(',', ' '); ParsingLog.AddWarning(error, decl.Line, decl.Character, decl.Source); } }
/// <summary> /// Génère un modèle abstrait représentant les classes à créer pour le serveur du projet cible. /// </summary> /// <returns></returns> public List <Language.Instruction> GenerateServerProject() { List <Language.Instruction> classes = new List <Language.Instruction>(); // Copie de la classe state Language.ClassDeclaration stateClass = State.StateClass.Copy(); stateClass.Modifiers.Add("public"); stateClass.Comment = "Contient toutes les informations concernant l'état du serveur."; // Copie des classes state List <Language.ClassDeclaration> stateClasses = new List <Language.ClassDeclaration>(); foreach (Language.ClassDeclaration decl in State.Classes) { stateClasses.Add(decl.Copy()); } ; // Ajoute les enums. classes.AddRange(stateClass.Instructions.Where((Language.Instruction inst) => { return(inst is Language.EnumDeclaration); })); // Ne conserve que les fonctions dans la classe state. stateClass.Instructions = stateClass.Instructions.Where((Language.Instruction inst) => { // Ne garde que les fonctions. return(inst is Language.FunctionDeclaration); }).ToList(); // Ajoute les méthodes access / write. foreach (Language.FunctionDeclaration method in Access.Declarations) { Language.FunctionDeclaration cpy = method.FuncCopy(); cpy.Func.Arguments.Add(new Language.FunctionArgument() { ArgType = Types.FetchInstancedType("int", new Semantic.TypeTable.Context()), ArgName = Language.SemanticConstants.ClientID }); stateClass.Instructions.Add(cpy); } foreach (Language.FunctionDeclaration method in Write.Declarations) { Language.FunctionDeclaration cpy = method.FuncCopy(); cpy.Func.Arguments.Add(new Language.FunctionArgument() { ArgType = Types.FetchInstancedType("int", new Semantic.TypeTable.Context()), ArgName = Language.SemanticConstants.ClientID }); stateClass.Instructions.Add(cpy); } // Ajoute la méthode de traitement des messages. // Le code effectif de cette méthode est créé par le générateur de code // du language cible. Language.Macros.ProcessMessageMacro processFunc = new Language.Macros.ProcessMessageMacro(Access, Write); processFunc.Comment = "Génère le code pour la fonction de traitement des messages."; stateClass.Instructions.Add(processFunc); // Classe de message //Language.ClassDeclaration messageClass = new Language.ClassDeclaration() { Name = "_Message" }; //messageClass.Instructions.Add(new Language.VariableDeclarationInstruction() { Var = new Language.Variable() { Name = "Type", Type = enumMessageTypeInstance } }); // Classes de message //List<Language.ClassDeclaration> messageClasses = new List<Language.ClassDeclaration>(); #if false // Ajout des fonctions de Write. #region Write foreach (Language.FunctionDeclaration ex in Write.Declarations) { // Membre de l'enum de message enumDecl.Members.Add("MessageType_" + ex.Func.Name); // Classe de message Language.ClankType klassType = new Language.ClankType() { Name = "Write_" + ex.Func.Name + "_Message" }; Language.ClassDeclaration klass = new Language.ClassDeclaration(); klass.Name = klassType.Name; // Création d'un constructeur. Language.Constructor cons = new Language.Constructor(); cons.Owner = klassType; // Création : // Des variables d'instance de la classe. // Des paramètres du constructeur, de l'initialisation de ces paramètres foreach (Language.FunctionArgument arg in ex.Func.Arguments) { Language.Variable argVar = new Language.Variable() { Name = "_" + arg.ArgName, Type = arg.ArgType }; // Déclaration de la variable klass.Instructions.Add(new Language.VariableDeclarationInstruction() { Var = argVar, Modifiers = new List <string>() { "public" } }); // Ajout de l'argument au constructeur. cons.Arguments.Add(arg); // Ajout de l'assignement de la variable cons.Code.Add(new Language.AffectationInstruction() { Expression = new Language.BinaryExpressionGroup() { Operand1 = argVar, Operand2 = new Language.Variable() { Name = arg.ArgName, Type = arg.ArgType }, Operator = Language.Operator.Affectation } }); } // Ajout de la nouvelle classe. klass.Instructions.Add(new Language.ConstructorDeclaration() { Func = cons }); messageClasses.Add(klass); // Déclaration de fonction dans State. stateClass.Instructions.Add(ex); } #endregion // Ajout des fonctions de Access. #region Access foreach (Language.FunctionDeclaration decl in Access.Declarations) { // Membre de l'enum de message enumDecl.Members.Add("MessageType_" + decl.Func.Name); // Classe de message Language.ClankType klassType = new Language.ClankType() { Name = "Access_" + decl.Func.Name + "_Message" }; Language.ClassDeclaration klass = new Language.ClassDeclaration(); klass.Name = klassType.Name; // Création d'un constructeur. Language.Constructor cons = new Language.Constructor(); cons.Owner = klassType; // Création : // Des variables d'instance de la classe. // Des paramètres du constructeur, de l'initialisation de ces paramètres foreach (Language.FunctionArgument arg in decl.Func.Arguments) { Language.Variable argVar = new Language.Variable() { Name = "_" + arg.ArgName, Type = arg.ArgType }; // Déclaration de la variable klass.Instructions.Add(new Language.VariableDeclarationInstruction() { Var = argVar, Modifiers = new List <string>() { "public" } }); // Ajout de l'argument au constructeur. cons.Arguments.Add(arg); // Ajout de l'assignement de la variable cons.Code.Add(new Language.AffectationInstruction() { Expression = new Language.BinaryExpressionGroup() { Operand1 = argVar, Operand2 = new Language.Variable() { Name = arg.ArgName, Type = arg.ArgType }, Operator = Language.Operator.Affectation } }); } // Ajout de la nouvelle classe. klass.Instructions.Add(new Language.ConstructorDeclaration() { Func = cons }); messageClasses.Add(klass); // Déclaration de fonction dans State. stateClass.Instructions.Add(decl); } #endregion #endif //classes.AddRange(messageClasses); classes.AddRange(stateClasses); classes.Add(stateClass); return(classes); }