| 1 | unit Optimizer;
|
|---|
| 2 |
|
|---|
| 3 | interface
|
|---|
| 4 |
|
|---|
| 5 | uses
|
|---|
| 6 | Classes, SysUtils, Source, SourceNode;
|
|---|
| 7 |
|
|---|
| 8 | type
|
|---|
| 9 | TOptimizeFeature = (ofReplaceRepeatUntilByWhileDo, ofReplaceResultByReturn);
|
|---|
| 10 | TOptimizeFeatures = set of TOptimizeFeature;
|
|---|
| 11 |
|
|---|
| 12 | { TOptimizer }
|
|---|
| 13 |
|
|---|
| 14 | TOptimizer = class
|
|---|
| 15 | private
|
|---|
| 16 | procedure OptimizeNodes(SourceNodes: TSourceNodeList<TSourceNode>; out NewNode: TSourceNode);
|
|---|
| 17 | procedure OptimizeNode(SourceNode: TSourceNode; out NewNode: TSourceNode);
|
|---|
| 18 | public
|
|---|
| 19 | Prog: TProgram;
|
|---|
| 20 | Features: TOptimizeFeatures;
|
|---|
| 21 | procedure Optimize;
|
|---|
| 22 | end;
|
|---|
| 23 |
|
|---|
| 24 | implementation
|
|---|
| 25 |
|
|---|
| 26 | resourcestring
|
|---|
| 27 | SUnsupportedNodeType = 'Unsupported node type';
|
|---|
| 28 |
|
|---|
| 29 | { TOptimizer }
|
|---|
| 30 |
|
|---|
| 31 | procedure TOptimizer.OptimizeNodes(SourceNodes: TSourceNodeList<TSourceNode>; out
|
|---|
| 32 | NewNode: TSourceNode);
|
|---|
| 33 | var
|
|---|
| 34 | I: Integer;
|
|---|
| 35 | TempNewNode: TSourceNode;
|
|---|
| 36 | begin
|
|---|
| 37 | for I := 0 to SourceNodes.Count - 1 do begin
|
|---|
| 38 | if SourceNodes[I] is TSourceNode then begin
|
|---|
| 39 | OptimizeNode(TSourceNode(SourceNodes[I]), TempNewNode);
|
|---|
| 40 | if Assigned(TempNewNode) and (TempNewNode <> TSourceNode(SourceNodes[I])) then begin
|
|---|
| 41 | SourceNodes[I] := TempNewNode;
|
|---|
| 42 | end;
|
|---|
| 43 | end else raise Exception.Create(SUnsupportedNodeType);
|
|---|
| 44 | end;
|
|---|
| 45 | end;
|
|---|
| 46 |
|
|---|
| 47 | procedure TOptimizer.OptimizeNode(SourceNode: TSourceNode; out
|
|---|
| 48 | NewNode: TSourceNode);
|
|---|
| 49 | var
|
|---|
| 50 | I: Integer;
|
|---|
| 51 | WhileDo: TWhileDo;
|
|---|
| 52 | Condition: TIfThenElse;
|
|---|
| 53 | Return: TReturn;
|
|---|
| 54 | Field: TField;
|
|---|
| 55 | Obj: TObject;
|
|---|
| 56 | TempNewNode: TSourceNode;
|
|---|
| 57 | ListValue: TSourceNodeList<TSourceNode>;
|
|---|
| 58 | begin
|
|---|
| 59 | NewNode := nil;
|
|---|
| 60 | if (ofReplaceRepeatUntilByWhileDo in Features) and (SourceNode is TRepeatUntil) then begin
|
|---|
| 61 | WhileDo := TWhileDo.Create;
|
|---|
| 62 | WhileDo.Command := TBeginEnd.Create;
|
|---|
| 63 | WhileDo.Parent := TRepeatUntil(SourceNode).Parent;
|
|---|
| 64 | TBeginEnd(WhileDo.Command).Commands := TRepeatUntil(SourceNode).Commands;
|
|---|
| 65 | TBeginEnd(WhileDo.Command).Parent := WhileDo;
|
|---|
| 66 | TRepeatUntil(SourceNode).Commands := TCommands.Create;
|
|---|
| 67 | WhileDo.Expression := TExpressionOperand.Create;
|
|---|
| 68 | WhileDo.Expression.Parent := WhileDo;
|
|---|
| 69 | TExpressionOperand(WhileDo.Expression).OperandType := otConstantDirect;
|
|---|
| 70 | TExpressionOperand(WhileDo.Expression).ConstantDirect := TConstant.Create;
|
|---|
| 71 | TConstant(TExpressionOperand(WhileDo.Expression).ConstantDirect).Value := TValueBoolean.Create;
|
|---|
| 72 | TValueBoolean(TConstant(TExpressionOperand(WhileDo.Expression).ConstantDirect).Value).Value := True;
|
|---|
| 73 |
|
|---|
| 74 | // Add final if
|
|---|
| 75 | Condition := TIfThenElse.Create;
|
|---|
| 76 | Condition.Parent := WhileDo;
|
|---|
| 77 | Condition.Expression := TRepeatUntil(SourceNode).Expression;
|
|---|
| 78 | Condition.CommandThen := TBreak.Create;
|
|---|
| 79 | Condition.CommandThen.Parent := Condition;
|
|---|
| 80 | TRepeatUntil(SourceNode).Expression := TExpression.Create;
|
|---|
| 81 | TBeginEnd(WhileDo.Command).Commands.Add(Condition);
|
|---|
| 82 | NewNode := WhileDo;
|
|---|
| 83 | end else
|
|---|
| 84 | if (ofReplaceResultByReturn in Features) and (SourceNode is TAssignment) then begin
|
|---|
| 85 | if TAssignment(SourceNode).Variable.Name = 'Result' then begin
|
|---|
| 86 | Return := TReturn.Create;
|
|---|
| 87 | Return.Parent := TAssignment(SourceNode).Parent;
|
|---|
| 88 | Return.Expression.Free;
|
|---|
| 89 | Return.Expression := TAssignment(SourceNode).Expression;
|
|---|
| 90 | Return.Expression.Parent := Return;
|
|---|
| 91 | TAssignment(SourceNode).Expression := TExpression.Create;
|
|---|
| 92 | NewNode := Return;
|
|---|
| 93 | end;
|
|---|
| 94 | end else
|
|---|
| 95 | if SourceNode is TSourceNode then begin
|
|---|
| 96 | for I := 0 to SourceNode.FieldsCount - 1 do begin
|
|---|
| 97 | Field := SourceNode.GetField(I);
|
|---|
| 98 | if Field.DataType = dtObject then begin
|
|---|
| 99 | SourceNode.GetValue(I, Obj);
|
|---|
| 100 | if Obj is TSourceNode then begin
|
|---|
| 101 | OptimizeNode(TSourceNode(Obj), TempNewNode);
|
|---|
| 102 | if Assigned(TempNewNode) and (TempNewNode <> TSourceNode(Obj)) then begin
|
|---|
| 103 | SourceNode.SetValueObject(I, TempNewNode);
|
|---|
| 104 | end;
|
|---|
| 105 | end;
|
|---|
| 106 | end;
|
|---|
| 107 | Field.Free;
|
|---|
| 108 | end;
|
|---|
| 109 | end else
|
|---|
| 110 | raise Exception.Create(SUnsupportedNodeType);
|
|---|
| 111 |
|
|---|
| 112 | for I := 0 to SourceNode.FieldsCount - 1 do begin
|
|---|
| 113 | Field := SourceNode.GetField(I);
|
|---|
| 114 | if Field.DataType = dtList then begin
|
|---|
| 115 | SourceNode.GetValue(I, ListValue);
|
|---|
| 116 | OptimizeNodes(TSourceNodeList<TSourceNode>(ListValue), NewNode)
|
|---|
| 117 | end;
|
|---|
| 118 | end;
|
|---|
| 119 | end;
|
|---|
| 120 |
|
|---|
| 121 | procedure TOptimizer.Optimize;
|
|---|
| 122 | var
|
|---|
| 123 | NewProg: TSourceNode;
|
|---|
| 124 | begin
|
|---|
| 125 | OptimizeNode(Prog, NewProg);
|
|---|
| 126 | end;
|
|---|
| 127 |
|
|---|
| 128 | end.
|
|---|
| 129 |
|
|---|