/// <summary>
 /// Perform a full reset on the block.
 /// </summary>
 void FullReset()
 {
     _breakBlock = null;
     _processedLines.Clear();
     _currBlock = _rootBlock;
     _rootBlock.ResetEntries();
 }
 /// <summary>
 /// Add an entry to the block.
 /// </summary>
 /// <param name="line">The <see cref="T:DotNetAsm.SourceLine"/> of the entry</param>
 /// <param name="block">The <see cref="T:DotNetAsm.ForNextHandler.ForNextBlock"/> of the entry</param>
 public void AddEntry(SourceLine line, ForNextBlock block)
 {
     if (block != null)
     {
         block.Parent = this;
     }
     _entries.AddLast(new ForNextEntry(line, block));
 }
 /// <summary>
 /// Constructs a <see cref="T:DotNetAsm.RepetitionHandler.RepetitionBlock.RepetitionEntry"/>.
 /// </summary>
 /// <param name="line">The <see cref="T:DotNetAsm.SourceLine"/> to add. This value can
 /// be null.</param>
 /// <param name="block">The <see cref="T:DotNetAsm.RepetitionHandler.RepetitionBlock"/>
 /// to link to. This value can be null.</param>
 public ForNextEntry(SourceLine line, ForNextBlock block)
 {
     if (line != null)
     {
         Line = line.Clone() as SourceLine;
     }
     else
     {
         Line = null;
     }
     LinkedBlock = block;
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Constructs an instance of the <see cref="T:DotNetAsm.ForNextHandler"/>.
 /// </summary>
 public ForNextHandler()
 {
     Reserved.DefineType("Directives",
                         ".for", ".next", ".break",
                         "@@ for @@", "@@ next @@", "@@ break @@"
                         );
     _currBlock      =
         _rootBlock  = new ForNextBlock();
     _breakBlock     = null;
     _levels         = 0;
     _processedLines = new List <SourceLine>();
 }
        public void Process(SourceLine line)
        {
            var instruction = line.Instruction.ToLower();

            if (instruction.Equals(".for"))
            {
                if (string.IsNullOrEmpty(line.Operand))
                {
                    Controller.Log.LogEntry(line, ErrorStrings.TooFewArguments, line.Instruction);
                    return;
                }
                if (string.IsNullOrEmpty(line.Label) == false)
                {
                    // capture the label
                    _processedLines.Add(new SourceLine
                    {
                        Label        = line.Label,
                        SourceString = line.Label,
                        LineNumber   = line.LineNumber,
                        Filename     = line.Filename
                    });
                }
                // .for <init_expression>, <condition>, <iteration_expression>
                var csvs = line.Operand.CommaSeparate();
                if (csvs.Count < 2)
                {
                    Controller.Log.LogEntry(line, ErrorStrings.TooFewArguments, line.Instruction);
                    return;
                }

                if (_levels > 0)
                {
                    var block = new ForNextBlock();
                    _currBlock.AddEntry(null, block);
                    _currBlock = block;
                }
                else
                {
                    _currBlock = _rootBlock;
                }
                _levels++;
                _currBlock.Scope          = line.Scope;
                _currBlock.InitExpression = csvs.First();
                _currBlock.Condition      = csvs[1];

                if (_currBlock == _rootBlock)
                {
                    if (!string.IsNullOrEmpty(_currBlock.InitExpression))
                    {
                        var iteratorvar = Controller.Symbols.Variables.SetVariable(_currBlock.InitExpression, _currBlock.Scope);
                        if (string.IsNullOrEmpty(iteratorvar.Key))
                        {
                            Controller.Log.LogEntry(line, ErrorStrings.BadExpression, csvs.First());
                            return;
                        }
                        _processedLines.Add(new SourceLine
                        {
                            SourceString = ConstStrings.SHADOW_SOURCE,
                            Instruction  = ConstStrings.VAR_DIRECTIVE,
                            Operand      = string.Format("{0}={1}", iteratorvar.Key, iteratorvar.Value)
                        });
                    }
                }
                _currBlock.AddEntry(new SourceLine
                {
                    SourceString = ConstStrings.SHADOW_SOURCE,
                    Instruction  = "@@ for @@"
                }, null);

                if (csvs.Count >= 3)
                {
                    _currBlock.IterExpressions.Clear();
                    _currBlock.IterExpressions.AddRange(csvs.GetRange(2, csvs.Count - 2));
                }
            }
            else if (instruction.Equals(".next"))
            {
                if (_levels == 0)
                {
                    Controller.Log.LogEntry(line, ErrorStrings.ClosureDoesNotCloseBlock, line.Instruction);
                    return;
                }
                if (string.IsNullOrEmpty(line.Operand) == false)
                {
                    Controller.Log.LogEntry(line, ErrorStrings.TooManyArguments, line.Instruction);
                    return;
                }
                if (string.IsNullOrEmpty(line.Label) == false)
                {
                    Controller.Log.LogEntry(line, ErrorStrings.None);
                    return;
                }
                var loopLine = new SourceLine
                {
                    SourceString = ConstStrings.SHADOW_SOURCE,
                    Instruction  = "@@ next @@"
                };
                _currBlock.AddEntry(loopLine, null);
                _currBlock.Begin();
                _levels--;
                _currBlock = _currBlock.Parent;

                if (_levels == 0)
                {
                    _currBlock = _rootBlock;
                    _processedLines.AddRange(_rootBlock.GetProcessedLines());
                }
            }
            else if (instruction.Equals(".break"))
            {
                if (_levels == 0)
                {
                    Controller.Log.LogEntry(line, "Illegal use of .break");
                    return;
                }
                string procinst = "@@ break @@";
                var    shadow   = new SourceLine
                {
                    SourceString = ConstStrings.SHADOW_SOURCE,
                    Instruction  = procinst
                };
                _currBlock.AddEntry(shadow, null);
            }
            else if (instruction.Equals("@@ for @@"))
            {
                if (_currBlock.IsBeginning())
                {
                    if (_currBlock == _rootBlock)
                    {
                        _currBlock.Begin();
                    }
                    _currBlock.Advance();
                }
                else
                {
                    var child = _currBlock.NextChild();
                    _currBlock.Advance();
                    _currBlock = child;
                    _currBlock.Begin();
                    _currBlock.Advance();

                    if (_breakBlock == null && !string.IsNullOrEmpty(_currBlock.InitExpression))
                    {
                        var initval = Controller.Symbols.Variables.SetVariable(_currBlock.InitExpression, _currBlock.Scope);
                        _processedLines.Add(new SourceLine
                        {
                            SourceString = ConstStrings.SHADOW_SOURCE,
                            Instruction  = ConstStrings.VAR_DIRECTIVE,
                            Operand      = string.Format("{0}={1}", initval.Key, initval.Value)
                        });
                    }
                }
            }
            else if (instruction.Equals("@@ next @@"))
            {
                if (_breakBlock != null)
                {
                    if (_currBlock == _breakBlock)
                    {
                        _breakBlock = null;
                    }

                    _currBlock = _currBlock.Parent;
                    if (_currBlock == null)
                    {
                        FullReset();
                    }
                    return;
                }

                // update each var in the expressions during runtime as well as
                // in output source (i.e., emit .let n = ... epxressions)
                foreach (var iterexp in _currBlock.IterExpressions)
                {
                    var itervar = Controller.Symbols.Variables.SetVariable(iterexp, _currBlock.Scope);
                    _processedLines.Add(new SourceLine
                    {
                        SourceString = ConstStrings.SHADOW_SOURCE,
                        Instruction  = ConstStrings.VAR_DIRECTIVE,
                        Operand      = string.Format("{0}={1}", itervar.Key, itervar.Value)
                    });
                }

                _currBlock.Begin();

                if (Controller.Evaluator.EvalCondition(_currBlock.Condition))
                {
                    _processedLines.AddRange(_currBlock.GetProcessedLines());
                }
                else
                {
                    _breakBlock = null;
                    _currBlock  = _currBlock.Parent;
                    if (_currBlock == null)
                    {
                        FullReset();
                    }
                }
            }
            else if (instruction.Equals("@@ break @@"))
            {
                if (_breakBlock == null)
                {
                    _breakBlock = _currBlock;
                }
            }
            else if (_breakBlock == null)
            {
                _currBlock.AddEntry(line, null);
            }
        }