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 |
|
---|