Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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);
        }
Esempio n. 3
0
        /// <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]);
            }
        }