Wrapper for values passed around the cse expression Parse methods. This allows the values to have metadata attached to them for better decision making in some cases
Inheritance: ICloneable
        ///
        /// <summary>
        ///		Adds a temporary identifier of the given type and name and initializes
        ///		it to the given initValue
        /// </summary>
        ///
        /// <param name="type">Type of identifier</param>
        /// <param name="name">Name of identifier</param>
        /// <param name="initValue">Initial value of identifer</param>
        ///
        public static void AddIdent(Type type, string name, dynamic initValue)
        {
            dynamic value = (initValue is CseObject ? initValue.Value : initValue);

            // TODO: Make CseExceptionType for type assign mismatch
            if (!TypeExp.TypeAssignMatch(type, value))
            {
                throw new Exception(String.Format("Cannot assign {0} to variable of type {1}", value, type.ToString()));
            }

            CseObject ident = new CseObject(value)
            {
                CompileTimeType = type,
                IsLiteral       = false,
                CallMod         = CallArgMod.VAL
            };

            /* TODO: Add custom error type and message for duplicate ident names
             * if (tempIdents.ContainsKey(name))
             *	throw new CseLogicException(CseLogicExceptionType.??, name);
             *
             * TODO: Add keyword (maybe with a prefix) that returns a list of all
             * currently stored temp vars along with their type and value
             */

            tempIdents.Add(name, ident);
        }
示例#2
0
    ///
    /// <summary>
    ///		Parses array expressions
    /// </summary>
    /// 
    /// <param name="rootInstance">Environment where the array is implemented</param>
    /// <param name="arrayIdent">Name of the array</param>
    /// <param name="index">Object for the index value</param>
    /// 
    /// <returns>CseObject containing the array element at the specified index</returns>
    /// 
    /// <exception cref="CseLogicExceptionType.IDENT_IS_NOT_ARRAY" />
    /// <exception cref="CseLogicExceptionType.IDENT_NOT_FOUND" />
    ///
    public static CseObject Parse(CseObject rootInstance, string arrayIdent, CseObject index) {
      BindingFlags flags = BindingFlags.NonPublic |
                 BindingFlags.Public |
                 BindingFlags.Static |
                 BindingFlags.Instance;

      Type rootInstanceType = TypeExp.GetTypeObj(rootInstance.Value);

      object result = null;
      FieldInfo fieldInfo = rootInstanceType.GetField(arrayIdent, flags);
      if (fieldInfo != null) {
        result = fieldInfo.GetValue(rootInstance.Value);
      }
      else {
        PropertyInfo propertyInfo = rootInstanceType.GetProperty(arrayIdent);
        if (propertyInfo != null)
          result = propertyInfo.GetValue(rootInstance.Value, null);
        else
          throw new CseLogicException(CseLogicExceptionType.IDENT_NOT_FOUND, arrayIdent);
      }

      IDictionary dictionary = result as IDictionary;
      Array array = result as Array;

      if (dictionary != null) {
        return new CseObject(dictionary[index.Value]);
      }
      else if (array != null) {
        return new CseObject(array.GetValue(long.Parse(index.Value.ToString())));
      }
      else {
        throw new CseLogicException(CseLogicExceptionType.IDENT_IS_NOT_ARRAY, arrayIdent);
      }
    }
示例#3
0
        ///
        /// <summary>
        ///		Applies numeric affirmation (i.e. unary plus) to numeric values
        /// </summary>
        ///
        /// <param name="obj">The CseObject with the value to affirm</param>
        ///
        /// <returns>The CseObject after affirmation</returns>
        ///
        /// <exception cref="CseLogicExceptionType.CANT_AFFIRM_NON_NUM" />
        ///
        internal static CseObject Affirm(CseObject obj)
        {
            CseObject result = (CseObject)obj.Clone();

            dynamic value = obj.Value;
            double  numValue;

            if (value is string)
            {
                throw new CseLogicException(CseLogicExceptionType.CANT_AFFIRM_NON_NUM, value.ToString());
            }
            else if (!double.TryParse(value.ToString(), out numValue))
            {
                MethodInfo mi = value.GetType().GetMethod(OpOverloadNames.UPLUS);
                if (null != mi)
                {
                    result.Value = value.GetType().InvokeMember(OpOverloadNames.UPLUS, OpOverloadNames.Flags, null, CsEval.evalEnvironment, new object[] { value });
                    return(result);
                }
                else
                {
                    throw new CseLogicException(CseLogicExceptionType.CANT_AFFIRM_NON_NUM, value.ToString());
                }
            }

            return(result);
        }
示例#4
0
        ///
        /// <summary>
        ///		Determines if a boxing conversion exists between the passed object and the type
        /// </summary>
        ///
        /// <param name="fromArg">The object to convert</param>
        /// <param name="to">The type to attempt to convert the object to.</param>
        ///
        /// <returns>True if a boxing conversion exists between the object and the type, false otherwise</returns>
        ///
        public static bool IsBoxingConversion(CseObject fromArg, Type to)
        {
            Type unwrappedBox = fromArg.ValueType;

            if (IsNullableType(unwrappedBox))
            {
                unwrappedBox = Nullable.GetUnderlyingType(unwrappedBox);
            }

            if (to.Equals(typeof(System.ValueType)) || to.Equals(typeof(object)))
            {
                return(true);
            }
            else if (CrawlThatShit(to.GetHashCode(), unwrappedBox, new List <int>()))
            {
                return(true);
            }
            else if (unwrappedBox.IsEnum && to.Equals(typeof(System.Enum)))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
示例#5
0
        ///
        /// <summary>
        ///		Determines if it is possible to coerce the given list of arguments
        ///		so a method signature can be matched.
        /// </summary>
        ///
        /// <param name="args">List of arguments to check</param>
        ///
        /// <returns>
        ///		True if exactly one argument is of an integral type, false otherwise.
        ///		Idea is to only coerce integral arguments since floating point arguments
        ///		would lose precision when converted to a narrower type and objects don't
        ///		need it due to inheritance (i.e. they will match the method signature without
        ///		it). If there is more than one integral argument, then the chance that the
        ///		wrong overloaded method is called is too great, and so this method returns
        ///		false meaning it can't safely coerce the integral args. If only one is found,
        ///		and a method can't be matched without coercion, then we can safely narrow
        ///		down that one integral arg without worry about matching the wrong method.
        /// </returns>
        ///
        private static bool CanCoerce(List <CseObject> args)
        {
            if (args == null)
            {
                return(false);
            }

            bool foundIntType = false;
            bool canCoerce    = false;

            for (int i = 0; i < args.Count; i++)
            {
                CseObject arg = args[i];

                if (LiteralExp.IsIntType(arg))
                {
                    if (!foundIntType)
                    {
                        canCoerce    = true;
                        foundIntType = true;
                    }
                    else
                    {
                        canCoerce = false;
                        break;
                    }
                }
            }

            return(canCoerce);
        }
示例#6
0
        ///
        /// <summary>
        ///		Parses literals that contain the exponential 'e' character
        /// </summary>
        ///
        /// <param name="data">String containing the literal</param>
        ///
        /// <returns>A double value</returns>
        ///
        /// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_DBL" />
        ///
        internal static CseObject ParseEType(string data)
        {
            double value;

            Regex r = new Regex(@"(f|m|d)$", RegexOptions.IgnoreCase);

            Match  m      = r.Match(data);
            string suffix = m.Groups[1].Value;
            string number = data.Substring(0, data.Length - suffix.Length);

            if (!double.TryParse(number, out value))
            {
                throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_DBL, data);
            }

            CseObject result = null;

            if (suffix != "")
            {
                result = ParseFloatType(value.ToString(), suffix);
            }
            else
            {
                result = new CseObject(value);
            }

            result.IsLiteral = true;
            return(result);
        }
示例#7
0
        ///
        /// <summary>
        ///		Parses integral-type literals
        /// </summary>
        ///
        /// <param name="data">String containing the literal</param>
        /// <param name="suffix">Optional type suffix</param>
        ///
        /// <returns>An integral-type value or float-type if float-type suffix is supplied</returns>
        ///
        /// <exception cref="CseLogicExceptionType.NOT_A_NUM" />
        /// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_INT_TYPE" />
        ///
        internal static CseObject ParseIntType(string data, string suffix)
        {
            CseObject result = null;

            if (suffix != null && suffix != "")
            {
                switch (suffix.ToLower())
                {
                case "f":
                    result = new CseObject(float.Parse(data));
                    break;

                case "m":
                    result = new CseObject(decimal.Parse(data));
                    break;

                case "d":
                    result = new CseObject(double.Parse(data));
                    break;

                case "ul":
                    result = new CseObject(ulong.Parse(data));
                    break;

                case "u":
                    result = new CseObject(uint.Parse(data));
                    break;

                case "l":
                    result = new CseObject(long.Parse(data));
                    break;
                }
            }
            else
            {
                // TODO: if long cannot parse number, it may mean an overflow/underflow not a NaN problem
                int  intAttempt;
                long longAttempt;
                if (int.TryParse(data, out intAttempt))
                {
                    result = new CseObject(intAttempt);
                }
                else if (long.TryParse(data, out longAttempt))
                {
                    result = new CseObject(longAttempt);
                }
                else
                {
                    throw new CseLogicException(CseLogicExceptionType.NOT_A_NUM, data);
                }
            }

            if (result == null)
            {
                throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_INT_TYPE, data);
            }

            result.IsLiteral = true;
            return(result);
        }
示例#8
0
		///
		/// <summary>
		///		Parses conditional expressions
		/// </summary>
		/// 
		/// <param name="leftOp">Left operand</param>
		/// <param name="rightOp">Right operand</param>
		/// <param name="type">Conditional operator type</param>
		/// 
		/// <returns>The result of applying the conditional operator</returns>
		/// 
		public static CseObject Parse(CseObject leftOp, CseObject rightOp, CondType type) {
			CseObject obj = new CseObject(null) { IsLiteral = leftOp.IsLiteral && rightOp.IsLiteral };

			try {
				switch (type) {
					case CondType.EQ:
						obj.Value = leftOp.Value == rightOp.Value;
						break;
					case CondType.NEQ:
						obj.Value = leftOp.Value != rightOp.Value;
						break;
					case CondType.GT:
						obj.Value = leftOp.Value > rightOp.Value;
						break;
					case CondType.GTE:
						obj.Value = leftOp.Value >= rightOp.Value;
						break;
					case CondType.LT:
						obj.Value = leftOp.Value < rightOp.Value;
						break;
					case CondType.LTE:
						obj.Value = leftOp.Value <= rightOp.Value;
						break;
					default:
						throw new System.NotImplementedException("Not implemented.");
				}
			}
			catch {
				// TODO: Fill this out!
			}

			return obj;
		}
示例#9
0
        ///
        /// <summary>
        ///		Parses object construction expression (expressions using "new")
        /// </summary>
        ///
        /// <param name="instance">The root object</param>
        /// <param name="typeName">Name of the type to create</param>
        /// <param name="constructorParams">
        ///		CseObject array containing arguments to be sent to the constructor.
        ///		Each CseObject is one argument
        /// </param>
        ///
        /// <returns>CseObject containing the new object</returns>
        ///
        /// <exception cref="CseLogicExceptionType.UNKNOWN_TYPE" />
        ///
        internal static CseObject Parse(CseObject instance, string typeName, List <CseObject> constructorParams)
        {
            BindingFlags flags = BindingFlags.CreateInstance |
                                 BindingFlags.Instance |
                                 BindingFlags.NonPublic |
                                 BindingFlags.Public;

            Type      typeFound = TypeExp.GetType(typeName);
            CseObject result    = null;

            if (typeFound != null)
            {
                if (constructorParams != null && constructorParams.Count > 0)
                {
                    object[] objArgs = new object[constructorParams.Count];
                    for (int i = 0; i < constructorParams.Count; i++)
                    {
                        objArgs[i] = constructorParams[i].Value;
                    }

                    result = new CseObject(Activator.CreateInstance(typeFound, flags, null, objArgs, null));
                }
                else
                {
                    result = new CseObject(Activator.CreateInstance(typeFound, flags, null, null, null));
                }
            }
            else
            {
                throw new CseLogicException(CseLogicExceptionType.UNKNOWN_TYPE, typeName);
            }

            return(result);
        }
		///
		/// <summary>
		///		Parses object construction expression (expressions using "new")
		/// </summary>
		/// 
		/// <param name="instance">The root object</param>
		/// <param name="typeName">Name of the type to create</param>
		/// <param name="constructorParams">
		///		CseObject array containing arguments to be sent to the constructor. 
		///		Each CseObject is one argument
		/// </param>
		/// 
		/// <returns>CseObject containing the new object</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.UNKNOWN_TYPE" />
		///
		internal static CseObject Parse(CseObject instance, string typeName, List<CseObject> constructorParams) {
			BindingFlags flags = BindingFlags.CreateInstance |
								 BindingFlags.Instance |
								 BindingFlags.NonPublic |
								 BindingFlags.Public;

			Type typeFound = TypeExp.GetType(typeName);
			CseObject result = null;

			if (typeFound != null) {
				if (constructorParams != null && constructorParams.Count > 0) {
					object[] objArgs = new object[constructorParams.Count];
					for (int i = 0; i < constructorParams.Count; i++)
						objArgs[i] = constructorParams[i].Value;

					result = new CseObject(Activator.CreateInstance(typeFound, flags, null, objArgs, null));
				}
				else {
					result = new CseObject(Activator.CreateInstance(typeFound, flags, null, null, null));
				}
			}
			else {
				throw new CseLogicException(CseLogicExceptionType.UNKNOWN_TYPE, typeName);
			}

			return result;
		}
示例#11
0
    ///
    /// <summary>
    ///		Used for quick evaluation.
    ///		Use this when the evaluation environment changes often.
    ///		If the environment is consistent, set CsEval.EvalEnvironment
    ///		then call CsEval.Eval(string data).
    /// </summary>
    /// 
    /// <param name="evalEnvironment">
    ///		Provides an evaluation environment for the given expression.
    ///		The stored evaluation environment is temporarily replaced
    ///		when the given statement is evaluated and restored afterwards.
    ///	</param>
    /// <param name="data">The expression to evaluate</param>
    /// 
    /// <returns>The return result of evaluating the expression</returns>
    /// 
    public static object Eval(object evalEnvironment, string data) {
      CseObject saveDebugInstance = CsEval.evalEnvironment;
      CsEval.evalEnvironment = new CseObject(evalEnvironment);
      object result = Eval(data);
      CsEval.evalEnvironment = saveDebugInstance;

      return result;
    }
示例#12
0
		///
		/// <summary>
		///		Parses ternary expressions
		/// </summary>
		/// 
		/// <param name="cond">Conditional to test</param>
		/// <param name="truePart">Expression to return if condition is true</param>
		/// <param name="falsePart">Expression to return if condition is false</param>
		/// 
		/// <returns>truePart if cond is true, falsePart otherwise</returns>
		/// 
		public static CseObject Ternary(CseObject cond, CseObject truePart, CseObject falsePart) {
			bool? condBool = cond.Value as bool?;

			if (condBool != null)
				return condBool.Value ? truePart : falsePart;
			else {
				MethodInfo mi = cond.Value.GetType().GetMethod(OpOverloadNames.TRUE);
				if (mi != null)
					return new CseObject(cond.Value.GetType().InvokeMember(OpOverloadNames.TRUE, OpOverloadNames.Flags, null, CsEval.evalEnvironment, new object[] { cond.Value }));
				else
					return null;
				//TODO: throw new logic exception for this 
			}
		}
示例#13
0
        ///
        /// <summary>
        ///		Parses float-type literals
        /// </summary>
        ///
        /// <param name="data">String containing the literal</param>
        /// <param name="hasSuffix">Indicates whether a suffix is present or not</param>
        ///
        /// <returns>A float-type value</returns>
        ///
        /// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_FLT_TYPE" />
        /// <exception cref="CseLogicExceptionType.NOT_A_NUM" />
        ///
        internal static CseObject ParseFloatType(string data, bool hasSuffix)
        {
            CseObject result = null;

            if (hasSuffix)
            {
                // Determine the suffix
                Regex r = new Regex(@"((?:\d|\.)+)([A-Za-z]{1,2})$");

                Match m = r.Match(data);

                data = m.Groups[1].Value;
                string suffix = m.Groups[2].Value;

                switch (suffix.ToLower())
                {
                case "f":
                    result = new CseObject(float.Parse(data));
                    break;

                case "m":
                    result = new CseObject(decimal.Parse(data));
                    break;

                case "d":
                    result = new CseObject(double.Parse(data));
                    break;
                }
            }
            else
            {
                double doubleAttempt;
                if (double.TryParse(data, out doubleAttempt))
                {
                    result = new CseObject(doubleAttempt);
                }
                else
                {
                    throw new CseLogicException(CseLogicExceptionType.NOT_A_NUM, data);
                }
            }

            if (result == null)
            {
                throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_FLT_TYPE, data);
            }

            result.IsLiteral = true;
            return(result);
        }
示例#14
0
        ///
        /// <summary>
        ///		Tests for an implicit enum conversion, given a CseObject and a type.
        /// </summary>
        ///
        /// <param name="data">The object to test converting</param>
        /// <param name="t">The type to attempt to convert the object to</param>
        ///
        /// <returns>True if an implicit enum conversion is valid, false otherwise</returns>
        ///
        public static bool ImpEnumConv(CseObject data, Type t)
        {
            long num = -1;

            if (data.IsLiteral && t.IsEnum && long.TryParse(data.Value.ToString(), out num))
            {
                if (num == 0)
                {
                    return(true);
                }
            }

            return(false);
        }
示例#15
0
        ///
        /// <summary>
        ///		Determines whether the xdata's CompileTimeType is an unsigned integral type or not
        /// </summary>
        ///
        /// <param name="xdata">CseObject to examine the CompileTimeType of</param>
        ///
        /// <returns>True if xdata's CompileTimeType is an unsigned integral type, false otherwise</returns>
        ///
        private static bool IsUnsignedType(CseObject xdata)
        {
            List <Type> unsignedTypes = new List <Type> {
                typeof(byte), typeof(UInt16), typeof(UInt32), typeof(UInt64)
            };

            if (unsignedTypes.Contains(xdata.CompileTimeType))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
示例#16
0
        ///
        /// <summary>
        ///		Applies numeric negation (i.e. unary minus) to numeric values
        /// </summary>
        ///
        /// <param name="obj">The CseObject with the value to negate</param>
        ///
        /// <returns>The CseObject after negation</returns>
        ///
        /// <exception cref="CseLogicExceptionType.CANT_NEGATE_NON_NUM" />
        /// <exception cref="CseLogicExceptionType.ERROR_NEGATING_VALUE_OF_TYPE" />
        ///
        internal static CseObject Negate(CseObject obj)
        {
            CseObject result = (CseObject)obj.Clone();

            dynamic value = obj.Value;
            double  numValue;

            if (value is string)
            {
                throw new CseLogicException(CseLogicExceptionType.CANT_NEGATE_NON_NUM, value.ToString());
            }
            else if (!double.TryParse(value.ToString(), out numValue))
            {
                MethodInfo mi = value.GetType().GetMethod(OpOverloadNames.UMINUS);
                if (null != mi)
                {
                    result.Value = value.GetType().InvokeMember(OpOverloadNames.UMINUS, OpOverloadNames.Flags, null, CsEval.evalEnvironment, new object[] { value });
                    return(result);
                }
                else
                {
                    throw new CseLogicException(CseLogicExceptionType.CANT_NEGATE_NON_NUM, value.ToString());
                }
            }

            numValue    *= -1;
            result.Value = numValue;

            try {
                result = CastExp.Parse(CsEval.evalEnvironment, value.GetType().Name, result);
            }
            catch {
                if (value.ToString().ToLower().Contains("e"))
                {
                    result = LiteralExp.ParseEType(numValue.ToString());
                }
                else if (value.ToString().Contains("."))
                {
                    result = LiteralExp.ParseFloatType(numValue.ToString(), null);
                }
                else
                {
                    throw new CseLogicException(CseLogicExceptionType.ERROR_NEGATING_VALUE_OF_TYPE, value.ToString(), value.GetType().Name);
                }
            }

            return(result);
        }
示例#17
0
        ///
        /// <summary>
        ///		Parses char literals
        /// </summary>
        ///
        /// <param name="data">String containing the literal</param>
        ///
        /// <returns>A char value</returns>
        ///
        /// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_CHAR" />
        ///
        internal static CseObject ParseChar(string data)
        {
            data = data.Remove(data.Length - 1, 1).Remove(0, 1);
            if (data.Length > 1 && !data.StartsWith("\\"))
            {
                throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_CHAR, data);
            }
            else
            {
                ParseEscSeqs(ref data, false);

                CseObject result = new CseObject(data[0]);
                result.IsLiteral = true;
                return(result);
            }
        }
示例#18
0
        ///
        /// <summary>
        ///		Parses bool literals
        /// </summary>
        ///
        /// <param name="data">String containing the literal</param>
        ///
        /// <returns>A bool value</returns>
        ///
        internal static CseObject ParseBool(string data)
        {
            CseObject result = null;

            if (data.Equals("true"))
            {
                result = new CseObject(true);
            }
            else
            {
                result = new CseObject(false);
            }

            result.IsLiteral = true;
            return(result);
        }
示例#19
0
    ///
    /// <summary>
    ///		Parses identifiers (fields or properties)
    /// </summary>
    /// 
    /// <param name="environment">The environment containing the field or property</param>
    /// <param name="data">The name of the field or property</param>
    /// 
    /// <returns>An CseObject containing the value of the identifier or containing null if identifier cannot be found</returns>
    /// 
    /// <exception cref="CseLogicExceptionType.IDENT_NOT_FOUND" />
    ///
    internal static CseObject Parse(CseObject environment, string data) {
      if (data[0].Equals('@'))
        data = data.Remove(0, 1);

      LiteralExp.ParseEscSeqs(ref data, false);

      CseObject result = null;
      Type instanceType = TypeExp.GetTypeObj(environment.Value);

      if (!instanceType.IsEnum) {
        if (environment == CsEval.EvalEnvironment) {
          CseObject tempLookup = TempIdentifierExp.Lookup(data);
          if (tempLookup != null)
            return tempLookup;
        }

        FieldInfo fieldInfo = instanceType.GetField(data, defaultFlags | BindingFlags.GetField);
        if (fieldInfo != null) {
          result = new CseObject(fieldInfo.GetValue(environment.Value));
          result.CompileTimeType = fieldInfo.FieldType;
        }
        else {
          PropertyInfo propertyInfo = instanceType.GetProperty(data, defaultFlags | BindingFlags.GetProperty);
          if (propertyInfo != null) {
            result = new CseObject(propertyInfo.GetValue(environment.Value, null));
            result.CompileTimeType = propertyInfo.PropertyType;
          }
          else {
            Type t = TypeExp.GetType(data);
            if (t != null) {
              result = new CseObject(t);
              result.CompileTimeType = t.GetType();
            }
            else {
              throw new CseLogicException(CseLogicExceptionType.IDENT_NOT_FOUND, data);
            }
          }
        }
      }
      else {
        dynamic resultObj = Enum.Parse(instanceType, data);
        result = new CseObject(resultObj);
        result.CompileTimeType = resultObj.GetType();
      }

      return result;
    }
示例#20
0
        ///
        /// <summary>
        ///		Parses string literals
        /// </summary>
        ///
        /// <param name="data">String containing the literal</param>
        ///
        /// <returns>A string value</returns>
        ///
        internal static CseObject ParseStr(string data)
        {
            if (data.StartsWith("@"))
            {
                data = data.Remove(0, 1);
                ParseEscSeqs(ref data, true);
            }
            else
            {
                ParseEscSeqs(ref data, false);
            }

            CseObject result = new CseObject(data.Remove(data.Length - 1, 1).Remove(0, 1));

            result.IsLiteral = true;
            return(result);
        }
示例#21
0
        ///
        /// <summary>
        ///		Parses array expressions
        /// </summary>
        ///
        /// <param name="rootInstance">Environment where the array is implemented</param>
        /// <param name="arrayIdent">Name of the array</param>
        /// <param name="index">Object for the index value</param>
        ///
        /// <returns>CseObject containing the array element at the specified index</returns>
        ///
        /// <exception cref="CseLogicExceptionType.IDENT_IS_NOT_ARRAY" />
        /// <exception cref="CseLogicExceptionType.IDENT_NOT_FOUND" />
        ///
        public static CseObject Parse(CseObject rootInstance, string arrayIdent, CseObject index)
        {
            BindingFlags flags = BindingFlags.NonPublic |
                                 BindingFlags.Public |
                                 BindingFlags.Static |
                                 BindingFlags.Instance;

            Type rootInstanceType = TypeExp.GetTypeObj(rootInstance.Value);

            object    result    = null;
            FieldInfo fieldInfo = rootInstanceType.GetField(arrayIdent, flags);

            if (fieldInfo != null)
            {
                result = fieldInfo.GetValue(rootInstance.Value);
            }
            else
            {
                PropertyInfo propertyInfo = rootInstanceType.GetProperty(arrayIdent);
                if (propertyInfo != null)
                {
                    result = propertyInfo.GetValue(rootInstance.Value, null);
                }
                else
                {
                    throw new CseLogicException(CseLogicExceptionType.IDENT_NOT_FOUND, arrayIdent);
                }
            }

            IDictionary dictionary = result as IDictionary;
            Array       array      = result as Array;

            if (dictionary != null)
            {
                return(new CseObject(dictionary[index.Value]));
            }
            else if (array != null)
            {
                return(new CseObject(array.GetValue(long.Parse(index.Value.ToString()))));
            }
            else
            {
                throw new CseLogicException(CseLogicExceptionType.IDENT_IS_NOT_ARRAY, arrayIdent);
            }
        }
示例#22
0
		///
		/// <summary>
		///		Parses assignment expressions. This method basically just prepares
		///		the parameters for a call to IdentifierExp.Assign(). Reference that
		///		method for more information on this method's parameters.
		/// </summary>
		/// 
		/// <param name="envChain">
		///		List of CseObjects from the chain expression of the lhs.
		///		This makes up the list of environment objects.
		///	</param>
		/// <param name="envNames">List of field/property names in the lhs chain expression.</param>
		/// <param name="envIndices">
		///		List of array indices for each array in the lhs chain expression.
		///		For each non-array, the envIndices at that index is null.
		///	</param>
		/// <param name="rhs">Rhs expression</param>
		/// 
		/// <returns>The rhs parameter</returns>
		/// 
		public static CseObject Parse(List<CseObject> envChain, List<string> envNames, List<CseObject> envIndices, CseObject rhs) {
			Type envType;

			while (envChain.Count > 1) {
				envType = envChain[1].Value.GetType();
				if (!envType.IsValueType) {
					envChain.RemoveAt(0);
					envNames.RemoveAt(0);
					envIndices.RemoveAt(0);
				}
				else {
					break;
				}
			}

			IdentifierExp.Assign(envChain, envNames, envIndices, rhs);
			return rhs;
		}
示例#23
0
        ///
        /// <summary>
        ///		Inspects all CseObjects in args and for the literal integral values, it
        ///		converts their type to the most narrow type that can contain their value.
        ///		E.g. if the value is a literal 300 (not the value of an identifier as those
        ///		types aren't changed), then the smallest integral data type that can store
        ///		that would be a short. This increases the chance that the given args will
        ///		match a wider method signature.
        /// </summary>
        ///
        /// <param name="args">Arguments to inspect and convert</param>
        ///
        private static void NarrowAllIntTypes(ref List <CseObject> args)
        {
            if (args == null)
            {
                return;
            }

            for (int i = 0; i < args.Count; i++)
            {
                CseObject arg = args[i];

                if (LiteralExp.IsIntType(arg) && arg.IsLiteral)
                {
                    args[i] = LiteralExp.NarrowIntType(arg);
                    args[i].CompileTimeType = args[i].Value.GetType();
                }
            }
        }
示例#24
0
        ///
        /// <summary>
        ///		Parses conditional expressions
        /// </summary>
        ///
        /// <param name="leftOp">Left operand</param>
        /// <param name="rightOp">Right operand</param>
        /// <param name="type">Conditional operator type</param>
        ///
        /// <returns>The result of applying the conditional operator</returns>
        ///
        public static CseObject Parse(CseObject leftOp, CseObject rightOp, CondType type)
        {
            CseObject obj = new CseObject(null)
            {
                IsLiteral = leftOp.IsLiteral && rightOp.IsLiteral
            };

            try {
                switch (type)
                {
                case CondType.EQ:
                    obj.Value = leftOp.Value == rightOp.Value;
                    break;

                case CondType.NEQ:
                    obj.Value = leftOp.Value != rightOp.Value;
                    break;

                case CondType.GT:
                    obj.Value = leftOp.Value > rightOp.Value;
                    break;

                case CondType.GTE:
                    obj.Value = leftOp.Value >= rightOp.Value;
                    break;

                case CondType.LT:
                    obj.Value = leftOp.Value < rightOp.Value;
                    break;

                case CondType.LTE:
                    obj.Value = leftOp.Value <= rightOp.Value;
                    break;

                default:
                    throw new System.NotImplementedException("Not implemented.");
                }
            }
            catch {
                // TODO: Fill this out!
            }

            return(obj);
        }
示例#25
0
		///
		/// <summary>
		///		Parses integral-type literals
		/// </summary>
		/// 
		/// <param name="data">String containing the literal</param>
		/// <param name="suffix">Optional type suffix</param>
		/// 
		/// <returns>An integral-type value or float-type if float-type suffix is supplied</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.NOT_A_NUM" />
		/// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_INT_TYPE" />
		///
		internal static CseObject ParseIntType(string data, string suffix) {
			CseObject result = null;

			if (suffix != null && suffix != "") {
				switch (suffix.ToLower()) {
					case "f":
						result = new CseObject(float.Parse(data));
						break;
					case "m":
						result = new CseObject(decimal.Parse(data));
						break;
					case "d":
						result = new CseObject(double.Parse(data));
						break;
					case "ul":
						result = new CseObject(ulong.Parse(data));
						break;
					case "u":
						result = new CseObject(uint.Parse(data));
						break;
					case "l":
						result = new CseObject(long.Parse(data));
						break;
				}
			}
			else {
				// TODO: if long cannot parse number, it may mean an overflow/underflow not a NaN problem
				int intAttempt;
				long longAttempt;
				if (int.TryParse(data, out intAttempt))
					result = new CseObject(intAttempt);
				else if (long.TryParse(data, out longAttempt))
					result = new CseObject(longAttempt);
				else
					throw new CseLogicException(CseLogicExceptionType.NOT_A_NUM, data);
			}

			if (result == null)
				throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_INT_TYPE, data);

			result.IsLiteral = true;
			return result;
		}
示例#26
0
        ///
        /// <summary>
        ///		Parses float-type literals
        /// </summary>
        ///
        /// <param name="data">String containing the literal</param>
        /// <param name="suffix">Optional type suffix</param>
        ///
        /// <returns>A float-type value</returns>
        ///
        /// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_FLT_TYPE" />
        /// <exception cref="CseLogicExceptionType.NOT_A_NUM" />
        ///
        internal static CseObject ParseFloatType(string data, string suffix)
        {
            CseObject result = null;

            if (suffix != null && suffix != "")
            {
                switch (suffix.ToLower())
                {
                case "f":
                    result = new CseObject(float.Parse(data));
                    break;

                case "m":
                    result = new CseObject(decimal.Parse(data));
                    break;

                case "d":
                    result = new CseObject(double.Parse(data));
                    break;
                }
            }
            else
            {
                double doubleAttempt;
                if (double.TryParse(data, out doubleAttempt))
                {
                    result = new CseObject(doubleAttempt);
                }
                else
                {
                    throw new CseLogicException(CseLogicExceptionType.NOT_A_NUM, data);
                }
            }

            if (result == null)
            {
                throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_FLT_TYPE, data);
            }

            result.IsLiteral = true;
            return(result);
        }
示例#27
0
        ///
        /// <summary>
        ///		Parses ternary expressions
        /// </summary>
        ///
        /// <param name="cond">Conditional to test</param>
        /// <param name="truePart">Expression to return if condition is true</param>
        /// <param name="falsePart">Expression to return if condition is false</param>
        ///
        /// <returns>truePart if cond is true, falsePart otherwise</returns>
        ///
        public static CseObject Ternary(CseObject cond, CseObject truePart, CseObject falsePart)
        {
            bool?condBool = cond.Value as bool?;

            if (condBool != null)
            {
                return(condBool.Value ? truePart : falsePart);
            }
            else
            {
                MethodInfo mi = cond.Value.GetType().GetMethod(OpOverloadNames.TRUE);
                if (mi != null)
                {
                    return(new CseObject(cond.Value.GetType().InvokeMember(OpOverloadNames.TRUE, OpOverloadNames.Flags, null, CsEval.evalEnvironment, new object[] { cond.Value })));
                }
                else
                {
                    return(null);
                }
                //TODO: throw new logic exception for this
            }
        }
示例#28
0
		///
		/// <summary>
		///		Adds a temporary identifier of the given type and name and initializes
		///		it to the given initValue
		/// </summary>
		/// 
		/// <param name="type">Type of identifier</param>
		/// <param name="name">Name of identifier</param>
		/// <param name="initValue">Initial value of identifer</param>
		/// 
		public static void AddIdent(Type type, string name, dynamic initValue) {
			dynamic value = (initValue is CseObject ? initValue.Value : initValue);

			// TODO: Make CseExceptionType for type assign mismatch
			if (!TypeExp.TypeAssignMatch(type, value))
				throw new Exception(String.Format("Cannot assign {0} to variable of type {1}", value, type.ToString()));

			CseObject ident = new CseObject(value) {
				CompileTimeType = type,
				IsLiteral = false,
				CallMod = CallArgMod.VAL
			};

			/* TODO: Add custom error type and message for duplicate ident names
			 * if (tempIdents.ContainsKey(name))
			 *	throw new CseLogicException(CseLogicExceptionType.??, name);
			 * 
			 * TODO: Add keyword (maybe with a prefix) that returns a list of all 
			 * currently stored temp vars along with their type and value
			 */

			tempIdents.Add(name, ident);
		}
示例#29
0
		///
		/// <summary>
		///		Parses bool literals
		/// </summary>
		/// 
		/// <param name="data">String containing the literal</param>
		/// 
		/// <returns>A bool value</returns>
		///
		internal static CseObject ParseBool(string data) {
			CseObject result = null;

			if (data.Equals("true"))
				result = new CseObject(true);
			else
				result = new CseObject(false);

			result.IsLiteral = true;
			return result;
		}
示例#30
0
		///
		/// <summary>
		///		Parses arithmetic expressions
		/// </summary>
		/// 
		/// <param name="leftOperand">Left operand</param>
		/// <param name="rightOperand">Right operand</param>
		/// <param name="arithType">Arithmetic operator type</param>
		/// 
		/// <remarks>
		///		Only works with operands that evaluate to either numeric or string types. If both operands are strings
		///		and arithType is ADD, concatenation is performed. Else, if either operand is of a float type, both are 
		///		treated as float type. Else, both are treated as int types. This is to ensure proper behavior of operators 
		///		such as addition and division. If operands are of int type, result is then parsed as a literal expression
		///		to ensure correct return type.
		///	</remarks>
		///	
		/// <returns>Result of arithmetic operation</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.ARITH_EXCEPTION" />
		/// <exception cref="CseLogicExceptionType.LEFT_OP_NON_NUM" />
		/// <exception cref="CseLogicExceptionType.RIGHT_OP_NON_NUM" />
		/// 
		internal static CseObject Parse(CseObject leftOperand, CseObject rightOperand, ArithType arithType) {
			dynamic result = null;
			dynamic leftOpValue = leftOperand.Value;
			dynamic rightOpValue = rightOperand.Value;
			string methOpName = null;

			try {
				switch (arithType) {
					case ArithType.ADD:
						methOpName = OpOverloadNames.ADD;
						result = leftOpValue + rightOpValue;
						break;
					case ArithType.DIV:
						methOpName = OpOverloadNames.DIV;
						result = leftOpValue / rightOpValue;
						break;
					case ArithType.MOD:
						methOpName = OpOverloadNames.MOD;
						result = leftOpValue % rightOpValue;
						break;
					case ArithType.MUL:
						methOpName = OpOverloadNames.MUL;
						result = leftOpValue * rightOpValue;
						break;
					case ArithType.POW:
						result = Math.Pow(leftOpValue, rightOpValue);
						break;
					case ArithType.SUB:
						methOpName = OpOverloadNames.SUB;
						result = leftOpValue - rightOpValue;
						break;
				}
				return new CseObject(result);
			}
			catch {
				if (methOpName == null)
					throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);

				MethodInfo leftOpMeth = leftOpValue.GetType().GetMethod(methOpName, OpOverloadNames.Flags);
				MethodInfo rightOpMeth = rightOpValue.GetType().GetMethod(methOpName, OpOverloadNames.Flags);

				if (leftOpMeth == null && rightOpMeth == null)
					throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);
				else if (leftOpMeth != null) {
					try {
						result = new CseObject(leftOpMeth.Invoke(leftOpValue, new object[] { leftOpValue, rightOpValue }));
					}
					catch {
						throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);
					}
				}
				else if (rightOpMeth != null) {
					try {
						result = new CseObject(rightOpMeth.Invoke(rightOpValue, new object[] { leftOpValue, rightOpValue }));
					}
					catch {
						throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);
					}
				}
				else {
					throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);
				}
			}

			return new CseObject(result);
		}
示例#31
0
		///
		/// <summary>
		///		Tests for an implicit enum conversion, given a CseObject and a type.
		/// </summary>
		/// 
		/// <param name="data">The object to test converting</param>
		/// <param name="t">The type to attempt to convert the object to</param>
		/// 
		/// <returns>True if an implicit enum conversion is valid, false otherwise</returns>
		/// 
		public static bool ImpEnumConv(CseObject data, Type t) {
			long num = -1;

			if (data.IsLiteral && t.IsEnum && long.TryParse(data.Value.ToString(), out num))
				if (num == 0)
					return true;

			return false;
		}
示例#32
0
        ///
        /// <summary>
        ///		Parses casts
        /// </summary>
        ///
        /// <remarks>
        ///		Can only perform a real cast in certain situations. When it can't it
        ///		tries to mimic a cast using parsing or conversion.
        ///	</remarks>
        ///
        /// <param name="instance">The root object</param>
        /// <param name="typeName">Type to cast to</param>
        /// <param name="cseData">Expression to cast</param>
        ///
        /// <returns>The converted object</returns>
        ///
        /// <exception cref="CseLogicExceptionType.CANT_CAST_VALUE_TO_TYPE" />
        /// <exception cref="CseLogicExceptionType.OVERFLOW_TRYING_TO_CAST" />
        ///
        // TODO: Check if the generic Cast<T> method would work
        internal static CseObject Parse(CseObject instance, string typeName, CseObject cseData)
        {
            dynamic data      = cseData.Value;
            dynamic castedObj = null;
            Type    dataType  = TypeExp.GetTypeObj(data);

            if (dataType.IsEnum)
            {
                switch (typeName.ToLower())
                {
                case "bool":
                    castedObj = (bool)data;
                    break;

                case "byte":
                    castedObj = (byte)data;
                    break;

                case "decimal":
                    castedObj = (decimal)data;
                    break;

                case "double":
                    castedObj = (double)data;
                    break;

                case "float":
                    castedObj = (float)data;
                    break;

                case "int":
                    castedObj = (int)data;
                    break;

                case "int16":
                    castedObj = (Int16)data;
                    break;

                case "int32":
                    castedObj = (Int32)data;
                    break;

                case "int64":
                    castedObj = (Int64)data;
                    break;

                case "long":
                    castedObj = (long)data;
                    break;

                case "sbyte":
                    castedObj = (sbyte)data;
                    break;

                case "short":
                    castedObj = (short)data;
                    break;

                case "single":
                    castedObj = (Single)data;
                    break;

                case "uint":
                    castedObj = (uint)data;
                    break;

                case "uint16":
                    castedObj = (UInt16)data;
                    break;

                case "uint32":
                    castedObj = (UInt32)data;
                    break;

                case "uint64":
                    castedObj = (UInt64)data;
                    break;

                case "ulong":
                    castedObj = (ulong)data;
                    break;

                case "ushort":
                    castedObj = (ushort)data;
                    break;

                default:
                    castedObj = Enum.Parse(dataType, cseData.Value.ToString());                             // instance.Value;
                    break;
                }
            }
            else
            {
                switch (typeName.ToLower())
                {
                case "bool":
                    bool boolAttempt;
                    if (bool.TryParse(data.ToString(), out boolAttempt))
                    {
                        castedObj = boolAttempt;
                    }
                    break;

                case "byte":
                    byte byteAttempt;
                    if (byte.TryParse(data.ToString(), out byteAttempt))
                    {
                        castedObj = byteAttempt;
                    }
                    break;

                case "decimal":
                    decimal decimalAttempt;
                    if (decimal.TryParse(data.ToString(), out decimalAttempt))
                    {
                        castedObj = decimalAttempt;
                    }
                    break;

                case "double":
                    double doubleAttempt;
                    if (double.TryParse(data.ToString(), out doubleAttempt))
                    {
                        castedObj = doubleAttempt;
                    }
                    break;

                case "float":
                    float floatAttempt;
                    if (float.TryParse(data.ToString(), out floatAttempt))
                    {
                        castedObj = floatAttempt;
                    }
                    break;

                case "int":
                    int intAttempt;
                    if (int.TryParse(data.ToString(), out intAttempt))
                    {
                        castedObj = intAttempt;
                    }
                    break;

                case "int16":
                    Int16 int16Attempt;
                    if (Int16.TryParse(data.ToString(), out int16Attempt))
                    {
                        castedObj = int16Attempt;
                    }
                    break;

                case "int32":
                    Int32 int32Attempt;
                    if (Int32.TryParse(data.ToString(), out int32Attempt))
                    {
                        castedObj = int32Attempt;
                    }
                    break;

                case "int64":
                    Int64 int64Attempt;
                    if (Int64.TryParse(data.ToString(), out int64Attempt))
                    {
                        castedObj = int64Attempt;
                    }
                    break;

                case "long":
                    long longAttempt;
                    if (long.TryParse(data.ToString(), out longAttempt))
                    {
                        castedObj = longAttempt;
                    }
                    break;

                case "sbyte":
                    sbyte sbyteAttempt;
                    if (sbyte.TryParse(data.ToString(), out sbyteAttempt))
                    {
                        castedObj = sbyteAttempt;
                    }
                    break;

                case "short":
                    short shortAttempt;
                    if (short.TryParse(data.ToString(), out shortAttempt))
                    {
                        castedObj = shortAttempt;
                    }
                    break;

                case "single":
                    Single singleAttempt;
                    if (Single.TryParse(data.ToString(), out singleAttempt))
                    {
                        castedObj = singleAttempt;
                    }
                    break;

                case "uint":
                    uint uintAttempt;
                    if (uint.TryParse(data.ToString(), out uintAttempt))
                    {
                        castedObj = uintAttempt;
                    }
                    break;

                case "uint16":
                    UInt16 uint16Attempt;
                    if (UInt16.TryParse(data.ToString(), out uint16Attempt))
                    {
                        castedObj = uint16Attempt;
                    }
                    break;

                case "uint32":
                    UInt32 uint32Attempt;
                    if (UInt32.TryParse(data.ToString(), out uint32Attempt))
                    {
                        castedObj = uint32Attempt;
                    }
                    break;

                case "uint64":
                    UInt64 uint64Attempt;
                    if (UInt64.TryParse(data.ToString(), out uint64Attempt))
                    {
                        castedObj = uint64Attempt;
                    }
                    break;

                case "ulong":
                    ulong ulongAttempt;
                    if (ulong.TryParse(data.ToString(), out ulongAttempt))
                    {
                        castedObj = ulongAttempt;
                    }
                    break;

                case "ushort":
                    ushort ushortAttempt;
                    if (ushort.TryParse(data.ToString(), out ushortAttempt))
                    {
                        castedObj = ushortAttempt;
                    }
                    break;
                }

                if (castedObj == null)
                {
                    double dataAsDouble;
                    if (double.TryParse(data.ToString(), out dataAsDouble))
                    {
                        try {
                            switch (typeName.ToLower())
                            {
                            case "byte":
                                castedObj = checked ((byte)dataAsDouble);
                                break;

                            case "int":
                                castedObj = checked ((int)dataAsDouble);
                                break;

                            case "int16":
                                castedObj = checked ((Int16)dataAsDouble);
                                break;

                            case "int32":
                                castedObj = checked ((Int32)dataAsDouble);
                                break;

                            case "int64":
                                castedObj = checked ((Int64)dataAsDouble);
                                break;

                            case "long":
                                castedObj = checked ((long)dataAsDouble);
                                break;

                            case "sbyte":
                                castedObj = checked ((sbyte)dataAsDouble);
                                break;

                            case "short":
                                castedObj = checked ((short)dataAsDouble);
                                break;

                            case "single":
                                castedObj = checked ((Single)dataAsDouble);
                                break;

                            case "uint":
                                castedObj = checked ((uint)dataAsDouble);
                                break;

                            case "uint16":
                                castedObj = checked ((UInt16)dataAsDouble);
                                break;

                            case "uint32":
                                castedObj = checked ((UInt32)dataAsDouble);
                                break;

                            case "uint64":
                                castedObj = checked ((UInt64)dataAsDouble);
                                break;

                            case "ulong":
                                castedObj = checked ((ulong)dataAsDouble);
                                break;

                            case "ushort":
                                castedObj = checked ((ushort)dataAsDouble);
                                break;
                            }
                        }
                        catch (OverflowException) {
                            throw new CseLogicException(CseLogicExceptionType.OVERFLOW_TRYING_TO_CAST, data.ToString(), typeName);
                        }
                    }
                }

                if (castedObj == null)
                {
                    try {
                        /* If parsing is not possible, try a conversion */
                        Type typeToCastTo = TypeExp.GetType(typeName);
                        castedObj = Convert.ChangeType(data, typeToCastTo);
                    }
                    catch {
                        throw new CseLogicException(CseLogicExceptionType.CANT_CAST_VALUE_TO_TYPE, data.ToString(), typeName);
                    }
                }
            }

            return(new CseObject(castedObj)
            {
                IsLiteral = cseData.IsLiteral
            });
            //return cseData.Clone(castedObj);
        }
示例#33
0
        ///
        /// <summary>
        ///		Changes the given integral-type object to the smallest integral data type
        ///		that can contain its value. If xdata has a CompileTimeType that is
        ///		unsigned, then the smallest unsigned integral type is used. Otherwise
        ///		the smallest signed type is used. The only current exception to this is
        ///		byte vs. sbyte as they are considered special cases and therefore, regardless
        ///		if the original type is unsigned or not, byte is always attempted in place
        ///		of sbyte.
        /// </summary>
        ///
        /// <param name="xdata">Integral-type value to narrow</param>
        ///
        /// <returns>An integral-type object with same Value as the xdata param</returns>
        ///
        /// <exception cref="System.ArgumentException" />
        ///
        public static CseObject NarrowIntType(CseObject xdata)
        {
            dynamic data   = xdata.Value;
            dynamic result = null;

            if (IsUnsignedType(xdata))
            {
                byte   byteAttempt;
                ushort ushortAttempt;
                uint   uintAttempt;
                ulong  ulongAttempt;

                if (byte.TryParse(data.ToString(), out byteAttempt))
                {
                    result = byteAttempt;
                }
                else if (ushort.TryParse(data.ToString(), out ushortAttempt))
                {
                    result = ushortAttempt;
                }
                else if (uint.TryParse(data.ToString(), out uintAttempt))
                {
                    result = uintAttempt;
                }
                else if (ulong.TryParse(data.ToString(), out ulongAttempt))
                {
                    result = ulongAttempt;
                }
                else
                {
                    throw new ArgumentException(data.ToString() + " is not an integral type");
                }
            }
            else
            {
                byte  byteAttempt;
                short shortAttempt;
                int   intAttempt;
                long  longAttempt;

                if (byte.TryParse(data.ToString(), out byteAttempt))
                {
                    result = byteAttempt;
                }
                else if (short.TryParse(data.ToString(), out shortAttempt))
                {
                    result = shortAttempt;
                }
                else if (int.TryParse(data.ToString(), out intAttempt))
                {
                    result = intAttempt;
                }
                else if (long.TryParse(data.ToString(), out longAttempt))
                {
                    result = longAttempt;
                }
                else
                {
                    throw new ArgumentException(data.ToString() + " is not an integral type");
                }
            }

            return(new CseObject(result));
        }
示例#34
0
		///
		/// <summary>
		///		Parses literals that contain the exponential 'e' character
		/// </summary>
		/// 
		/// <param name="data">String containing the literal</param>
		/// 
		/// <returns>A double value</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_DBL" />
		///
		internal static CseObject ParseEType(string data) {
			double value;

			Regex r = new Regex(@"(f|m|d)$", RegexOptions.IgnoreCase);

			Match m = r.Match(data);
			string suffix = m.Groups[1].Value;
			string number = data.Substring(0, data.Length - suffix.Length);

			if (!double.TryParse(number, out value))
				throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_DBL, data);

			CseObject result = null;

			if (suffix != "") {
				result = ParseFloatType(value.ToString(), suffix);
			}
			else {
				result = new CseObject(value);
			}

			result.IsLiteral = true;
			return result;
		}
示例#35
0
        ///
        /// <summary>
        ///		Assigns a value to the specified identifier (field or property).
        ///		Since any field or property that is a ValueType will not have its
        ///		value changed without explicitly being set, this method is given the
        ///		entire list of objects of the lhs chain expression and uses recursion to
        ///		set them right to left.
        /// </summary>
        ///
        /// <example>
        ///		<c language="C#">x.y.z = 3</c>
        ///		This will set z = 3, then y = z (the newly changed z), then x = y.
        ///		If the expression is simply <c language="C#">x = 3</c>, then that is the only assignment
        ///		performed and all List arguments contain only a single value.
        /// </example>
        ///
        /// <param name="envChain">
        ///		List of CseObjects from the chain expression of the lhs. This makes up the
        ///		list of environment objects. In the case of x = 3, envChain would contain
        ///		x's value.
        ///	</param>
        /// <param name="envNames">List of field/property names in the lhs chain expression. In the case of x = 3, envNames would contain "x".</param>
        /// <param name="envIndices">
        ///		List of array indices for each array in the lhs chain expression. For each non-array, the
        ///		envIndices at that index is null. In the case of x = 3, envIndices would contain null.
        ///		In the case of x[2] = 3, envIndices would contain 2.
        ///	</param>
        /// <param name="xrhs">Rhs expression</param>
        ///
        /// <returns>xrhs's Value property</returns>
        ///
        /// <exception cref="CseLogicExceptionType.ARRAY_INDEX_NOT_INT" />
        /// <exception cref="CseLogicExceptionType.CANT_FIND_IDENT_IN_ENV" />
        ///
        internal static object Assign(List <CseObject> envChain, List <string> envNames, List <CseObject> envIndices, CseObject xrhs)
        {
            object rhs = (xrhs == null ? null : xrhs.Value);

            if (envChain.Count == 0)
            {
                return(rhs);
            }

            CseObject env      = envChain[envChain.Count - 1];
            string    envName  = envNames[envNames.Count - 1];
            CseObject envIndex = envIndices[envIndices.Count - 1];

            //Type instanceType = TypeExp.GetTypeObj(env.Value);
            Type instanceType = env.ValueType;

            // Arrays
            if (envIndex != null)
            {
                MemberInfo  member;
                ICollection arrMember;

                member = instanceType.GetField(envName, defaultFlags | BindingFlags.GetField);
                if (member != null)
                {
                    arrMember = (ICollection)((FieldInfo)member).GetValue(env.Value);
                }
                else
                {
                    member = instanceType.GetProperty(envName, defaultFlags | BindingFlags.GetProperty);
                    if (member != null)
                    {
                        arrMember = (ICollection)((PropertyInfo)member).GetValue(env.Value, null);
                    }
                    else
                    {
                        throw new CseLogicException(CseLogicExceptionType.CANT_FIND_IDENT_IN_ENV, envName, env.Value.ToString());
                    }
                }

                Array       arrMemberAsArray = arrMember as Array;
                IDictionary arrMemberAsIDict = arrMember as IDictionary;

                if (arrMemberAsArray != null)
                {
                    int index;
                    if (int.TryParse(envIndex.Value.ToString(), out index))
                    {
                        arrMemberAsArray.SetValue(rhs, index);
                    }
                    else
                    {
                        throw new CseLogicException(CseLogicExceptionType.ARRAY_INDEX_NOT_INT);
                    }
                }
                else if (arrMemberAsIDict != null)
                {
                    arrMemberAsIDict[envIndex.Value] = rhs;
                }
            }
            // Nonarrays
            else
            {
                if (env == CsEval.EvalEnvironment)
                {
                    CseObject tempLookup = TempIdentifierExp.Lookup(envName);
                    if (tempLookup != null)
                    {
                        TempIdentifierExp.Assign(envName, rhs);
                        return(tempLookup);
                    }
                }

                FieldInfo fieldInfo = instanceType.GetField(envName, defaultFlags | BindingFlags.GetField);
                if (fieldInfo != null)
                {
                    fieldInfo.SetValue(env.Value, rhs);
                }
                else
                {
                    PropertyInfo propertyInfo = instanceType.GetProperty(envName, defaultFlags | BindingFlags.GetProperty);
                    if (propertyInfo != null)
                    {
                        propertyInfo.SetValue(env.Value, rhs, null);
                    }
                    else
                    {
                        throw new CseLogicException(CseLogicExceptionType.CANT_FIND_IDENT_IN_ENV, envName, env.Value.ToString());
                    }
                }
            }

            envChain.RemoveAt(envChain.Count - 1);
            envNames.RemoveAt(envNames.Count - 1);
            envIndices.RemoveAt(envIndices.Count - 1);

            return(IdentifierExp.Assign(envChain, envNames, envIndices, env));
        }
示例#36
0
		///
		/// <summary>
		///		Parses string literals
		/// </summary>
		/// 
		/// <param name="data">String containing the literal</param>
		/// 
		/// <returns>A string value</returns>
		///
		internal static CseObject ParseStr(string data) {
			if (data.StartsWith("@")) {
				data = data.Remove(0, 1);
				ParseEscSeqs(ref data, true);
			}
			else {
				ParseEscSeqs(ref data, false);
			}

			CseObject result = new CseObject(data.Remove(data.Length - 1, 1).Remove(0, 1));
			result.IsLiteral = true;
			return result;
		}
示例#37
0
		///
		/// <summary>
		///		Parses casts
		/// </summary>
		/// 
		/// <remarks>
		///		Can only perform a real cast in certain situations. When it can't it
		///		tries to mimic a cast using parsing or conversion.
		///	</remarks>
		///	
		/// <param name="instance">The root object</param>
		/// <param name="typeName">Type to cast to</param>
		/// <param name="cseData">Expression to cast</param>
		/// 
		/// <returns>The converted object</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.CANT_CAST_VALUE_TO_TYPE" />
		/// <exception cref="CseLogicExceptionType.OVERFLOW_TRYING_TO_CAST" />
		///
		// TODO: Check if the generic Cast<T> method would work
		internal static CseObject Parse(CseObject instance, string typeName, CseObject cseData) {
			dynamic data = cseData.Value;
			dynamic castedObj = null;
			Type dataType = TypeExp.GetTypeObj(data);

			if (dataType.IsEnum) {
				switch (typeName.ToLower()) {
					case "bool":
						castedObj = (bool)data;
						break;
					case "byte":
						castedObj = (byte)data;
						break;
					case "decimal":
						castedObj = (decimal)data;
						break;
					case "double":
						castedObj = (double)data;
						break;
					case "float":
						castedObj = (float)data;
						break;
					case "int":
						castedObj = (int)data;
						break;
					case "int16":
						castedObj = (Int16)data;
						break;
					case "int32":
						castedObj = (Int32)data;
						break;
					case "int64":
						castedObj = (Int64)data;
						break;
					case "long":
						castedObj = (long)data;
						break;
					case "sbyte":
						castedObj = (sbyte)data;
						break;
					case "short":
						castedObj = (short)data;
						break;
					case "single":
						castedObj = (Single)data;
						break;
					case "uint":
						castedObj = (uint)data;
						break;
					case "uint16":
						castedObj = (UInt16)data;
						break;
					case "uint32":
						castedObj = (UInt32)data;
						break;
					case "uint64":
						castedObj = (UInt64)data;
						break;
					case "ulong":
						castedObj = (ulong)data;
						break;
					case "ushort":
						castedObj = (ushort)data;
						break;
					default:
						castedObj = Enum.Parse(dataType, cseData.Value.ToString()); // instance.Value;
						break;
				}
			}
			else {
				switch (typeName.ToLower()) {
					case "bool":
						bool boolAttempt;
						if (bool.TryParse(data.ToString(), out boolAttempt))
							castedObj = boolAttempt;
						break;
					case "byte":
						byte byteAttempt;
						if (byte.TryParse(data.ToString(), out byteAttempt))
							castedObj = byteAttempt;
						break;
					case "decimal":
						decimal decimalAttempt;
						if (decimal.TryParse(data.ToString(), out decimalAttempt))
							castedObj = decimalAttempt;
						break;
					case "double":
						double doubleAttempt;
						if (double.TryParse(data.ToString(), out doubleAttempt))
							castedObj = doubleAttempt;
						break;
					case "float":
						float floatAttempt;
						if (float.TryParse(data.ToString(), out floatAttempt))
							castedObj = floatAttempt;
						break;
					case "int":
						int intAttempt;
						if (int.TryParse(data.ToString(), out intAttempt))
							castedObj = intAttempt;
						break;
					case "int16":
						Int16 int16Attempt;
						if (Int16.TryParse(data.ToString(), out int16Attempt))
							castedObj = int16Attempt;
						break;
					case "int32":
						Int32 int32Attempt;
						if (Int32.TryParse(data.ToString(), out int32Attempt))
							castedObj = int32Attempt;
						break;
					case "int64":
						Int64 int64Attempt;
						if (Int64.TryParse(data.ToString(), out int64Attempt))
							castedObj = int64Attempt;
						break;
					case "long":
						long longAttempt;
						if (long.TryParse(data.ToString(), out longAttempt))
							castedObj = longAttempt;
						break;
					case "sbyte":
						sbyte sbyteAttempt;
						if (sbyte.TryParse(data.ToString(), out sbyteAttempt))
							castedObj = sbyteAttempt;
						break;
					case "short":
						short shortAttempt;
						if (short.TryParse(data.ToString(), out shortAttempt))
							castedObj = shortAttempt;
						break;
					case "single":
						Single singleAttempt;
						if (Single.TryParse(data.ToString(), out singleAttempt))
							castedObj = singleAttempt;
						break;
					case "uint":
						uint uintAttempt;
						if (uint.TryParse(data.ToString(), out uintAttempt))
							castedObj = uintAttempt;
						break;
					case "uint16":
						UInt16 uint16Attempt;
						if (UInt16.TryParse(data.ToString(), out uint16Attempt))
							castedObj = uint16Attempt;
						break;
					case "uint32":
						UInt32 uint32Attempt;
						if (UInt32.TryParse(data.ToString(), out uint32Attempt))
							castedObj = uint32Attempt;
						break;
					case "uint64":
						UInt64 uint64Attempt;
						if (UInt64.TryParse(data.ToString(), out uint64Attempt))
							castedObj = uint64Attempt;
						break;
					case "ulong":
						ulong ulongAttempt;
						if (ulong.TryParse(data.ToString(), out ulongAttempt))
							castedObj = ulongAttempt;
						break;
					case "ushort":
						ushort ushortAttempt;
						if (ushort.TryParse(data.ToString(), out ushortAttempt))
							castedObj = ushortAttempt;
						break;
				}

				if (castedObj == null) {
					double dataAsDouble;
					if (double.TryParse(data.ToString(), out dataAsDouble)) {
						try {
							switch (typeName.ToLower()) {
								case "byte":
									castedObj = checked((byte)dataAsDouble);
									break;
								case "int":
									castedObj = checked((int)dataAsDouble);
									break;
								case "int16":
									castedObj = checked((Int16)dataAsDouble);
									break;
								case "int32":
									castedObj = checked((Int32)dataAsDouble);
									break;
								case "int64":
									castedObj = checked((Int64)dataAsDouble);
									break;
								case "long":
									castedObj = checked((long)dataAsDouble);
									break;
								case "sbyte":
									castedObj = checked((sbyte)dataAsDouble);
									break;
								case "short":
									castedObj = checked((short)dataAsDouble);
									break;
								case "single":
									castedObj = checked((Single)dataAsDouble);
									break;
								case "uint":
									castedObj = checked((uint)dataAsDouble);
									break;
								case "uint16":
									castedObj = checked((UInt16)dataAsDouble);
									break;
								case "uint32":
									castedObj = checked((UInt32)dataAsDouble);
									break;
								case "uint64":
									castedObj = checked((UInt64)dataAsDouble);
									break;
								case "ulong":
									castedObj = checked((ulong)dataAsDouble);
									break;
								case "ushort":
									castedObj = checked((ushort)dataAsDouble);
									break;
							}
						}
						catch (OverflowException) {
							throw new CseLogicException(CseLogicExceptionType.OVERFLOW_TRYING_TO_CAST, data.ToString(), typeName);
						}
					}
				}

				if (castedObj == null) {
					try {
						/* If parsing is not possible, try a conversion */
						Type typeToCastTo = TypeExp.GetType(typeName);
						castedObj = Convert.ChangeType(data, typeToCastTo);
					}
					catch {
						throw new CseLogicException(CseLogicExceptionType.CANT_CAST_VALUE_TO_TYPE, data.ToString(), typeName);
					}
				}
			}

			return new CseObject(castedObj) { IsLiteral = cseData.IsLiteral };
			//return cseData.Clone(castedObj);
		}
示例#38
0
		// Implicit reference conversions 6.1.6 
		// TODO: check if both ref, throw exc if not
		///
		/// <summary>
		///		Tests for an implicit reference conversion, given a CseObject and a type.
		/// </summary>
		/// 
		/// <param name="data">The object to test converting</param>
		/// <param name="t">The type to attempt to convert the object to</param>
		/// 
		/// <returns>True if an implicit reference conversion is valid, false otherwise</returns>
		/// 
		public static bool? ImpRefConv(CseObject fromArg, Type to) {
			bool? success = null;

			Type from = fromArg.ValueType;

			if (from == to)
				// identity
				success = true;

			else if (to == typeof(object))
				// ref -> object
				success = true;

			else if (fromArg.Value == null)
				// null literal -> Ref-type
				success = !to.IsValueType;

			else if (false)
				// ref -> dynamic (6.1.8)
				// figure out how to do this
				;

			else if (from.IsArray && to.IsArray) {
				// Array-type -> Array-type
				bool sameRank = (from.GetArrayRank() == to.GetArrayRank());
				bool bothRef = (!from.GetElementType().IsValueType && !to.GetElementType().IsValueType);
				bool? impConv = ImpRefConv(new CseObject(-1) { CompileTimeType = from.GetElementType() }, to.GetElementType());

				success = (sameRank && bothRef && impConv.GetValueOrDefault(false));
			}

			// Conversion involving type parameters (6.1.10)
			else if (to.IsGenericParameter) {

				//if ( fromArg.GetType().Name.Equals(to.Name)) {
				if (to.GenericParameterAttributes != GenericParameterAttributes.None) {

					if ((int)(to.GenericParameterAttributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0) {
						;
					}
				}
				else {
				}


				/*genArg.GetGenericParameterConstraints();
				genArg.GenericParameterAttributes;*/
				//if( mi.GetGenericArguments()[?]
				//var t = a.GetType().GetMethod("Foo", BindingFlags.Public | BindingFlags.Instance).GetGenericArguments()[0].GetGenericParameterConstraints();//.GenericParameterAttributes;
			}

			// Boxing Conversions (6.1.7)
			else if (from.IsValueType && !to.IsValueType) {
				return IsBoxingConversion(fromArg, to);
			}

			else if ((from.IsClass && to.IsClass) || (from.IsClass && to.IsInterface) || (from.IsInterface && to.IsInterface))
				// class -> class  OR  class -> interface  OR  interface -> interface
				success = CrawlThatShit(to.GetHashCode(), from, new List<int>());

			else if (from.IsArray && CrawlThatShit(to.GetHashCode(), typeof(Array), new List<int>())) {
				// Array-type -> System.array
				return true;
			}

			else if (from.IsArray && from.GetArrayRank() == 1 && to.IsGenericType && CrawlThatShit(to.GetHashCode(), typeof(IList<>), new List<int>()))
				// Single dim array -> IList<>
				success = ImpRefConv(new CseObject(-1) { CompileTimeType = from.GetElementType() }, to.GetGenericTypeDefinition());



			return success;
		}
示例#39
0
		///
		/// <summary>
		///		Parses method calls
		/// </summary>
		/// 
		/// <param name="environment">The environment containing the method</param>
		/// <param name="methName">Name of the method</param>
		/// <param name="args">CseObject array containing arguments to be sent to the method. Each CseObject is one argument</param>
		/// 
		/// <returns>CseObject containing the return result of the method call or CseObject containing null if method is void</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.METHOD_CALL_AMBIGUOUS" />
		/// <exception cref="CseLogicExceptionType.METHOD_CANT_IMPLICITLY_COERCE_ARGS" />
		/// <exception cref="CseLogicExceptionType.METHOD_DOESNT_EXIST" />
		/// <exception cref="CseLogicExceptionType.METHOD_EXISTS_BUT_CANT_BE_INVOKED" />
		///
		public static CseObject Parse(CseObject environment, string methName, List<CseObject> args) {
			MethResSettings mrSettings = new MethResSettings() {
				Args = (args == null ? new CseObject[] { } : args.ToArray()),
				Env = environment.Value,
				Name = methName
			};
			List<MethResObject> appMeths = MethRes.GetApplicableMembers(mrSettings);

			if (appMeths.Count == 0) {
				mrSettings.IsExtInvocation = true;
				appMeths = MethRes.GetApplicableMembers(mrSettings);
			}

			MethodInfo mi = null;
			Type envType = TypeExp.GetTypeObj(environment.Value);

			try {
				switch (appMeths.Count) {
					// No methods exist with that name
					case 0:
						// TODO: doesn't exist OR no applicable methods can be called
						throw new CseLogicException(CseLogicExceptionType.METHOD_DOESNT_EXIST, methName);

					// Only 1 method exists with that name, so try to do what's necessary to coerce args (if they exist)
					// to match its signature.
					case 1:
						MethResObject mrObj = appMeths[0];

						if (args != null) {
							for (int i = 0; i < args.Count; i++) {
								try {
									args[i] = CastExp.Parse(environment, mrObj.MethInfo.GetParameters()[i].ParameterType.Name, args[i]);
								}
								catch (CseLogicException) {
									// f**k it, continue
								}
							}
						}
						//NarrowAllIntTypes(ref args);

						mi = mrObj.MethInfo;
						break;

					// Method is overloaded.
					// Idea is to simulate C#'s best match algorithm for finding the most appropriate method to call
					// and if still unsure, throw exception so user can use casting for further clarification.
					default:
						Type[] types = GetTypeArray(args);

						mi = envType.GetMethod(methName, findFlags | BindingFlags.ExactBinding, null, types, null);

						if (mi != null)
							break;

						if (CanCoerce(args)) {
							NarrowAllIntTypes(ref args);
							types = GetTypeArray(args);
						}

						MethodInfo tryMeth = envType.GetMethod(methName, findFlags, null, types, null);
						foreach (MethResObject m in appMeths) {
							if (m.MethInfo == tryMeth) {
								mi = tryMeth;
								break;
							}
						}

						if (mi != null)
							break;

						// TODO: Attempt to coerce args to formal param types of overloaded methods



						if (mi == null)
							throw new CseLogicException(CseLogicExceptionType.METHOD_CALL_AMBIGUOUS, methName);

						break;
				}
			}
			catch (AmbiguousMatchException) {
				throw new CseLogicException(CseLogicExceptionType.METHOD_CALL_AMBIGUOUS, methName);
			}
			catch (CseLogicException) {
				throw;
			}
			catch {
				throw new CseLogicException(CseLogicExceptionType.METHOD_EXISTS_BUT_CANT_BE_INVOKED, methName);
			}

			if (mi == null) {
				throw new CseLogicException(CseLogicExceptionType.METHOD_EXISTS_BUT_CANT_BE_INVOKED, methName);
			}
			else {
				dynamic result = mi.Invoke(environment.Value, GetObjArgs(args));

				CseObject xo = new CseObject(result);
				xo.CompileTimeType = mi.ReturnType;

				if (args != null) {
					foreach (CseObject arg in args) {
						if (arg.CallMod != CallArgMod.VAL) {
							AssignExp.Parse(arg.EnvChain, arg.EnvNames, arg.EnvIndices, arg.Value);
						}
					}
				}

				return xo;
			}
		}
示例#40
0
		///
		/// <summary>
		///		Parses char literals
		/// </summary>
		/// 
		/// <param name="data">String containing the literal</param>
		/// 
		/// <returns>A char value</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_CHAR" />
		///
		internal static CseObject ParseChar(string data) {
			data = data.Remove(data.Length - 1, 1).Remove(0, 1);
			if (data.Length > 1 && !data.StartsWith("\\"))
				throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_CHAR, data);
			else {
				ParseEscSeqs(ref data, false);

				CseObject result = new CseObject(data[0]);
				result.IsLiteral = true;
				return result;
			}
		}
示例#41
0
		///
		/// <summary>
		///		Changes the given integral-type object to the smallest integral data type
		///		that can contain its value. If xdata has a CompileTimeType that is
		///		unsigned, then the smallest unsigned integral type is used. Otherwise
		///		the smallest signed type is used. The only current exception to this is
		///		byte vs. sbyte as they are considered special cases and therefore, regardless
		///		if the original type is unsigned or not, byte is always attempted in place
		///		of sbyte.
		/// </summary>
		/// 
		/// <param name="xdata">Integral-type value to narrow</param>
		/// 
		/// <returns>An integral-type object with same Value as the xdata param</returns>
		/// 
		/// <exception cref="System.ArgumentException" />
		///
		public static CseObject NarrowIntType(CseObject xdata) {
			dynamic data = xdata.Value;
			dynamic result = null;

			if (IsUnsignedType(xdata)) {
				byte byteAttempt;
				ushort ushortAttempt;
				uint uintAttempt;
				ulong ulongAttempt;

				if (byte.TryParse(data.ToString(), out byteAttempt))
					result = byteAttempt;
				else if (ushort.TryParse(data.ToString(), out ushortAttempt))
					result = ushortAttempt;
				else if (uint.TryParse(data.ToString(), out uintAttempt))
					result = uintAttempt;
				else if (ulong.TryParse(data.ToString(), out ulongAttempt))
					result = ulongAttempt;
				else
					throw new ArgumentException(data.ToString() + " is not an integral type");
			}
			else {
				byte byteAttempt;
				short shortAttempt;
				int intAttempt;
				long longAttempt;

				if (byte.TryParse(data.ToString(), out byteAttempt))
					result = byteAttempt;
				else if (short.TryParse(data.ToString(), out shortAttempt))
					result = shortAttempt;
				else if (int.TryParse(data.ToString(), out intAttempt))
					result = intAttempt;
				else if (long.TryParse(data.ToString(), out longAttempt))
					result = longAttempt;
				else
					throw new ArgumentException(data.ToString() + " is not an integral type");
			}

			return new CseObject(result);
		}
示例#42
0
		///
		/// <summary>
		///		Applies numeric negation (i.e. unary minus) to numeric values
		/// </summary>
		/// 
		/// <param name="obj">The CseObject with the value to negate</param>
		/// 
		/// <returns>The CseObject after negation</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.CANT_NEGATE_NON_NUM" />
		/// <exception cref="CseLogicExceptionType.ERROR_NEGATING_VALUE_OF_TYPE" />
		/// 
		internal static CseObject Negate(CseObject obj) {
			CseObject result = (CseObject)obj.Clone();

			dynamic value = obj.Value;
			double numValue;

			if (value is string)
				throw new CseLogicException(CseLogicExceptionType.CANT_NEGATE_NON_NUM, value.ToString());
			else if (!double.TryParse(value.ToString(), out numValue)) {
				MethodInfo mi = value.GetType().GetMethod(OpOverloadNames.UMINUS);
				if (null != mi) {
					result.Value = value.GetType().InvokeMember(OpOverloadNames.UMINUS, OpOverloadNames.Flags, null, CsEval.evalEnvironment, new object[] { value });
					return result;
				}
				else
					throw new CseLogicException(CseLogicExceptionType.CANT_NEGATE_NON_NUM, value.ToString());
			}

			numValue *= -1;
			result.Value = numValue;

			try {
				result = CastExp.Parse(CsEval.evalEnvironment, value.GetType().Name, result);
			}
			catch {
				if (value.ToString().ToLower().Contains("e"))
					result = LiteralExp.ParseEType(numValue.ToString());
				else if (value.ToString().Contains("."))
					result = LiteralExp.ParseFloatType(numValue.ToString(), null);
				else
					throw new CseLogicException(CseLogicExceptionType.ERROR_NEGATING_VALUE_OF_TYPE, value.ToString(), value.GetType().Name);
			}

			return result;
		}
示例#43
0
		///
		/// <summary>
		///		Determines whether the xdata's CompileTimeType is an unsigned integral type or not
		/// </summary>
		/// 
		/// <param name="xdata">CseObject to examine the CompileTimeType of</param>
		/// 
		/// <returns>True if xdata's CompileTimeType is an unsigned integral type, false otherwise</returns>
		///
		private static bool IsUnsignedType(CseObject xdata) {
			List<Type> unsignedTypes = new List<Type> { typeof(byte), typeof(UInt16), typeof(UInt32), typeof(UInt64) };

			if (unsignedTypes.Contains(xdata.CompileTimeType))
				return true;
			else
				return false;
		}
示例#44
0
		///
		/// <summary>
		///		Applies numeric affirmation (i.e. unary plus) to numeric values
		/// </summary>
		/// 
		/// <param name="obj">The CseObject with the value to affirm</param>
		/// 
		/// <returns>The CseObject after affirmation</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.CANT_AFFIRM_NON_NUM" />
		/// 
		internal static CseObject Affirm(CseObject obj) {
			CseObject result = (CseObject)obj.Clone();

			dynamic value = obj.Value;
			double numValue;

			if (value is string)
				throw new CseLogicException(CseLogicExceptionType.CANT_AFFIRM_NON_NUM, value.ToString());
			else if (!double.TryParse(value.ToString(), out numValue)) {
				MethodInfo mi = value.GetType().GetMethod(OpOverloadNames.UPLUS);
				if (null != mi) {
					result.Value = value.GetType().InvokeMember(OpOverloadNames.UPLUS, OpOverloadNames.Flags, null, CsEval.evalEnvironment, new object[] { value });
					return result;
				}
				else
					throw new CseLogicException(CseLogicExceptionType.CANT_AFFIRM_NON_NUM, value.ToString());
			}

			return result;
		}
示例#45
0
		///
		/// <summary>
		///		A holistic method to use for testing coercion of objects
		/// </summary>
		/// 
		/// <param name="fromArg">The object to be coerced</param>
		/// 
		/// <param name="to">The type to convert the object to.</param>
		/// 
		/// <returns>True if the coercion is valid, false otherwise</returns>
		///
		public static bool CanConvertType(CseObject fromArg, Type to) {

			CseObject fromData = (CseObject)fromArg.Clone();


			if (fromData == null || to == null) {
				throw new ArgumentException("Param '" + (fromData == null ? "fromData" : "to") + "' must not be null");
			}

			Type from = fromData.ValueType;

			// null literal conversion 6.1.5
			if (fromArg.Value == null) {
				return IsNullableType(to);
			}

			// identity conversion 6.1.1
			if (from.GetHashCode().Equals(to.GetHashCode()))
				return true;

			// implicit constant expressions 6.1.9
			if (fromData.IsLiteral) {
				bool canConv = false;

				dynamic num = fromData.Value;
				if (from == typeof(int)) {
					switch (Type.GetTypeCode(to)) {
						case TypeCode.SByte:
							if (num >= sbyte.MinValue && num <= sbyte.MaxValue)
								canConv = true;
							break;
						case TypeCode.Byte:
							if (num >= byte.MinValue && num <= byte.MaxValue)
								canConv = true;
							break;
						case TypeCode.Int16:
							if (num >= short.MinValue && num <= short.MaxValue)
								canConv = true;
							break;
						case TypeCode.UInt16:
							if (num >= ushort.MinValue && num <= ushort.MaxValue)
								canConv = true;
							break;
						case TypeCode.UInt32:
							if (num >= uint.MinValue && num <= uint.MaxValue)
								canConv = true;
							break;
						case TypeCode.UInt64:
							if (num >= 0)
								canConv = true;
							break;
					}
				}
				else if (from == typeof(long)) {
					if (to == typeof(ulong)) {
						if (num >= 0)
							canConv = true;
					}
				}

				if (canConv)
					return true;
			}

			// string conversion
			// TODO: check if this is necessary
			if (from == typeof(string)) {
				if (to == typeof(object))
					return true;
				else
					return false;
			}


			// implicit nullable conversion 6.1.4
			if (IsNullableType(to)) {

				if (IsNullableType(fromData.ValueType)) {

					// If the source value is null, then just return successfully (because the target value is a nullable type)
					if (fromData.Value == null) {
						return true;
					}

					fromData.CompileTimeType = Nullable.GetUnderlyingType(fromData.ValueType);
				}

				return CanConvertType(fromData, Nullable.GetUnderlyingType(to));

			}

			// implicit enumeration conversion 6.1.3
			long longTest = -1;

			if (fromData.IsLiteral && to.IsEnum && long.TryParse(fromData.Value.ToString(), out longTest)) {
				if (longTest == 0)
					return true;
			}

			// implicit reference conversion 6.1.5
			if (!from.IsValueType && !to.IsValueType) {
				bool? irc = ImpRefConv(fromData, to);
				if (irc.HasValue)
					return irc.Value;
			}

			// implicit numeric conversion 6.1.2
			try {
				object fromObj = null;
				double dblTemp;
				decimal decTemp;
				char chrTemp;
				fromObj = Activator.CreateInstance(from);

				if (char.TryParse(fromObj.ToString(), out chrTemp) || double.TryParse(fromObj.ToString(), out dblTemp) || decimal.TryParse(fromObj.ToString(), out decTemp)) {
					if (NumConv.ContainsKey(from) && NumConv[from].Contains(to))
						return true;
					else
						return CrawlThatShit(to.GetHashCode(), from, new List<int>());
				}
				//else {
				//   return CrawlThatShit(to.GetHashCode(), from, new List<int>());
				//}
			}
			catch {
				//return CrawlThatShit(to.GetHashCode(), from, new List<int>());
			}

			return false;
		}
示例#46
0
        ///
        /// <summary>
        ///		Determines if value passed in is an integral-type
        /// </summary>
        ///
        /// <param name="data">Value to examine</param>
        ///
        /// <returns>True if value is an integral-type, false otherwise</returns>
        ///
        public static bool IsIntType(CseObject data)
        {
            long longAttempt;

            return(long.TryParse(data.Value.ToString(), out longAttempt));
        }
示例#47
0
        ///
        /// <summary>
        ///		Parses method calls
        /// </summary>
        ///
        /// <param name="environment">The environment containing the method</param>
        /// <param name="methName">Name of the method</param>
        /// <param name="args">CseObject array containing arguments to be sent to the method. Each CseObject is one argument</param>
        ///
        /// <returns>CseObject containing the return result of the method call or CseObject containing null if method is void</returns>
        ///
        /// <exception cref="CseLogicExceptionType.METHOD_CALL_AMBIGUOUS" />
        /// <exception cref="CseLogicExceptionType.METHOD_CANT_IMPLICITLY_COERCE_ARGS" />
        /// <exception cref="CseLogicExceptionType.METHOD_DOESNT_EXIST" />
        /// <exception cref="CseLogicExceptionType.METHOD_EXISTS_BUT_CANT_BE_INVOKED" />
        ///
        public static CseObject Parse(CseObject environment, string methName, List <CseObject> args)
        {
            MethResSettings mrSettings = new MethResSettings()
            {
                Args = (args == null ? new CseObject[] { } : args.ToArray()),
                Env  = environment.Value,
                Name = methName
            };
            List <MethResObject> appMeths = MethRes.GetApplicableMembers(mrSettings);

            if (appMeths.Count == 0)
            {
                mrSettings.IsExtInvocation = true;
                appMeths = MethRes.GetApplicableMembers(mrSettings);
            }

            MethodInfo mi      = null;
            Type       envType = TypeExp.GetTypeObj(environment.Value);

            try {
                switch (appMeths.Count)
                {
                // No methods exist with that name
                case 0:
                    // TODO: doesn't exist OR no applicable methods can be called
                    throw new CseLogicException(CseLogicExceptionType.METHOD_DOESNT_EXIST, methName);

                // Only 1 method exists with that name, so try to do what's necessary to coerce args (if they exist)
                // to match its signature.
                case 1:
                    MethResObject mrObj = appMeths[0];

                    if (args != null)
                    {
                        for (int i = 0; i < args.Count; i++)
                        {
                            try {
                                args[i] = CastExp.Parse(environment, mrObj.MethInfo.GetParameters()[i].ParameterType.Name, args[i]);
                            }
                            catch (CseLogicException) {
                                // f**k it, continue
                            }
                        }
                    }
                    //NarrowAllIntTypes(ref args);

                    mi = mrObj.MethInfo;
                    break;

                // Method is overloaded.
                // Idea is to simulate C#'s best match algorithm for finding the most appropriate method to call
                // and if still unsure, throw exception so user can use casting for further clarification.
                default:
                    Type[] types = GetTypeArray(args);

                    mi = envType.GetMethod(methName, findFlags | BindingFlags.ExactBinding, null, types, null);

                    if (mi != null)
                    {
                        break;
                    }

                    if (CanCoerce(args))
                    {
                        NarrowAllIntTypes(ref args);
                        types = GetTypeArray(args);
                    }

                    MethodInfo tryMeth = envType.GetMethod(methName, findFlags, null, types, null);
                    foreach (MethResObject m in appMeths)
                    {
                        if (m.MethInfo == tryMeth)
                        {
                            mi = tryMeth;
                            break;
                        }
                    }

                    if (mi != null)
                    {
                        break;
                    }

                    // TODO: Attempt to coerce args to formal param types of overloaded methods



                    if (mi == null)
                    {
                        throw new CseLogicException(CseLogicExceptionType.METHOD_CALL_AMBIGUOUS, methName);
                    }

                    break;
                }
            }
            catch (AmbiguousMatchException) {
                throw new CseLogicException(CseLogicExceptionType.METHOD_CALL_AMBIGUOUS, methName);
            }
            catch (CseLogicException) {
                throw;
            }
            catch {
                throw new CseLogicException(CseLogicExceptionType.METHOD_EXISTS_BUT_CANT_BE_INVOKED, methName);
            }

            if (mi == null)
            {
                throw new CseLogicException(CseLogicExceptionType.METHOD_EXISTS_BUT_CANT_BE_INVOKED, methName);
            }
            else
            {
                dynamic result = mi.Invoke(environment.Value, GetObjArgs(args));

                CseObject xo = new CseObject(result);
                xo.CompileTimeType = mi.ReturnType;

                if (args != null)
                {
                    foreach (CseObject arg in args)
                    {
                        if (arg.CallMod != CallArgMod.VAL)
                        {
                            AssignExp.Parse(arg.EnvChain, arg.EnvNames, arg.EnvIndices, arg.Value);
                        }
                    }
                }

                return(xo);
            }
        }
示例#48
0
		///
		/// <summary>
		///		Determines if value passed in is an integral-type
		/// </summary>
		/// 
		/// <param name="data">Value to examine</param>
		/// 
		/// <returns>True if value is an integral-type, false otherwise</returns>
		///
		public static bool IsIntType(CseObject data) {
			long longAttempt;
			return long.TryParse(data.Value.ToString(), out longAttempt);
		}
示例#49
0
        ///
        /// <summary>
        ///		A holistic method to use for testing coercion of objects
        /// </summary>
        ///
        /// <param name="fromArg">The object to be coerced</param>
        ///
        /// <param name="to">The type to convert the object to.</param>
        ///
        /// <returns>True if the coercion is valid, false otherwise</returns>
        ///
        public static bool CanConvertType(CseObject fromArg, Type to)
        {
            CseObject fromData = (CseObject)fromArg.Clone();


            if (fromData == null || to == null)
            {
                throw new ArgumentException("Param '" + (fromData == null ? "fromData" : "to") + "' must not be null");
            }

            Type from = fromData.ValueType;

            // null literal conversion 6.1.5
            if (fromArg.Value == null)
            {
                return(IsNullableType(to));
            }

            // identity conversion 6.1.1
            if (from.GetHashCode().Equals(to.GetHashCode()))
            {
                return(true);
            }

            // implicit constant expressions 6.1.9
            if (fromData.IsLiteral)
            {
                bool canConv = false;

                dynamic num = fromData.Value;
                if (from == typeof(int))
                {
                    switch (Type.GetTypeCode(to))
                    {
                    case TypeCode.SByte:
                        if (num >= sbyte.MinValue && num <= sbyte.MaxValue)
                        {
                            canConv = true;
                        }
                        break;

                    case TypeCode.Byte:
                        if (num >= byte.MinValue && num <= byte.MaxValue)
                        {
                            canConv = true;
                        }
                        break;

                    case TypeCode.Int16:
                        if (num >= short.MinValue && num <= short.MaxValue)
                        {
                            canConv = true;
                        }
                        break;

                    case TypeCode.UInt16:
                        if (num >= ushort.MinValue && num <= ushort.MaxValue)
                        {
                            canConv = true;
                        }
                        break;

                    case TypeCode.UInt32:
                        if (num >= uint.MinValue && num <= uint.MaxValue)
                        {
                            canConv = true;
                        }
                        break;

                    case TypeCode.UInt64:
                        if (num >= 0)
                        {
                            canConv = true;
                        }
                        break;
                    }
                }
                else if (from == typeof(long))
                {
                    if (to == typeof(ulong))
                    {
                        if (num >= 0)
                        {
                            canConv = true;
                        }
                    }
                }

                if (canConv)
                {
                    return(true);
                }
            }

            // string conversion
            // TODO: check if this is necessary
            if (from == typeof(string))
            {
                if (to == typeof(object))
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }


            // implicit nullable conversion 6.1.4
            if (IsNullableType(to))
            {
                if (IsNullableType(fromData.ValueType))
                {
                    // If the source value is null, then just return successfully (because the target value is a nullable type)
                    if (fromData.Value == null)
                    {
                        return(true);
                    }

                    fromData.CompileTimeType = Nullable.GetUnderlyingType(fromData.ValueType);
                }

                return(CanConvertType(fromData, Nullable.GetUnderlyingType(to)));
            }

            // implicit enumeration conversion 6.1.3
            long longTest = -1;

            if (fromData.IsLiteral && to.IsEnum && long.TryParse(fromData.Value.ToString(), out longTest))
            {
                if (longTest == 0)
                {
                    return(true);
                }
            }

            // implicit reference conversion 6.1.5
            if (!from.IsValueType && !to.IsValueType)
            {
                bool?irc = ImpRefConv(fromData, to);
                if (irc.HasValue)
                {
                    return(irc.Value);
                }
            }

            // implicit numeric conversion 6.1.2
            try {
                object  fromObj = null;
                double  dblTemp;
                decimal decTemp;
                char    chrTemp;
                fromObj = Activator.CreateInstance(from);

                if (char.TryParse(fromObj.ToString(), out chrTemp) || double.TryParse(fromObj.ToString(), out dblTemp) || decimal.TryParse(fromObj.ToString(), out decTemp))
                {
                    if (NumConv.ContainsKey(from) && NumConv[from].Contains(to))
                    {
                        return(true);
                    }
                    else
                    {
                        return(CrawlThatShit(to.GetHashCode(), from, new List <int>()));
                    }
                }
                //else {
                //   return CrawlThatShit(to.GetHashCode(), from, new List<int>());
                //}
            }
            catch {
                //return CrawlThatShit(to.GetHashCode(), from, new List<int>());
            }

            return(false);
        }
示例#50
0
        ///
        /// <summary>
        ///		Parses identifiers (fields or properties)
        /// </summary>
        ///
        /// <param name="environment">The environment containing the field or property</param>
        /// <param name="data">The name of the field or property</param>
        ///
        /// <returns>An CseObject containing the value of the identifier or containing null if identifier cannot be found</returns>
        ///
        /// <exception cref="CseLogicExceptionType.IDENT_NOT_FOUND" />
        ///
        internal static CseObject Parse(CseObject environment, string data)
        {
            if (data[0].Equals('@'))
            {
                data = data.Remove(0, 1);
            }

            LiteralExp.ParseEscSeqs(ref data, false);

            CseObject result       = null;
            Type      instanceType = TypeExp.GetTypeObj(environment.Value);

            if (!instanceType.IsEnum)
            {
                if (environment == CsEval.EvalEnvironment)
                {
                    CseObject tempLookup = TempIdentifierExp.Lookup(data);
                    if (tempLookup != null)
                    {
                        return(tempLookup);
                    }
                }

                FieldInfo fieldInfo = instanceType.GetField(data, defaultFlags | BindingFlags.GetField);
                if (fieldInfo != null)
                {
                    result = new CseObject(fieldInfo.GetValue(environment.Value));
                    result.CompileTimeType = fieldInfo.FieldType;
                }
                else
                {
                    PropertyInfo propertyInfo = instanceType.GetProperty(data, defaultFlags | BindingFlags.GetProperty);
                    if (propertyInfo != null)
                    {
                        result = new CseObject(propertyInfo.GetValue(environment.Value, null));
                        result.CompileTimeType = propertyInfo.PropertyType;
                    }
                    else
                    {
                        Type t = TypeExp.GetType(data);
                        if (t != null)
                        {
                            result = new CseObject(t);
                            result.CompileTimeType = t.GetType();
                        }
                        else
                        {
                            throw new CseLogicException(CseLogicExceptionType.IDENT_NOT_FOUND, data);
                        }
                    }
                }
            }
            else
            {
                dynamic resultObj = Enum.Parse(instanceType, data);
                result = new CseObject(resultObj);
                result.CompileTimeType = resultObj.GetType();
            }

            return(result);
        }
示例#51
0
        // Implicit reference conversions 6.1.6
        // TODO: check if both ref, throw exc if not
        ///
        /// <summary>
        ///		Tests for an implicit reference conversion, given a CseObject and a type.
        /// </summary>
        ///
        /// <param name="data">The object to test converting</param>
        /// <param name="t">The type to attempt to convert the object to</param>
        ///
        /// <returns>True if an implicit reference conversion is valid, false otherwise</returns>
        ///
        public static bool?ImpRefConv(CseObject fromArg, Type to)
        {
            bool?success = null;

            Type from = fromArg.ValueType;

            if (from == to)
            {
                // identity
                success = true;
            }

            else if (to == typeof(object))
            {
                // ref -> object
                success = true;
            }

            else if (fromArg.Value == null)
            {
                // null literal -> Ref-type
                success = !to.IsValueType;
            }

            else if (false)
            {
                // ref -> dynamic (6.1.8)
                // figure out how to do this
                ;
            }

            else if (from.IsArray && to.IsArray)
            {
                // Array-type -> Array-type
                bool sameRank = (from.GetArrayRank() == to.GetArrayRank());
                bool bothRef  = (!from.GetElementType().IsValueType&& !to.GetElementType().IsValueType);
                bool?impConv  = ImpRefConv(new CseObject(-1)
                {
                    CompileTimeType = from.GetElementType()
                }, to.GetElementType());

                success = (sameRank && bothRef && impConv.GetValueOrDefault(false));
            }

            // Conversion involving type parameters (6.1.10)
            else if (to.IsGenericParameter)
            {
                //if ( fromArg.GetType().Name.Equals(to.Name)) {
                if (to.GenericParameterAttributes != GenericParameterAttributes.None)
                {
                    if ((int)(to.GenericParameterAttributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0)
                    {
                        ;
                    }
                }
                else
                {
                }


                /*genArg.GetGenericParameterConstraints();
                 * genArg.GenericParameterAttributes;*/
                //if( mi.GetGenericArguments()[?]
                //var t = a.GetType().GetMethod("Foo", BindingFlags.Public | BindingFlags.Instance).GetGenericArguments()[0].GetGenericParameterConstraints();//.GenericParameterAttributes;
            }

            // Boxing Conversions (6.1.7)
            else if (from.IsValueType && !to.IsValueType)
            {
                return(IsBoxingConversion(fromArg, to));
            }

            else if ((from.IsClass && to.IsClass) || (from.IsClass && to.IsInterface) || (from.IsInterface && to.IsInterface))
            {
                // class -> class  OR  class -> interface  OR  interface -> interface
                success = CrawlThatShit(to.GetHashCode(), from, new List <int>());
            }

            else if (from.IsArray && CrawlThatShit(to.GetHashCode(), typeof(Array), new List <int>()))
            {
                // Array-type -> System.array
                return(true);
            }

            else if (from.IsArray && from.GetArrayRank() == 1 && to.IsGenericType && CrawlThatShit(to.GetHashCode(), typeof(IList <>), new List <int>()))
            {
                // Single dim array -> IList<>
                success = ImpRefConv(new CseObject(-1)
                {
                    CompileTimeType = from.GetElementType()
                }, to.GetGenericTypeDefinition());
            }



            return(success);
        }
示例#52
0
		///
		/// <summary>
		///		Determines if a boxing conversion exists between the passed object and the type
		/// </summary>
		/// 
		/// <param name="fromArg">The object to convert</param>
		/// <param name="to">The type to attempt to convert the object to.</param>
		/// 
		/// <returns>True if a boxing conversion exists between the object and the type, false otherwise</returns>
		/// 
		public static bool IsBoxingConversion(CseObject fromArg, Type to) {

			Type unwrappedBox = fromArg.ValueType;

			if (IsNullableType(unwrappedBox)) {
				unwrappedBox = Nullable.GetUnderlyingType(unwrappedBox);
			}

			if (to.Equals(typeof(System.ValueType)) || to.Equals(typeof(object))) {
				return true;
			}
			else if (CrawlThatShit(to.GetHashCode(), unwrappedBox, new List<int>())) {
				return true;
			}
			else if (unwrappedBox.IsEnum && to.Equals(typeof(System.Enum))) {
				return true;
			}
			else {
				return false;
			}
		}
示例#53
0
        ///
        /// <summary>
        ///		Parses arithmetic expressions
        /// </summary>
        ///
        /// <param name="leftOperand">Left operand</param>
        /// <param name="rightOperand">Right operand</param>
        /// <param name="arithType">Arithmetic operator type</param>
        ///
        /// <remarks>
        ///		Only works with operands that evaluate to either numeric or string types. If both operands are strings
        ///		and arithType is ADD, concatenation is performed. Else, if either operand is of a float type, both are
        ///		treated as float type. Else, both are treated as int types. This is to ensure proper behavior of operators
        ///		such as addition and division. If operands are of int type, result is then parsed as a literal expression
        ///		to ensure correct return type.
        ///	</remarks>
        ///
        /// <returns>Result of arithmetic operation</returns>
        ///
        /// <exception cref="CseLogicExceptionType.ARITH_EXCEPTION" />
        /// <exception cref="CseLogicExceptionType.LEFT_OP_NON_NUM" />
        /// <exception cref="CseLogicExceptionType.RIGHT_OP_NON_NUM" />
        ///
        internal static CseObject Parse(CseObject leftOperand, CseObject rightOperand, ArithType arithType)
        {
            dynamic result       = null;
            dynamic leftOpValue  = leftOperand.Value;
            dynamic rightOpValue = rightOperand.Value;
            string  methOpName   = null;

            try {
                switch (arithType)
                {
                case ArithType.ADD:
                    methOpName = OpOverloadNames.ADD;
                    result     = leftOpValue + rightOpValue;
                    break;

                case ArithType.DIV:
                    methOpName = OpOverloadNames.DIV;
                    result     = leftOpValue / rightOpValue;
                    break;

                case ArithType.MOD:
                    methOpName = OpOverloadNames.MOD;
                    result     = leftOpValue % rightOpValue;
                    break;

                case ArithType.MUL:
                    methOpName = OpOverloadNames.MUL;
                    result     = leftOpValue * rightOpValue;
                    break;

                case ArithType.POW:
                    result = Math.Pow(leftOpValue, rightOpValue);
                    break;

                case ArithType.SUB:
                    methOpName = OpOverloadNames.SUB;
                    result     = leftOpValue - rightOpValue;
                    break;
                }
                return(new CseObject(result));
            }
            catch {
                if (methOpName == null)
                {
                    throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);
                }

                MethodInfo leftOpMeth  = leftOpValue.GetType().GetMethod(methOpName, OpOverloadNames.Flags);
                MethodInfo rightOpMeth = rightOpValue.GetType().GetMethod(methOpName, OpOverloadNames.Flags);

                if (leftOpMeth == null && rightOpMeth == null)
                {
                    throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);
                }
                else if (leftOpMeth != null)
                {
                    try {
                        result = new CseObject(leftOpMeth.Invoke(leftOpValue, new object[] { leftOpValue, rightOpValue }));
                    }
                    catch {
                        throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);
                    }
                }
                else if (rightOpMeth != null)
                {
                    try {
                        result = new CseObject(rightOpMeth.Invoke(rightOpValue, new object[] { leftOpValue, rightOpValue }));
                    }
                    catch {
                        throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);
                    }
                }
                else
                {
                    throw new CseLogicException(CseLogicExceptionType.ARITH_EXCEPTION, leftOpValue, rightOpValue);
                }
            }

            return(new CseObject(result));
        }
示例#54
0
    ///
    /// <summary>
    ///		Assigns a value to the specified identifier (field or property).
    ///		Since any field or property that is a ValueType will not have its
    ///		value changed without explicitly being set, this method is given the
    ///		entire list of objects of the lhs chain expression and uses recursion to
    ///		set them right to left.
    /// </summary>
    /// 
    /// <example>
    ///		<c language="C#">x.y.z = 3</c>
    ///		This will set z = 3, then y = z (the newly changed z), then x = y.
    ///		If the expression is simply <c language="C#">x = 3</c>, then that is the only assignment
    ///		performed and all List arguments contain only a single value.
    /// </example>
    /// 
    /// <param name="envChain">
    ///		List of CseObjects from the chain expression of the lhs. This makes up the
    ///		list of environment objects. In the case of x = 3, envChain would contain
    ///		x's value.
    ///	</param>
    /// <param name="envNames">List of field/property names in the lhs chain expression. In the case of x = 3, envNames would contain "x".</param>
    /// <param name="envIndices">
    ///		List of array indices for each array in the lhs chain expression. For each non-array, the
    ///		envIndices at that index is null. In the case of x = 3, envIndices would contain null.
    ///		In the case of x[2] = 3, envIndices would contain 2.
    ///	</param>
    /// <param name="xrhs">Rhs expression</param>
    /// 
    /// <returns>xrhs's Value property</returns>
    /// 
    /// <exception cref="CseLogicExceptionType.ARRAY_INDEX_NOT_INT" />
    /// <exception cref="CseLogicExceptionType.CANT_FIND_IDENT_IN_ENV" />
    ///
    internal static object Assign(List<CseObject> envChain, List<string> envNames, List<CseObject> envIndices, CseObject xrhs) {
      object rhs = (xrhs == null ? null : xrhs.Value);

      if (envChain.Count == 0)
        return rhs;

      CseObject env = envChain[envChain.Count - 1];
      string envName = envNames[envNames.Count - 1];
      CseObject envIndex = envIndices[envIndices.Count - 1];

      //Type instanceType = TypeExp.GetTypeObj(env.Value);
      Type instanceType = env.ValueType;

      // Arrays
      if (envIndex != null) {
        MemberInfo member;
        ICollection arrMember;

        member = instanceType.GetField(envName, defaultFlags | BindingFlags.GetField);
        if (member != null) {
          arrMember = (ICollection)((FieldInfo)member).GetValue(env.Value);
        }
        else {
          member = instanceType.GetProperty(envName, defaultFlags | BindingFlags.GetProperty);
          if (member != null)
            arrMember = (ICollection)((PropertyInfo)member).GetValue(env.Value, null);
          else
            throw new CseLogicException(CseLogicExceptionType.CANT_FIND_IDENT_IN_ENV, envName, env.Value.ToString());
        }

        Array arrMemberAsArray = arrMember as Array;
        IDictionary arrMemberAsIDict = arrMember as IDictionary;

        if (arrMemberAsArray != null) {
          int index;
          if (int.TryParse(envIndex.Value.ToString(), out index))
            arrMemberAsArray.SetValue(rhs, index);
          else
            throw new CseLogicException(CseLogicExceptionType.ARRAY_INDEX_NOT_INT);
        }
        else if (arrMemberAsIDict != null) {
          arrMemberAsIDict[envIndex.Value] = rhs;
        }
      }
      // Nonarrays
      else {
        if (env == CsEval.EvalEnvironment) {
          CseObject tempLookup = TempIdentifierExp.Lookup(envName);
          if (tempLookup != null) {
            TempIdentifierExp.Assign(envName, rhs);
            return tempLookup;
          }
        }

        FieldInfo fieldInfo = instanceType.GetField(envName, defaultFlags | BindingFlags.GetField);
        if (fieldInfo != null) {
          fieldInfo.SetValue(env.Value, rhs);
        }
        else {
          PropertyInfo propertyInfo = instanceType.GetProperty(envName, defaultFlags | BindingFlags.GetProperty);
          if (propertyInfo != null)
            propertyInfo.SetValue(env.Value, rhs, null);
          else
            throw new CseLogicException(CseLogicExceptionType.CANT_FIND_IDENT_IN_ENV, envName, env.Value.ToString());
        }
      }

      envChain.RemoveAt(envChain.Count - 1);
      envNames.RemoveAt(envNames.Count - 1);
      envIndices.RemoveAt(envIndices.Count - 1);

      return IdentifierExp.Assign(envChain, envNames, envIndices, env);
    }
示例#55
0
		///
		/// <summary>
		///		Parses float-type literals
		/// </summary>
		/// 
		/// <param name="data">String containing the literal</param>
		/// <param name="suffix">Optional type suffix</param>
		/// 
		/// <returns>A float-type value</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_FLT_TYPE" />
		/// <exception cref="CseLogicExceptionType.NOT_A_NUM" />
		///
		internal static CseObject ParseFloatType(string data, string suffix) {
			CseObject result = null;

			if (suffix != null && suffix != "") {
				switch (suffix.ToLower()) {
					case "f":
						result = new CseObject(float.Parse(data));
						break;
					case "m":
						result = new CseObject(decimal.Parse(data));
						break;
					case "d":
						result = new CseObject(double.Parse(data));
						break;
				}
			}
			else {
				double doubleAttempt;
				if (double.TryParse(data, out doubleAttempt))
					result = new CseObject(doubleAttempt);
				else
					throw new CseLogicException(CseLogicExceptionType.NOT_A_NUM, data);
			}

			if (result == null)
				throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_FLT_TYPE, data);

			result.IsLiteral = true;
			return result;
		}
示例#56
0
        ///
        /// <summary>
        ///		Parses assignment expressions. This method basically just prepares
        ///		the parameters for a call to IdentifierExp.Assign(). Reference that
        ///		method for more information on this method's parameters.
        /// </summary>
        ///
        /// <param name="envChain">
        ///		List of CseObjects from the chain expression of the lhs.
        ///		This makes up the list of environment objects.
        ///	</param>
        /// <param name="envNames">List of field/property names in the lhs chain expression.</param>
        /// <param name="envIndices">
        ///		List of array indices for each array in the lhs chain expression.
        ///		For each non-array, the envIndices at that index is null.
        ///	</param>
        /// <param name="rhs">Rhs expression</param>
        ///
        /// <returns>The rhs parameter</returns>
        ///
        public static CseObject Parse(List <CseObject> envChain, List <string> envNames, List <CseObject> envIndices, CseObject rhs)
        {
            Type envType;

            while (envChain.Count > 1)
            {
                envType = envChain[1].Value.GetType();
                if (!envType.IsValueType)
                {
                    envChain.RemoveAt(0);
                    envNames.RemoveAt(0);
                    envIndices.RemoveAt(0);
                }
                else
                {
                    break;
                }
            }

            IdentifierExp.Assign(envChain, envNames, envIndices, rhs);
            return(rhs);
        }
示例#57
0
		///
		/// <summary>
		///		Parses float-type literals
		/// </summary>
		/// 
		/// <param name="data">String containing the literal</param>
		/// <param name="hasSuffix">Indicates whether a suffix is present or not</param>
		/// 
		/// <returns>A float-type value</returns>
		/// 
		/// <exception cref="CseLogicExceptionType.CANT_CONVERT_TO_FLT_TYPE" />
		/// <exception cref="CseLogicExceptionType.NOT_A_NUM" />
		///
		internal static CseObject ParseFloatType(string data, bool hasSuffix) {
			CseObject result = null;

			if (hasSuffix) {
				// Determine the suffix
				Regex r = new Regex(@"((?:\d|\.)+)([A-Za-z]{1,2})$");

				Match m = r.Match(data);

				data = m.Groups[1].Value;
				string suffix = m.Groups[2].Value;

				switch (suffix.ToLower()) {
					case "f":
						result = new CseObject(float.Parse(data));
						break;
					case "m":
						result = new CseObject(decimal.Parse(data));
						break;
					case "d":
						result = new CseObject(double.Parse(data));
						break;
				}
			}
			else {
				double doubleAttempt;
				if (double.TryParse(data, out doubleAttempt))
					result = new CseObject(doubleAttempt);
				else
					throw new CseLogicException(CseLogicExceptionType.NOT_A_NUM, data);
			}

			if (result == null)
				throw new CseLogicException(CseLogicExceptionType.CANT_CONVERT_TO_FLT_TYPE, data);

			result.IsLiteral = true;
			return result;
		}