/// <summary> /// Ajoute des déclarations à ce Container à partir d'un block Access. /// </summary> /// <param name="block"></param> void AddDeclarationsFromStateBlock(Language.NamedBlockDeclaration block, Semantic.TypeTable types) { foreach (Language.Instruction instruction in block.Instructions) { if (instruction is Language.ClassDeclaration) { PerformSerializableChecking((Language.ClassDeclaration)instruction, types); Classes.Add((Language.ClassDeclaration)instruction); } else if (instruction is Language.EnumDeclaration) { StateClass.Instructions.Add(instruction); } else if (instruction is Language.VariableDeclarationInstruction) { Language.VariableDeclarationInstruction variable = (Language.VariableDeclarationInstruction)instruction; StateClass.Instructions.Add(variable); } else if (instruction is Language.PlaceholderInstruction) { } else { ParsingLog.AddError("Instruction de type " + instruction.GetType().Name + " invalide dans un StateBlock", instruction.Line, instruction.Character, instruction.Source ); } } }
/// <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 ); } } }
/// <summary> /// Ajoute des déclarations à ce Container à partir d'un block. /// </summary> /// <param name="block"></param> public void AddDeclarationsFromScript(Language.NamedBlockDeclaration block, Semantic.TypeTable table) { foreach (Language.Instruction instruction in block.Instructions) { if (instruction is Language.NamedBlockDeclaration && ((Language.NamedBlockDeclaration)instruction).Name == Language.SemanticConstants.MacroBk) { AddDeclarationsFromMacroBlock((Language.NamedBlockDeclaration)instruction, table); } } }
/// <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> /// 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); } } }