Changeset 211


Ignore:
Timestamp:
Apr 22, 2020, 9:00:02 AM (4 years ago)
Author:
chronos
Message:
  • Added: Executor support for Break and Continue statements.
Location:
branches/interpreter2
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • branches/interpreter2/Forms/UFormMain.pas

    r210 r211  
    209209begin
    210210  ACompile.Execute;
    211   //AOptimize.Execute;
     211  AOptimize.Execute;
    212212  FormOutput.SynEditOutput.Highlighter := nil;
    213213  FormOutput.SynEditOutput.Lines.Clear;
  • branches/interpreter2/UExecutor.pas

    r207 r211  
    5757  end;
    5858
    59     { TExecutorBlock }
     59  { TExecutorBlock }
    6060
    6161  TExecutorBlock = class
     
    468468      if not TValueBoolean(Value).Value then Break;
    469469      ExecuteCommand(Block, WhileDo.Command);
     470      if WhileDo.DoContinue then begin
     471        WhileDo.DoContinue := False;
     472        Continue;
     473      end;
     474      if WhileDo.DoBreak then begin
     475        WhileDo.DoBreak := False;
     476        Break;
     477      end;
    470478    end else raise Exception.Create('Expected boolean value.');
    471479    Value.Free;
     
    480488begin
    481489  while True do begin
    482     for I := 0 to RepeatUntil.Commands.Count - 1 do
     490    for I := 0 to RepeatUntil.Commands.Count - 1 do begin
    483491      ExecuteCommand(Block, TCommand(RepeatUntil.Commands[I]));
     492      if RepeatUntil.DoContinue then begin
     493        RepeatUntil.DoContinue := False;
     494        Continue;
     495      end;
     496      if RepeatUntil.DoBreak then begin
     497        RepeatUntil.DoBreak := False;
     498        Break;
     499      end;
     500    end;
    484501    Value := ExecuteExpression(Block, RepeatUntil.Expression);
    485502    if Value is TValueBoolean then begin
     
    501518  while True do begin
    502519    ExecuteCommand(Block, ForToDo.Command);
     520    if ForToDo.DoContinue then begin
     521      ForToDo.DoContinue := False;
     522      Continue;
     523    end;
     524    if ForToDo.DoBreak then begin
     525      ForToDo.DoBreak := False;
     526      Break;
     527    end;
    503528    TValueInteger(Variable.Value).Value := TValueInteger(Variable.Value).Value + 1;
    504529    if TValueInteger(Variable.Value).Value > TValueInteger(Limit).Value then Break;
     
    509534procedure TExecutor.ExecuteContinue(Block: TExecutorBlock;
    510535  ContinueCmd: TContinue);
    511 begin
    512 
     536var
     537  Node: TSourceNode;
     538begin
     539  Node := ContinueCmd.Parent;
     540  while Assigned(Node) and not (Node is TLoop) and Assigned(Node.Parent) do
     541    Node := Node.Parent;
     542
     543  if Node is TLoop then TLoop(Node).DoContinue := True
     544  else raise Exception.Create('Break used outside of loop.');
    513545end;
    514546
    515547procedure TExecutor.ExecuteBreak(Block: TExecutorBlock; BreakCmd: TBreak);
    516 begin
    517 
     548var
     549  Node: TSourceNode;
     550begin
     551  Node := BreakCmd.Parent;
     552  while Assigned(Node) and not (Node is TLoop) and Assigned(Node.Parent) do
     553    Node := Node.Parent;
     554
     555  if Node is TLoop then TLoop(Node).DoBreak := True
     556  else raise Exception.Create('Break used outside of loop.');
    518557end;
    519558
  • branches/interpreter2/UOptimizer.pas

    r208 r211  
    5858    WhileDo := TWhileDo.Create;
    5959    WhileDo.Command := TBeginEnd.Create;
     60    WhileDo.Parent := TRepeatUntil(SourceNode).Parent;
    6061    TBeginEnd(WhileDo.Command).Commands := TRepeatUntil(SourceNode).Commands;
     62    TBeginEnd(WhileDo.Command).Parent := WhileDo;
    6163    TRepeatUntil(SourceNode).Commands := TCommands.Create;
    6264    WhileDo.Expression := TExpressionOperand.Create;
     65    WhileDo.Expression.Parent := WhileDo;
    6366    TExpressionOperand(WhileDo.Expression).OperandType := otConstantDirect;
    6467    TExpressionOperand(WhileDo.Expression).ConstantDirect := TConstant.Create;
     
    6871    // Add final if
    6972    Condition := TIfThenElse.Create;
     73    Condition.Parent := WhileDo;
    7074    Condition.Expression := TRepeatUntil(SourceNode).Expression;
    7175    Condition.CommandThen := TBreak.Create;
     76    Condition.CommandThen.Parent := Condition;
    7277    TRepeatUntil(SourceNode).Expression := TExpression.Create;
    7378    TBeginEnd(WhileDo.Command).Commands.Add(Condition);
  • branches/interpreter2/UParser.pas

    r207 r211  
    6363    while not Tokenizer.CheckNext('end', tkKeyword) do begin
    6464      if ParseCommand(Block, Command) then begin
     65        Command.Parent := BeginEnd;
    6566        BeginEnd.Commands.Add(Command);
    6667        Tokenizer.Expect(';', tkSpecialSymbol);
     
    185186    Prog.Block.Free;
    186187    Prog.Block := Block;
     188    Block.Parent := Prog;
    187189    Tokenizer.Expect('.', tkSpecialSymbol);
    188190  end else begin
     
    198200  Result := False;
    199201  Block := TBlock.Create;
    200   Block.Parent := ParentBlock;
     202  Block.ParentBlock := ParentBlock;
    201203  ParseBlockVar(Block);
    202204  ParseBlockConst(Block);
     
    205207    Block.BeginEnd.Free;
    206208    Block.BeginEnd := BeginEnd;
     209    BeginEnd.Parent := Block;
    207210  end else Block.Free;
    208211end;
     
    293296  Variable: TVariable;
    294297  Expression: TExpression;
    295 begin
     298  LastPos: TTokenizerPos;
     299begin
     300  LastPos := Tokenizer.Pos;
    296301  Result := False;
    297302  Token := Tokenizer.GetNext;
    298303  if Token.Kind = tkIdentifier then begin
    299     Result := True;
    300304    Variable := Block.GetVariable(Token.Text);
    301305    if Assigned(Variable) then begin
     
    308312          Assignment.Expression.Free;
    309313          Assignment.Expression := Expression;
     314          Expression.Parent := Assignment;
    310315        end else begin
    311316          Result := False;
     
    316321    end else Error('Variable ' + Token.Text + ' not defined.');
    317322  end;
     323  if not Result then Tokenizer.Pos := LastPos;
    318324end;
    319325
     
    481487        IfThenElse.CommandThen.Free;
    482488        IfThenElse.CommandThen := Command;
     489        Command.Parent := IfThenElse;
    483490        if Tokenizer.CheckNext('else', tkKeyword) then begin
    484491          Tokenizer.Expect('else', tkKeyword);
     
    486493            IfThenElse.CommandElse.Free;
    487494            IfThenElse.CommandElse := Command;
     495            Command.Parent := IfThenElse;
    488496          end else Error('Expected command');
    489497        end;
     
    510518        WhileDo.Command.Free;
    511519        WhileDo.Command := Command;
     520        Command.Parent := WhileDo;
    512521      end else Error('Expected command');
    513522    end else Error('Expected expression');
     
    529538      if ParseCommand(Block, Command) then begin
    530539        RepeatUntil.Commands.Add(Command);
     540        Command.Parent := RepeatUntil;
    531541        Tokenizer.Expect(';', tkSpecialSymbol);
    532542      end else begin
     
    569579            ForToDo.Command.Free;
    570580            ForToDo.Command := Command;
     581            Command.Parent := ForToDo;
    571582          end else Error('Expected command.');
    572583        end else Error('Expected expression.');
  • branches/interpreter2/USource.pas

    r208 r211  
    3434    function GetFieldsCount: Integer; virtual;
    3535  public
     36    Parent: TSourceNode;
    3637    function GetField(Index: Integer): TField; virtual;
    3738    procedure GetValue(Index: Integer; out Value); virtual;
     
    5455  TSourceNodes = class(TSourceNode)
    5556  private
     57    Parent: TSourceNode;
    5658    function GetCount: Integer;
    5759    function GetItem(Index: Integer): TObject;
     
    316318  end;
    317319
     320  TLoop = class(TCommand)
     321    DoBreak: Boolean;
     322    DoContinue: Boolean;
     323  end;
     324
    318325  { TWhileDo }
    319326
    320   TWhileDo = class(TCommand)
     327  TWhileDo = class(TLoop)
    321328  private
    322329    function GetFieldsCount: Integer; override;
     
    333340  { TRepeatUntil }
    334341
    335   TRepeatUntil = class(TCommand)
     342  TRepeatUntil = class(TLoop)
    336343  private
    337344    function GetFieldsCount: Integer; override;
     
    354361  { TForToDo }
    355362
    356   TForToDo = class(TCommand)
     363  TForToDo = class(TLoop)
    357364  private
    358365    function GetFieldsCount: Integer; override;
     
    375382    function GetFieldsCount: Integer; override;
    376383  public
    377     Parent: TBlock;
     384    ParentBlock: TBlock;
    378385    Variables: TVariables;
    379386    Constants: TConstants;
     
    12341241begin
    12351242  Result := Types.SearchByName(Name);
    1236   if not Assigned(Result) and Assigned(Parent) then
    1237     Result := Parent.Types.SearchByName(Name);
     1243  if not Assigned(Result) and Assigned(ParentBlock) then
     1244    Result := ParentBlock.Types.SearchByName(Name);
    12381245end;
    12391246
     
    12411248begin
    12421249  Result := Constants.SearchByName(Name);
    1243   if not Assigned(Result) and Assigned(Parent) then
    1244     Result := Parent.Constants.SearchByName(Name);
     1250  if not Assigned(Result) and Assigned(ParentBlock) then
     1251    Result := ParentBlock.Constants.SearchByName(Name);
    12451252end;
    12461253
     
    12481255begin
    12491256  Result := Variables.SearchByName(Name);
    1250   if not Assigned(Result) and Assigned(Parent) then
    1251     Result := Parent.Variables.SearchByName(Name);
     1257  if not Assigned(Result) and Assigned(ParentBlock) then
     1258    Result := ParentBlock.Variables.SearchByName(Name);
    12521259end;
    12531260
     
    12551262begin
    12561263  Result := Functions.SearchByName(Name);
    1257   if not Assigned(Result) and Assigned(Parent) then
    1258     Result := Parent.Functions.SearchByName(Name);
     1264  if not Assigned(Result) and Assigned(ParentBlock) then
     1265    Result := ParentBlock.Functions.SearchByName(Name);
    12591266end;
    12601267
  • branches/interpreter2/interpreter.lpi

    r210 r211  
    189189      </Options>
    190190    </Linking>
     191    <Other>
     192      <CompilerMessages>
     193        <IgnoredMessages idx5024="True"/>
     194      </CompilerMessages>
     195    </Other>
    191196  </CompilerOptions>
    192197  <Debugging>
Note: See TracChangeset for help on using the changeset viewer.