public static Token ExecuteUserFunction(string funcName, List <Token> arguments) { functionCallNumber++; Token result = Token.Error("Invalid call to user function"); if (!userFunctions.ContainsKey(variables.GetStringData(funcName))) { return(result); } UserFunction userFunc = userFunctions[variables.GetStringData(funcName)]; Dictionary <string, string> names = new Dictionary <string, string>(); for (int i = 0; i < arguments.Count; i++) { //var tempName = "_" + Guid.NewGuid().ToString("N"); var tempName = GenerateRandomName(); //This is much faster than Guid due to smaller string length names.Add(tempName, arguments[i].TokenName); arguments[i].TokenName = tempName; variables.AddToken(arguments[i]); } string executbleCode = ReplaceNames(arguments, userFunc); Token temp = new Token(TokenType.Block, "", executbleCode); callDepth++; if (callDepth == 0) { variables.RemoveReservedWord("return"); } try { temp = BlockCommands.ExecuteBlock(temp); } catch (Exception) { temp = Token.Error("An error occured while performaing the operation"); } callDepth--; if (callDepth < 0) { variables.AddReservedWord("return"); } foreach (var pair in names) { var item = variables.GetToken(pair.Key); item.TokenName = pair.Value; variables.Remove(pair.Key); } if (userFunc.returns && temp.TokenType != TokenType.Error) { try { temp = variables.GetToken("return"); } catch (Exception) { temp = Token.Error("Return value not valid in function definition"); } } return(temp); }
public static Token Calculate(List <Token> postfixTokens) { Stack <Token> operands = new Stack <Token>(); Token result = Token.Void; try { for (int index = 0; index < postfixTokens.Count; index++) { Token t = postfixTokens[index]; if (t.TokenType == TokenType.Vector || t.TokenType == TokenType.Text || t.TokenType == TokenType.Bool || t.TokenType == TokenType.Block || t.TokenType == TokenType.Break || t.TokenType == TokenType.Matrix || t.TokenType == TokenType.Custom) { operands.Push(t); } else if (t.TokenType == TokenType.Function || t.TokenType == TokenType.Loop || t.TokenType == TokenType.Condition || t.TokenType == TokenType.UserFunction || t.TokenType == TokenType.FunctionDefiner) { int paramCount = (int)(operands.Pop().FirstValue); List <Token> parameters = new List <Token>(); for (int i = 0; i < paramCount; i++) { parameters.Add(operands.Pop()); } parameters.Reverse(); Token resultToken; if (t.TokenType == TokenType.Function) { resultToken = Function.InvokeFunction(t.TokenName, parameters); if (resultToken.TokenType == TokenType.Error) { return(resultToken); } } else if (t.TokenType == TokenType.UserFunction) { resultToken = FunctionDefiner.ExecuteUserFunction(t.TokenName, parameters); if (resultToken.TokenType == TokenType.Error) { return(resultToken); } } else if (t.TokenType == TokenType.Loop) { loopDepth++; resultToken = BlockCommands.ExecuteLoop(t.TokenName, parameters); if (resultToken.TokenType == TokenType.Error) { loopDepth = 0; return(resultToken); } loopDepth--; } else if (t.TokenType == TokenType.Condition) { Token param = Token.Void; if (t.TokenName == "elseif" || t.TokenName == "else") { param = operands.Pop(); } resultToken = BlockCommands.ExecuteCondition(t.TokenName, param, parameters); if (resultToken.TokenType == TokenType.Error) { return(resultToken); } } else { if (operands.Count == 0) { return(Token.Error("User function must be assigned to a name")); } resultToken = FunctionDefiner.CreateUserFunction(parameters); if (resultToken.TokenType == TokenType.Error) { return(resultToken); } } operands.Push(resultToken); } else if (operands.Count >= 1 && t.TokenName.StartsWith("u")) { if (operands.Peek().TokenType != TokenType.Vector && operands.Peek().TokenType != TokenType.Bool && operands.Peek().TokenType != TokenType.Matrix) { return(Token.Error("Operand not valid for [ " + t.TokenName + " ]")); } Token firstParam = operands.Pop(); Token temp = null; if (!DoCalculateUnary(t.TokenName, firstParam, out temp)) { return(Token.Error("Operand not valid for [ " + t.TokenName + " ]")); } operands.Push(temp); } else if (operands.Count > 1) { Token temp = null; Token firstParam = operands.Pop(); Token secondParam = operands.Pop(); switch (t.TokenName) { case "*": case "/": case "%": case "+": case "-": case "^": case "==": case "!=": case "?": case "??": case "<": case ">": case ">=": case "<=": if (firstParam.TokenType == TokenType.Text && secondParam.TokenType == TokenType.Text) { temp = new Token(TokenType.Bool, 1, firstParam.StrData == secondParam.StrData ? 1 : 0); } else if (firstParam.TokenType == TokenType.Custom && secondParam.TokenType == TokenType.Custom && firstParam.IsOfType(typeof(StringsToken)) && secondParam.IsOfType(typeof(StringsToken))) { List <string> first = (List <string>)firstParam.CustomData; List <string> second = (List <string>)secondParam.CustomData; if (first.Count == second.Count) { for (var i = 0; i < first.Count; i++) { if (first[i] != second[i]) { temp = new Token(TokenType.Bool, 1, 0); } } } else { temp = new Token(TokenType.Bool, 1, 0); } temp = new Token(TokenType.Bool, 1, 1); } else if ((firstParam.TokenType != TokenType.Vector && firstParam.TokenType != TokenType.Bool && firstParam.TokenType != TokenType.Matrix) || (secondParam.TokenType != TokenType.Vector && secondParam.TokenType != TokenType.Bool && secondParam.TokenType != TokenType.Matrix) ) { return(Token.Error("Operands not valid for [ " + t.TokenName + " ]. Both must be the same type.")); } else { temp = DoCalculate(t.TokenName, secondParam, firstParam); } if (temp.TokenType == TokenType.Error) //yep stack is upside down! { return(temp); } break; case "=": if (firstParam.TokenType == TokenType.Void || string.IsNullOrEmpty(secondParam.TokenName)) { return(Token.Error("Assignment not valid.")); } secondParam.ResetValues(firstParam); if (variables.Contains(secondParam.TokenName)) { temp = variables.SetTokenVerify(secondParam); } else { temp = variables.AddTokenVerify(secondParam); } if (temp.TokenType == TokenType.Error) { return(temp); } else { temp = secondParam; } if (secondParam.TokenType == TokenType.UserFunction) { if (operands.Count == 0) { return(new Token(TokenType.Text, "", "User function named [ " + temp.TokenName + " ] added")); } else { return(Token.Error("Bad definition of User function")); } } break; default: return(Token.Error("Error in expression")); } operands.Push(temp); } else { return(Token.Error("Error in expression")); } } if (operands.Count != 1) { return(Token.Error("Error in expression")); } result = operands.Pop(); if (result.TokenType == TokenType.Block) { result = BlockCommands.ExecuteBlock(result); if (result.TokenType != TokenType.Error) { return(Token.Void); } } else if (result.TokenType == TokenType.Operator || result.TokenType == TokenType.Loop || result.TokenType == TokenType.Condition) { return(Token.Error("Error in expression")); } } catch (Exception) { return(Token.Error("Error in expression")); } if (result.TokenType == TokenType.ConditionExecuted) { return(Token.Void); } return(result); }