Ejemplo n.º 1
0
        /// <summary>
        /// Retourne une copie de ce contexte.
        /// </summary>
        public Context Copy()
        {
            Context ret = new Context(GlobalContext);

            ret.Include(this);
            return(ret);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Exécute le block, et retourne une valeur.
        /// Des arguments peuvent êtres passés, et seront transformés en
        /// variables pour le contexte.
        /// CopyContext indique si une copie du contexte doit être faite pour l'exécution
        /// (utile dans le cas d'appel récursif à une fonction).
        /// </summary>
        /// <returns></returns>
        public object Execute(Context externalContext, List <string> argumentNames,
                              object[] arguments,
                              Dictionary <string, object> embeddedVariables,
                              bool copyContext)
        {
            // Contexte externe au moment de l'appel (priorité minimale).
            if (copyContext)
            {
                // Fait une copie du contexte externe, afin de ne pas le modifier.
                if (Context == externalContext)
                {
                    Context = externalContext.Copy();
                }

                // Effectue un reset du context, et inclue le contexte externe dans
                // ce contexte.
                Context.Reset();
                if (externalContext != null)
                {
                    Context.Include(externalContext);
                }
            }
            else
            {
                Context = externalContext;
            }


            // On effectue une copie du contexte de la fonction, afin que chaque appel
            // ait son propre contexte (pas optimisé).

            /*Context = Context.Copy();
             * Context.Include(externalContext);*/
            HasReturned = false;



            if (argumentNames != null && arguments != null)
            {
                // Arguments en priorité ++
                if (arguments.Count() != argumentNames.Count)
                {
                    throw new InterpreterException("Mauvais nombre d'arguments pour l'appel à la fonction");
                }

                // Ajout des arguments au contexte.
                for (int i = 0; i < arguments.Count(); i++)
                {
                    if (!Context.LocalVariables.ContainsKey(argumentNames[i]))
                    {
                        Context.LocalVariables.Add(argumentNames[i], new Mutable(arguments[i]));
                    }
                    else
                    {
                        Context.LocalVariables[argumentNames[i]] = new Mutable(arguments[i]);
                    }
                }
            }

            // Variables imbriquées (au moment de la déclaration) en priorité +++
            if (embeddedVariables != null && embeddedVariables.Count != 0)
            {
                foreach (KeyValuePair <string, object> kvp in embeddedVariables)
                {
                    // Si kvp.Value est mutable, on conserve sa référence.
                    // Sinon, on crée une référence mutable locale pour la valeur de la variable
                    Mutable val = (Mutable)(kvp.Value is Mutable ? kvp.Value : new Mutable(kvp.Value));
                    if (!Context.LocalVariables.ContainsKey(kvp.Key))
                    {
                        Context.LocalVariables.Add(kvp.Key, val);
                    }
                    else
                    {
                        Context.LocalVariables[kvp.Key] = val;
                    }
                }
            }


            // ExternalContext peut être nul.
            foreach (Instruction inst in Instructions)
            {
                // Exécute l'instruction
                var action = inst.GetAction();
                if (action != null)
                {
                    action(Context);
                }

                // Prise en charge du return.
                if (inst is ReturnInstruction || inst.HasReturned)
                {
                    HasReturned = true;
                    return(inst.ReturnValue);
                }
            }
            return(null);
        }