public Value InvokeUserFunction(List <Value> arguments)
        {
            if (!(arguments.Count >= 1))
            {
                throw new ArgumentException("The amount of arguments passed into the function do not match the amount of expected arguments.");
            }
            if (arguments[0].Type != ValueType.String)
            {
                throw new Exception("An invalid argument type has been passed into a built in function.");
            }
            if (CallStack.Count > 1000)
            {
                throw new StackOverflowException("The call stack's size has exceeded the 1000 item limit.");
            }
            FunctionFrame f = functions[arguments[0].String].CloneTemplate();

            if (arguments.Count == 1)
            {
                f.SetArguments(new List <Value>());
            }
            else
            {
                f.SetArguments(arguments.GetRange(1, arguments.Count - 1));
            }
            f.ReturnPosition = (Marker)keywordMarker.Clone();
            f.ReturnResult   = Value.Null;
            CallStack.Push(f);
            lexer.ShiftCurrentPosition(functions[arguments[0].String].StartPosition);
            return(null);
        }
Beispiel #2
0
        public FunctionFrame CloneTemplate()
        {
            FunctionFrame functionStructure = new FunctionFrame(Identifier);

            functionStructure.SetArgumentParameters(argument_identifiers);
            functionStructure.SetArguments(LocalVariables.Values.ToList());
            return(functionStructure);
        }
        //gets the next value
        Value NextValue(FunctionFrame current)
        {
            Value val = Value.Null;

            if (lastToken == Token.Value) //raw value
            {
                val = lexer.TokenValue;
                ReadNextToken();
            }
            else if (lastToken == Token.Identifier)
            {
                if (GlobalVariables.ContainsKey(lexer.TokenIdentifier)) //see if it's a variable
                {
                    string vid = lexer.TokenIdentifier;
                    if (PeekNextToken() == Token.OpenBracket)
                    {
                        ReadNextToken();
                        ReadNextToken();
                        Value v = EvaluateNextExpression(0, current);
                        if (v == null)
                        {
                            return(null);
                        }
                        if (v.Type != ValueType.Double)
                        {
                            throw new Exception("Indicie's must be of type double.");
                        }
                        if (GlobalVariables[vid].Type == ValueType.String)
                        {
                            val = new Value(GlobalVariables[vid].String[(int)v.Double]);
                        }
                        else if (GlobalVariables[vid].Type == ValueType.Array)
                        {
                            val = GlobalVariables[vid].Array[(int)v.Double];
                        }
                        else
                        {
                            throw new Exception("Only arrays and strings can be indexed.");
                        }
                        MatchToken(Token.CloseBracket);
                    }
                    else
                    {
                        val = GlobalVariables[vid];
                    }
                }
                else if (functions.ContainsKey(lexer.TokenIdentifier) || builtInFunctions.ContainsKey(lexer.TokenIdentifier)) //see if it's a function
                {
                    ReadNextToken();
                    MatchToken(Token.OpenParenthesis);
                    string       fid       = lexer.TokenIdentifier;
                    int          aid       = lexer.Position.Index;
                    List <Value> arguments = new List <Value>();
                    int          argno     = 0;                 //current argument index
                    while (lastToken != Token.CloseParenthesis) //collect all the arguments
                    {
                        ReadNextToken();
                        if (lastToken == Token.Comma || lastToken == Token.CloseParenthesis)
                        {
                            continue; //just skip the comma's
                        }
                        else
                        {
                            if (argno >= arguments.Count)
                            {
                                Value v = EvaluateNextExpression(0, current);
                                if (v == null)
                                {
                                    return(null); //this is how to escape the recursive function when a function needs to be evaluated through the main loop first
                                }
                                arguments.Add(v);
                            }
                            else
                            {
                                int paramCount = 0; //skip open params, close params till it balances out
                                do
                                {
                                    ReadNextToken();
                                    if (lastToken == Token.OpenParenthesis)
                                    {
                                        paramCount++;
                                    }
                                    else if (lastToken == Token.CloseParenthesis)
                                    {
                                        paramCount--;
                                    }
                                }while (paramCount >= 0 && lastToken != Token.Comma);
                            }
                        }
                        argno++;
                    }
                    //bracket_counter++;
                    if (current.functionResults.Count > 0)
                    {
                        Value value = current.functionResults.Dequeue();
                        current.processedFunctionResults.Enqueue(value);
                        ReadNextToken();
                        return(value);
                    }
                    if (functions.ContainsKey(fid))
                    {
                        if (CallStack.Count > 1000)
                        {
                            throw new StackOverflowException("The call stack's size has exceeded the 1000 item limit.");
                        }
                        FunctionFrame f = functions[fid].CloneTemplate();
                        f.SetArguments(arguments);
                        f.ReturnPosition = (Marker)keywordMarker.Clone();
                        f.ReturnResult   = Value.Null;
                        CallStack.Push(f);
                        lexer.ShiftCurrentPosition(functions[fid].StartPosition);
                        ReadNextToken();
                        return(null);
                    }
                    else
                    {
                        val = builtInFunctions[fid].Invoke(arguments);
                        ReadNextToken();
                        if (val == null)
                        {
                            return(null);
                        }
                        current.processedFunctionResults.Enqueue(val);
                        return(val);
                    }
                }
                else
                {
                    val = null;
                    FunctionFrame function = GetCurrentContext();
                    if (function.LocalVariables.ContainsKey(lexer.TokenIdentifier))
                    {
                        string fid = lexer.TokenIdentifier;
                        if (PeekNextToken() == Token.OpenBracket)
                        {
                            ReadNextToken();
                            ReadNextToken();
                            Value v = EvaluateNextExpression(0, current);
                            if (v == null)
                            {
                                return(null);
                            }
                            if (v.Type != ValueType.Double)
                            {
                                throw new Exception("Indicie's must be of type double.");
                            }
                            if (function.LocalVariables[fid].Type == ValueType.String)
                            {
                                val = new Value(function.LocalVariables[fid].String[(int)v.Double]);
                            }
                            else if (function.LocalVariables[fid].Type == ValueType.Array)
                            {
                                val = function.LocalVariables[fid].Array[(int)v.Double];
                            }
                            else
                            {
                                throw new Exception("Only arrays and strings can be indexed.");
                            }
                            MatchToken(Token.CloseBracket);
                        }
                        else
                        {
                            val = function.LocalVariables[fid];
                        }
                    }

                    if (val == null)
                    {
                        throw new UnidentifiedTokenExcepion();
                    }
                }
                ReadNextToken();
            }
            else if (lastToken == Token.OpenParenthesis) //it's an expression
            {
                ReadNextToken();
                val = EvaluateNextExpression(0, current); //call the evaluate function
                if (val == null)
                {
                    return(null);
                }
                MatchToken(Token.CloseParenthesis);
                ReadNextToken();
            }
            else if (lastToken == Token.OpenBracket)
            {
                List <Value> values = new List <Value>();
                while (lastToken != Token.CloseBracket) //collect all the arguments
                {
                    ReadNextToken();
                    if (lastToken == Token.Comma || lastToken == Token.CloseBracket)
                    {
                        continue; //just skip the comma's
                    }
                    else
                    {
                        Value v = EvaluateNextExpression(0, current);
                        if (v == null)
                        {
                            return(null); //this is how to escape the recursive function when a function needs to be evaluated through the main loop first
                        }
                        values.Add(v);
                    }
                }
                ReadNextToken();
                val = new Value(values);
            }
            //this part handles uniary operations
            else
            {
                Token tok = lastToken;
                ReadNextToken();
                if (tok == Token.Refrence)
                {
                    val = new Value(lexer.TokenIdentifier);
                }
                else
                {
                    Value val1 = NextValue(current);
                    if (val1 == null)
                    {
                        return(null);
                    }
                    val = val1.PerformUniaryOperation(tok);
                }
            }
            return(val);
        }