/// <summary>
        /// Gets a "meta" operation on this userdata. If a descriptor does not support this functionality,
        /// it should return "null" (not a nil).
        /// See <see cref="IUserDataDescriptor.MetaIndex" /> for further details.
        ///
        /// If a method exists marked with <see cref="MoonSharpUserDataMetamethodAttribute" /> for the specific
        /// metamethod requested, that method is returned.
        ///
        /// If the above fails, the following dispatching occur:
        ///
        /// __add, __sub, __mul, __div, __mod and __unm are dispatched to C# operator overloads (if they exist)
        /// __eq is dispatched to System.Object.Equals.
        /// __lt and __le are dispatched IComparable.Compare, if the type implements IComparable or IComparable{object}
        /// __len is dispatched to Length and Count properties, if those exist.
        /// __iterator is handled if the object implements IEnumerable or IEnumerator.
        /// __tonumber is dispatched to implicit or explicit conversion operators to standard numeric types.
        /// __tobool is dispatched to an implicit or explicit conversion operator to bool. If that fails, operator true is used.
        ///
        /// <param name="script">The script originating the request</param>
        /// <param name="obj">The object (null if a static request is done)</param>
        /// <param name="metaname">The name of the metamember.</param>
        /// </summary>
        /// <returns></returns>
        public virtual DynValue MetaIndex(Script script, object obj, string metaname)
        {
            IMemberDescriptor desc = m_MetaMembers.GetOrDefault(metaname);

            if (desc != null)
            {
                return(desc.GetValue(script, obj));
            }

            switch (metaname)
            {
            case "__add":
                return(DispatchMetaOnMethod(script, obj, "op_Addition"));

            case "__sub":
                return(DispatchMetaOnMethod(script, obj, "op_Subtraction"));

            case "__mul":
                return(DispatchMetaOnMethod(script, obj, "op_Multiply"));

            case "__div":
                return(DispatchMetaOnMethod(script, obj, "op_Division"));

            case "__mod":
                return(DispatchMetaOnMethod(script, obj, "op_Modulus"));

            case "__unm":
                return(DispatchMetaOnMethod(script, obj, "op_UnaryNegation"));

            case "__eq":
                return(MultiDispatchEqual(script, obj));

            case "__lt":
                return(MultiDispatchLessThan(script, obj));

            case "__le":
                return(MultiDispatchLessThanOrEqual(script, obj));

            case "__len":
                return(TryDispatchLength(script, obj));

            case "__tonumber":
                return(TryDispatchToNumber(script, obj));

            case "__tobool":
                return(TryDispatchToBool(script, obj));

            case "__iterator":
                return(ClrToScriptConversions.EnumerationToDynValue(script, obj));

            default:
                return(null);
            }
        }
        private DynValue DispatchMetaOnMethod(Script script, object obj, string methodName)
        {
            IMemberDescriptor desc = m_Members.GetOrDefault(methodName);

            if (desc != null)
            {
                return(desc.GetValue(script, obj));
            }
            else
            {
                return(null);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Executes the specified indexer method.
        /// </summary>
        /// <param name="ecToken">The execution control token used to cancel scripts if needed.</param>
        /// <param name="mdesc">The method descriptor</param>
        /// <param name="script">The script.</param>
        /// <param name="obj">The object.</param>
        /// <param name="index">The indexer parameter</param>
        /// <param name="value">The dynvalue to set on a setter, or null.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        protected virtual DynValue ExecuteIndexer(ExecutionControlToken ecToken, IMemberDescriptor mdesc, Script script,
                                                  object obj, DynValue index, DynValue value)
        {
            IList <DynValue> values;

            if (index.Type == DataType.Tuple)
            {
                if (value == null)
                {
                    values = index.Tuple;
                }
                else
                {
                    values = new List <DynValue>(index.Tuple);
                    values.Add(value);
                }
            }
            else
            {
                if (value == null)
                {
                    values = new[] { index };
                }
                else
                {
                    values = new[] { index, value };
                }
            }

            var args    = new CallbackArguments(values, false);
            var execCtx = script.CreateDynamicExecutionContext(ecToken);

            var v = mdesc.GetValue(script, obj);

            if (v.Type != DataType.ClrFunction)
            {
                throw new ScriptRuntimeException("a clr callback was expected in member {0}, while a {1} was found",
                                                 mdesc.Name, v.Type);
            }

            return(v.Callback.ClrCallback(execCtx, args));
        }
Esempio n. 4
0
 /// <summary>
 /// Gets the getter of the member as a DynValue containing a callback
 /// </summary>
 /// <param name="desc">The descriptor instance.</param>
 /// <param name="script">The script.</param>
 /// <param name="obj">The object.</param>
 /// <returns></returns>
 public static DynValue GetGetterCallbackAsDynValue(this IMemberDescriptor desc, Script script, object obj)
 {
     return(DynValue.NewCallback((p1, p2) => desc.GetValue(script, obj)));
 }
		/// <summary>
		/// Executes the specified indexer method.
		/// </summary>
		/// <param name="mdesc">The method descriptor</param>
		/// <param name="script">The script.</param>
		/// <param name="obj">The object.</param>
		/// <param name="index">The indexer parameter</param>
		/// <param name="value">The dynvalue to set on a setter, or null.</param>
		/// <returns></returns>
		/// <exception cref="System.NotImplementedException"></exception>
		protected virtual DynValue ExecuteIndexer(IMemberDescriptor mdesc, Script script, object obj, DynValue index, DynValue value)
		{
			IList<DynValue> values;

			if (index.Type == DataType.Tuple)
			{
				if (value == null)
				{
					values = index.Tuple;
				}
				else
				{
					values = new List<DynValue>(index.Tuple);
					values.Add(value);
				}
			}
			else
			{
				if (value == null)
				{
					values = new DynValue[] { index };
				}
				else
				{
					values = new DynValue[] { index, value };
				}
			}

			CallbackArguments args = new CallbackArguments(values, false);
			ScriptExecutionContext execCtx = script.CreateDynamicExecutionContext();

			DynValue v = mdesc.GetValue(script, obj);

			if (v.Type != DataType.ClrFunction)
				throw new ScriptRuntimeException("a clr callback was expected in member {0}, while a {1} was found", mdesc.Name, v.Type);

			return v.Callback.ClrCallback(execCtx, args);
		}