Ejemplo n.º 1
0
        private Expression ParseBuildInFunction(BuildInFunction func, List <Expression> arguments, string pos)
        {
            Expression funcExpression;

            switch (func.id)
            {
            case "abs":
                funcExpression = CallUnaryMathFunction(func.id, "Abs", arguments[0], pos);
                break;

            case "acos":
                funcExpression = ToDeg(func.id, CallUnaryMathFunction(func.id, "Acos", arguments[0], pos), pos);
                break;

            case "acos_rad":
                funcExpression = CallUnaryMathFunction(func.id, "Acos", arguments[0], pos);
                break;

            case "asin":
                funcExpression = ToDeg(func.id, CallUnaryMathFunction(func.id, "Asin", arguments[0], pos), pos);
                break;

            case "asin_rad":
                funcExpression = CallUnaryMathFunction(func.id, "Asin", arguments[0], pos);
                break;

            case "atan":
                funcExpression = ToDeg(func.id, CallUnaryMathFunction(func.id, "Atan", arguments[0], pos), pos);
                break;

            case "atan_rad":
                funcExpression = CallUnaryMathFunction(func.id, "Atan", arguments[0], pos);
                break;

            case "ceil":
                funcExpression = CallUnaryMathFunction(func.id, "Ceiling", arguments[0], pos);
                break;

            case "cos":
                funcExpression = CallUnaryMathFunction(func.id, "Cos", ToRad(func.id, arguments[0], pos), pos);
                break;

            case "cos_rad":
                funcExpression = CallUnaryMathFunction(func.id, "Cos", arguments[0], pos);
                break;

            case "cosh":
                funcExpression = CallUnaryMathFunction(func.id, "Cosh", ToRad(func.id, arguments[0], pos), pos);
                break;

            case "cosh_rad":
                funcExpression = CallUnaryMathFunction(func.id, "Cosh", arguments[0], pos);
                break;

            case "exp":
                funcExpression = CallUnaryMathFunction(func.id, "Exp", arguments[0], pos);
                break;

            case "floor":
                funcExpression = CallUnaryMathFunction(func.id, "Floor", arguments[0], pos);
                break;

            case "ln":
            case "log":
                funcExpression = CallUnaryMathFunction(func.id, "Log", arguments[0], pos);
                break;

            case "log10":
                funcExpression = CallUnaryMathFunction(func.id, "Log10", arguments[0], pos);
                break;

            case "max":
                funcExpression = CallBinaryMathFunction(func.id, "Max", arguments[0], arguments[1], pos);
                break;

            case "min":
                funcExpression = CallBinaryMathFunction(func.id, "Min", arguments[0], arguments[1], pos);
                break;

            case "pow":
                funcExpression = CallBinaryMathFunction(func.id, "Pow", arguments[0], arguments[1], pos);
                break;

            case "rand":
                funcExpression = Expression.Call(
                    Expression.Constant(random, typeof(Random)),
                    typeof(Random).GetMethod("NextDouble"),
                    new Expression[] {}
                    );
                break;

            case "round":
                funcExpression = CallBinaryLambda(func.id, (a, b) => Math.Round(a, (int)b), arguments[0], arguments[1], pos);
                break;

            case "sign":
                funcExpression = CallUnaryLambda(func.id, a => (int)Math.Sign(a), arguments[0], pos);
                break;

            case "sin":
                funcExpression = CallUnaryMathFunction(func.id, "Sin", ToRad(func.id, arguments[0], pos), pos);
                break;

            case "sin_rad":
                funcExpression = CallUnaryMathFunction(func.id, "Sin", arguments[0], pos);
                break;

            case "sinh":
                funcExpression = CallUnaryMathFunction(func.id, "Sinh", ToRad(func.id, arguments[0], pos), pos);
                break;

            case "sinh_rad":
                funcExpression = CallUnaryMathFunction(func.id, "Sinh", arguments[0], pos);
                break;

            case "sqrt":
                funcExpression = CallUnaryMathFunction(func.id, "Sqrt", arguments[0], pos);
                break;

            case "tan":
                funcExpression = CallUnaryMathFunction(func.id, "Tan", ToRad(func.id, arguments[0], pos), pos);
                break;

            case "tan_rad":
                funcExpression = CallUnaryMathFunction(func.id, "Tan", arguments[0], pos);
                break;

            case "tanh":
                funcExpression = CallUnaryMathFunction(func.id, "Tanh", ToRad(func.id, arguments[0], pos), pos);
                break;

            case "tanh_rad":
                funcExpression = CallUnaryMathFunction(func.id, "Tanh", arguments[0], pos);
                break;

            case "len":
                funcExpression = Expression.Call(
                    typeof(VectorMath).GetMethod("Len"),
                    arguments[0],
                    Expression.Constant(pos)
                    );
                break;

            case "dot":
                funcExpression = Expression.Call(
                    typeof(VectorMath).GetMethod("Dot"),
                    arguments[0], arguments[1],
                    Expression.Constant(pos)
                    );
                break;

            case "mag":
                funcExpression = Expression.Call(
                    typeof(VectorMath).GetMethod("Mag"),
                    arguments[0],
                    Expression.Constant(pos)
                    );
                break;

            case "norm":
                funcExpression = Expression.Call(
                    typeof(VectorMath).GetMethod("Norm"),
                    arguments[0],
                    Expression.Constant(pos)
                    );
                break;

            case "cross":
                funcExpression = Expression.Call(
                    typeof(VectorMath).GetMethod("Cross"),
                    arguments[0], arguments[1],
                    Expression.Constant(pos)
                    );
                break;

            default:
                throw new Exception(pos + "unknown build-in function: " + func.id);
            }

            return(Expression.Convert(funcExpression, typeof(Object)));
        }
Ejemplo n.º 2
0
        private void ParseIdentifier(Stack <Expression> expr, Stack <Operator> ops)
        {
            Token t = tokens.Dequeue();

            if (kalc.Functions.ContainsKey(t.val))
            {
                // User function call
                JITFunction f = kalc.Functions[t.val];
                if (tokens.Count > 0 && tokens.Peek().val == "(")
                {
                    // Parameter list supplied, execute function now
                    List <Expression> args = ParseArgumentList();
                    expr.Push(ParseUserFunction(t.val, args, t.pos));
                }
                else if (f.Ins.Count == 0)
                {
                    // Function takes no arguments, execute now
                    expr.Push(ParseUserFunction(t.val, new List <Expression>(), t.pos));
                }
                else
                {
                    // Do function call later, when parameters are known
                    ops.Push(kalc.Operators["user-function"]);
                    expr.Push(Expression.Constant(t.val));
                }
            }
            else if (kalc.BuildInFunctions.ContainsKey(t.val))
            {
                BuildInFunction f = kalc.BuildInFunctions[t.val];

                if (tokens.Count > 0 && tokens.Peek().val == "(")
                {
                    // Parameter list supplied, execute function now
                    List <Expression> args = ParseArgumentList();
                    if (args.Count != f.numArgs)
                    {
                        throw new Exception(t.pos + "function " + f + " takes " + f.numArgs + " arguments, but " + args.Count + " were supplied");
                    }
                    expr.Push(ParseBuildInFunction(f, args, t.pos));
                }
                else if (f.numArgs == 0)
                {
                    // Function takes no arguments, execute now
                    expr.Push(ParseBuildInFunction(f, new List <Expression>(), t.pos));
                }
                else
                {
                    // Do function call later, when parameters are known
                    ops.Push(kalc.Operators["buildin-function"]);
                    expr.Push(Expression.Constant(t.val));
                }
            }
            else
            {
                // Variable identifier
                if (tokens.Count > 0 && tokens.Peek().val == "(")
                {
                    // Parameter list supplied, but function doesn't exist
                    throw new Exception(t.pos + "function " + t.val + " does not exist");
                }

                expr.Push(
                    Expression.Call(
                        thisExpression,
                        typeof(JITFunction).GetMethod("GetVar"),
                        Expression.Constant(t.val),
                        Expression.Constant(t.pos)
                        )
                    );
            }
        }