/// <summary>
        /// This ought to be implemented with a FunctionMartix but it would be huge.
        /// This way is easier!
        /// </summary>
        internal static Tuple <OperandType, OperandType> DoSetEquals(DoubleOperandFunctionMatrix matrix, Stack <IOperand> stack, IBackingStore backingStore, long parserPosition)
        {
            IOperand second = PopAndResolve(stack, backingStore);
            IOperand first  = stack.Pop();      // Not PopAndResolve. LHS must be a variable.

            if (first.Type != OperandType.Variable)
            {
                throw new ExpressionEvaluatorException(parserPosition, ExpressionEvaluatorException.ExceptionCause.BadOperand, "LHS of '=' is a '" + first.Type + "' when it must be a variable");
            }
            else
            {
                string varName = (string)first.GetValue();

                (OperandType type, object value)valueAndType;
                try
                {
                    // We need the type, don't need the value because it's going to be overwritten.
                    valueAndType = backingStore.GetValue(varName);
                }
                catch (Exception ex)
                {
                    throw new ExpressionEvaluatorException(-1, ExpressionEvaluatorException.ExceptionCause.UndefinedVariable, $"'{varName}'");
                }

                // type is needed so we can pick out the correct martrix operation. Value is irrelevant as it is overwritten.
                var firstOperand = new Operand(first.ParserPosition, valueAndType.type, valueAndType.value);

                IOperand result = matrix.PerformDelegate(firstOperand, second);

                if (result != null)
                {
                    backingStore.SetValue(varName, result.GetValue());
                    stack.Push(result);
                    return(null);
                }
                else
                {
                    // Signal an error ...
                    return(new Tuple <OperandType, OperandType>(first.Type, second.Type));
                }
            }
        }
        /// <summary>
        /// Peeks an operand from the stack. If it's a variable it returns an operand holding the variable value, otherwise it returns the operand.
        /// </summary>
        /// <param name="stack"></param>
        /// <param name="variables"></param>
        /// <returns></returns>
        public static IOperand PeekAndResolve(Stack <IOperand> stack, IBackingStore backingStore)
        {
            IOperand operand = stack.Peek();

            if (operand.Type == OperandType.Variable)
            {
                //var variable = ResolveVariable(variables, retVal);

                try
                {
                    var valueAndType = backingStore.GetValue((string)operand.GetValue());
                    operand = new Operand(operand.ParserPosition, valueAndType.type, valueAndType.value);
                }
                catch// (KeyNotFoundException)
                {
                    throw new ExpressionEvaluatorException(operand.ParserPosition, ExpressionEvaluatorException.ExceptionCause.UndefinedVariable, $"'{operand.GetValue().ToString()}'");
                }
            }
            return(operand);
        }
예제 #3
0
 public Task <TValue> GetValueAsync(TKey key)
 {
     return(_taskFactory.StartNew(() =>
     {
         lock (_cache)
         {
             if (_cache.ContainsKey(key))
             {
                 return _cache[key];
             }
         }
         var result = _backingStore.GetValue(key);
         lock (_cache)
         {
             if (_cache.ContainsKey(key))
             {
                 return _cache[key];
             }
             _cache[key] = result;
         }
         return result;
     }));
 }