Beispiel #1
0
        public ExitFlag Interpret(bool debug = false)
        {
            List <Token> tokens = Tokenize();

            if (debug)
            {
                PrintTokens(tokens);
            }

            globalScope = new GlobalScope();

            ExitFlag f;

            try
            {
                f = Execute(tokens, globalScope, debug, true);
            }
            catch (FatalErrorException e)
            {
                Functions.WriteLineColor(e.Message, ConsoleColor.Red);
                Functions.WriteLineColor(e.StackTrace, ConsoleColor.DarkYellow);
                f = ExitFlag.FatalError;
            }
            return(f);
        }
        public void Should_return_entire_bound_scope_name_as_path_to_root_scope()
        {
            var fakeNode  = A.Fake <INode <AstNode> >();
            var fakeScope = A.Fake <INamedScope <SymbolNode> >();

            A.CallTo(() => fakeScope.Name).Returns("FakeScope");

            var globalScope = new GlobalScope <SymbolNode>();

            A.CallTo(() => fakeScope.OuterScope).Returns(globalScope);

            var boundScope = new BoundScope <SymbolNode>(fakeScope, fakeNode);

            boundScope.Name.ShouldBe("global/FakeScope");
        }
        public override BoundNode VisitScope(BoundScope node)
        {
            Debug.Assert(!node.Locals.IsEmpty);
            var newLocals = ArrayBuilder <LocalSymbol> .GetInstance();

            var hoistedLocalsWithDebugScopes = ArrayBuilder <StateMachineFieldSymbol> .GetInstance();

            foreach (var local in node.Locals)
            {
                Debug.Assert(local.SynthesizedKind == SynthesizedLocalKind.UserDefined &&
                             local.ScopeDesignatorOpt?.Kind() == SyntaxKind.SwitchSection);

                if (!NeedsProxy(local))
                {
                    newLocals.Add(local);
                    continue;
                }

                hoistedLocalsWithDebugScopes.Add(((CapturedToStateMachineFieldReplacement)proxies[local]).HoistedField);
            }

            var statements = VisitList(node.Statements);

            // wrap the node in an iterator scope for debugging
            if (hoistedLocalsWithDebugScopes.Count != 0)
            {
                BoundStatement translated;

                if (newLocals.Count == 0)
                {
                    newLocals.Free();
                    translated = new BoundStatementList(node.Syntax, statements);
                }
                else
                {
                    translated = node.Update(newLocals.ToImmutableAndFree(), statements);
                }

                return(MakeStateMachineScope(hoistedLocalsWithDebugScopes.ToImmutable(), translated));
            }
            else
            {
                hoistedLocalsWithDebugScopes.Free();
                newLocals.Free();
                return(node.Update(node.Locals, statements));
            }
        }
Beispiel #4
0
        public override BoundNode VisitScope(BoundScope node)
        {
            Debug.Assert(!node.Locals.IsEmpty);
            var newLocalsBuilder = ArrayBuilder <LocalSymbol> .GetInstance();

            var hoistedLocalsWithDebugScopes = ArrayBuilder <StateMachineFieldSymbol> .GetInstance();

            bool localsRewritten = false;

            foreach (var local in node.Locals)
            {
                // BoundScope is only used for switch
                Debug.Assert(local.SynthesizedKind == SynthesizedLocalKind.UserDefined &&
                             (local.ScopeDesignatorOpt?.Kind() == SyntaxKind.SwitchSection ||
                              local.ScopeDesignatorOpt?.Kind() == SyntaxKind.SwitchExpressionArm));

                LocalSymbol localToUse;
                if (TryRewriteLocal(local, out localToUse))
                {
                    newLocalsBuilder.Add(localToUse);
                    localsRewritten |= ((object)local != localToUse);
                    continue;
                }

                hoistedLocalsWithDebugScopes.Add(((CapturedToStateMachineFieldReplacement)proxies[local]).HoistedField);
            }

            var statements = VisitList(node.Statements);

            // wrap the node in an iterator scope for debugging
            if (hoistedLocalsWithDebugScopes.Count != 0)
            {
                BoundStatement translated;

                if (newLocalsBuilder.Count == 0)
                {
                    newLocalsBuilder.Free();
                    translated = new BoundStatementList(node.Syntax, statements);
                }
                else
                {
                    translated = node.Update(newLocalsBuilder.ToImmutableAndFree(), statements);
                }

                return(MakeStateMachineScope(hoistedLocalsWithDebugScopes.ToImmutable(), translated));
            }
            else
            {
                hoistedLocalsWithDebugScopes.Free();
                ImmutableArray <LocalSymbol> newLocals;

                if (localsRewritten)
                {
                    newLocals = newLocalsBuilder.ToImmutableAndFree();
                }
                else
                {
                    newLocalsBuilder.Free();
                    newLocals = node.Locals;
                }

                return(node.Update(newLocals, statements));
            }
        }
Beispiel #5
0
        protected virtual void ProcessAdd(IList newItems, int newStartingIndex)
        {
            var niCopy = (from a in newItems.Cast <Object>() select a).ToList();

            foreach (T ni in niCopy)
            {
                _contains[ni] = true;
            }

            if (!EnableIntegration)
            {
                return;
            }

            if (BoundScope != null)
            {
                // First, we inspect to see if we have a wrapped object or not - if not, we try to do so and REPLACE the current item
                if (!BoundScope.Settings.EntitySetUsesUnwrapped)
                {
                    var idx2 = 0;
                    foreach (var ni in niCopy.ToArray())
                    {
                        if (ni != null)
                        {
                            if (BoundScope.InternalCreateAddBase(ni, true, null, null, null, new Dictionary <object, object>(Globals.DefaultDictionaryCapacity), true, false) is ICEFWrapper w)
                            {
                                var cast = w as T;

                                if (ni != cast)
                                {
                                    try
                                    {
                                        this.SuspendNotifications(true);

                                        using (new WriterLock(_lock))
                                        {
                                            this.Replace(ni as T, cast);

                                            _contains.Add(cast, true);
                                            _contains.Remove(newItems[idx2] as T);
                                        }
                                    }
                                    finally
                                    {
                                        this.SuspendNotifications(false);
                                    }
                                }

                                niCopy[idx2] = cast;
                            }
                        }

                        idx2++;
                    }
                }
            }

            if (ParentContainer != null && EnableLinking)
            {
                foreach (var ni in niCopy)
                {
                    if (ni != null)
                    {
                        // Attempt to establish a FK relationship, carry parent key down
                        CEF.CurrentKeyService()?.LinkChildInParentContainer(BoundScope, ParentTypeName, ParentFieldName, ParentContainer, ni);
                    }
                }
            }
        }
Beispiel #6
0
 public override abstract BoundNode VisitScope(BoundScope node);
Beispiel #7
0
 public abstract override BoundNode VisitScope(BoundScope node);
Beispiel #8
0
        private DataType EvaluateExpression(List <Token> expression, BoundScope localScope, out object result)
        {
            if (expression == null)
            {
                result = 0;
                return(DataType.Undefined);
            }

            if (expression.Count > 2)
            {
                // Strip away wrapping separators
                while (expression.Count(e => e.Type == TokenType.Parenthesis) >= 2 &&
                       expression[0].Type == TokenType.Parenthesis && (char)expression[0].Value == '(' &&
                       expression[expression.Count - 1].Type == TokenType.Parenthesis && (char)expression[expression.Count - 1].Value == ')')
                {
                    // If the expression is wrapped with two parentathes, remove them (it's the same thing). This will otherwise cause a weird bug
                    expression.RemoveAt(0);
                    expression.RemoveAt(expression.Count - 1);
                }

                // Replace any text-code with mathematical symbols
                for (int i = 0; i < expression.Count; i++)
                {
                    switch (expression[i].Type)
                    {
                    case TokenType.Is:
                        if (i + 1 < expression.Count && expression[i + 1].Type == TokenType.Equal)
                        {
                            expression.RemoveAt(i);
                            i--;
                        }
                        break;
                    }
                }
            }
            else if (expression.Count == 2)
            {
                if (expression[0].Type == TokenType.Operator && (char)expression[0].Value == '-' &&
                    expression[1].Type == TokenType.Expression && expression[1].ValueType == typeof(double))
                {
                    result = (double)expression[1].Value * -1;
                    return(DataType.Number);
                }
            }
            if (expression.Count == 1)
            {
                Token e = expression[0];
                // Check for literals and therefore variables and functions
                if (e.Type == TokenType.Literal)
                {
                    if (localScope.TryLookup(e.Name, out Variable v))
                    {
                        result = v.Value;
                        return(v.Type);
                    }
                    else
                    {
                        Error.Undefined(e, "variable");
                        result = 0;
                        return(DataType.Undefined);
                    }
                }
                else if (e.Type == TokenType.String)
                {
                    result = e.Value;
                    return(DataType.String);
                }
                else
                {
                    result = e.Value;
                }

                switch (e.Value)
                {
                case string v: return(DataType.String);

                case int v1:
                case long v2:
                case float v3:
                case double v4: return(DataType.Number);

                case bool v: return(DataType.Boolean);

                default: return(DataType.Undefined);
                }
            }

            result = 0;
            List <Token> newExpression;
            Token        expressionValue = Token.Empty;

            for (int i = 0; i < orderOfOperations.Length; i++)
            {
                if (expression.Count == 1)
                {
                    break;
                }
                string operation = orderOfOperations[i];
                for (int j = 0; j < expression.Count; j++)
                {
                    Token t = expression[j];
                    if ((t.Type == TokenType.Expression ||
                         t.Type == TokenType.Operator ||
                         t.Type == TokenType.Equal ||
                         t.Type == TokenType.Or ||
                         t.Type == TokenType.And) && t.Value.ToString().Equals(operation))
                    {
                        if (!(j > 0 && j < expression.Count))
                        {
                            Error.UnexpectedToken(t, "expressions on both sides of the operator");
                            return(DataType.Undefined);
                        }

                        int k = 1;
                        int expressionStart  = -1;
                        int expressionEnd    = -1;
                        int parenthisesDepth = 0;

                        // Get LHS
                        List <Token> LHS    = new List <Token>();
                        Token        temp_t = Token.Empty;
                        while (j - k >= 0 && (temp_t.Type == TokenType.Expression || temp_t.Type == TokenType.Operator || temp_t.Type == TokenType.Parenthesis || temp_t.Type == TokenType.Undefined))
                        {
                            temp_t = expression[j - k];
                            if (isOperator(temp_t.Value.ToString()) && parenthisesDepth == 0)
                            {
                                k--; break;
                            }
                            else if (temp_t.Type == TokenType.Parenthesis && (char)temp_t.Value == '(')
                            {
                                parenthisesDepth++;
                                if (parenthisesDepth == 0)
                                {
                                    k++; continue;
                                }                                             // Do not add token
                            }
                            else if (temp_t.Type == TokenType.Parenthesis && (char)temp_t.Value == ')')
                            {
                                parenthisesDepth--;
                                if (parenthisesDepth == 0 - 1)
                                {
                                    k++; continue;
                                }                                                 // Do not add token
                            }
                            LHS.Insert(0, temp_t);
                            k++;
                        }
                        expressionStart = (j - k < 0) ? 0 : j - k;

                        // Get RHS
                        k = 1;
                        parenthisesDepth = 0;
                        List <Token> RHS = new List <Token>();
                        temp_t = Token.Empty;
                        while (j + k < expression.Count && (temp_t.Type == TokenType.Expression || temp_t.Type == TokenType.Operator || temp_t.Type == TokenType.Parenthesis || temp_t.Type == TokenType.Literal || temp_t.Type == TokenType.Undefined))
                        {
                            temp_t = expression[j + k];
                            if (isOperator(temp_t.Value.ToString()) && parenthisesDepth == 0)
                            {
                                k--; break;
                            }
                            else if (temp_t.Type == TokenType.Parenthesis && (char)temp_t.Value == '(')
                            {
                                parenthisesDepth++;
                            }
                            else if (temp_t.Type == TokenType.Parenthesis && (char)temp_t.Value == ')')
                            {
                                parenthisesDepth--;
                            }
                            RHS.Add(temp_t);
                            k++;
                        }
                        expressionEnd = j + k;

                        object   LHS_Value;
                        DataType LHS_TYPE = EvaluateExpression(LHS, localScope, out LHS_Value);

                        object   RHS_Value;
                        DataType RHS_TYPE = EvaluateExpression(RHS, localScope, out RHS_Value);

                        bool insureType(DataType value, DataType expected, string side, bool throwError)
                        {
                            if (value != expected)
                            {
                                if (throwError)
                                {
                                    Error.WrongType(t, $"the {side} side of the operation sign was not evaluated to a {expected}");
                                }
                                return(false);
                            }
                            return(true);
                        }

                        bool insureTypes(DataType left, DataType right) => insureType(LHS_TYPE, left, "left", true) && insureType(RHS_TYPE, right, "right", true);
                        bool testTypes(DataType left, DataType right) => insureType(LHS_TYPE, left, "left", false) && insureType(RHS_TYPE, right, "right", false);

                        switch (operation)
                        {
                        // Aritmetic expressions
                        case "/":
                            if (insureTypes(DataType.Number, DataType.Number))
                            {
                                expressionValue = new Token("EXPR_DIV", TokenType.Expression, (double)LHS_Value / (double)RHS_Value, typeof(double), t.Line, t.Column);
                            }
                            else
                            {
                                return(DataType.Undefined);
                            }
                            break;

                        case "*":
                            if (insureTypes(DataType.Number, DataType.Number))
                            {
                                expressionValue = new Token("EXPR_MUL", TokenType.Expression, (double)LHS_Value * (double)RHS_Value, typeof(double), t.Line, t.Column);
                            }
                            else
                            {
                                return(DataType.Undefined);
                            }
                            break;

                        case "+":
                            if (testTypes(DataType.Number, DataType.Number))
                            {
                                expressionValue = new Token("EXPR_ADD_NUM", TokenType.Expression, (double)LHS_Value + (double)RHS_Value, typeof(double), t.Line, t.Column);
                            }
                            else
                            {
                                expressionValue = new Token("EXPR_ADD_STR", TokenType.Expression, LHS_Value.ToString() + RHS_Value.ToString(), typeof(string), t.Line, t.Column);
                            }
                            break;

                        case "-":
                            if (insureTypes(DataType.Number, DataType.Number))
                            {
                                expressionValue = new Token("EXPR_SUB", TokenType.Expression, (double)LHS_Value - (double)RHS_Value, typeof(double), t.Line, t.Column);
                            }
                            else
                            {
                                return(DataType.Undefined);
                            }
                            break;

                        case "^":
                            if (insureTypes(DataType.Number, DataType.Number))
                            {
                                expressionValue = new Token("EXPR_POW", TokenType.Expression, Math.Pow((double)LHS_Value, (double)RHS_Value), typeof(double), t.Line, t.Column);
                            }
                            else
                            {
                                return(DataType.Undefined);
                            }
                            break;

                        case "&":
                            if (insureTypes(DataType.Number, DataType.Number))
                            {
                                expressionValue = new Token("EXPR_BIT_AND", TokenType.Expression, (long)LHS_Value & (long)RHS_Value, typeof(long), t.Line, t.Column);
                            }
                            else
                            {
                                return(DataType.Undefined);
                            }
                            break;

                        // Boolean expressions
                        case "=":
                            expressionValue = new Token("EXPR_EQ", TokenType.Boolean, LHS_Value.Equals(RHS_Value), typeof(bool), t.Line, t.Column);
                            break;

                        case "==":
                            expressionValue = new Token("EXPR_STRICT_EQ", TokenType.Boolean, insureType(RHS_TYPE, LHS_TYPE, "right", false) && LHS_Value.Equals(RHS_Value), typeof(bool), t.Line, t.Column);
                            break;

                        case "&&":
                            if (insureTypes(DataType.Boolean, DataType.Boolean))
                            {
                                expressionValue = new Token("EXPR_LOGIC_AND", TokenType.Expression, (bool)LHS_Value && (bool)RHS_Value, typeof(long), t.Line, t.Column);
                            }
                            else
                            {
                                return(DataType.Undefined);
                            }
                            break;

                        case "||":
                            if (insureTypes(DataType.Boolean, DataType.Boolean))
                            {
                                expressionValue = new Token("EXPR_LOGIC_OR", TokenType.Expression, (bool)LHS_Value || (bool)RHS_Value, typeof(long), t.Line, t.Column);
                            }
                            else
                            {
                                return(DataType.Undefined);
                            }
                            break;

                        default:
                            Error.UnexpectedToken(new Token(operation, TokenType.Expression, t.Value, t.ValueType, t.Line, t.Column), "valid operation");
                            return(DataType.Undefined);
                        }

                        newExpression = new List <Token>();
                        for (int l = 0; l < expression.Count; l++)
                        {
                            if (l == expressionStart)
                            {
                                newExpression.Add(expressionValue);
                            }
                            else if (l > expressionStart && l <= expressionEnd)
                            {
                                continue;
                            }
                            else
                            {
                                newExpression.Add(expression[l]);
                            }
                        }
                        expression = newExpression;
                    }
                }
            }

            // Eval multiplication and division
            result = expressionValue.Value;
            switch (expressionValue.Value)
            {
            case string v: return(DataType.String);

            case int v1:
            case long v2:
            case float v3:
            case double v4: return(DataType.Number);

            case bool v: return(DataType.Boolean);

            default: return(DataType.Undefined);
            }
        }
Beispiel #9
0
        private ExitFlag Execute(List <Token> tokens, BoundScope parentScope, bool debug, bool title)
        {
            BoundScope localScope = new BoundScope(parentScope);

            #region Local Functions
            int i = 0;
            Token nextToken(bool ignoreWhitespace = true)
            {
                if (i < tokens.Count)
                {
                    Token t = tokens[i++];
                    if (t.Type == TokenType.Comment ||
                        (ignoreWhitespace && t.Type == TokenType.WhiteSpace))
                    {
                        return(nextToken(ignoreWhitespace));
                    }
                    else
                    {
                        return(t);
                    }
                }
                return(null);
            }

            Token peekToken(int j = 0) // j is the offset
            {
                if (i < tokens.Count)
                {
                    Token t = tokens[i + j];
                    if (t.Type == TokenType.Comment)
                    {
                        return(peekToken(++j));
                    }
                    else
                    {
                        return(t);
                    }
                }
                return(null);
            }

            List <Token> getExpression()
            {
                List <Token> expressions = new List <Token>();
                Token        t           = nextToken();

                while (t != null && (t.Type == TokenType.Expression || t.Type == TokenType.Operator || t.Type == TokenType.Boolean || t.Type == TokenType.Literal || t.Type == TokenType.String || t.Type == TokenType.Parenthesis))
                {
                    expressions.Add(t);
                    t = nextToken();
                }
                i--;
                if (expressions.Count == 0)
                {
                    Error.UnexpectedToken(tokens[i], "Expression"); return(null);
                }
                return(expressions);
            }

            List <Token> getStatement()
            {
                List <Token> statement = new List <Token>();
                Token        t         = nextToken();

                while (t.Type == TokenType.Expression || t.Type == TokenType.Operator || t.Type == TokenType.Boolean || t.Type == TokenType.Literal || t.Type == TokenType.String || t.Type == TokenType.Parenthesis || t.Type == TokenType.Separator || t.Type == TokenType.Is || t.Type == TokenType.And || t.Type == TokenType.Or || t.Type == TokenType.Equal)
                {
                    statement.Add(t);
                    t = nextToken();
                }
                i--;
                if (statement.Count == 0)
                {
                    Error.UnexpectedToken(tokens[i], "påstående"); return(null);
                }
                return(statement);
            }

            Branch getBranch()
            {
                List <Token> block = new List <Token>();
                int          scope = 0;
                Token        t     = nextToken();

                if (t.Type != TokenType.Then)
                {
                    Error.UnexpectedToken(tokens[i], "start of code block"); return(null);
                }
                t = nextToken(); // Börja med nästa token innanför kodblocket
                while (t != null)
                {
                    if (t.Type == TokenType.Done && scope == 0)
                    {
                        break;
                    }
                    else if (t.Type == TokenType.Then)
                    {
                        scope++;
                    }
                    else if (t.Type == TokenType.Done)
                    {
                        scope--;
                    }

                    if (t.Type != TokenType.WhiteSpace && (t.Type != TokenType.NewLine || (t.Type == TokenType.NewLine && block.Count > 0)))
                    {
                        block.Add(t);
                    }
                    t = nextToken();
                }
                if (block.Count == 0)
                {
                    Error.UnexpectedToken(tokens[i], "Non-empty code block"); return(null);
                }
                if (new[] { TokenType.WhiteSpace, TokenType.NewLine }.Contains(block.Last().Type))
                {
                    block.RemoveAt(block.Count - 1);
                }
                return(new Branch(block));
            }

            #endregion

            if (debug)
            {
                Console.WriteLine();
                if (title)
                {
                    Functions.WriteTitle(ConsoleColor.Green, ConsoleColor.DarkGreen, "Execution Debugging");
                    Functions.WriteTableTitles(ConsoleColor.Green, ConsoleColor.DarkGreen, "Row:Col", "Action");
                }
            }

            Token    ct       = Token.Empty;
            object   result   = null;
            DataType dataType = DataType.Undefined;
            while (ct != null)
            {
                ct = nextToken();
                if (ct == null)
                {
                    break;
                }
                else if (new[] { TokenType.WhiteSpace, TokenType.NewLine, TokenType.And }.Contains(ct.Type))
                {
                    continue;                                                                                          // Should and be skipped?
                }
                else if (ct.Type == TokenType.Literal)
                {
                    // functionName param1 param2 =
                    //      ...
                    // # or
                    // variable = ...

                    // variable == variable()

                    Token literal = ct;

                    List <Token> rawParameters = new List <Token>();
                    Token        nxt           = nextToken();
                    if (nxt != null)
                    {
                        while (!new[] { TokenType.Equal, TokenType.And, TokenType.NewLine }.Contains(nxt.Type))
                        {
                            rawParameters.Add(nxt);
                            nxt = nextToken();
                            if (nxt == null)
                            {
                                nxt = new Token("Newline", TokenType.NewLine, null, null, literal.Line, literal.Column);
                            }
                        }
                    }
                    switch (nxt.Type)
                    {
                    case TokenType.And:
                    case TokenType.NewLine:
                        // Function call: literal(...parameters)
                        List <Token> statement = getStatement();

                        if (localScope.TryInvoke(literal, rawParameters, (Function f) =>
                        {
                            if (debug)
                            {
                                Functions.WriteMessage(literal.Line, literal.Column, "Invokation", "Calling Function " + f);
                            }
                            Execute(f.Block, localScope, debug, false);
                        }, debug) && debug)
                        {
                            Functions.WriteMessage(literal.Line, literal.Column, "Invokation", "Function was successfully invoked!");
                        }
                        else
                        {
                            if (debug)
                            {
                                Error.Undefined(literal, $"could not find function ");
                            }
                            return(ExitFlag.FatalError);
                        }
                        break;

                    case TokenType.Equal:
                        // nxt is an equal sign.
                        if (rawParameters.Count > 0)
                        {
                            // Function declaration
                        }
                        else
                        {
                            // A parameterless function or variable initialization. Variables can be invoked as parameterless functions to return its value, but this is unrecommended and is assumed by the compiler.
                            List <Token> expression = getExpression();
                            dataType = EvaluateExpression(expression, localScope, out result);
                            if (dataType != DataType.Undefined)
                            {
                                Variable v = new Variable(literal.Name, result, dataType);
                                if (parentScope.TryDeclare(v))
                                {
                                    if (debug)
                                    {
                                        Functions.WriteLineVariableMessage(ct.Line, ct.Column, "Variable Initialization", v, ConsoleColor.Cyan, ConsoleColor.Yellow);
                                    }
                                }
                                else
                                {
                                    if (parentScope.TryReassign(v))
                                    {
                                        if (debug)
                                        {
                                            Functions.WriteLineVariableMessage(ct.Line, ct.Column, "Variable Re-assignment", v, ConsoleColor.Cyan, ConsoleColor.Yellow);
                                        }
                                    }
                                    else
                                    {
                                        Error.FailedToDeclare(literal);
                                        return(ExitFlag.SyntaxError);
                                    }
                                }
                            }
                            else
                            {
                                Error.UnexpectedToken(literal, "definable value");
                                return(ExitFlag.SyntaxError);
                            }
                        }
                        break;
                    }
                }
                else if (ct.Type == TokenType.If)
                {
                    List <Token> statement = getStatement();
                    Branch       branch    = getBranch();
                    dataType = EvaluateExpression(statement, localScope, out result);

                    if (dataType != DataType.Undefined)
                    {
                        if ((dataType == DataType.Number && (double)result != 0) ||
                            (dataType == DataType.String) ||
                            (dataType == DataType.Boolean && (bool)result))
                        {
                            if (debug)
                            {
                                Functions.WriteMessage(ct.Line, ct.Column, "Branching", $"Entering {branch}. '" + Functions.TokenListToString(statement) + "' was true.", ConsoleColor.Yellow);
                            }
                            Execute(branch.Block, localScope, debug, false);
                        }
                        else if (debug)
                        {
                            Functions.WriteMessage(ct.Line, ct.Column, "Branching", $"Skipping {branch}. '" + Functions.TokenListToString(statement) + "' was false.", ConsoleColor.Yellow);
                        }
                    }
                    else
                    {
                        Error.WithExpected("Invalid statement: " + Functions.TokenListToString(statement), "calculable truth value");
                        return(ExitFlag.SyntaxError);
                    }
                }
                else
                {
                    Error.UnexpectedToken(ct, "instruction with context");
                    return(ExitFlag.SyntaxError);
                }
            }
            return(ExitFlag.Successfull);
        }