Ejemplo n.º 1
0
        /// <summary>
        /// Ajoute des déclarations à ce Container à partir d'un block Access.
        /// </summary>
        /// <param name="block"></param>
        void AddDeclarationsFromAccessBlock(Language.NamedBlockDeclaration block, Semantic.TypeTable table)
        {
            foreach (Language.Instruction instruction in block.Instructions)
            {
                if (instruction is Language.FunctionDeclaration)
                {
                    // Vérifie que le type de retour de la fonction est public.
                    Language.FunctionDeclaration decl = (Language.FunctionDeclaration)instruction;
                    decl.Func.Owner = table.Types[Language.SemanticConstants.StateClass];
                    if (!decl.Func.IsPublic)
                    {
                        ParsingLog.AddWarning("Les fonctions contenues dans le block access doivent être publiques.",
                                              instruction.Line, instruction.Character, instruction.Source);
                    }
                    if (decl.Func.ReturnType.IsPrivateOrHasPrivateGenericArgs())
                    {
                        ParsingLog.AddWarning("Les types de retour des déclaration de fonction du bloc access doivent être des types publics" +
                                              " et ne pas contenir de paramètre générique privé. (donné : "
                                              + decl.Func.ReturnType.GetFullName() + ")",
                                              instruction.Line, instruction.Character, instruction.Source);
                    }

                    // Vérification du return type.
                    List <string> outReasons;
                    if (!decl.Func.ReturnType.DoesSupportSerialization(out outReasons))
                    {
                        string error;
                        error = "Le type de retour de la fonction '" + decl.Func.GetFullName() + "' (" + decl.Func.ReturnType.GetFullName() +
                                ") ne prend pas en charge la sérialisation. Raisons : ";
                        error += Tools.StringUtils.Join(outReasons, ", ") + ".";
                        ParsingLog.AddWarning(error, decl.Line, decl.Character, decl.Source);
                    }

                    // Vérification des types des arguments.
                    foreach (Language.FunctionArgument arg in decl.Func.Arguments)
                    {
                        if (!arg.ArgType.DoesSupportSerialization(out outReasons))
                        {
                            string error;
                            error = "Le type de l'argument '" + arg.ArgName + "' (" + arg.ArgType + ") de la fonction " + decl.Func.GetFullName() +
                                    " ne prend pas en charge la sérialisation. Reasons : ";


                            error += Tools.StringUtils.Join(outReasons, ", ") + ".";
                            ParsingLog.AddWarning(error, decl.Line, decl.Character, decl.Source);
                        }
                    }
                    Declarations.Add((Language.FunctionDeclaration)instruction);
                }
                else
                {
                    ParsingLog.AddError("Instruction de type " + instruction.GetType().Name + " invalide dans un AccessBlock",
                                        instruction.Line,
                                        instruction.Character,
                                        instruction.Source
                                        );
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Retourne une copie superficielle de cet objet et une copie profonde de la fonction encapsulée.
        /// </summary>
        /// <returns></returns>
        public FunctionDeclaration FuncCopy()
        {
            FunctionDeclaration func = new FunctionDeclaration();

            func.Func      = Func.DeepCopy();
            func.Character = Character;
            func.Line      = Line;
            func.Source    = Source;
            func.Code      = Code;
            func.Comment   = Comment;
            return(func);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Crée le dictionnaire associant nom du langage et nom de la fonction à partir des variables contenues dans la fonction.
        /// </summary>
        Dictionary <string, string> ParseLanguageTranslations(Language.FunctionDeclaration decl)
        {
            Dictionary <string, string> langToFuncName = new Dictionary <string, string>();

            foreach (Language.Instruction instruction in decl.Code)
            {
                Language.VariableDeclarationAndAssignmentInstruction varDecl = instruction as Language.VariableDeclarationAndAssignmentInstruction;
                if (varDecl != null)
                {
                    // Vérification du type de la variable.
                    if (varDecl.Declaration.Var.Type.GetFullName() == "string")
                    {
                        // Vérification des doublons.
                        if (!langToFuncName.ContainsKey(varDecl.Declaration.Var.Name))
                        {
                            Language.StringLiteral literal = varDecl.Assignment.Expression.Operand2 as Language.StringLiteral;
                            // Vérification de la rvalue.
                            if (literal != null)
                            {
                                langToFuncName.Add(varDecl.Declaration.Var.Name, literal.Value);
                            }
                            else
                            {
                                ParsingLog.AddError("La valeur affectée à une variable dans une fonction d'un block macro doit être un litéral de string.",
                                                    varDecl.Line, varDecl.Character, varDecl.Source);
                            }
                        }
                        else
                        {
                            ParsingLog.AddWarning("Présente de doublon pour la déclaration de " + varDecl.Declaration.Var.Name + " dans la fonction " + decl.Func.Name + ".",
                                                  varDecl.Line, varDecl.Character, varDecl.Source);
                        }
                    }
                    else
                    {
                        ParsingLog.AddWarning("Les fonctions des blocs macro ne peuvent contenir que des variables de type string, obtenu : " + varDecl.Declaration.Var.Type.GetFullName(),
                                              varDecl.Line, varDecl.Character, varDecl.Source);
                    }
                }
                else
                {
                    ParsingLog.AddWarning("Instruction de type " + instruction.GetType() + " inatendue dans une déclaration de fonction macro",
                                          decl.Line, decl.Character, decl.Source);
                }
            }
            return(langToFuncName);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Ajoute des déclarations à ce Container à partir d'un block Access.
        /// </summary>
        /// <param name="block"></param>
        void AddDeclarationsFromMacroBlock(Language.NamedBlockDeclaration block, Semantic.TypeTable table)
        {
            foreach (Language.Instruction instruction in block.Instructions)
            {
                if (instruction is Language.ClassDeclaration)
                {
                    Language.ClassDeclaration classDecl = (Language.ClassDeclaration)instruction;
                    MacroClass classMacro = new MacroClass();

                    // Récupération du type en language Clank.Core.
                    Language.ClankType type = table.Types[classDecl.GetFullName()];
                    classMacro.Type = type;


                    bool foundName = false;
                    // Parse les instructions à la recherche de :
                    //  - une fonction Name qui retourne un string et qui contient des variables de type string
                    //  - d'autres fonctions qui ne contiennent que des variables de type string.
                    foreach (Language.Instruction funcDeclInstruction in classDecl.Instructions)
                    {
                        Language.FunctionDeclaration funcDecl = funcDeclInstruction as Language.FunctionDeclaration;
                        if (funcDecl != null)
                        {
                            if (funcDecl.Func.Name == "name")
                            {
                                // Nom de la classe
                                foundName = true;
                                classMacro.LanguageToTypeName = ParseLanguageTranslations(funcDecl);
                            }
                            else
                            {
                                // Ajout de la fonction.
                                MacroFunction func = new MacroFunction();
                                func.Function = funcDecl.Func;
                                func.LanguageToFunctionName = ParseLanguageTranslations(funcDecl);
                                classMacro.Functions.Add(func.Function.GetFullName(), func);
                            }
                        }
                        else if (funcDeclInstruction is Language.PlaceholderInstruction)
                        {
                        }
                        else
                        {
                            ParsingLog.AddWarning("Seules les déclarations de fonctions sont autorisées dans les classes de block macro. Obtenu : " +
                                                  funcDeclInstruction.GetType().Name + ".",
                                                  instruction.Line, instruction.Character, instruction.Source);
                        }
                    }
                    ClassDeclarations.Add(classMacro);
                    // Erreur si pas de nom de classe trouvé :
                    if (!foundName)
                    {
                        ParsingLog.AddError("Fonction 'string name()' attendue dans la déclaration de macro du type '" + type.Name + "'.",
                                            instruction.Line, instruction.Character, instruction.Source);
                    }
                }
                else if (instruction is Language.FunctionDeclaration)
                {
                    Language.FunctionDeclaration funcDecl = (Language.FunctionDeclaration)instruction;
                    MacroFunction func = new MacroFunction();
                    func.Function = funcDecl.Func;
                    func.LanguageToFunctionName = ParseLanguageTranslations(funcDecl);
                    FunctionDeclarations.Add(func);
                }
                else
                {
                    ParsingLog.AddWarning("Déclaration de classe attendue dans le block macro. Obtenu : " + instruction.GetType() + ".",
                                          instruction.Line, instruction.Character, instruction.Source);
                }
            }
        }
Ejemplo n.º 5
0
        /// <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);
        }