Пример #1
0
        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);
        }
Пример #2
0
        public FunctionFrame CloneTemplate()
        {
            FunctionFrame functionStructure = new FunctionFrame(Identifier);

            functionStructure.SetArgumentParameters(argument_identifiers);
            functionStructure.SetArguments(LocalVariables.Values.ToList());
            return(functionStructure);
        }
Пример #3
0
        //this and next value are really important because that's how values for arguments are ascertained
        //gets the next expression (conditions, expressions) and evaluates it. Return's 0 or 1 for conditions
        Value EvaluateNextExpression(int min, FunctionFrame current, bool multiterm = true, bool candivide = true)
        {
            Dictionary <Token, int> precedens = new Dictionary <Token, int>()
            {
                { Token.Or, 0 }, { Token.And, 0 },
                { Token.Equals, 1 }, { Token.NotEqual, 1 },
                { Token.Less, 1 }, { Token.More, 1 },
                { Token.LessEqual, 1 }, { Token.MoreEqual, 1 },
                { Token.Plus, 2 }, { Token.Minus, 2 },
                { Token.Asterisk, 3 }, { Token.Modulous, 3 }, { Token.Slash, 3 },
                { Token.Caret, 4 }
            }; //counts the amount of required "arguments" for each operand
            Value value = NextValue(current);

            if (value == null)
            {
                return(null);
            }
            while (true)
            {
                //we could just put precedens.contains token but you know....
                if (lastToken < Token.Plus || lastToken > Token.And || precedens[lastToken] < min)
                {
                    break;
                }
                if (!multiterm && precedens[lastToken] < 3)
                {
                    break;
                }
                Token op = lastToken;
                if (!candivide && op == Token.Slash)
                {
                    break;
                }
                int prec    = precedens[lastToken]; // Operator Precedence
                int assoc   = 0;                    // 0 left, 1 right; Operator associativity
                int nextmin = assoc == 0 ? prec : prec + 1;
                ReadNextToken();
                bool divide = true;
                if (op == Token.Slash)
                {
                    divide = false;
                }
                Value rhs = EvaluateNextExpression(nextmin, current, false, divide);
                if (rhs == null)
                {
                    return(null);
                }
                value = value.PerformBinaryOperation(op, rhs);
            }

            return(value);
        }
Пример #4
0
        Value EvaluateNextExpression()
        {
            FunctionFrame function = GetCurrentContext();
            Value         val      = EvaluateNextExpression(0, function);

            if (val == null)
            {
                while (function.processedFunctionResults.Count > 0)
                {
                    function.functionResults.Enqueue(function.processedFunctionResults.Dequeue());
                }
                return(null);
            }
            else
            {
                function.processedFunctionResults.Clear();
                return(val);
            }
        }
Пример #5
0
        FunctionFrame GetCurrentContext()
        {
            Stack <CallFrame> searched = new Stack <CallFrame>();
            FunctionFrame     function = null;

            while (CallStack.Count > 0)
            {
                searched.Push(CallStack.Pop());
                if (searched.Peek().GetType() == typeof(FunctionFrame))
                {
                    function = (FunctionFrame)searched.Peek();
                    break;
                }
            }
            while (searched.Count > 0)
            {
                CallStack.Push(searched.Pop());
            }
            return(function);
        }
Пример #6
0
        //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);
        }
Пример #7
0
        //executes a single statement
        void ExecuteNextStatement()
        {
            Token keyword = lastToken;

            expressionMarker = (Marker)lexer.Position.Clone();
            ReadNextToken();
            Value         expr;
            IfElifFrame   prevElifFrame;
            FunctionFrame functionFrame;

            switch (keyword)
            {
            case Token.Global:
                MatchToken(Token.Identifier);
                GlobalVariables.Add(lexer.TokenIdentifier, Value.Null);
                ReadNextToken();
                break;

            case Token.Abstract:
                MatchToken(Token.Identifier);
                GlobalVariables.Add(lexer.TokenIdentifier, new Value(new Expression(lexer.TokenIdentifier)));
                ReadNextToken();
                break;

            case Token.Identifier:
                string id = lexer.TokenIdentifier;
                if (lastToken == Token.Set)
                {
                    if (ReadOnlyVariables.Contains(id))
                    {
                        throw new Exception("FastCode cannot write to a read only variable.");
                    }
                    ReadNextToken();
                    expr = EvaluateNextExpression();
                    if (expr == null)
                    {
                        return;
                    }
                    if (GlobalVariables.ContainsKey(id))
                    {
                        GlobalVariables[id] = expr;
                        break;
                    }
                    else
                    {
                        functionFrame = GetCurrentContext();
                        if (functionFrame.LocalVariables.ContainsKey(id))
                        {
                            functionFrame.LocalVariables[id] = expr;
                        }
                        else
                        {
                            functionFrame.LocalVariables.Add(id, expr);
                        }
                    }
                    break;
                }
                else if (lastToken == Token.OpenParenthesis)
                {
                    if (functions.ContainsKey(id) || builtInFunctions.ContainsKey(id))
                    {
                        lexer.ShiftCurrentPosition(keywordMarker);
                        ReadNextToken();
                        EvaluateNextExpression();
                        break;
                    }
                }
                else if (lastToken == Token.OpenBracket)
                {
                    ReadNextToken();
                    Value indexValue = EvaluateNextExpression();
                    if (indexValue == null)
                    {
                        return;
                    }
                    if (indexValue.Type != ValueType.Double)
                    {
                        throw new Exception("Indicie's must be of type double.");
                    }
                    MatchToken(Token.CloseBracket);
                    ReadNextToken();
                    MatchToken(Token.Set);
                    ReadNextToken();
                    Value setval = EvaluateNextExpression();
                    if (setval == null)
                    {
                        return;
                    }
                    if (GlobalVariables.ContainsKey(id))
                    {
                        if (GlobalVariables[id].Type == ValueType.Array)
                        {
                            GlobalVariables[id].Array[(int)indexValue.Double] = setval;
                            break;
                        }
                        else if (GlobalVariables[id].Type == ValueType.String)
                        {
                            if (setval.Type != ValueType.Character)
                            {
                                throw new Exception("Strings can only index characters.");
                            }
                            char[] str = GlobalVariables[id].String.ToCharArray();
                            str[(int)indexValue.Double] = setval.Character;
                            GlobalVariables[id]         = new Value(new string(str));
                            break;
                        }
                    }
                    else
                    {
                        functionFrame = GetCurrentContext();
                        if (functionFrame.LocalVariables[id].Type == ValueType.Array)
                        {
                            functionFrame.LocalVariables[id].Array[(int)indexValue.Double] = setval;
                            break;
                        }
                        else if (functionFrame.LocalVariables[id].Type == ValueType.String)
                        {
                            if (setval.Type != ValueType.Character)
                            {
                                throw new Exception("Strings can only index characters.");
                            }
                            char[] str = functionFrame.LocalVariables[id].String.ToCharArray();
                            str[(int)indexValue.Double]      = setval.Character;
                            functionFrame.LocalVariables[id] = new Value(new string(str));
                            break;
                        }
                    }
                }
                throw new Exception("Identifier \"" + id + "\" cannot stand alone without a keyword.");

            case Token.Break:
                int i = 0;
                while (!(CallStack.Peek().GetType() == typeof(WhileFrame) || CallStack.Peek().GetType() == typeof(ForFrame)))
                {
                    if (CallStack.Peek().GetType() == typeof(FunctionFrame))
                    {
                        throw new UnexpectedStatementException(Token.Break.ToString());
                    }
                    i++;
                    prevCallFrame = CallStack.Pop();
                }
                prevCallFrame = CallStack.Pop();
                SkipCallFrame(i);
                break;

            case Token.Return:
                functionFrame = null;
                int j = 0;
                while (CallStack.Count != 0)
                {
                    if (CallStack.Peek().GetType() == typeof(FunctionFrame))
                    {
                        functionFrame = (FunctionFrame)CallStack.Pop();
                        if (functionFrame.Identifier == "MAINSTRUCTURE")
                        {
                            throw new Exception("Only functions may return values.");
                        }
                        break;
                    }
                    CallStack.Pop();
                    j++;
                }
                if (PeekNextToken() != Token.Newline && PeekNextToken() != Token.Semicolon)
                {
                    CallStack.Push(functionFrame);
                    expr = EvaluateNextExpression();
                    if (expr == null)
                    {
                        return;
                    }
                    functionFrame = (FunctionFrame)CallStack.Pop();
                    functionFrame.ReturnResult = expr;
                }
                CallStack.Push(functionFrame);
                SkipCallFrame(j, true);
                ExecuteNextStatement();
                break;

            case Token.Stop:
                Exit = true;
                return;

            case Token.Import:
                MatchToken(Token.Value);
                if (lexer.TokenValue.Type != ValueType.String)
                {
                    throw new Exception("Expected string, got " + lexer.TokenValue.Type);
                }

                ReadNextToken();
                break;

            case Token.EndOfFile:
                Exit = true;
                return;

            case Token.If:
                IfElifFrame ifFrame = new IfElifFrame();
                expr = EvaluateNextExpression();
                if (expr == null)
                {
                    return;
                }
                ifFrame.Result = (expr.PerformBinaryOperation(Token.Equals, new Value(0)).Double == 1);     //not not the actual result, it just checks if the condition failed so it can skip that section. Kinda misleading if you didn't know - just refer to the assertion token's case.
                CallStack.Push(ifFrame);

                readTillCallFrameStart();     //read till open bracket

                if (ifFrame.Result == true)   //skip till close bracket.
                {
                    SkipCallFrame();
                    prevCallFrame = CallStack.Pop();
                }

                break;

            case Token.Else:     //not if results are inverted
                if (prevCallFrame.GetType() != typeof(IfElifFrame))
                {
                    throw new UnexpectedStatementException(keyword.ToString());
                }
                prevElifFrame = (IfElifFrame)prevCallFrame;
                if (prevElifFrame.Result == true)     //skip all the crap
                {
                    CallStack.Push(new ElseFrame());
                    readTillCallFrameStart();
                }
                else if (prevElifFrame.Result == false)
                {
                    CallStack.Push(new ElseFrame());
                    readTillCallFrameStart();
                    SkipCallFrame();
                    prevCallFrame = CallStack.Pop();
                }
                break;

            case Token.Elif:
                if (prevCallFrame.GetType() != typeof(IfElifFrame))
                {
                    throw new UnexpectedStatementException(keyword.ToString());
                }
                IfElifFrame elifFrame = new IfElifFrame();
                prevElifFrame = (IfElifFrame)prevCallFrame;
                if (prevElifFrame.Result == true)
                {
                    expr = EvaluateNextExpression();
                    if (expr == null)
                    {
                        return;
                    }
                    elifFrame.Result = (expr.PerformBinaryOperation(Token.Equals, new Value(0)).Double == 1);
                    CallStack.Push(elifFrame);
                    readTillCallFrameStart();
                    if (elifFrame.Result == true)
                    {
                        SkipCallFrame();
                        prevCallFrame = CallStack.Pop();
                    }
                }
                else
                {
                    CallStack.Push(elifFrame);
                    readTillCallFrameStart();
                    SkipCallFrame();
                    prevCallFrame = CallStack.Pop();
                }
                break;

            case Token.While:
                WhileFrame whileFrame = new WhileFrame();
                whileFrame.ExpressionMarker = (Marker)expressionMarker.Clone();
                expr = EvaluateNextExpression();
                if (expr == null)
                {
                    return;
                }
                CallStack.Push(whileFrame);
                readTillCallFrameStart();
                if (expr.PerformBinaryOperation(Token.Equals, new Value(0)).Double == 1)
                {
                    SkipCallFrame();
                    prevCallFrame = CallStack.Pop();
                }
                break;

            case Token.For:
                ForFrame forFrame = new ForFrame();
                MatchToken(Token.Identifier);
                forFrame.IndexerIdentifier = lexer.TokenIdentifier;
                ReadNextToken();
                MatchToken(Token.In);
                ReadNextToken();
                expr = EvaluateNextExpression();
                if (expr == null)
                {
                    return;
                }
                if (expr.Type == ValueType.Array)
                {
                    forFrame.Values = expr.Array;
                }
                else if (expr.Type == ValueType.String)
                {
                    forFrame.Values = new List <Value>();
                    for (int k = 0; k < expr.String.Length; k++)
                    {
                        forFrame.Values.Add(new Value(expr.String[k]));
                    }
                }
                else
                {
                    throw new Exception("Fastcode can only iterate through an array or string.");
                }
                forFrame.currentIndex = 0;
                functionFrame         = GetCurrentContext();
                if (forFrame.Values.Count > 0)
                {
                    if (functionFrame.LocalVariables.ContainsKey(forFrame.IndexerIdentifier))
                    {
                        functionFrame.LocalVariables[forFrame.IndexerIdentifier] = forFrame.Values[0];
                    }
                    else
                    {
                        functionFrame.LocalVariables.Add(forFrame.IndexerIdentifier, forFrame.Values[0]);
                    }
                }

                CallStack.Push(forFrame);
                readTillCallFrameStart();
                if (forFrame.currentIndex >= forFrame.Values.Count)
                {
                    SkipCallFrame();
                    prevCallFrame = CallStack.Pop();
                }
                break;

            case Token.Function:
                MatchToken(Token.Identifier);
                string fid = lexer.TokenIdentifier;
                if (functions.ContainsKey(fid) || GlobalVariables.ContainsKey(fid) || builtInFunctions.ContainsKey(fid))
                {
                    throw new Exception("Identifiers must be unique");
                }
                functionFrame = new FunctionFrame(fid);
                ReadNextToken();
                MatchToken(Token.OpenParenthesis);
                List <string> argument_identifiers = new List <string>();
                while (lastToken != Token.CloseParenthesis)
                {
                    ReadNextToken();
                    if (lastToken == Token.Comma || lastToken == Token.CloseParenthesis)
                    {
                        continue;
                    }
                    else if (lastToken == Token.Identifier)
                    {
                        if (argument_identifiers.Contains(lexer.TokenIdentifier) || GlobalVariables.ContainsKey(lexer.TokenIdentifier))
                        {
                            throw new Exception("Argument identifiers must be unique.");
                        }
                        argument_identifiers.Add(lexer.TokenIdentifier);
                    }
                    else if (lastToken == Token.CloseParenthesis)
                    {
                        break;
                    }
                    else
                    {
                        throw new UnexpectedStatementException("an identifier", lastToken.ToString());
                    }
                }
                functionFrame.SetArgumentParameters(argument_identifiers);
                CallStack.Push(functionFrame);
                readTillCallFrameStart();
                functionFrame  = (FunctionFrame)CallStack.Pop();
                functions[fid] = functionFrame;
                SkipCallFrame();
                break;

            case Token.CloseBrace:     //checks to return or repeat.
                if (CallStack.Peek().GetType() == typeof(WhileFrame))
                {
                    Marker currentpos = (Marker)lexer.Position.Clone();
                    lexer.ShiftCurrentPosition(((WhileFrame)CallStack.Peek()).ExpressionMarker);
                    ReadNextToken();
                    expr = EvaluateNextExpression();
                    if (expr == null)
                    {
                        return;
                    }
                    if (expr.PerformBinaryOperation(Token.Equals, new Value(0)).Double == 1)
                    {
                        prevCallFrame = CallStack.Pop();
                        lexer.ShiftCurrentPosition(currentpos);
                    }
                    else
                    {
                        lexer.ShiftCurrentPosition(CallStack.Peek().StartPosition);
                        ReadNextToken();
                    }
                }
                else if (CallStack.Peek().GetType() == typeof(ForFrame))
                {
                    ForFrame forStructure2 = (ForFrame)CallStack.Pop();
                    forStructure2.currentIndex++;
                    functionFrame = GetCurrentContext();
                    if (forStructure2.currentIndex < forStructure2.Values.Count)
                    {
                        functionFrame.LocalVariables[forStructure2.IndexerIdentifier] = forStructure2.Values[forStructure2.currentIndex];
                        CallStack.Push(forStructure2);
                        lexer.ShiftCurrentPosition(CallStack.Peek().StartPosition);
                        ReadNextToken();
                    }
                    else
                    {
                        functionFrame.LocalVariables.Remove(forStructure2.IndexerIdentifier);
                    }
                }
                else if (CallStack.Peek().GetType() == typeof(FunctionFrame))
                {
                    functionFrame = (FunctionFrame)CallStack.Pop();
                    lexer.ShiftCurrentPosition(functionFrame.ReturnPosition);
                    GetCurrentContext().functionResults.Enqueue(functionFrame.ReturnResult);
                }
                else
                {
                    prevCallFrame = CallStack.Pop();
                }

                break;

            default:
                throw new UnexpectedStatementException(keyword.ToString());
            }
            if (lastToken == Token.Semicolon)
            {
                keywordMarker = (Marker)lexer.Position.Clone();
                ReadNextToken();
                while (lastToken == Token.Newline)
                {
                    ReadNextToken();
                }
                ExecuteNextStatement();
            }
        }