Changeset 147


Ignore:
Timestamp:
Jan 17, 2018, 3:34:13 PM (6 years ago)
Author:
chronos
Message:
  • Added: Support for Repeat blocks and Break command.
Location:
branches/easy compiler
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • branches/easy compiler/Steps.txt

    r144 r147  
    2020Add begin-end block support
    2121- local variables, constants, types
    22 
     22Add ifzero support
     23- if condition is valid then skip next command
     24Add Repeat keyword
     25- can be exited by Break command and reiterated by Continue
    2326
    2427TODO:
  • branches/easy compiler/UCompiler.pas

    r146 r147  
    4444    procedure Parse(Code: TSourceCode);
    4545    function ParseBeginEnd(SourceCode: TSourceCode; out BeginEnd: TCommandBeginEnd): Boolean;
     46    function ParseBreak(SourceCode: TSourceCode; out CommandBreak: TCommandBreak
     47      ): Boolean;
     48    function ParseCommand(SourceCode: TSourceCode; out Command: TSourceCommand
     49      ): Boolean;
    4650    function ParseFunctionCall(SourceCode: TSourceCode; out FunctionCall: TCommandFunctionCall): Boolean;
    4751    function ParseIfZero(SourceCode: TSourceCode; out IfZero: TCommandIfZero): Boolean;
    4852    function ParseReference(SourceCode: TSourceCode): TSourceReference;
    4953    function ParseReferenceVariable(SourceCode: TSourceCode): TSourceReference;
     54    function ParseRepeat(SourceCode: TSourceCode; out
     55      CommandRepeat: TCommandRepeat): Boolean;
    5056    function ParseVar(SourceCode: TSourceCode): Boolean;
    5157  public
     
    306312  if Keyword = 'ifzero' then begin
    307313    IfZero := TCommandIfZero.Create;
    308     IfZero.Variable := TSourceReferenceVariable(ParseReferenceVariable(SourceCode)).Variable;
    309     Result := True;
    310   end;
    311   if not Result then Tokenizer.TokenIndex := TokenIndex;
    312 end;
    313 
    314 function TCompiler.ParseBeginEnd(SourceCode: TSourceCode; out BeginEnd: TCommandBeginEnd): Boolean;
    315 var
    316   Token: TSourceToken;
     314    IfZero.Variable := TSourceReferenceVariable(ParseReferenceVariable(SourceCode));
     315    Result := True;
     316  end;
     317  if not Result then Tokenizer.TokenIndex := TokenIndex;
     318end;
     319
     320function TCompiler.ParseBreak(SourceCode: TSourceCode; out CommandBreak: TCommandBreak): Boolean;
     321var
     322  Token: TSourceToken;
     323  TokenIndex: Integer;
    317324  Keyword: string;
    318   TokenIndex: Integer;
     325begin
     326  Result := False;
     327  TokenIndex := Tokenizer.TokenIndex;
     328  Token := Tokenizer.GetNext;
     329  Keyword := LowerCase(Token.Text);
     330  if Keyword = 'break' then begin
     331    CommandBreak := TCommandBreak.Create;
     332    Result := True;
     333  end;
     334  if not Result then Tokenizer.TokenIndex := TokenIndex;
     335end;
     336
     337function TCompiler.ParseRepeat(SourceCode: TSourceCode; out CommandRepeat: TCommandRepeat): Boolean;
     338var
     339  Token: TSourceToken;
     340  TokenIndex: Integer;
     341  Keyword: string;
     342  Command: TSourceCommand;
     343begin
     344  Result := False;
     345  TokenIndex := Tokenizer.TokenIndex;
     346  Token := Tokenizer.GetNext;
     347  Keyword := LowerCase(Token.Text);
     348  if Keyword = 'repeat' then begin
     349    CommandRepeat := TCommandRepeat.Create;
     350    if ParseCommand(SourceCode, Command) then begin
     351      CommandRepeat := TCommandRepeat.Create;
     352      CommandRepeat.Command := Command;
     353      Command.Parent := CommandRepeat;
     354    end else
     355    raise Exception.Create('Unexpected token');
     356    Result := True;
     357  end;
     358  if not Result then Tokenizer.TokenIndex := TokenIndex;
     359end;
     360
     361function TCompiler.ParseCommand(SourceCode: TSourceCode; out Command: TSourceCommand): Boolean;
     362var
    319363  CommandBeginEnd: TCommandBeginEnd;
    320364  CommandIfZero: TCommandIfZero;
    321365  CommandFunctionCall: TCommandFunctionCall;
     366  CommandBreak: TCommandBreak;
     367  CommandRepeat: TCommandRepeat;
     368begin
     369  Command := nil;
     370  Result := True;
     371  if ParseVar(SourceCode) then else
     372  if ParseBeginEnd(SourceCode, CommandBeginEnd) then begin
     373    Command := CommandBeginEnd;
     374  end else
     375  if ParseIfZero(SourceCode, CommandIfZero) then begin
     376    Command := CommandIfZero;
     377  end else
     378  if ParseBreak(SourceCode, CommandBreak) then begin
     379    Command := CommandBreak;
     380  end else
     381  if ParseRepeat(SourceCode, CommandRepeat) then begin
     382    Command := CommandRepeat;
     383  end else
     384  if ParseFunctionCall(SourceCode, CommandFunctionCall) then begin
     385    Command := CommandFunctionCall;
     386  end else Result := False;
     387end;
     388
     389function TCompiler.ParseBeginEnd(SourceCode: TSourceCode; out BeginEnd: TCommandBeginEnd): Boolean;
     390var
     391  Token: TSourceToken;
     392  Keyword: string;
     393  TokenIndex: Integer;
     394  Command: TSourceCommand;
    322395begin
    323396  Result := False;
     
    329402    BeginEnd.SourceCode := SourceCode;
    330403    while True do begin
    331       if ParseVar(SourceCode) then
    332       else if ParseBeginEnd(SourceCode, CommandBeginEnd) then
    333         BeginEnd.Instructions.Add(CommandBeginEnd)
    334       else if ParseIfZero(SourceCode, CommandIfZero) then
    335         BeginEnd.Instructions.Add(CommandIfZero)
    336       else if ParseFunctionCall(SourceCode, CommandFunctionCall) then
    337         BeginEnd.Instructions.Add(CommandFunctionCall)
    338       else if Tokenizer.CheckNext('end', stIdentifier) then begin
     404      if ParseCommand(SourceCode, Command) then begin
     405        if Assigned(Command) then begin
     406          BeginEnd.Commands.Add(Command);
     407          Command.Parent := BeginEnd;
     408        end;
     409      end else
     410      if Tokenizer.CheckNext('end', stIdentifier) then begin
    339411        Break;
    340       end
    341       else raise Exception.Create('Unknown token: ' + Keyword);
     412      end else begin
     413        Token := Tokenizer.GetNext;
     414        Keyword := LowerCase(Token.Text);
     415        raise Exception.Create('Unknown token: ' + Keyword);
     416      end;
    342417    end;
    343418    Token := Tokenizer.GetNext;
  • branches/easy compiler/UFormMain.pas

    r146 r147  
    5555    Add('var I Integer');
    5656    Add('Assign I 10');
    57     //Add('Repeat');
     57    Add('Repeat');
    5858    Add('Begin');
    59     //Add('Decrement I 1');
     59    Add('PrintLn I');
     60    Add('Decrement I 1');
    6061    Add('IfZero I');
    61     Add('Print ''condition''');
    62     //Add('Break');
     62    Add('Break');
    6363    Add('End');
    6464    Add('End');
  • branches/easy compiler/USourceCode.pas

    r146 r147  
    1010type
    1111  TSourceCommand = class
    12   end;
    13 
    14   TSourceInstructions = class(TObjectList)
     12    Parent: TSourceCommand;
     13  end;
     14
     15  TSourceCommands = class(TObjectList)
    1516  end;
    1617
     
    140141  TCommandBeginEnd = class(TSourceCommand)
    141142    SourceCode: TSourceCode;
    142     Instructions: TSourceInstructions;
     143    Commands: TSourceCommands;
    143144    constructor Create;
    144145    destructor Destroy; override;
    145146  end;
    146147
     148  { TCommandIfZero }
     149
    147150  TCommandIfZero = class(TSourceCommand)
    148     Variable: TSourceVariable;
     151    Variable: TSourceReferenceVariable;
     152    destructor Destroy; override;
     153  end;
     154
     155  { TCommandRepeat }
     156
     157  TCommandRepeat = class(TSourceCommand)
     158    Command: TSourceCommand;
     159    destructor Destroy; override;
     160  end;
     161
     162  TCommandBreak = class(TSourceCommand)
     163  end;
     164
     165  TCommandContinue = class(TSourceCommand)
    149166  end;
    150167
     
    167184implementation
    168185
     186{ TCommandIfZero }
     187
     188destructor TCommandIfZero.Destroy;
     189begin
     190  Variable.Free;
     191  inherited Destroy;
     192end;
     193
     194{ TCommandRepeat }
     195
     196destructor TCommandRepeat.Destroy;
     197begin
     198  Command.Free;
     199  inherited Destroy;
     200end;
     201
    169202{ TSourceConstant }
    170203
     
    192225constructor TCommandBeginEnd.Create;
    193226begin
    194   Instructions := TSourceInstructions.Create;
     227  Commands := TSourceCommands.Create;
    195228end;
    196229
    197230destructor TCommandBeginEnd.Destroy;
    198231begin
    199   Instructions.Free;
     232  Commands.Free;
    200233  inherited Destroy;
    201234end;
     
    388421
    389422  Funct := Functions.AddNew('increment');
     423  Funct.AddParameter('Variable', pkVariable);
     424  Funct.AddParameter('Addition', pkString);
     425
     426  Funct := Functions.AddNew('decrement');
    390427  Funct.AddParameter('Variable', pkVariable);
    391428  Funct.AddParameter('Addition', pkString);
  • branches/easy compiler/USourceExecutor.pas

    r146 r147  
    2222  TExecutorVariables = class(TObjectList)
    2323    function Search(Variable: TSourceVariable): TExecutorVariable;
     24  end;
     25
     26  TExecutorRepeat = class
     27    RepeatCommand: TCommandRepeat;
     28    Terminated: Boolean;
     29  end;
     30
     31  { TExecutorRepeats }
     32
     33  TExecutorRepeats = class(TObjectList)
     34    function Search(RepeatCommand: TCommandRepeat): TExecutorRepeat;
    2435  end;
    2536
     
    3142    FOnOutput: TOutputEvent;
    3243    Variables: TExecutorVariables;
     44    RepeatBlocks: TExecutorRepeats;
     45    SkipNext: Boolean;
    3346    procedure ExecuteBeginEnd(BeginEnd: TCommandBeginEnd);
     47    procedure ExecuteCommand(Command: TSourceCommand);
     48    procedure ExecuteBreak(CommandBreak: TCommandBreak);
     49    procedure ExecuteRepeat(CommandRepeat: TCommandRepeat);
     50    function ReadValueReference(Reference: TSourceReference): TSourceValue;
     51    function ReadVarReference(Reference: TSourceReference): TSourceVariable;
    3452  public
    3553    constructor Create;
     
    4361implementation
    4462
     63{ TExecutorRepeat }
     64
     65function TExecutorRepeats.Search(RepeatCommand: TCommandRepeat): TExecutorRepeat;
     66var
     67  Item: TExecutorRepeat;
     68begin
     69  Result := nil;
     70  for Item in Self do
     71  if Item.RepeatCommand = RepeatCommand then begin
     72    Result := Item;
     73    Break;
     74  end;
     75end;
     76
    4577{ TExecutorVariable }
    4678
     
    71103begin
    72104  Variables := TExecutorVariables.Create;
     105  RepeatBlocks := TExecutorRepeats.Create;
    73106end;
    74107
    75108destructor TSourceExecutor.Destroy;
    76109begin
     110  RepeatBlocks.Free;
    77111  Variables.Free;
    78112  inherited Destroy;
     
    81115procedure TSourceExecutor.Execute(SourceCode: TSourceCode);
    82116begin
     117  SkipNext := False;
    83118  ExecuteBeginEnd(SourceCode.Main);
    84119end;
    85120
     121function TSourceExecutor.ReadValueReference(Reference: TSourceReference): TSourceValue;
     122begin
     123  Result := nil;
     124  if Reference is TSourceReferenceConstant then begin
     125    Result := TSourceReferenceConstant(Reference).Constant.Value;
     126  end else
     127  if Reference is TSourceReferenceVariable then begin
     128    Result := Variables.Search(TSourceReferenceVariable(Reference).Variable).Value;
     129  end else raise Exception.Create('Unsupported reference');
     130end;
     131
     132function TSourceExecutor.ReadVarReference(Reference: TSourceReference): TSourceVariable;
     133begin
     134  Result := nil;
     135  if Reference is TSourceReferenceVariable then begin
     136    Result := TSourceReferenceVariable(Reference).Variable;
     137  end else raise Exception.Create('Unsupported reference');
     138end;
     139
    86140procedure TSourceExecutor.ExecuteBeginEnd(BeginEnd: TCommandBeginEnd);
    87141var
    88142  IP: Integer;
    89   Instruction: TSourceCommand;
     143begin
     144  IP := 0;
     145  while IP < BeginEnd.Commands.Count do begin
     146    if SkipNext then begin
     147      SkipNext := False;
     148      Inc(IP);
     149      Continue;
     150    end;
     151    ExecuteCommand(TSourceCommand(BeginEnd.Commands[IP]));
     152    Inc(IP);
     153  end;
     154end;
     155
     156procedure TSourceExecutor.ExecuteBreak(CommandBreak: TCommandBreak);
     157var
     158  RepeatBlock: TSourceCommand;
     159  ExecutorRepeat: TExecutorRepeat;
     160begin
     161  RepeatBlock := CommandBreak.Parent;
     162  while not (RepeatBlock is TCommandRepeat) and (RepeatBlock <> nil) do
     163    RepeatBlock := RepeatBlock.Parent;
     164  if Assigned(RepeatBlock) then begin
     165    ExecutorRepeat := RepeatBlocks.Search(RepeatBlock as TCommandRepeat);
     166    if Assigned(ExecutorRepeat) then begin
     167      ExecutorRepeat.Terminated := True;
     168    end else
     169    raise Exception.Create('Missing executor repeat block');
     170  end else
     171  raise Exception.Create('Used break outside repeat loop');
     172end;
     173
     174procedure TSourceExecutor.ExecuteRepeat(CommandRepeat: TCommandRepeat);
     175var
     176  RepeatBlock: TExecutorRepeat;
     177begin
     178  RepeatBlock := TExecutorRepeat.Create;
     179  RepeatBlock.RepeatCommand := CommandRepeat;
     180  RepeatBlock.Terminated := False;
     181  RepeatBlocks.Add(RepeatBlock);
     182  repeat
     183    ExecuteCommand(CommandRepeat.Command);
     184  until RepeatBlock.Terminated;
     185  RepeatBlocks.Remove(RepeatBlock);
     186end;
     187
     188procedure TSourceExecutor.ExecuteCommand(Command: TSourceCommand);
     189var
    90190  Variable: TSourceVariable;
    91191  Value: TSourceValue;
     
    93193  Text: string;
    94194  IntValue: Integer;
    95   SkipNext: Boolean;
    96 
    97 function ReadValueReference(Reference: TSourceReference): TSourceValue;
    98 begin
    99   Result := nil;
    100   if Reference is TSourceReferenceConstant then begin
    101     Result := TSourceReferenceConstant(Reference).Constant.Value;
    102   end else
    103   if Reference is TSourceReferenceVariable then begin
    104     Result := Variables.Search(TSourceReferenceVariable(Reference).Variable).Value;
    105   end else raise Exception.Create('Unsupported reference');
    106 end;
    107 
    108 function ReadVarReference(Reference: TSourceReference): TSourceVariable;
    109 begin
    110   Result := nil;
    111   if Reference is TSourceReferenceVariable then begin
    112     Result := TSourceReferenceVariable(Reference).Variable;
    113   end else raise Exception.Create('Unsupported reference');
    114 end;
    115 
    116 begin
    117   SkipNext := False;
    118   IP := 0;
    119   while IP < BeginEnd.Instructions.Count do begin
    120     if SkipNext then begin
    121       SkipNext := False;
    122       Inc(IP);
    123       Continue;
    124     end;
    125     Instruction := TSourceCommand(BeginEnd.Instructions[IP]);
    126     if Instruction is TCommandFunctionCall then
    127     with TCommandFunctionCall(Instruction) do begin
    128       if Name = 'print' then begin
    129         if Assigned(FOnOutput) then begin
    130           Value := ReadValueReference(TSourceReference(Parameters[0]));
    131           if Value is TSourceValueString then
    132             FOnOutput(TSourceValueString(Value).Value)
    133           else if Value is TSourceValueInteger then
    134             FOnOutput(IntToStr(TSourceValueInteger(Value).Value))
    135           else raise Exception.Create('Unsupported value type');
    136         end;
     195begin
     196  if Command is TCommandFunctionCall then
     197  with TCommandFunctionCall(Command) do begin
     198    if Name = 'print' then begin
     199      if Assigned(FOnOutput) then begin
     200        Value := ReadValueReference(TSourceReference(Parameters[0]));
     201        if Value is TSourceValueString then
     202          FOnOutput(TSourceValueString(Value).Value)
     203        else if Value is TSourceValueInteger then
     204          FOnOutput(IntToStr(TSourceValueInteger(Value).Value))
     205        else raise Exception.Create('Unsupported value type');
     206      end;
     207    end else
     208    if Name = 'println' then begin
     209      if Assigned(FOnOutput) then begin
     210        Value := ReadValueReference(TSourceReference(Parameters[0]));
     211        if Value is TSourceValueString then
     212          FOnOutput(TSourceValueString(Value).Value + LineEnding)
     213        else if Value is TSourceValueInteger then
     214          FOnOutput(IntToStr(TSourceValueInteger(Value).Value) + LineEnding)
     215        else raise Exception.Create('Unsupported value type');
     216      end;
     217    end else
     218    if Name = 'inputln' then begin
     219      if Assigned(FOnInput) then begin
     220        Variable := ReadVarReference(TSourceReference(Parameters[0]));
     221        ExecutorVar := Variables.Search(Variable);
     222        if ExecutorVar.Value is TSourceValueString then begin
     223          TSourceValueString(ExecutorVar.Value).Value := FOnInput;
     224          FOnOutput(TSourceValueString(ExecutorVar.Value).Value + LineEnding);
     225        end else
     226        if ExecutorVar.Value is TSourceValueInteger then begin
     227          Text := FOnInput;
     228          if TryStrToInt(Text, IntValue) then
     229            TSourceValueInteger(ExecutorVar.Value).Value := IntValue
     230            else TSourceValueInteger(ExecutorVar.Value).Value := 0;
     231          FOnOutput(IntToStr(TSourceValueInteger(ExecutorVar.Value).Value) + LineEnding);
     232        end else
     233        raise Exception.Create('Unsupported value type');
     234      end;
     235    end else
     236    if Name = 'assign' then begin
     237      Variable := ReadVarReference(TSourceReference(Parameters[0]));
     238      Value := ReadValueReference(TSourceReference(Parameters[1]));
     239      ExecutorVar := Variables.Search(Variable);
     240      if not Assigned(ExecutorVar) then begin
     241        ExecutorVar := TExecutorVariable.Create;
     242        ExecutorVar.Variable := Variable;
     243        Variables.Add(ExecutorVar);
     244        ExecutorVar.Value := Variable.ValueType.ValueClass.Create;
     245      end;
     246      ExecutorVar.Value.Assign(Value);
     247    end else
     248    if Name = 'increment' then begin
     249      Variable := ReadVarReference(TSourceReference(Parameters[0]));
     250      Value := ReadValueReference(TSourceReference(Parameters[1]));
     251      ExecutorVar := Variables.Search(Variable);
     252      if not Assigned(ExecutorVar) then raise Exception.Create('Variable not found');
     253      if (ExecutorVar.Value is TSourceValueInteger) and (Value is TSourceValueInteger) then
     254        Inc(TSourceValueInteger(ExecutorVar.Value).Value, TSourceValueInteger(Value).Value)
     255      else raise Exception.Create('Wrong type for increment');
     256    end else
     257    if Name = 'decrement' then begin
     258      Variable := ReadVarReference(TSourceReference(Parameters[0]));
     259      Value := ReadValueReference(TSourceReference(Parameters[1]));
     260      ExecutorVar := Variables.Search(Variable);
     261      if not Assigned(ExecutorVar) then raise Exception.Create('Variable not found');
     262      if (ExecutorVar.Value is TSourceValueInteger) and (Value is TSourceValueInteger) then
     263        Dec(TSourceValueInteger(ExecutorVar.Value).Value, TSourceValueInteger(Value).Value)
     264      else raise Exception.Create('Wrong type for increment');
     265    end else
     266    raise Exception.Create('Unsupported function: ' + TCommandFunctionCall(Command).Name);
     267  end else
     268  if Command is TCommandBeginEnd then begin
     269    ExecuteBeginEnd(TCommandBeginEnd(Command));
     270  end else
     271  if Command is TCommandBreak then begin
     272    ExecuteBreak(TCommandBreak(Command));
     273  end else
     274  if Command is TCommandIfZero then begin
     275    ExecutorVar := Variables.Search(TCommandIfZero(Command).Variable.Variable);
     276    if Assigned(ExecutorVar) then begin
     277      if ExecutorVar.Variable.ValueType.Name = 'Integer' then begin
     278        if TSourceValueInteger(ExecutorVar.Value).Value <> 0 then SkipNext := True;
    137279      end else
    138       if Name = 'println' then begin
    139         if Assigned(FOnOutput) then begin
    140           Value := ReadValueReference(TSourceReference(Parameters[0]));
    141           if Value is TSourceValueString then
    142             FOnOutput(TSourceValueString(Value).Value + LineEnding)
    143           else if Value is TSourceValueInteger then
    144             FOnOutput(IntToStr(TSourceValueInteger(Value).Value) + LineEnding)
    145           else raise Exception.Create('Unsupported value type');
    146         end;
    147       end else
    148       if Name = 'inputln' then begin
    149         if Assigned(FOnInput) then begin
    150           Variable := ReadVarReference(TSourceReference(Parameters[0]));
    151           ExecutorVar := Variables.Search(Variable);
    152           if ExecutorVar.Value is TSourceValueString then begin
    153             TSourceValueString(ExecutorVar.Value).Value := FOnInput;
    154             FOnOutput(TSourceValueString(ExecutorVar.Value).Value + LineEnding);
    155           end else
    156           if ExecutorVar.Value is TSourceValueInteger then begin
    157             Text := FOnInput;
    158             if TryStrToInt(Text, IntValue) then
    159               TSourceValueInteger(ExecutorVar.Value).Value := IntValue
    160               else TSourceValueInteger(ExecutorVar.Value).Value := 0;
    161             FOnOutput(IntToStr(TSourceValueInteger(ExecutorVar.Value).Value) + LineEnding);
    162           end else
    163           raise Exception.Create('Unsupported value type');
    164         end;
    165       end else
    166       if Name = 'assign' then begin
    167         Variable := ReadVarReference(TSourceReference(Parameters[0]));
    168         Value := ReadValueReference(TSourceReference(Parameters[1]));
    169         ExecutorVar := Variables.Search(Variable);
    170         if not Assigned(ExecutorVar) then begin
    171           ExecutorVar := TExecutorVariable.Create;
    172           ExecutorVar.Variable := Variable;
    173           Variables.Add(ExecutorVar);
    174           ExecutorVar.Value := Variable.ValueType.ValueClass.Create;
    175         end;
    176         ExecutorVar.Value.Assign(Value);
    177       end else
    178       if Name = 'increment' then begin
    179         Variable := ReadVarReference(TSourceReference(Parameters[0]));
    180         Value := ReadValueReference(TSourceReference(Parameters[1]));
    181         ExecutorVar := Variables.Search(Variable);
    182         if not Assigned(ExecutorVar) then raise Exception.Create('Variable not found');
    183         if (ExecutorVar.Value is TSourceValueInteger) and (Value is TSourceValueInteger) then
    184           Inc(TSourceValueInteger(ExecutorVar.Value).Value, TSourceValueInteger(Value).Value)
    185         else raise Exception.Create('Wrong type for increment');
    186       end else
    187       raise Exception.Create('Unsupported function: ' + TCommandFunctionCall(Instruction).Name);
    188     end else
    189     if Instruction is TCommandBeginEnd then begin
    190       ExecuteBeginEnd(TCommandBeginEnd(Instruction));
    191     end else
    192     if Instruction is TCommandIfZero then begin
    193       ExecutorVar := Variables.Search(TCommandIfZero(Instruction).Variable);
    194       if Assigned(ExecutorVar) then begin
    195         if ExecutorVar.Variable.ValueType.Name = 'Integer' then begin
    196           if TSourceValueInteger(ExecutorVar.Value).Value = 0 then SkipNext := True;
    197         end else
    198         raise Exception.Create('Can compare only integers');
    199       end else
    200       raise Exception.Create('Variable not found');
    201     end else
    202     raise Exception.Create('Unsupported instruction');
    203     Inc(IP);
    204   end;
     280      raise Exception.Create('Can compare only integers');
     281    end else
     282    raise Exception.Create('Variable not found');
     283  end else
     284  if Command is TCommandRepeat then begin
     285    ExecuteRepeat(Command as TCommandRepeat);
     286  end else
     287  raise Exception.Create('Unsupported instruction');
    205288end;
    206289
  • branches/easy compiler/USourceGenerator.pas

    r146 r147  
    1515    Indent: Integer;
    1616    function GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string;
     17    function GenerateCommand(Command: TSourceCommand): string;
     18    function GenerateRef(Reference: TSourceReference): string;
    1719    function IndentStr: string;
    1820  public
     
    4951end;
    5052
    51 function TSourceGenerator.GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string;
     53function TSourceGenerator.GenerateRef(Reference: TSourceReference): string;
    5254var
    53   Instruction: TSourceCommand;
    54   I: Integer;
    5555  Value: TSourceValue;
    56 
    57 function GenerateRef(Reference: TSourceReference): string;
    5856begin
    5957  Result := '';
     
    7169end;
    7270
     71function TSourceGenerator.GenerateCommand(Command: TSourceCommand): string;
     72begin
     73  Result := '';
     74  if Command is TCommandFunctionCall then
     75  with TCommandFunctionCall(Command) do begin
     76    if Name = 'print' then begin
     77      Result := Result + IndentStr + 'Write(' + GenerateRef(TSourceReference(Parameters[0])) + ');' +
     78        LineEnding;
     79    end else
     80    if Name = 'println' then begin
     81      Result := Result + IndentStr + 'WriteLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' +
     82        LineEnding;
     83    end else
     84    if Name = 'assign' then begin
     85      Result := Result + IndentStr + GenerateRef(TSourceReference(Parameters[0])) + ' := ' +
     86        GenerateRef(TSourceReference(Parameters[1])) + ';' + LineEnding;
     87    end else
     88    if Name = 'inputln' then begin
     89      Result := Result + IndentStr + 'ReadLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + LineEnding;
     90    end else
     91    if Name = 'increment' then begin
     92      Result := Result + IndentStr + 'Inc(' + GenerateRef(TSourceReference(Parameters[0])) + ', ' +
     93        GenerateRef(TSourceReference(Parameters[1])) + ');' + LineEnding;
     94    end else
     95    if Name = 'decrement' then begin
     96      Result := Result + IndentStr + 'Dec(' + GenerateRef(TSourceReference(Parameters[0])) + ', ' +
     97        GenerateRef(TSourceReference(Parameters[1])) + ');' + LineEnding;
     98    end else
     99    raise Exception.Create('Unsupported instruction name.');
     100  end else
     101  if Command is TCommandBeginEnd then begin
     102    Result := Result + GenerateBeginEnd(TCommandBeginEnd(Command)) +
     103      ';' + LineEnding;
     104  end else
     105  if Command is TCommandBreak then begin
     106    Result := Result + IndentStr + 'Break;' + LineEnding;
     107  end else
     108  if Command is TCommandContinue then begin
     109    Result := Result + IndentStr + 'Continue;' + LineEnding;
     110  end else
     111  if Command is TCommandRepeat then begin
     112    Result := Result + IndentStr + 'repeat' + LineEnding;
     113    Inc(Indent);
     114    Result := Result + IndentStr +  GenerateCommand(TCommandRepeat(Command).Command) + LineEnding;
     115    Dec(Indent);
     116    Result := Result + IndentStr + 'until False;' + LineEnding;
     117  end else
     118  if Command is TCommandIfZero then begin
     119    Result := Result + IndentStr + 'if ' + TCommandIfZero(Command).Variable.Variable.Name + ' = 0 then ';
     120  end else
     121  raise Exception.Create('Unsupported instruction');
     122end;
     123
     124function TSourceGenerator.GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string;
     125var
     126  I: Integer;
    73127begin
    74128  Result := '';
     
    76130  Inc(Indent);
    77131  with BeginEnd do
    78   for I := 0 to Instructions.Count - 1 do begin
    79     Instruction := TSourceCommand(Instructions[I]);
    80     if Instruction is TCommandFunctionCall then
    81     with TCommandFunctionCall(Instruction) do begin
    82       if Name = 'print' then begin
    83         Result := Result + IndentStr + 'Write(' + GenerateRef(TSourceReference(Parameters[0])) + ');' +
    84           LineEnding;
    85       end else
    86       if Name = 'println' then begin
    87         Result := Result + IndentStr + 'WriteLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' +
    88           LineEnding;
    89       end else
    90       if Name = 'assign' then begin
    91         Result := Result + IndentStr + GenerateRef(TSourceReference(Parameters[0])) + ' := ' +
    92           GenerateRef(TSourceReference(Parameters[1])) + ';' + LineEnding;
    93       end else
    94       if Name = 'inputln' then begin
    95         Result := Result + IndentStr + 'ReadLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + LineEnding;
    96       end else
    97       if Name = 'increment' then begin
    98         Result := Result + IndentStr + 'Inc(' + GenerateRef(TSourceReference(Parameters[0])) + ', ' +
    99           GenerateRef(TSourceReference(Parameters[1])) + ');' + LineEnding;
    100       end else
    101       raise Exception.Create('Unsupported instruction name.');
    102     end else
    103     if Instruction is TCommandBeginEnd then begin
    104       Result := Result + GenerateBeginEnd(TCommandBeginEnd(Instruction)) +
    105         ';' + LineEnding;
    106     end else
    107     if Instruction is TCommandIfZero then begin
    108       Result := Result + IndentStr + 'if ' + TCommandIfZero(Instruction).Variable.Name + ' = 0 then ';
    109     end else
    110     raise Exception.Create('Unsupported instruction');
     132  for I := 0 to Commands.Count - 1 do begin
     133    Result := Result + GenerateCommand(TSourceCommand(Commands[I]));
    111134  end;
    112135  Dec(Indent);
Note: See TracChangeset for help on using the changeset viewer.