Exemple #1
0
        public void InitDefaults()
        {
            this.Add("about", new StaticFunction("About", delegate(object[] ps) { return("@Calculator - a Tiny Expression Evaluator v1.0\r\nby Herre Kuijpers - Copyright © 2011 under the CPOL license"); }, 0, 0));
            this.Add("help", new StaticFunction("Help", Help, 0, 0));

            // high precision functions
            this.Add("abs", new StaticFunction("Abs", delegate(object[] ps) { return(Math.Abs(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("acos", new StaticFunction("Acos", delegate(object[] ps) { return(Math.Acos(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("asin", new StaticFunction("Asin", delegate(object[] ps) { return(Math.Asin(Convert.ToDouble(ps[0]))); }, 1, 1));

            this.Add("atan", new StaticFunction("Atan", delegate(object[] ps) { return(Math.Atan(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("atan2", new StaticFunction("Atan2", delegate(object[] ps) { return(Math.Atan2(Convert.ToDouble(ps[0]), Convert.ToDouble(ps[1]))); }, 2, 2));
            this.Add("ceiling", new StaticFunction("Ceiling", delegate(object[] ps) { return(Math.Ceiling(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("cos", new StaticFunction("Cos", delegate(object[] ps) { return(Math.Cos(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("cosh", new StaticFunction("Cosh", delegate(object[] ps) { return(Math.Cosh(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("exp", new StaticFunction("Exp", delegate(object[] ps) { return(Math.Exp(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("int", new StaticFunction("int", delegate(object[] ps) { return((int)Math.Floor(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("fact", new StaticFunction("Fact", Fact, 1, 1)); // factorials 1*2*3*4...
            this.Add("floor", new StaticFunction("Floor", delegate(object[] ps) { return(Math.Floor(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("log", new StaticFunction("Log", Log, 1, 2));    // log allows 1 or 2 parameters
            this.Add("ln", new StaticFunction("Ln", delegate(object[] ps) { return(Math.Log(Convert.ToDouble(ps[0]))); }, 1, 1));

            this.Add("pow", new StaticFunction("Pow", delegate(object[] ps)
            {
                if (
                    (Convert.ToInt64(ps[0]) != Convert.ToDouble(ps[0]))
                    ||
                    (Convert.ToInt64(ps[1]) != Convert.ToDouble(ps[1]))
                    )
                {
                    return(Math.Pow(Convert.ToDouble(ps[0]), Convert.ToDouble(ps[1])));
                }
                else     // use integral maths instead to avoid silent overflow
                {
                    long number = Convert.ToInt64(ps[0]);
                    long power  = Convert.ToInt64(ps[1]);
                    long result = 1L;
                    for (long i = 0; i < power; i++)
                    {
                        result *= number;
                    }
                    return(result);
                }
            }, 2, 2));
            this.Add("round", new StaticFunction("Round", delegate(object[] ps) { return(Math.Round(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("sign", new StaticFunction("Sign", delegate(object[] ps) { return(Math.Sign(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("sin", new StaticFunction("Sin", delegate(object[] ps) { return(Math.Sin(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("sinh", new StaticFunction("Sinh", delegate(object[] ps) { return(Math.Sinh(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("sqr", new StaticFunction("Sqr", delegate(object[] ps) { return(Convert.ToDouble(ps[0]) * Convert.ToDouble(ps[0])); }, 1, 1));
            this.Add("sqrt", new StaticFunction("Sqrt", delegate(object[] ps) { return(Math.Sqrt(Convert.ToDouble(ps[0]))); }, 1, 1));
            this.Add("trunc", new StaticFunction("Trunc", delegate(object[] ps) { return(Math.Truncate(Convert.ToDouble(ps[0]))); }, 1, 1));

            // array functions
            this.Add("avg", new StaticFunction("Avg", Avg, 1, int.MaxValue));
            this.Add("stdev", new StaticFunction("StDev", StDev, 1, int.MaxValue));
            this.Add("var", new StaticFunction("Var", Var, 1, int.MaxValue));
            this.Add("max", new StaticFunction("Max", Max, 1, int.MaxValue));
            this.Add("median", new StaticFunction("Min", Median, 1, int.MaxValue));
            this.Add("min", new StaticFunction("Min", Min, 1, int.MaxValue));

            //boolean functions
            this.Add("not", new StaticFunction("Not", delegate(object[] ps) { return(!Convert.ToBoolean(ps[0])); }, 1, 1));
            this.Add("if", new StaticFunction("If", delegate(object[] ps) { return(Convert.ToBoolean(ps[0]) ? ps[1] : ps[2]); }, 3, 3));
            this.Add("and", new StaticFunction("And", delegate(object[] ps) { return(Convert.ToBoolean(ps[0]) && Convert.ToBoolean(ps[1])); }, 2, 2));
            this.Add("or", new StaticFunction("Or", delegate(object[] ps) { return(Convert.ToBoolean(ps[0]) || Convert.ToBoolean(ps[1])); }, 2, 2));

            // string functions
            this.Add("left", new StaticFunction("Left", delegate(object[] ps)
            {
                int len = Convert.ToInt32(ps[1]) < ps[0].ToString().Length ? Convert.ToInt32(ps[1]) : ps[0].ToString().Length;
                return(ps[0].ToString().Substring(0, len));
            }, 2, 2));

            this.Add("right", new StaticFunction("Right", delegate(object[] ps)
            {
                int len = Convert.ToInt32(ps[1]) < ps[0].ToString().Length ? Convert.ToInt32(ps[1]) : ps[0].ToString().Length;
                return(ps[0].ToString().Substring(ps[0].ToString().Length - len, len));
            }, 2, 2));

            this.Add("mid", new StaticFunction("Mid", delegate(object[] ps)
            {
                int idx = Convert.ToInt32(ps[1]) < ps[0].ToString().Length ? Convert.ToInt32(ps[1]) : ps[0].ToString().Length;
                int len = Convert.ToInt32(ps[2]) < ps[0].ToString().Length - idx ? Convert.ToInt32(ps[2]) : ps[0].ToString().Length - idx;
                return(ps[0].ToString().Substring(idx, len));
            }, 3, 3));

            this.Add("hex", new StaticFunction("Hex", delegate(object[] ps) { return(String.Format("0x{0:X}", Convert.ToInt32(ps[0].ToString()))); }, 1, 1));
            this.Add("format", new StaticFunction("Format", delegate(object[] ps) { return(string.Format(ps[0].ToString(), ps[1])); }, 2, 2));
            this.Add("len", new StaticFunction("Len", delegate(object[] ps) { return(Convert.ToDouble(ps[0].ToString().Length)); }, 1, 1));
            this.Add("lower", new StaticFunction("Lower", delegate(object[] ps) { return(ps[0].ToString().ToLowerInvariant()); }, 1, 1));
            this.Add("upper", new StaticFunction("Upper", delegate(object[] ps) { return(ps[0].ToString().ToUpperInvariant()); }, 1, 1));
            this.Add("val", new StaticFunction("Val", delegate(object[] ps) { return(Convert.ToDouble(ps[0])); }, 1, 1));
        }
Exemple #2
0
        // Methods
        // Todo: We're missing type-checking and appropriate error handling!
        // Todo: Switch to an type operator based computation!
        // Todo: Introduce Implicit Casting!
        public object Evaluate()
        {
            var stack     = new SpecializedStack <Operand>();
            var variables = new Dictionary <string, Operand>();

            foreach (var token in _lexer.GetTokens())
            {
                switch (token.Kind)
                {
                // Arithmetic Operators
                case TokenKind.Add:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber((decimal)left.Value + (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Subtract:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber((decimal)left.Value - (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Multiply:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber((decimal)left.Value * (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Divide:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber((decimal)left.Value / (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.ClearStackAndVariables:
                {
                    variables.Clear();
                    stack.Clear();

                    break;
                }

                case TokenKind.ClearStack:
                {
                    stack.Clear();

                    break;
                }

                case TokenKind.ClearVariables:
                {
                    variables.Clear();

                    break;
                }

                case TokenKind.BooleanNot:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Boolean)
                    {
                        stack.Push(Operand.FromBoolean(!(bool)operand.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Modulus:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber((decimal)left.Value % (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Increment:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber((decimal)operand.Value + 1));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Decrement:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber((decimal)operand.Value - 1));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                // Bitwise Operators
                case TokenKind.BitwiseAnd:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend we can always convert to a long.
                        stack.Push(Operand.FromNumber((long)(decimal)left.Value & (long)(decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.BitwiseOr:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend we can always convert to a long.
                        stack.Push(Operand.FromNumber((long)(decimal)left.Value | (long)(decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.BitwiseXor:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend we can always convert to a long.
                        stack.Push(Operand.FromNumber((long)(decimal)left.Value ^ (long)(decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.BitwiseNot:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend we can always convert to a long.
                        stack.Push(Operand.FromNumber(~(long)(decimal)operand.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.BitwiseShiftLeft:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend we can always convert to an int/long.
                        stack.Push(Operand.FromNumber((long)(decimal)left.Value << (int)(decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.BitwiseShiftRight:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend we can always convert to an int/long.
                        stack.Push(Operand.FromNumber((long)(decimal)left.Value >> (int)(decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                // Boolean Operators
                case TokenKind.BooleanAnd:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Boolean && right.Kind == OperandKind.Boolean)
                    {
                        stack.Push(Operand.FromBoolean((bool)left.Value && (bool)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.BooleanOr:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Boolean && right.Kind == OperandKind.Boolean)
                    {
                        stack.Push(Operand.FromBoolean((bool)left.Value || (bool)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.BooleanXor:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Boolean && right.Kind == OperandKind.Boolean)
                    {
                        var leftValue  = (bool)left.Value;
                        var rightValue = (bool)right.Value;

                        stack.Push(Operand.FromBoolean((leftValue && leftValue == false) || (leftValue == false && leftValue)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                // Comparison Operators
                case TokenKind.LessThan:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromBoolean((decimal)left.Value < (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.LessThanOrEqualTo:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromBoolean((decimal)left.Value <= (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.EqualTo:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromBoolean((decimal)left.Value == (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.GreaterThan:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromBoolean((decimal)left.Value > (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.GreaterThanOrEqualTo:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromBoolean((decimal)left.Value >= (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.NotEqualTo:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromBoolean((decimal)left.Value != (decimal)right.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                // Trigonometric Functions
                case TokenKind.Acos:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Acos((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Asin:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Asin((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Atan:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Atan((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Cos:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Cos((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Cosh:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Cosh((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Sin:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Sin((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Sinh:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Sinh((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Tanh:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Tanh((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                // Numeric Utilities
                case TokenKind.Ceil:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber(Math.Ceiling((decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Floor:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber(Math.Floor((decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Round:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber(Math.Round((decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.IntegerPart:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber(Math.Truncate((decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.FloatingPart:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        var value = (decimal)operand.Value;
                        stack.Push(Operand.FromNumber(value - Math.Truncate(value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Sign:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: I'm not sure I understand the documentation on this one!
                        var value = (decimal)operand.Value;
                        stack.Push(Operand.FromNumber(value < 0 ? -1 : 0));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Absolute:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber(Math.Abs((decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Max:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber(Math.Max((decimal)left.Value, (decimal)right.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Min:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber(Math.Min((decimal)left.Value, (decimal)right.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                // Display Modes
                case TokenKind.DisplayAsHex:
                {
                    DisplayMode = EvaluatorDisplayMode.Hexadecimal;
                    break;
                }

                case TokenKind.DisplayAsDecimal:
                {
                    DisplayMode = EvaluatorDisplayMode.Decimal;
                    break;
                }

                case TokenKind.DisplayAsBinary:
                {
                    DisplayMode = EvaluatorDisplayMode.Binary;
                    break;
                }

                case TokenKind.DisplayAsOctal:
                {
                    DisplayMode = EvaluatorDisplayMode.Octal;
                    break;
                }

                // Constants
                case TokenKind.PushE:
                {
                    stack.Push(Operand.FromNumber((decimal)Math.E));
                    break;
                }

                case TokenKind.PushPi:
                {
                    stack.Push(Operand.FromNumber((decimal)Math.PI));
                    break;
                }

                case TokenKind.PushRandom:
                {
                    stack.Push(Operand.FromNumber((decimal)_random.Next()));
                    break;
                }

                // Mathematic Functions
                case TokenKind.Exp:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Exp((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Fact:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber(BuiltIn.Factorial((decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Sqrt:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Sqrt((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Ln:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Log((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Log:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to double!
                        stack.Push(Operand.FromNumber((decimal)Math.Log10((double)(decimal)operand.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Pow:
                {
                    var right = stack.Pop();
                    var left  = stack.Pop();

                    if (left.Kind == OperandKind.Number && right.Kind == OperandKind.Number)
                    {
                        stack.Push(Operand.FromNumber((decimal)Math.Pow((double)(decimal)left.Value, (double)(decimal)right.Value)));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                // Networking
                case TokenKind.HostToNetworkLong:
                case TokenKind.HostToNetworkShort:
                case TokenKind.NetworkToHostLong:
                case TokenKind.NetworkToHostShort:
                {
                    throw new NotImplementedException();
                }

                // Stack Manipulation
                case TokenKind.Pick:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to int!
                        stack.Push(stack.Pick((int)operand.Value));
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Repeat:
                {
                    // Todo: Complete!
                    throw new NotImplementedException();
                }

                case TokenKind.Depth:
                {
                    stack.Push(Operand.FromNumber(stack.Count));
                    break;
                }

                case TokenKind.Drop:
                {
                    stack.Pop();
                    break;
                }

                case TokenKind.DropN:
                {
                    var operand = stack.Pop();

                    if (operand.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to int!
                        for (int i = 0; i < (int)operand.Value; i++)
                        {
                            stack.Pop();
                        }
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Dup:
                {
                    stack.Push(stack.Peek());
                    break;
                }

                case TokenKind.DupN:
                {
                    var op1 = stack.Pop();
                    var op2 = stack.Peek();

                    if (op1.Kind == OperandKind.Number)
                    {
                        // Todo: Let's pretend it's ok to convert to int!
                        for (int i = 0; i < (int)op1.Value; i++)
                        {
                            stack.Push(op2);
                        }
                    }
                    else
                    {
                        throw new FormatException();
                    }

                    break;
                }

                case TokenKind.Roll:
                case TokenKind.RollDownwards:
                case TokenKind.ToggleStack:
                case TokenKind.Swap:
                {
                    // Todo: Implement!
                    throw new NotImplementedException();
                }

                // Macros and Variables
                case TokenKind.Macro:
                    //case TokenKind.Variable:
                {
                    // Todo: Implement!
                    throw new NotImplementedException();
                }

                // Operand
                case TokenKind.Operand:
                {
                    stack.Push(Operand.FromNumber((decimal)token.Value));
                    break;
                }

                default:
                    break;
                }
            }

            return(stack.Count > 0 ? stack.Pop().Value : null);
        }
Exemple #3
0
        //Event handler for when one of the yellow buttons are clicked
        public void MathOnClick(object sender, EventArgs args)
        {
            Button button     = (Button)sender;
            string buttonText = button.Text;

            selectedButtons.Remove(mainLabel.Text);
            double num = 0;

            switch (buttonText)
            {
            case "sin":
                num = Math.Sin(Double.Parse(mainLabel.Text));
                break;

            case "asin":
                num = Math.Asin(Double.Parse(mainLabel.Text));
                break;

            case "cos":
                num = Math.Cos(Double.Parse(mainLabel.Text));
                break;

            case "acos":
                num = Math.Acos(Double.Parse(mainLabel.Text));
                break;

            case "tan":
                num = Math.Tan(Double.Parse(mainLabel.Text));
                break;

            case "atan":
                num = Math.Atan(Double.Parse(mainLabel.Text));
                break;

            case "√":
                num = Math.Sqrt(Double.Parse(mainLabel.Text));
                break;

            case "x^2":
                num = Math.Pow(Double.Parse(mainLabel.Text), 2);
                break;

            case "10^x":
                num = Math.Pow(10, Double.Parse(mainLabel.Text));
                break;

            case "ln":
                num = Math.Log(Double.Parse(mainLabel.Text));
                break;

            case "log":
                num = Math.Log10(Double.Parse(mainLabel.Text));
                break;

            case "1/x":
                num = 1 / (Double.Parse(mainLabel.Text));
                break;

            case "x!":
                double value = Double.Parse(mainLabel.Text);
                for (double i = value - 1; i != 0; i--)
                {
                    value = value * i;
                }
                num = value;
                break;

            default:
                break;
            }
            num            = Math.Round(num, Int32.Parse(picker.SelectedIndex.ToString()));
            mainLabel.Text = num.ToString();
            selectedButtons.Add(num.ToString());
        }
        private void calculate()
        {
            string temp = null;

            switch (operations.Peek())
            {
            case Constant.PLUS:
            case Constant.MINUS:
            case Constant.MULTIPLY:
            case Constant.DIVIDE:
            case Constant.EXPONENT:
            case Constant.LOG:
            case Constant.OLD_MULTIPLY:
            case Constant.OLD_DIVIDE:
                Decimal apfloat2 = Decimal.Parse(numbers.Pop());
                Decimal apfloat1 = Decimal.Parse(numbers.Pop());

                switch (operations.Pop())
                {
                case Constant.PLUS:
                    temp = String.Concat((apfloat1 + apfloat2));
                    break;

                case Constant.MINUS:
                    temp = String.Concat((apfloat1 - apfloat2));
                    break;

                case Constant.MULTIPLY:
                case Constant.OLD_MULTIPLY:
                    temp = String.Concat((apfloat1 * apfloat2));
                    break;

                case Constant.DIVIDE:
                case Constant.OLD_DIVIDE:
                    temp = String.Concat((apfloat1 / apfloat2));
                    break;

                case Constant.EXPONENT:
                    temp = String.Concat((Math.Pow((double)apfloat1, (double)apfloat2)));
                    break;

                case Constant.LOG:
                    temp = String.Concat((Math.Log((double)apfloat2) / Math.Log((double)apfloat1)));
                    break;
                }

                break;

            case Constant.FACTORIAL:
            case Constant.PERCENT:
            case Constant.SIN:
            case Constant.COS:
            case Constant.TAN:
            case Constant.ROOT:
            case Constant.UNARY_MINUS:
            case Constant.ARCSIN:
            case Constant.ARCCOS:
            case Constant.ARCTAN:
                string myStringNumber = numbers.Pop();

                switch (operations.Pop())
                {
                case Constant.FACTORIAL:
                {
                    temp = String.Concat(factorial(Int64.Parse(myStringNumber)));
                }
                break;

                case Constant.PERCENT:
                {
                    apfloat1 = Decimal.Parse(myStringNumber);
                    apfloat2 = Decimal.Parse("100");
                    temp     = String.Concat((apfloat1 / apfloat2));
                }
                break;

                case Constant.ROOT:
                {
                    apfloat1 = Decimal.Parse(myStringNumber);
                    temp     = String.Concat((Math.Sqrt((double)apfloat1)));
                }
                break;

                case Constant.SIN:
                {
                    apfloat1 = Decimal.Parse(myStringNumber);
                    if (Constant.isRadian)
                    {
                        temp = String.Concat((Math.Sin((double)apfloat1)));
                    }
                    else
                    {
                        temp = String.Concat((Math.Sin(toDegrees((double)apfloat1))));
                    }
                }
                break;

                case Constant.COS:
                {
                    apfloat1 = Decimal.Parse(myStringNumber);
                    if (Constant.isRadian)
                    {
                        temp = String.Concat((Math.Cos((double)apfloat1)));
                    }
                    else
                    {
                        temp = String.Concat((Math.Cos(toDegrees((double)apfloat1))));
                    }
                }
                break;

                case Constant.TAN:
                {
                    apfloat1 = Decimal.Parse(myStringNumber);
                    if (Constant.isRadian)
                    {
                        temp = String.Concat((Math.Tan((double)apfloat1)));
                    }
                    else
                    {
                        temp = String.Concat((Math.Tan(toDegrees((double)apfloat1))));
                    }
                }
                break;

                case Constant.ARCSIN:
                {
                    apfloat1 = Decimal.Parse(myStringNumber);
                    if (Constant.isRadian)
                    {
                        temp = String.Concat((Math.Asin((double)apfloat1)));
                    }
                    else
                    {
                        temp = String.Concat((Math.Asin(toDegrees((double)apfloat1))));
                    }
                }
                break;

                case Constant.ARCCOS:
                {
                    apfloat1 = Decimal.Parse(myStringNumber);
                    if (Constant.isRadian)
                    {
                        temp = String.Concat((Math.Acos((double)apfloat1)));
                    }
                    else
                    {
                        temp = String.Concat((Math.Acos(toDegrees((double)apfloat1))));
                    }
                }
                break;

                case Constant.ARCTAN:
                {
                    apfloat1 = Decimal.Parse(myStringNumber);
                    if (Constant.isRadian)
                    {
                        temp = String.Concat((Math.Atan((double)apfloat1)));
                    }
                    else
                    {
                        temp = String.Concat((Math.Atan(toDegrees((double)apfloat1))));
                    }
                }
                break;

                case Constant.UNARY_MINUS:
                {
                    decimal myNumber = Decimal.Parse(myStringNumber);
                    temp = String.Concat(myNumber * -1);
                }
                break;
                }

                break;

            default:
                if (operations.Count != 0)
                {
                    operations.Pop();
                }
                break;
            }

            if (temp != null)
            {
                numbers.Push(temp);
            }
        }