/// <summary>
 /// Create a new SuperSendCallSiteBinder.
 /// </summary>
 /// <param name="runtime">SmalltalkRuntine that this binder belongs to.</param>
 /// <param name="selector">Selector of the message being sent.</param>
 /// <param name="superScope">The name of the class ABOVE which to start the method lookup.</param>
 public SuperSendCallSiteBinder(SmalltalkRuntime runtime, Symbol selector, Symbol superScope)
     : base(runtime, selector)
 {
     if (superScope == null)
         throw new ArgumentNullException("superScope");
     this.SuperScope = superScope;
 }
 public SmalltalkClass GetClass(Symbol name)
 {
     ClassBinding binding = this.Runtime.GlobalScope.GetClassBinding(name);
     if (binding == null)
         return null;
     return binding.Value;
 }
 /// <summary>
 /// Create a new MessageSendCallSiteBinder.
 /// </summary>
 /// <param name="runtime">SmalltalkRuntine that this binder belongs to.</param>
 /// <param name="selector">Selector of the message being sent.</param>
 /// <param name="nativeName">Name of the method that the target is asked to bind.</param>
 /// <param name="argumentCount">Number of method arguments.</param>
 public MessageSendCallSiteBinder(SmalltalkRuntime runtime, Symbol selector, string nativeName, int argumentCount)
     : base(runtime, selector)
 {
     if (argumentCount < 0)
         throw new ArgumentOutOfRangeException("argumentCount");
     this.NativeName = nativeName;
     this.ArgumentCount = argumentCount;
 }
 public object GetGlobal(Symbol name)
 {
     if (name == null)
         throw new ArgumentNullException();
     object value;
     if (!this.TryGetGlobal(name, out value))
         throw new KeyNotFoundException(name.Value);
     return value;
 }
 /// <summary>
 /// Create a new ConstantSendCallSiteBinder.
 /// </summary>
 /// <param name="runtime">SmalltalkRuntine that this binder belongs to.</param>
 /// <param name="selector">Selector of the message being sent.</param>
 /// <param name="nativeName">Name of the method that the target is asked to bind.</param>
 /// <param name="argumentCount">Number of method arguments.</param>
 public ConstantSendCallSiteBinder(SmalltalkRuntime runtime, Symbol selector, string nativeName, int argumentCount)
     : base(runtime, selector, nativeName, argumentCount)
 {
 }
 /// <summary>
 /// Set the value of the given global variable.
 /// </summary>
 /// <param name="name">Name of the global variable.</param>
 /// <param name="value">New value of the global variable.</param>
 /// <returns>True if the variable exists, otherwise false.</returns>
 public bool SetGlobal(Symbol name, object value)
 {
     GlobalVariableBinding binding = this.GlobalScope.GetGlobalVariableBinding(name);
     if (binding == null)
         return false;
     binding.Value = value;
     return true;
 }
 /// <summary>
 /// Get the Smalltalk shared pool with the given name.
 /// </summary>
 /// <param name="name">Shared pool name.</param>
 /// <returns>The Smalltalk shared pool with the given name or null if none found.</returns>
 public Pool GetPool(Symbol name)
 {
     PoolBinding binding = this.GlobalScope.GetPoolBinding(name);
     if (binding != null)
         return binding.Value;
     else
         return null;
 }
 /// <summary>
 /// Get global variable or global constant with the given name.
 /// </summary>
 /// <param name="name">Global variable or global constant name.</param>
 /// <param name="exists">True if the global variable or global constant exists, otherwise false.</param>
 /// <returns>Value of the global variable or global constant. If not found, null is returned.</returns>
 public object GetGlobal(Symbol name, out bool exists)
 {
     GlobalVariableOrConstantBinding binding = this.GlobalScope.GetGlobalVariableOrConstantBinding(name);
     if (binding == null)
     {
         exists = false;
         return null;
     }
     else
     {
         exists = true;
         return binding.Value;
     }
 }
 /// <summary>
 /// Get global variable or global constant with the given name.
 /// </summary>
 /// <param name="name">Global variable or global constant name.</param>
 /// <returns>Value of the global variable or global constant. If not found, null is returned.</returns>
 public object GetGlobal(Symbol name)
 {
     bool na;
     return this.GetGlobal(name, out na);
 }
 public bool TryGetGlobal(Symbol name, out object value)
 {
     GlobalVariableOrConstantBinding binding = this.Runtime.GlobalScope.GetGlobalVariableOrConstantBinding(name);
     if ((binding == null) || !binding.HasBeenSet)
     {
         value = null;
         return false;
     }
     value = binding.Value;
     return true;
 }
 public bool TrySetGlobal(Symbol name, object value)
 {
     GlobalVariableBinding binding = this.Runtime.GlobalScope.GetGlobalVariableBinding(name);
     if ((binding == null) || binding.IsConstantBinding)
         return false;
     binding.Value = value;
     return true;
 }
 public void SetGlobal(Symbol name, object value)
 {
     if (name == null)
         throw new ArgumentNullException();
     if (!this.TrySetGlobal(name, value))
         throw new KeyNotFoundException(name.Value);
 }
 public Pool GetPool(Symbol name)
 {
     PoolBinding binding = this.Runtime.GlobalScope.GetPoolBinding(name);
     if (binding == null)
         return null;
     return binding.Value;
 }
        /// <summary>
        /// Look-up a method implementation starting with the given class.
        /// </summary>
        /// <param name="cls">Class where to start searching for the method (unless superLookupScope) is set.</param>
        /// <param name="superLookupScope">If set, start the lookup from the superclass of this class.</param>
        /// <param name="lookupFunction">Function to perform the method lookup.</param>
        /// <returns>Returns the compiled method for the given selector or null if none was found.</returns>
        public static CompiledMethod LookupMethod(ref SmalltalkClass cls, ref Symbol superLookupScope, Func<SmalltalkClass, CompiledMethod> lookupFunction)
        {
            if (lookupFunction == null)
                throw new ArgumentNullException("lookupFunction");

            while (cls != null)
            {
                if (superLookupScope == null)
                {
                    CompiledMethod method = lookupFunction(cls);
                    if (method != null)
                        return method;
                }
                else
                {
                    if (cls.Name == superLookupScope)
                        superLookupScope = null;
                }
                cls = cls.Superclass;
            }

            // No method ... no luck;
            return null;
        }
 /// <summary>
 /// Look-up for an instance method implementation given a method selector and a class.
 /// </summary>
 /// <param name="selector">Method selector to look for.</param>
 /// <param name="cls">Class where to start searching for the method (unless superLookupScope) is set.</param>
 /// <param name="superLookupScope">If set, start the lookup from the superclass of this class.</param>
 /// <returns>Returns the compiled method for the given selector or null if none was found.</returns>
 public static CompiledMethod LookupInstanceMethod(Symbol selector, ref SmalltalkClass cls, ref Symbol superLookupScope)
 {
     return MethodLookupHelper.LookupMethod(ref cls, ref superLookupScope, delegate(SmalltalkClass c)
     {
         CompiledMethod method;
         if (c.InstanceBehavior.TryGetValue(selector, out method))
             return method;
         return null;
     });
 }
        /// <summary>
        /// This method is the core of the dynamic method lookup system.
        /// It determines the class of an object and looks-up the method implementation
        /// for a given method selector.
        /// </summary>
        /// <param name="runtime">Required.</param>
        /// <param name="selector">Required.</param>
        /// <param name="superLookupScope">Optional.</param>
        /// <param name="receiver">Optional.</param>
        /// <param name="self">Required.</param>
        /// <param name="arguments">Required (currently not used).</param>
        /// <param name="receiverClass">Must Return!</param>
        /// <param name="restrictions">Must Return!</param>
        /// <param name="executableCode">Return null if missing.</param>
        public static void GetMethodInformation(SmalltalkRuntime runtime, 
            Symbol selector,
            Symbol superLookupScope,
            object receiver,
            DynamicMetaObject self,
            DynamicMetaObject[] arguments,
            out SmalltalkClass receiverClass,
            out BindingRestrictions restrictions,
            out Expression executableCode)
        {
            restrictions = null;
            SmalltalkClass cls = null;

            // Special case for Smalltalk classes, because we want the class behavior first ...
            if (receiver is SmalltalkClass)
            {
                cls = (SmalltalkClass)receiver;
                if (cls.Runtime == runtime)
                {
                    receiverClass = runtime.NativeTypeClassMap.Class;
                    if (receiverClass == null)
                        receiverClass = runtime.NativeTypeClassMap.Object;
                    // Lookup method in class behavior
                    CompiledMethod mth = MethodLookupHelper.LookupClassMethod(selector, ref cls, ref superLookupScope);
                    if (mth != null)
                    {
                        // A class method, special restrictions
                        restrictions = BindingRestrictions.GetInstanceRestriction(self.Expression, receiver);
                        var compilationResult = mth.Code.CompileClassMethod(runtime, cls, self, arguments, superLookupScope);
                        if (compilationResult == null)
                        {
                            executableCode = null;
                        }
                        else
                        {
                            executableCode = compilationResult.ExecutableCode;
                            restrictions = compilationResult.MergeRestrictions(restrictions);
                        }
                        return;
                    }
                    // Not in class behavior ... fallback to instance / Object behavior
                    cls = receiverClass;
                    restrictions = BindingRestrictions.GetTypeRestriction(self.Expression, typeof(SmalltalkClass));
                }
            }

            if ((cls == null) || (restrictions == null))
                cls = GetClassAndRestrictions(runtime, receiver, self, arguments, out restrictions);
            receiverClass = cls;

            // Look-up the method
            CompiledMethod method = MethodLookupHelper.LookupInstanceMethod(selector, ref cls, ref superLookupScope);
            if (method == null)
            {
                executableCode = null;
            }
            else
            {
                var compilationResult = method.Code.CompileInstanceMethod(runtime, cls, self, arguments, superLookupScope);
                if (compilationResult == null)
                {
                    executableCode = null;
                }
                else
                {
                    executableCode = compilationResult.ExecutableCode;
                    restrictions = compilationResult.MergeRestrictions(restrictions);
                }

            }
        }