예제 #1
0
        // dynamic dispatch to "const_missing" if not found
        public object ResolveConstant(bool autoload, string /*!*/ name)
        {
            object result;

            if (TryResolveConstant(autoload, name, out result))
            {
                return(result);
            }

            RubyUtils.CheckConstantName(name);
            return(RubySites.ModuleConstMissing(RubyContext, GetInnerMostModule(), name));
        }
예제 #2
0
            public static MutableString Inspect(RubyContext /*!*/ context, YamlStream /*!*/ self)
            {
                MutableString result = MutableString.CreateMutable("#<YAML::Stream:");

                RubyUtils.AppendFormatHexObjectId(result, RubyUtils.GetObjectId(context, self))
                .Append(" @documents=")
                .Append(RubySites.Inspect(context, self.Documents))
                .Append(", options=")
                .Append(RubySites.Inspect(context, self.Options))
                .Append('>');
                return(result);
            }
예제 #3
0
 public static object Tagurize(RubyContext context, RubyModule self, object arg)
 {
     if (arg == null)
     {
         return(null);
     }
     if (RubySites.RespondTo(context, arg, "to_str"))
     {
         return(MutableString.Create("tag:yaml.org,2002:").Append(Protocols.ConvertToString(context, arg)));
     }
     return(arg);
 }
예제 #4
0
        /// <summary>
        /// Try to coerce the values of self and other (using other as the object) then dynamically invoke "&lt;=&gt;".
        /// </summary>
        /// <returns>
        /// 1 if self is greater than other
        /// 0 if self is equal to other
        /// -1 if self is less than other
        /// null otherwise (like if self and other cannot be coerced)
        /// </returns>
        /// <remarks>
        /// This method is used when comparing Numerics.
        /// If we can't coerce then they are not the same, so return null.
        /// But if the &lt;=&gt; doesn't exist on the first item in the array returned from coerce then throw missing method error.
        /// </remarks>
        public static object CoerceAndCallCompare(RubyContext /*!*/ context, object self, object other)
        {
            RubyArray coercedValues;

            try {
                // Swap self and other around to do the coercion.
                coercedValues = RubySites.Coerce(context, other, self);
            } catch (Exception) {
                // The coercion failed so return null.
                return(null);
            }
            // This call is outside the try block as we do want problems with this call being raised up.
            return(LibrarySites.Compare(context, coercedValues[0], coercedValues[1]));
        }
예제 #5
0
 /// <summary>
 /// Compare the values of self and other (coerce using other as the object then call the passed in comparison operator).
 /// </summary>
 /// <remarks>
 /// This method is used for &lt;, &lt;=, &gt; and &gt;= operators.  If we can't coerce then throw a specific comparison exception.
 /// </remarks>
 /// <exception cref="ArgumentException">If self and other cannot be coerced to the same type.</exception>
 public static bool CoerceAndCallRelationOperator(RubyContext /*!*/ context, object self, object other, DynamicInvocation invoke)
 {
     try {
         // Swap self and other around to do the coercion.
         RubyArray coercedValues = RubySites.Coerce(context, other, self);
         return(RubyOps.IsTrue(invoke(context, coercedValues[0], coercedValues[1])));
     } catch (MemberAccessException x) {
         throw RubyExceptions.MakeComparisonError(context, self, other, x);
     } catch (ArgumentException x) {
         throw RubyExceptions.MakeComparisonError(context, self, other, x);
     } catch (NullReferenceException x) {
         throw RubyExceptions.MakeComparisonError(context, self, other, x);
     }
 }
예제 #6
0
        /// <summary>
        /// Coerce the values of self and other (using other as the object) then call the passed in method.
        /// </summary>
        public static object CoerceAndCall(RubyContext /*!*/ context, object self, object other, DynamicInvocation invoke)
        {
            RubyArray coercedValues;

            try {
                // Swap self and other around to do the coercion.
                coercedValues = RubySites.Coerce(context, other, self);
            } catch (MemberAccessException x) {
                throw RubyExceptions.MakeCoercionError(context, self, other, x);
            } catch (ArgumentException x) {
                throw RubyExceptions.MakeCoercionError(context, self, other, x);
            }
            // But then swap them back when invoking the operation
            return(invoke(context, coercedValues[0], coercedValues[1]));
        }
예제 #7
0
        public static MutableString /*!*/ ObjectToMutableString(RubyContext /*!*/ context, object obj)
        {
            using (IDisposable handle = RubyUtils.InfiniteInspectTracker.TrackObject(obj)) {
                if (handle == null)
                {
                    return(MutableString.Create("..."));
                }

                MutableString str = MutableString.CreateMutable();
                str.Append("#<");
                str.Append(context.GetClassOf(obj).Name);

                // Ruby prints 2*object_id for objects
                str.Append(':');
                AppendFormatHexObjectId(str, GetObjectId(context, obj));

                // display instance variables
                RubyInstanceData data = context.TryGetInstanceData(obj);
                if (data != null)
                {
                    var  vars  = data.GetInstanceVariablePairs();
                    bool first = true;
                    foreach (KeyValuePair <string, object> var in vars)
                    {
                        if (first)
                        {
                            str.Append(" ");
                            first = false;
                        }
                        else
                        {
                            str.Append(", ");
                        }
                        str.Append(var.Key);
                        str.Append("=");
                        str.Append(RubySites.Inspect(context, var.Value));
                    }
                }
                str.Append(">");

                return(str);
            }
        }
예제 #8
0
        private static string /*!*/ FormatMethodMissingMessage(RubyContext /*!*/ context, object self, string /*!*/ name, string /*!*/ message)
        {
            Assert.NotNull(name);
            string strObject;

            if (self == null)
            {
                strObject = "nil:NilClass";
            }
            else
            {
                strObject = RubySites.ToS(context, self).ConvertToString();
                if (!strObject.StartsWith("#"))
                {
                    strObject += ":" + RubyUtils.GetClassName(context, self);
                }
            }

            return(String.Format(message, name, strObject));
        }
예제 #9
0
        /// <summary>
        /// Try to cast the object to an Integer using to_int
        /// Returns null if the object doesn't implement to_int
        /// Can return either Bignum or Fixnum
        /// </summary>
        public static bool AsInteger(RubyContext /*!*/ context, object obj, out int fixnum, out BigInteger bignum)
        {
            // Don't call to_int on types derived from Integer
            if (AsPrimitiveInteger(obj, out fixnum, out bignum))
            {
                return(true);
            }

            if (RubySites.RespondTo(context, obj, "to_int"))
            {
                object result = _ToInt.Target(_ToInt, context, obj);
                if (AsPrimitiveInteger(result, out fixnum, out bignum))
                {
                    return(true);
                }

                throw RubyExceptions.InvalidValueForType(context, result, "Integer");
            }

            return(false);
        }
예제 #10
0
        /// <summary>
        /// Standard way to convert to a Ruby String, using to_str
        ///
        /// Checks if it's already a string, and if so returns it.
        /// Then calls to_str if it exists, otherwise returns null
        /// </summary>
        public static MutableString AsString(RubyContext /*!*/ context, object obj)
        {
            MutableString str = obj as MutableString;

            if (str != null)
            {
                return(str);
            }
            if (RubySites.RespondTo(context, obj, "to_str"))
            {
                str = _ToStr.Target(_ToStr, context, obj) as MutableString;
                if (str != null)
                {
                    return(str);
                }

                throw RubyExceptions.MethodShouldReturnType(context, obj, "to_str", "String");
            }

            return(null);
        }
예제 #11
0
        public static Node /*!*/ ToYaml(double self, [NotNull] RubyRepresenter /*!*/ rep)
        {
            MutableString str = RubySites.ToS(rep.Context, self);

            if (str != null)
            {
                if (str.Equals("Infinity"))
                {
                    str = MutableString.Create(".Inf");
                }
                else if (str.Equals("-Infinity"))
                {
                    str = MutableString.Create("-.Inf");
                }
                else if (str.Equals("NaN"))
                {
                    str = MutableString.Create(".NaN");
                }
            }
            return(rep.Scalar(self, str));
        }
예제 #12
0
        public static object GetConstant(RubyScope /*!*/ scope, RubyModule /*!*/ owner, string /*!*/ name, bool lookupObject)
        {
            Assert.NotNull(scope, owner, name);

            object result;

            if (owner.TryResolveConstant(scope.GlobalScope, name, out result))
            {
                return(result);
            }

            RubyClass objectClass = owner.Context.ObjectClass;

            if (owner != objectClass && lookupObject && objectClass.TryResolveConstant(scope.GlobalScope, name, out result))
            {
                return(result);
            }

            CheckConstantName(name);
            return(RubySites.ModuleConstMissing(scope.RubyContext, owner, name));
        }
예제 #13
0
        /// <summary>
        /// Try to convert obj to an Array using #to_ary
        /// 1. If obj is an Array (or a subtype), returns it
        /// 2. Calls to_ary if it exists, possibly throwing if to_ary doesn't return an Array
        /// 3. else returns null
        /// </summary>
        public static IList AsArray(RubyContext /*!*/ context, object obj)
        {
            // Don't call to_a on types derived from Array
            IList ary = obj as IList;

            if (ary != null)
            {
                return(ary);
            }

            if (RubySites.RespondTo(context, obj, "to_ary"))
            {
                object result = _ToAry.Target(_ToAry, context, obj);
                ary = result as IList;
                if (ary != null)
                {
                    return(ary);
                }

                throw RubyExceptions.MethodShouldReturnType(context, obj, "to_ary", "Array");
            }

            return(null);
        }
예제 #14
0
            protected CallSite <Func <CallSite, RubyContext, object, Proc, object> > /*!*/ GetSite(string /*!*/ name)
            {
                CallSite <Func <CallSite, RubyContext, object, Proc, object> > result;

                lock (_siteCache) {
                    if (!_siteCache.TryGetValue(name, out result))
                    {
                        result = CallSite <Func <CallSite, RubyContext, object, Proc, object> > .Create(RubySites.InstanceCallAction(name, RubyCallSignature.WithBlock(0)));

                        _siteCache[name] = result;
                    }
                }
                return(result);
            }
예제 #15
0
 /// <summary>
 /// Protocol for determining value equality in Ruby (uses IsTrue protocol on result of == call)
 /// </summary>
 public static bool IsEqual(RubyContext /*!*/ context, object lhs, object rhs)
 {
     return(IsTrue(RubySites.Equal(context, lhs, rhs)));
 }
예제 #16
0
        /// <summary>
        /// Casts to symbol. Note that this doesn't actually use to_sym -- it uses to_str.
        /// That's just how Ruby does it.
        ///
        /// Another fun detail: you can pass Fixnums as Symbols. If you pass a Fixnum that
        /// doesn't map to a Symbol (i.e. Fixnum#to_sym returns nil), you get an ArgumentError
        /// instead of a TypeError. At least it produces a warning about using Fixnums as Symbols
        /// </summary>
        public static string /*!*/ CastToSymbol(RubyContext /*!*/ context, object obj)
        {
            if (obj is SymbolId)
            {
                return(SymbolTable.IdToString((SymbolId)obj));
            }

            if (obj is int)
            {
                return(RubyOps.ConvertFixnumToSymbol(context, (int)obj));
            }
            else
            {
                MutableString str = AsString(context, obj);
                if (str != null)
                {
                    return(RubyOps.ConvertMutableStringToSymbol(str));
                }
            }

            throw RubyExceptions.CreateTypeError(String.Format("{0} is not a symbol", RubySites.Inspect(context, obj)));
        }
예제 #17
0
 public static Exception /*!*/ InvalidValueForType(RubyContext /*!*/ context, object obj, string type)
 {
     return(CreateArgumentError(String.Format("invalid value for {0}: {1}", type, RubySites.Inspect(context, obj).ConvertToString())));
 }
예제 #18
0
 public static Node ToYaml(object self, [NotNull] RubyRepresenter /*!*/ rep)
 {
     return(rep.Scalar(self, RubySites.ToS(rep.Context, self)));
 }
예제 #19
0
            public static MutableString InflateStream(RubyClass /*!*/ self, MutableString zstring)
            {
                object obj = RubySites.Allocate(self);

                return(InflateSite.Target(InflateSite, self.Context, obj, zstring));
            }
예제 #20
0
 public static void ConvertToIntegerRange(RubyContext /*!*/ context, Range /*!*/ range, out int begin, out int end, out bool excludeEnd)
 {
     begin      = Protocols.CastToFixnum(context, RubySites.RangeBegin(context, range));
     end        = Protocols.CastToFixnum(context, RubySites.RangeEnd(context, range));
     excludeEnd = RubySites.RangeExcludeEnd(context, range);
 }
예제 #21
0
            internal RubyPropertyDescriptor(string name, object testObject, Type componentType)
                : base(name, null)
            {
                _name          = name;
                _componentType = componentType;

                _getterSite = CallSite <Func <CallSite, RubyContext, object, object> > .Create(RubySites.InstanceCallAction(_name));

                _setterSite = CallSite <Func <CallSite, RubyContext, object, object, object> > .Create(RubySites.InstanceCallAction(_name + "="));

                try {
                    _propertyType = GetValue(testObject).GetType();
                } catch (Exception) {
                    _propertyType = typeof(object);
                }
            }