source: tags/1.1.0/UBFTarget.pas

Last change on this file was 115, checked in by chronos, 4 years ago
  • Fixed: Build with Lazarus 2.0.10.
  • Modified: CoolTranslator package replaced by Translator in Common package.
  • Modified: About dialog moved to Common package.
File size: 20.1 KB
Line 
1unit UBFTarget;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, UTarget;
9
10type
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
58const
59 BrainFuckCommandText: array[TMachineCommand] of Char = (
60 ' ', '+', '-', '>', '<', '.', ',', '[', ']', '@', '=', '*');
61
62
63implementation
64
65{ TMachineOperation }
66
67class function TMachineOperation.Create(Command: TMachineCommand; Parameter,
68 RelIndex: Integer): TMachineOperation;
69begin
70 Result.Command := Command;
71 Result.Parameter := Parameter;
72 Result.RelIndex := RelIndex;
73end;
74
75function TBFTarget.CheckClear: Boolean;
76begin
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);
81end;
82
83function TBFTarget.CheckOccurence(C: TMachineCommand): Integer;
84begin
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;
90end;
91
92function TBFTarget.CheckOccurenceSumParam(C: TMachineCommand): Integer;
93begin
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;
99end;
100
101procedure TBFTarget.OptimizeAddSub;
102var
103 NewProgram: array of TMachineOperation;
104 NewProgramIndex: Integer;
105 NewTargetPos: Integer;
106 FirstIndex: Integer;
107begin
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));
144end;
145
146procedure TBFTarget.OptimizeMerge;
147var
148 NewProgram: array of TMachineOperation;
149 NewProgramIndex: Integer;
150 PreviousCommand: TMachineCommand;
151 FirstIndex: Integer;
152 NewTargetIndex: Integer;
153begin
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));
284end;
285
286procedure TBFTarget.OptimizeZeroInitMemory;
287begin
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
291end;
292
293procedure TBFTarget.OptimizeRelativeIndexes;
294var
295 NewProgram: array of TMachineOperation;
296 NewProgramIndex: Integer;
297 RelIndex: Integer;
298 FirstIndex: Integer;
299 NewTargetIndex: Integer;
300begin
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));
351end;
352
353procedure TBFTarget.OptimizeCopyMultiply;
354var
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;
364begin
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));
455end;
456
457function TBFTarget.GetOperationText(Operation: TMachineOperation): string;
458begin
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);
467end;
468
469procedure TBFTarget.LoadProgram;
470var
471 I: Integer;
472begin
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);
516end;
517
518constructor TBFTarget.Create;
519begin
520 inherited Create;
521 MemorySize := 30000;
522 CellSize := 256;
523end;
524
525procedure TBFTarget.OptimizeSource;
526var
527 OldLength: Integer;
528begin
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;
539end;
540
541
542
543end.
544
Note: See TracBrowser for help on using the repository browser.