Пример #1
0
        private IntepreterInstruction[] CompileToInstructions(string source)
        {
            var instructions     = new List <IntepreterInstruction>();
            var beginLoopIndeces = new Stack <int>();

            var pointerPosition = 0;
            var knownPosition   = true;

            for (int i = 0; i < source.Length; i++)
            {
                var c        = source[i];
                var lastType = instructions.Count == 0 ? InterpreterInstructionType.Invalid : instructions.Peek().Type;
                var nextInsn = IntepreterInstruction.Invalid;

                switch (c)
                {
                case '+':
                case '-':
                case '<':
                case '>':
                    HandlePointerAndValues(instructions, ref pointerPosition, knownPosition, i, c, lastType, ref nextInsn);
                    break;

                case '[':
                    HandleBeginLoop(source, ref knownPosition, ref i, lastType, ref nextInsn);
                    break;

                case ']':
                    nextInsn = HandleEndLoop(instructions, i);
                    break;

                case '.':
                    nextInsn = new IntepreterInstruction(InterpreterInstructionType.Print, 0, i);
                    break;

                case ',':
                    nextInsn = new IntepreterInstruction(InterpreterInstructionType.Read, 0, i);
                    break;

                default:
                    if (c == this.BreakpointChar)
                    {
                        nextInsn = new IntepreterInstruction(InterpreterInstructionType.Breakpoint, 0, i);
                    }

                    break;
                }

                if (nextInsn.Type != InterpreterInstructionType.Invalid)
                {
                    instructions.Add(nextInsn);
                }
            }

            return(instructions.ToArray());
        }
Пример #2
0
        private static void HandleBeginLoop(string source, ref bool knownPosition, ref int i, InterpreterInstructionType lastType, ref IntepreterInstruction nextInsn)
        {
            // skip loop, after loop
            if (lastType == InterpreterInstructionType.EndLoop)
            {
                i = ScannLoop(source, i, true);
            }
            else
            {
                // check if pointer movements in loops are balanced, so we can know the absolute position of the pointer
                if (knownPosition && !BalancedPointerInLoop(source, i))
                {
                    knownPosition = false;
                }

                nextInsn = new IntepreterInstruction(InterpreterInstructionType.BeginLoop, 0, i);
            }
        }
Пример #3
0
        private static IntepreterInstruction HandleEndLoop(List <IntepreterInstruction> instructions, int i)
        {
            IntepreterInstruction nextInsn;

            if (instructions.Count >= 2 &&
                instructions[instructions.Count - 1].Type == InterpreterInstructionType.AddValue &&
                (instructions[instructions.Count - 1].Value & 1) == 0 &&
                instructions[instructions.Count - 2].Type == InterpreterInstructionType.BeginLoop)
            {
                var len = 1 + instructions.Pop().SourceLength + instructions.Pop().SourceLength;
                nextInsn = new IntepreterInstruction(InterpreterInstructionType.SetValue, 0, i + 1 - len);
                nextInsn.SourceLength = len;
            }
            else
            {
                nextInsn = new IntepreterInstruction(InterpreterInstructionType.EndLoop, 0, i);
            }

            return(nextInsn);
        }
Пример #4
0
        private static void HandlePointerAndValues(List <IntepreterInstruction> instructions, ref int pointerPosition, bool knownPosition, int i, char c, InterpreterInstructionType lastType, ref IntepreterInstruction nextInsn)
        {
            var movePointer = c == '<' || c == '>';
            var changeValue = c == '+' || c == '-';

            if (movePointer || changeValue)
            {
                var step = c == '-' || c == '<' ? -1 : +1;
                if (movePointer)
                {
                    pointerPosition += step;
                }

                if ((movePointer && (lastType == InterpreterInstructionType.SetPointer || lastType == InterpreterInstructionType.MovePointer)) ||
                    (changeValue && (lastType == InterpreterInstructionType.SetValue || lastType == InterpreterInstructionType.AddValue)))
                {
                    nextInsn        = instructions.Pop();
                    nextInsn.Value += step;
                    nextInsn.SourceLength++;
                }
                else if (movePointer)
                {
                    if (knownPosition)
                    {
                        nextInsn = new IntepreterInstruction(InterpreterInstructionType.SetPointer, pointerPosition, i);
                    }
                    else
                    {
                        nextInsn = new IntepreterInstruction(InterpreterInstructionType.MovePointer, pointerPosition, i);
                    }
                }
                else
                {
                    // if (changeValue)
                    nextInsn = new IntepreterInstruction(InterpreterInstructionType.AddValue, step, i);
                }
            }
        }