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))); }
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) ) ); } }