| 1 | unit UBFTarget;
|
|---|
| 2 |
|
|---|
| 3 | {$mode delphi}
|
|---|
| 4 |
|
|---|
| 5 | interface
|
|---|
| 6 |
|
|---|
| 7 | uses
|
|---|
| 8 | Classes, SysUtils, UTarget;
|
|---|
| 9 |
|
|---|
| 10 | type
|
|---|
| 11 |
|
|---|
| 12 | TMachineCommand = (cmNoOperation, cmInc, cmDec, cmPointerInc, cmPointerDec,
|
|---|
| 13 | cmOutput, cmInput, cmLoopStart, cmLoopEnd, cmDebug, cmSet, cmMultipy);
|
|---|
| 14 |
|
|---|
| 15 | { TMachineOperation }
|
|---|
| 16 |
|
|---|
| 17 | TMachineOperation = record
|
|---|
| 18 | Command: TMachineCommand;
|
|---|
| 19 | Parameter: Integer;
|
|---|
| 20 | RelIndex: Integer;
|
|---|
| 21 | class function Create(Command: TMachineCommand; Parameter, RelIndex: Integer): TMachineOperation; static;
|
|---|
| 22 | end;
|
|---|
| 23 |
|
|---|
| 24 | TOptimizations = record
|
|---|
| 25 | AddSub: Boolean;
|
|---|
| 26 | Merge: Boolean;
|
|---|
| 27 | RelativeIndexes: Boolean;
|
|---|
| 28 | CopyMultiply: Boolean;
|
|---|
| 29 | end;
|
|---|
| 30 |
|
|---|
| 31 | { TBFTarget }
|
|---|
| 32 |
|
|---|
| 33 | TBFTarget = class(TTarget)
|
|---|
| 34 | private
|
|---|
| 35 | function CheckClear: Boolean;
|
|---|
| 36 | function CheckOccurenceSumParam(C: TMachineCommand): Integer;
|
|---|
| 37 | function CheckOccurence(C: TMachineCommand): Integer;
|
|---|
| 38 | procedure OptimizeAddSub;
|
|---|
| 39 | procedure OptimizeMerge;
|
|---|
| 40 | procedure OptimizeZeroInitMemory;
|
|---|
| 41 | procedure OptimizeRelativeIndexes;
|
|---|
| 42 | procedure OptimizeCopyMultiply;
|
|---|
| 43 | protected
|
|---|
| 44 | FProgram: array of TMachineOperation;
|
|---|
| 45 | FProgramIndex: Integer;
|
|---|
| 46 | function GetOperationText(Operation: TMachineOperation): string; virtual;
|
|---|
| 47 | procedure LoadProgram; override;
|
|---|
| 48 | public
|
|---|
| 49 | MemorySize: Integer;
|
|---|
| 50 | MemoryMaxUsedAddr: Integer;
|
|---|
| 51 | CellSize: Integer;
|
|---|
| 52 | Optimizations: TOptimizations;
|
|---|
| 53 | constructor Create; override;
|
|---|
| 54 | procedure OptimizeSource; override;
|
|---|
| 55 | property ProgramIndex: Integer read FProgramIndex;
|
|---|
| 56 | end;
|
|---|
| 57 |
|
|---|
| 58 | const
|
|---|
| 59 | BrainFuckCommandText: array[TMachineCommand] of Char = (
|
|---|
| 60 | ' ', '+', '-', '>', '<', '.', ',', '[', ']', '@', '=', '*');
|
|---|
| 61 |
|
|---|
| 62 |
|
|---|
| 63 | implementation
|
|---|
| 64 |
|
|---|
| 65 | { TMachineOperation }
|
|---|
| 66 |
|
|---|
| 67 | class function TMachineOperation.Create(Command: TMachineCommand; Parameter,
|
|---|
| 68 | RelIndex: Integer): TMachineOperation;
|
|---|
| 69 | begin
|
|---|
| 70 | Result.Command := Command;
|
|---|
| 71 | Result.Parameter := Parameter;
|
|---|
| 72 | Result.RelIndex := RelIndex;
|
|---|
| 73 | end;
|
|---|
| 74 |
|
|---|
| 75 | function TBFTarget.CheckClear: Boolean;
|
|---|
| 76 | begin
|
|---|
| 77 | Result := (FProgram[FProgramIndex].Command = cmLoopStart) and (Length(FProgram) >= FProgramIndex + 2) and
|
|---|
| 78 | (((FProgram[FProgramIndex + 1].Command = cmDec) and (FProgram[FProgramIndex + 1].Parameter = 1)) or
|
|---|
| 79 | ((FProgram[FProgramIndex + 1].Command = cmInc) and (FProgram[FProgramIndex + 1].Parameter = -1)))
|
|---|
| 80 | and (FProgram[FProgramIndex + 2].Command = cmLoopEnd);
|
|---|
| 81 | end;
|
|---|
| 82 |
|
|---|
| 83 | function TBFTarget.CheckOccurence(C: TMachineCommand): Integer;
|
|---|
| 84 | begin
|
|---|
| 85 | Result := 1;
|
|---|
| 86 | while ((FProgramIndex + 1) < Length(FProgram)) and (FProgram[FProgramIndex + 1].Command = C) do begin
|
|---|
| 87 | Inc(Result);
|
|---|
| 88 | Inc(FProgramIndex);
|
|---|
| 89 | end;
|
|---|
| 90 | end;
|
|---|
| 91 |
|
|---|
| 92 | function TBFTarget.CheckOccurenceSumParam(C: TMachineCommand): Integer;
|
|---|
| 93 | begin
|
|---|
| 94 | Result := FProgram[FProgramIndex].Parameter;
|
|---|
| 95 | while ((FProgramIndex + 1) < Length(FProgram)) and (FProgram[FProgramIndex + 1].Command = C) do begin
|
|---|
| 96 | Inc(Result, FProgram[FProgramIndex + 1].Parameter);
|
|---|
| 97 | Inc(FProgramIndex);
|
|---|
| 98 | end;
|
|---|
| 99 | end;
|
|---|
| 100 |
|
|---|
| 101 | procedure TBFTarget.OptimizeAddSub;
|
|---|
| 102 | var
|
|---|
| 103 | NewProgram: array of TMachineOperation;
|
|---|
| 104 | NewProgramIndex: Integer;
|
|---|
| 105 | NewTargetPos: Integer;
|
|---|
| 106 | FirstIndex: Integer;
|
|---|
| 107 | begin
|
|---|
| 108 | NewProgramIndex := 0;
|
|---|
| 109 | NewTargetPos := 0;
|
|---|
| 110 | SetLength(NewProgram, Length(FProgram));
|
|---|
| 111 |
|
|---|
| 112 | FProgramIndex := 0;
|
|---|
| 113 | while (FProgramIndex < Length(FProgram)) do begin
|
|---|
| 114 | FirstIndex := FProgramIndex;
|
|---|
| 115 | case FProgram[FProgramIndex].Command of
|
|---|
| 116 | cmPointerInc: begin
|
|---|
| 117 | NewProgram[NewProgramIndex].Command := cmPointerInc;
|
|---|
| 118 | NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmPointerInc);
|
|---|
| 119 | end;
|
|---|
| 120 | cmPointerDec: begin
|
|---|
| 121 | NewProgram[NewProgramIndex].Command := cmPointerDec;
|
|---|
| 122 | NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmPointerDec);
|
|---|
| 123 | end;
|
|---|
| 124 | cmInc: begin
|
|---|
| 125 | NewProgram[NewProgramIndex].Command := cmInc;
|
|---|
| 126 | NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmInc);
|
|---|
| 127 | end;
|
|---|
| 128 | cmDec: begin
|
|---|
| 129 | NewProgram[NewProgramIndex].Command := cmDec;
|
|---|
| 130 | NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmDec);
|
|---|
| 131 | end;
|
|---|
| 132 | else NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 133 | end;
|
|---|
| 134 | DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgramIndex, NewTargetPos);
|
|---|
| 135 | Inc(NewTargetPos, Length(GetOperationText(NewProgram[NewProgramIndex])));
|
|---|
| 136 | Inc(FProgramIndex);
|
|---|
| 137 | Inc(NewProgramIndex);
|
|---|
| 138 | end;
|
|---|
| 139 | SetLength(NewProgram, NewProgramIndex);
|
|---|
| 140 |
|
|---|
| 141 | // Replace old program by new program
|
|---|
| 142 | SetLength(FProgram, Length(NewProgram));
|
|---|
| 143 | Move(Pointer(NewProgram)^, Pointer(FProgram)^, SizeOf(TMachineOperation) * Length(NewProgram));
|
|---|
| 144 | end;
|
|---|
| 145 |
|
|---|
| 146 | procedure TBFTarget.OptimizeMerge;
|
|---|
| 147 | var
|
|---|
| 148 | NewProgram: array of TMachineOperation;
|
|---|
| 149 | NewProgramIndex: Integer;
|
|---|
| 150 | PreviousCommand: TMachineCommand;
|
|---|
| 151 | FirstIndex: Integer;
|
|---|
| 152 | NewTargetIndex: Integer;
|
|---|
| 153 | begin
|
|---|
| 154 | // Merge together cmInc, cmDec, cmSet
|
|---|
| 155 | // Merge together cmPointerInc, cmPointerDec
|
|---|
| 156 | PreviousCommand := cmNoOperation;
|
|---|
| 157 | NewProgramIndex := 0;
|
|---|
| 158 | SetLength(NewProgram, Length(FProgram));
|
|---|
| 159 |
|
|---|
| 160 | FProgramIndex := 0;
|
|---|
| 161 | NewTargetIndex := 0;
|
|---|
| 162 | while (FProgramIndex < Length(FProgram)) do begin
|
|---|
| 163 | FirstIndex := FProgramIndex;
|
|---|
| 164 | case FProgram[FProgramIndex].Command of
|
|---|
| 165 | cmPointerInc: begin
|
|---|
| 166 | if PreviousCommand in [cmPointerInc, cmPointerDec] then begin
|
|---|
| 167 | if NewProgram[NewProgramIndex - 1].Command = cmPointerInc then
|
|---|
| 168 | NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter +
|
|---|
| 169 | FProgram[FProgramIndex].Parameter
|
|---|
| 170 | else if NewProgram[NewProgramIndex - 1].Command = cmPointerDec then
|
|---|
| 171 | NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter -
|
|---|
| 172 | FProgram[FProgramIndex].Parameter;
|
|---|
| 173 | // If value negative then change command
|
|---|
| 174 | if NewProgram[NewProgramIndex - 1].Parameter < 0 then begin
|
|---|
| 175 | NewProgram[NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter;
|
|---|
| 176 | if NewProgram[NewProgramIndex - 1].Command = cmPointerInc then
|
|---|
| 177 | NewProgram[NewProgramIndex - 1].Command := cmPointerDec
|
|---|
| 178 | else NewProgram[NewProgramIndex - 1].Command := cmPointerInc;
|
|---|
| 179 | end;
|
|---|
| 180 | if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex);
|
|---|
| 181 | Dec(NewProgramIndex);
|
|---|
| 182 | end else begin
|
|---|
| 183 | NewProgram[NewProgramIndex].Command := cmPointerInc;
|
|---|
| 184 | NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter;
|
|---|
| 185 | end;
|
|---|
| 186 | end;
|
|---|
| 187 | cmPointerDec: begin
|
|---|
| 188 | if PreviousCommand in [cmPointerInc, cmPointerDec] then begin
|
|---|
| 189 | if NewProgram[NewProgramIndex - 1].Command = cmPointerDec then
|
|---|
| 190 | NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter +
|
|---|
| 191 | FProgram[FProgramIndex].Parameter
|
|---|
| 192 | else if NewProgram[NewProgramIndex - 1].Command = cmPointerInc then
|
|---|
| 193 | NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter -
|
|---|
| 194 | FProgram[FProgramIndex].Parameter;
|
|---|
| 195 | // If value negative then change command
|
|---|
| 196 | if NewProgram[NewProgramIndex - 1].Parameter < 0 then begin
|
|---|
| 197 | NewProgram[NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter;
|
|---|
| 198 | if NewProgram[NewProgramIndex - 1].Command = cmPointerInc then
|
|---|
| 199 | NewProgram[NewProgramIndex - 1].Command := cmPointerDec
|
|---|
| 200 | else NewProgram[NewProgramIndex - 1].Command := cmPointerInc;
|
|---|
| 201 | end;
|
|---|
| 202 | if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex);
|
|---|
| 203 | Dec(NewProgramIndex);
|
|---|
| 204 | end else begin
|
|---|
| 205 | NewProgram[NewProgramIndex].Command := cmPointerDec;
|
|---|
| 206 | NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter;
|
|---|
| 207 | end;
|
|---|
| 208 | end;
|
|---|
| 209 | cmInc: begin
|
|---|
| 210 | if PreviousCommand in [cmInc, cmDec, cmSet] then begin
|
|---|
| 211 | if NewProgram[NewProgramIndex - 1].Command in [cmInc, cmSet] then
|
|---|
| 212 | NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter +
|
|---|
| 213 | FProgram[FProgramIndex].Parameter
|
|---|
| 214 | else if NewProgram[NewProgramIndex - 1].Command = cmDec then
|
|---|
| 215 | NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter -
|
|---|
| 216 | FProgram[FProgramIndex].Parameter;
|
|---|
| 217 | // If value negative then change command
|
|---|
| 218 | if (NewProgram[NewProgramIndex - 1].Parameter < 0) and (NewProgram[NewProgramIndex - 1].Command <> cmSet) then begin
|
|---|
| 219 | NewProgram[NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter;
|
|---|
| 220 | if NewProgram[NewProgramIndex - 1].Command = cmInc then
|
|---|
| 221 | NewProgram[NewProgramIndex - 1].Command := cmDec
|
|---|
| 222 | else NewProgram[NewProgramIndex - 1].Command := cmInc;
|
|---|
| 223 | end;
|
|---|
| 224 | if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex);
|
|---|
| 225 | Dec(NewProgramIndex);
|
|---|
| 226 | end else begin
|
|---|
| 227 | NewProgram[NewProgramIndex].Command := cmInc;
|
|---|
| 228 | NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter;
|
|---|
| 229 | end;
|
|---|
| 230 | end;
|
|---|
| 231 | cmDec: begin
|
|---|
| 232 | if PreviousCommand in [cmInc, cmDec, cmSet] then begin
|
|---|
| 233 | if NewProgram[NewProgramIndex - 1].Command = cmDec then
|
|---|
| 234 | NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter +
|
|---|
| 235 | FProgram[FProgramIndex].Parameter
|
|---|
| 236 | else if NewProgram[NewProgramIndex - 1].Command in [cmInc, cmSet] then
|
|---|
| 237 | NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter -
|
|---|
| 238 | FProgram[FProgramIndex].Parameter;
|
|---|
| 239 | // If value negative then change command
|
|---|
| 240 | if (NewProgram[NewProgramIndex - 1].Parameter < 0) and (NewProgram[NewProgramIndex - 1].Command <> cmSet) then begin
|
|---|
| 241 | NewProgram[NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter;
|
|---|
| 242 | if NewProgram[NewProgramIndex - 1].Command = cmInc then
|
|---|
| 243 | NewProgram[NewProgramIndex - 1].Command := cmDec
|
|---|
| 244 | else NewProgram[NewProgramIndex - 1].Command := cmInc;
|
|---|
| 245 | end;
|
|---|
| 246 | if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex);
|
|---|
| 247 | Dec(NewProgramIndex);
|
|---|
| 248 | end else begin
|
|---|
| 249 | NewProgram[NewProgramIndex].Command := cmDec;
|
|---|
| 250 | NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter;
|
|---|
| 251 | end;
|
|---|
| 252 | end;
|
|---|
| 253 | cmSet: begin
|
|---|
| 254 | if PreviousCommand in [cmInc, cmDec, cmSet] then begin
|
|---|
| 255 | // Set overrides value of previous commands
|
|---|
| 256 | Dec(NewProgramIndex);
|
|---|
| 257 | NewProgram[NewProgramIndex].Command := cmSet;
|
|---|
| 258 | NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter;
|
|---|
| 259 | end else begin
|
|---|
| 260 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 261 | end;
|
|---|
| 262 | end;
|
|---|
| 263 | cmLoopStart: begin
|
|---|
| 264 | if CheckClear then begin
|
|---|
| 265 | NewProgram[NewProgramIndex] := TMachineOperation.Create(cmSet, 0, 0);
|
|---|
| 266 | Inc(FProgramIndex, 2);
|
|---|
| 267 | end else begin
|
|---|
| 268 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 269 | end;
|
|---|
| 270 | end;
|
|---|
| 271 | else NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 272 | end;
|
|---|
| 273 | PreviousCommand := FProgram[FProgramIndex].Command;
|
|---|
| 274 | DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgramIndex, NewTargetIndex);
|
|---|
| 275 | Inc(NewTargetIndex, Length(GetOperationText(NewProgram[NewProgramIndex])));
|
|---|
| 276 | Inc(FProgramIndex);
|
|---|
| 277 | Inc(NewProgramIndex);
|
|---|
| 278 | end;
|
|---|
| 279 | SetLength(NewProgram, NewProgramIndex);
|
|---|
| 280 |
|
|---|
| 281 | // Replace old program by new program
|
|---|
| 282 | SetLength(FProgram, Length(NewProgram));
|
|---|
| 283 | Move(Pointer(NewProgram)^, Pointer(FProgram)^, SizeOf(TMachineOperation) * Length(NewProgram));
|
|---|
| 284 | end;
|
|---|
| 285 |
|
|---|
| 286 | procedure TBFTarget.OptimizeZeroInitMemory;
|
|---|
| 287 | begin
|
|---|
| 288 | // Here Optimizations related to assumption that initial memory is filled with zeroes
|
|---|
| 289 | // Then code for constants preparation can be translated to cmSet commands
|
|---|
| 290 | // To eliminate also loops for building constants code need to be somehow interpretted partialy
|
|---|
| 291 | end;
|
|---|
| 292 |
|
|---|
| 293 | procedure TBFTarget.OptimizeRelativeIndexes;
|
|---|
| 294 | var
|
|---|
| 295 | NewProgram: array of TMachineOperation;
|
|---|
| 296 | NewProgramIndex: Integer;
|
|---|
| 297 | RelIndex: Integer;
|
|---|
| 298 | FirstIndex: Integer;
|
|---|
| 299 | NewTargetIndex: Integer;
|
|---|
| 300 | begin
|
|---|
| 301 | NewProgramIndex := 0;
|
|---|
| 302 | SetLength(NewProgram, Length(FProgram));
|
|---|
| 303 |
|
|---|
| 304 | RelIndex := 0;
|
|---|
| 305 | FProgramIndex := 0;
|
|---|
| 306 | NewTargetIndex := 0;
|
|---|
| 307 | while (FProgramIndex < Length(FProgram)) do begin
|
|---|
| 308 | FirstIndex := FProgramIndex;
|
|---|
| 309 | case FProgram[FProgramIndex].Command of
|
|---|
| 310 | cmPointerInc: begin
|
|---|
| 311 | RelIndex := RelIndex + FProgram[FProgramIndex].Parameter;
|
|---|
| 312 | Dec(NewProgramIndex);
|
|---|
| 313 | end;
|
|---|
| 314 | cmPointerDec: begin
|
|---|
| 315 | RelIndex := RelIndex - FProgram[FProgramIndex].Parameter;
|
|---|
| 316 | Dec(NewProgramIndex);
|
|---|
| 317 | end;
|
|---|
| 318 | cmInc, cmDec, cmInput, cmOutput, cmSet: begin
|
|---|
| 319 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 320 | NewProgram[NewProgramIndex].RelIndex :=
|
|---|
| 321 | NewProgram[NewProgramIndex].RelIndex + RelIndex;
|
|---|
| 322 | end;
|
|---|
| 323 | cmLoopStart, cmLoopEnd: begin
|
|---|
| 324 | if RelIndex > 0 then begin
|
|---|
| 325 | NewProgram[NewProgramIndex] := TMachineOperation.Create(cmPointerInc,
|
|---|
| 326 | RelIndex, 0);
|
|---|
| 327 | Inc(NewProgramIndex);
|
|---|
| 328 | RelIndex := 0;
|
|---|
| 329 | end else
|
|---|
| 330 | if RelIndex < 0 then begin
|
|---|
| 331 | NewProgram[NewProgramIndex] := TMachineOperation.Create(cmPointerDec,
|
|---|
| 332 | Abs(RelIndex), 0);
|
|---|
| 333 | Inc(NewProgramIndex);
|
|---|
| 334 | RelIndex := 0;
|
|---|
| 335 | end;
|
|---|
| 336 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 337 | end;
|
|---|
| 338 | else raise Exception.Create(Format('Unsupported command %d', [FProgram[FProgramIndex].Command]));
|
|---|
| 339 | end;
|
|---|
| 340 | DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgramIndex, NewTargetIndex);
|
|---|
| 341 | Inc(NewTargetIndex, Length(GetOperationText(NewProgram[NewProgramIndex])));
|
|---|
| 342 | Inc(FProgramIndex);
|
|---|
| 343 | Inc(NewProgramIndex);
|
|---|
| 344 | end;
|
|---|
| 345 | SetLength(NewProgram, NewProgramIndex);
|
|---|
| 346 |
|
|---|
| 347 | // Replace old program by new program
|
|---|
| 348 | SetLength(FProgram, Length(NewProgram));
|
|---|
| 349 | Move(Pointer(NewProgram)^, Pointer(FProgram)^, SizeOf(TMachineOperation) *
|
|---|
| 350 | Length(NewProgram));
|
|---|
| 351 | end;
|
|---|
| 352 |
|
|---|
| 353 | procedure TBFTarget.OptimizeCopyMultiply;
|
|---|
| 354 | var
|
|---|
| 355 | NewProgram: array of TMachineOperation;
|
|---|
| 356 | NewProgramIndex: Integer;
|
|---|
| 357 | ProcessLoop: Boolean;
|
|---|
| 358 | PointerChange: Integer;
|
|---|
| 359 | NumberOfBaseDecrement: Integer;
|
|---|
| 360 | LoopStartIndex: Integer;
|
|---|
| 361 | LoopStartIndexNew: Integer;
|
|---|
| 362 | FirstIndex: Integer;
|
|---|
| 363 | NewTextIndex: Integer;
|
|---|
| 364 | begin
|
|---|
| 365 | NewProgramIndex := 0;
|
|---|
| 366 | SetLength(NewProgram, Length(FProgram));
|
|---|
| 367 |
|
|---|
| 368 | NumberOfBaseDecrement := 0;
|
|---|
| 369 | ProcessLoop := False;
|
|---|
| 370 | FProgramIndex := 0;
|
|---|
| 371 | NewTextIndex := 0;
|
|---|
| 372 | PointerChange := 0;
|
|---|
| 373 | while (FProgramIndex < Length(FProgram)) do begin
|
|---|
| 374 | FirstIndex := FProgramIndex;
|
|---|
| 375 | case FProgram[FProgramIndex].Command of
|
|---|
| 376 | cmPointerInc: begin
|
|---|
| 377 | PointerChange := PointerChange + FProgram[FProgramIndex].Parameter;
|
|---|
| 378 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 379 | end;
|
|---|
| 380 | cmPointerDec: begin
|
|---|
| 381 | PointerChange := PointerChange - FProgram[FProgramIndex].Parameter;
|
|---|
| 382 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 383 | end;
|
|---|
| 384 | cmInc: begin
|
|---|
| 385 | if not ProcessLoop then begin
|
|---|
| 386 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 387 | end else begin
|
|---|
| 388 | if ((FProgram[FProgramIndex].RelIndex + PointerChange) <> 0) then begin
|
|---|
| 389 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 390 | NewProgram[NewProgramIndex].Command := cmMultipy;
|
|---|
| 391 | end else Dec(NewProgramIndex);
|
|---|
| 392 | end;
|
|---|
| 393 | end;
|
|---|
| 394 | cmDec: begin
|
|---|
| 395 | if not ProcessLoop then begin
|
|---|
| 396 | if (PointerChange = 0) and (FProgram[FProgramIndex].RelIndex = 0) and
|
|---|
| 397 | (FProgram[FProgramIndex].Parameter = 1) then
|
|---|
| 398 | Inc(NumberOfBaseDecrement);
|
|---|
| 399 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 400 | end else begin
|
|---|
| 401 | if ((FProgram[FProgramIndex].RelIndex + PointerChange) <> 0) then begin
|
|---|
| 402 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 403 | NewProgram[NewProgramIndex].Command := cmMultipy;
|
|---|
| 404 | NewProgram[NewProgramIndex].Parameter := -FProgram[FProgramIndex].Parameter;
|
|---|
| 405 | end else Dec(NewProgramIndex);
|
|---|
| 406 | end;
|
|---|
| 407 | end;
|
|---|
| 408 | cmInput, cmOutput: begin
|
|---|
| 409 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 410 | Inc(NumberOfBaseDecrement, 2);
|
|---|
| 411 | end;
|
|---|
| 412 | cmSet: begin
|
|---|
| 413 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 414 | Inc(NumberOfBaseDecrement, 2);
|
|---|
| 415 | end;
|
|---|
| 416 | cmLoopStart: begin
|
|---|
| 417 | if not ProcessLoop then begin
|
|---|
| 418 | NumberOfBaseDecrement := 0;
|
|---|
| 419 | PointerChange := 0;
|
|---|
| 420 | LoopStartIndex := FProgramIndex;
|
|---|
| 421 | LoopStartIndexNew := NewProgramIndex;
|
|---|
| 422 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 423 | end else begin
|
|---|
| 424 | Dec(NewProgramIndex);
|
|---|
| 425 | end;
|
|---|
| 426 | end;
|
|---|
| 427 | cmLoopEnd: begin
|
|---|
| 428 | if not ProcessLoop then begin
|
|---|
| 429 | if (NumberOfBaseDecrement = 1) and (PointerChange = 0) then begin
|
|---|
| 430 | FProgramIndex := LoopstartIndex - 1;
|
|---|
| 431 | NewProgramIndex := LoopStartIndexNew - 1;
|
|---|
| 432 | ProcessLoop := True;
|
|---|
| 433 | end else begin
|
|---|
| 434 | NewProgram[NewProgramIndex] := FProgram[FProgramIndex];
|
|---|
| 435 | end;
|
|---|
| 436 | end else begin
|
|---|
| 437 | NewProgram[NewProgramIndex] := TMachineOperation.Create(cmSet, 0, 0);
|
|---|
| 438 | ProcessLoop := False;
|
|---|
| 439 | NumberOfBaseDecrement := 0;
|
|---|
| 440 | end;
|
|---|
| 441 | end;
|
|---|
| 442 | else raise Exception.Create(Format('Unsupported command %d', [FProgram[FProgramIndex].Command]));
|
|---|
| 443 | end;
|
|---|
| 444 | DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgramIndex, NewTextIndex);
|
|---|
| 445 | Inc(NewTextIndex, Length(GetOperationText(NewProgram[NewProgramIndex])));
|
|---|
| 446 | Inc(FProgramIndex);
|
|---|
| 447 | Inc(NewProgramIndex);
|
|---|
| 448 | end;
|
|---|
| 449 | SetLength(NewProgram, NewProgramIndex);
|
|---|
| 450 |
|
|---|
| 451 | // Replace old program by new program
|
|---|
| 452 | SetLength(FProgram, Length(NewProgram));
|
|---|
| 453 | Move(Pointer(NewProgram)^, Pointer(FProgram)^, SizeOf(TMachineOperation) *
|
|---|
| 454 | Length(NewProgram));
|
|---|
| 455 | end;
|
|---|
| 456 |
|
|---|
| 457 | function TBFTarget.GetOperationText(Operation: TMachineOperation): string;
|
|---|
| 458 | begin
|
|---|
| 459 | Result := BrainFuckCommandText[Operation.Command];
|
|---|
| 460 | if Operation.Command in [cmInc, cmDec, cmPointerInc, cmPointerDec,
|
|---|
| 461 | cmSet, cmMultipy] then begin
|
|---|
| 462 | if Operation.Parameter <> 1 then
|
|---|
| 463 | Result := Result + IntToStr(Operation.Parameter);
|
|---|
| 464 | end;
|
|---|
| 465 | if Operation.RelIndex <> 0 then
|
|---|
| 466 | Result := Result + 'R' + IntToStr(Operation.RelIndex);
|
|---|
| 467 | end;
|
|---|
| 468 |
|
|---|
| 469 | procedure TBFTarget.LoadProgram;
|
|---|
| 470 | var
|
|---|
| 471 | I: Integer;
|
|---|
| 472 | begin
|
|---|
| 473 | inherited;
|
|---|
| 474 | DebugSteps.Clear;
|
|---|
| 475 | SetLength(FProgram, Length(FSourceCode));
|
|---|
| 476 | FProgramIndex := 0;
|
|---|
| 477 | for I := 1 to Length(FSourceCode) do begin
|
|---|
| 478 | case FSourceCode[I] of
|
|---|
| 479 | '+': begin
|
|---|
| 480 | FProgram[FProgramIndex] := TMachineOperation.Create(cmInc, 1, 0);
|
|---|
| 481 | DebugSteps.AddStep(I - 1, FProgramIndex, soNormal);
|
|---|
| 482 | end;
|
|---|
| 483 | '-': begin
|
|---|
| 484 | FProgram[FProgramIndex] := TMachineOperation.Create(cmDec, 1, 0);
|
|---|
| 485 | DebugSteps.AddStep(I - 1, FProgramIndex, soNormal);
|
|---|
| 486 | end;
|
|---|
| 487 | '>': begin
|
|---|
| 488 | FProgram[FProgramIndex] := TMachineOperation.Create(cmPointerInc, 1, 0);
|
|---|
| 489 | DebugSteps.AddStep(I - 1, FProgramIndex, soNormal);
|
|---|
| 490 | end;
|
|---|
| 491 | '<': begin
|
|---|
| 492 | FProgram[FProgramIndex] := TMachineOperation.Create(cmPointerDec, 1, 0);
|
|---|
| 493 | DebugSteps.AddStep(I - 1, FProgramIndex, soNormal);
|
|---|
| 494 | end;
|
|---|
| 495 | ',': begin
|
|---|
| 496 | FProgram[FProgramIndex] := TMachineOperation.Create(cmInput, 0, 0);
|
|---|
| 497 | DebugSteps.AddStep(I - 1, FProgramIndex, soNormal);
|
|---|
| 498 | end;
|
|---|
| 499 | '.': begin
|
|---|
| 500 | FProgram[FProgramIndex] := TMachineOperation.Create(cmOutput, 0, 0);
|
|---|
| 501 | DebugSteps.AddStep(I - 1, FProgramIndex, soNormal);
|
|---|
| 502 | end;
|
|---|
| 503 | '[': begin
|
|---|
| 504 | FProgram[FProgramIndex] := TMachineOperation.Create(cmLoopStart, 0, 0);
|
|---|
| 505 | DebugSteps.AddStep(I - 1, FProgramIndex, soStepIn);
|
|---|
| 506 | end;
|
|---|
| 507 | ']': begin
|
|---|
| 508 | FProgram[FProgramIndex] := TMachineOperation.Create(cmLoopEnd, 0 ,0);
|
|---|
| 509 | DebugSteps.AddStep(I - 1, FProgramIndex, soStepOut);
|
|---|
| 510 | end
|
|---|
| 511 | else Dec(FProgramIndex);
|
|---|
| 512 | end;
|
|---|
| 513 | Inc(FProgramIndex);
|
|---|
| 514 | end;
|
|---|
| 515 | SetLength(FProgram, FProgramIndex);
|
|---|
| 516 | end;
|
|---|
| 517 |
|
|---|
| 518 | constructor TBFTarget.Create;
|
|---|
| 519 | begin
|
|---|
| 520 | inherited Create;
|
|---|
| 521 | MemorySize := 30000;
|
|---|
| 522 | CellSize := 256;
|
|---|
| 523 | end;
|
|---|
| 524 |
|
|---|
| 525 | procedure TBFTarget.OptimizeSource;
|
|---|
| 526 | var
|
|---|
| 527 | OldLength: Integer;
|
|---|
| 528 | begin
|
|---|
| 529 | inherited;
|
|---|
| 530 | if Optimizations.AddSub then OptimizeAddSub;
|
|---|
| 531 | if Optimizations.Merge then
|
|---|
| 532 | repeat
|
|---|
| 533 | OldLength := Length(FProgram);
|
|---|
| 534 | OptimizeMerge;
|
|---|
| 535 | until Length(FProgram) = OldLength;
|
|---|
| 536 | OptimizeZeroInitMemory;
|
|---|
| 537 | if Optimizations.RelativeIndexes then OptimizeRelativeIndexes;
|
|---|
| 538 | if Optimizations.CopyMultiply then OptimizeCopyMultiply;
|
|---|
| 539 | end;
|
|---|
| 540 |
|
|---|
| 541 |
|
|---|
| 542 |
|
|---|
| 543 | end.
|
|---|
| 544 |
|
|---|