/// <summary> /// Retourne le constructeur (instancié) pour un type donné. /// </summary> public Language.Function GetConstructor(Language.ClankType owner, Language.ClankTypeInstance inst, List <Language.Evaluable> args, Context context) { string fullName = owner.GetFullName() + "." + Language.SemanticConstants.New + Language.Evaluable.GetArgTypesString(args); var instanciedOverloads = InstanciatedFunc(inst); if (instanciedOverloads.ContainsKey(fullName)) { Language.Function func = instanciedOverloads[fullName]; // Vérification : la fonction est-elle bien marquée comme constructeur ? if (!func.IsConstructor) { throw new SemanticError("La fonction " + Language.SemanticConstants.New + " n'est pas un constructeur de " + owner.GetFullName() + "."); } return(func.Instanciate(inst.GenericArguments)); } if (args.Count != 0) { throw new SemanticError("Aucun constructeur de '" + owner.GetFullName() + "' ne matche les arguments de type : " + Language.Evaluable.GetArgTypesString(args) + ". Candidats possibles : " + GetCandidatesStr(inst, Language.SemanticConstants.New)); } // Si le constructeur n'existe pas, on crée le constructeur par défaut. Language.Function cons = new Language.Function() { Modifiers = new List <string>() { Language.SemanticConstants.Public, Language.SemanticConstants.Constructor }, ReturnType = inst, Arguments = new List <Language.FunctionArgument>(), Code = new List <Language.Instruction>(), Owner = owner, Type = inst, Name = Language.SemanticConstants.New }; return(cons); }
/// <summary> /// Retourne la fonction statique pour un type donné dont le nom est passé en paramètre. /// </summary> /// <param name="functionName"></param> /// <param name="context"></param> /// <returns></returns> public Language.Function GetStaticFunction(Language.ClankTypeInstance instancedType, string functionName, List <Language.Evaluable> args, Context context) { // Obtient le nom complet de la fonction (avec les args). Language.ClankType owner = instancedType.BaseType; string fullName = owner.GetFullName() + "." + functionName + Language.Evaluable.GetArgTypesString(args); var instanciatedOverloads = InstanciatedFunc(instancedType); if (instanciatedOverloads.ContainsKey(fullName)) { Language.Function func = instanciatedOverloads[fullName]; // Vérification : la fonction est-elle statique ? if (!func.IsStatic) { throw new SemanticError("La fonction " + functionName + " n'est pas une méthode statique de " + owner.GetFullName() + "."); } return(instanciatedOverloads[fullName]); } return(null); }
/// <summary> /// Parse le jeton pour en extraire une instance de type de base en fonction du contexte. /// </summary> public Language.ClankTypeInstance FetchInstancedType(Token token, Context context, bool containsType = false) { Language.ClankType baseType = null; bool isGeneric = false; List <Language.ClankTypeInstance> genericArguments = new List <Language.ClankTypeInstance>(); if (token.TkType == TokenType.List) { if (token.ListTokens.Count != 1) { throw new InvalidOperationException(); } return(FetchInstancedType(token.ListTokens[0], context, containsType)); } else if (token.TkType == TokenType.ArrayType) { // On crée un array avec comme param générique le type de cette array. baseType = Types["Array"]; Language.ClankTypeInstance inst = FetchInstancedType(token.ArrayTypeIdentifier, context, containsType); if (inst == null) { string error = "Le type " + token.ArrayTypeIdentifier.Content + " n'existe pas."; if (OnLog != null) { OnLog(new Tools.EventLog.Entry(Tools.EventLog.EntryType.Error, error, token.Line, token.Character, token.Source)); } throw new SemanticError(error); } genericArguments.Add(inst); isGeneric = true; } else if (token.TkType == TokenType.GenericType) { if (!Types.ContainsKey(token.GenericTypeIdentifier.Content)) { // Erreur type inconnu. string error = "Le type générique '" + token.GenericTypeIdentifier.Content + "' est n'existe pas."; OnLog(new Tools.EventLog.Entry(Tools.EventLog.EntryType.Error, error, token.Line, token.Character, token.Source)); throw new SemanticError(error); } baseType = Types[token.GenericTypeIdentifier.Content]; isGeneric = true; foreach (Token tok in token.GenericTypeArgs.ListTokens) { Language.ClankTypeInstance inst = FetchInstancedType(tok, context, true); if (inst == null) { string error = "Le type '" + tok.ToReadableCode() + "' n'existe pas."; if (OnLog != null) { OnLog(new Tools.EventLog.Entry(Tools.EventLog.EntryType.Error, error, token.Line, token.Character, token.Source)); } throw new SemanticError(error); } genericArguments.Add(inst); } // Vérification : le nombre d'arguments du type générique est-il correct ? if (baseType.GenericArgumentNames.Count != token.GenericTypeArgs.ListTokens.Count) { string error = "Nombre d'arguments pour le type '" + baseType.GetFullName() + "' incorrect. Attendu : " + baseType.GetFullNameAndGenericArgs() + ". Obtenu " + baseType.GetFullName() + "<" + token.GenericTypeArgs.ToReadableCode() + "> (" + token.GenericTypeArgs.ListTokens.Count + " args)."; if (OnLog != null) { OnLog(new Tools.EventLog.Entry(Tools.EventLog.EntryType.Error, error, token.Line, token.Character, token.Source)); } } } else if (token.TkType == TokenType.Name) { if (TypeInstances.ContainsKey(token.Content)) { return(TypeInstances[token.Content]); } else { Context c = context; while (c != null) { string contextPrefix = c.GetContextPrefix().Trim('.') + "'"; if (TypeInstances.ContainsKey(contextPrefix + token.Content)) { // Instance de type générique return(TypeInstances[contextPrefix + token.Content]); } c = c.ParentContext; } } baseType = new Language.ClankType() { Name = token.Content }; // FIXME : enlever true va créer une nouvelle instance de type basé sur un nouveau // type (baseType du dessus là) pas encore déclaré. -> on casse des références. if (!containsType || true) { // Rien n'a été trouvé, on retourne null. (ce n'est pas un type) return(null); } } Language.ClankTypeInstance type = new Language.ClankTypeInstance() { BaseType = baseType, GenericArguments = genericArguments }; string fullName = type.GetFullName(); if (!TypeInstances.ContainsKey(fullName)) { TypeInstances.Add(fullName, type); return(type); } else { return(TypeInstances[fullName]); } }