Exemplo n.º 1
0
        string DoGoto(RandomAccessIterator <SourceLine> lines)
        {
            var line = lines.Current;

            if (line.Operands.Count == 0)
            {
                throw new SyntaxException(line.Instruction.Position,
                                          "Destination not specified for \".goto\" directive.");
            }

            var gotoExp = line.Operands[0].Name;

            if ((!char.IsLetter(gotoExp[0]) && gotoExp[0] != '_') || line.Operands.Count > 1)
            {
                Services.Log.LogEntry(line.Operands[0],
                                      "\".goto\" operand must be a label.");
            }
            else if (line.Label != null && gotoExp.Equals(line.Label.Name, Services.StringViewComparer))
            {
                Services.Log.LogEntry(line.Instruction,
                                      "Destination cannot be the same line as \".goto\" directive.");
            }
            else
            {
                var        iterCopy = new RandomAccessIterator <SourceLine>(lines, true);
                SourceLine currLine;
                if ((currLine = iterCopy.FirstOrDefault(l =>
                {
                    if (l.Instruction != null && _openClosures.ContainsKey(l.Instruction.Name))
                    {
                        if (l.Instruction.Name.Equals(".function", Services.StringComparison))
                        {
                            throw new SyntaxException(l.Instruction, "Function block cannot be inside another block.");
                        }
                        // leap over any blocks we find along the way we are not currently in.
                        if (!_blocks.Any(b => b.Index == iterCopy.Index))
                        {
                            GetProcessor(l, iterCopy.Index).SeekBlockEnd(iterCopy);
                        }
                        return(false);
                    }
                    return(l.Label != null && l.Label.Name.Equals(gotoExp, Services.StringViewComparer));
                })) != null)
                {
                    if (currLine.Instruction != null &&
                        (currLine.Instruction.Name.Contains('=') ||
                         currLine.Instruction.Name.Equals(".equ", Services.StringComparison) ||
                         currLine.Instruction.Name.Equals(".global", Services.StringComparison)
                        )
                        )
                    {
                        Services.Log.LogEntry(line.Instruction,
                                              $"\"{gotoExp}\" is not a valid destination.");
                    }
                    else
                    {
                        while (_currentBlock != null)
                        {
                            // if where we landed lies outside of the current block scope
                            // we need to pop out of that scope.
                            _currentBlock.SeekBlockEnd(lines);
                            if (iterCopy.Index > _currentBlock.Index)
                            {
                                // did we land in a place still within the block scope?
                                if (iterCopy.Index > lines.Index)
                                {
                                    // no, pop out
                                    DoPop(lines);
                                }
                                else
                                {
                                    // we're still within the current block, don't pop it
                                    break;
                                }
                            }
                            else
                            {
                                // we went backwards, pop out of current scope
                                DoPop(lines);
                            }
                        }
                        if (iterCopy.Index >= lines.Index)
                        {
                            lines.FastForward(iterCopy.Index);
                        }
                        else if (iterCopy.Index == 0)
                        {
                            lines.Reset();
                        }
                        else
                        {
                            lines.Rewind(iterCopy.Index - 1);
                        }
                    }
                }
                else
                {
                    Services.Log.LogEntry(line.Instruction,
                                          $"Could not find destination \"{gotoExp}\".");
                }
            }
            return(string.Empty);
        }