source: trunk/Compiler/Compiler.pas

Last change on this file was 77, checked in by chronos, 6 months ago
  • Modified: Compiler targets moved into modules.
File size: 6.7 KB
Line 
1unit Compiler;
2
3interface
4
5uses
6 SysUtils, Variants, Classes, FileUtil, ModularSystem, CompilerAPI,
7 Dialogs, SourceCodePascal, Producer, Analyzer, Generics.Collections, Target;
8
9type
10 TErrorMessage = class
11 Text: string;
12 Position: TPoint;
13 FileName: string;
14 end;
15
16 { TSourceFileManager }
17
18 TSourceFileManager = class
19 Files: TStringList;
20 function LoadStringFromFile(FileName: string): string;
21 procedure SaveStringToFile(FileName: string; Content: string);
22 public
23 function GetFileContent(Name: string; var Content: string): Boolean;
24 function SetFileContent(Name: string; const Content: string): Boolean;
25 constructor Create;
26 destructor Destroy; override;
27 end;
28
29 { TCompilerList }
30
31 TCompiler = class
32 private
33 FAnalyzer: TAnalyzer;
34 FOnLoadSource: TGetSourceEvent;
35 FOnSaveTarget: TWriteTargetEvent;
36 FTarget: TTarget;
37 FOnErrorMessage: TErrorMessageEvent;
38 procedure SetAnalyzer(const AValue: TAnalyzer);
39 procedure AnalyzeAll;
40 procedure ProduceAll;
41 procedure SetTarget(AValue: TTarget);
42 public
43 AbstractCode: TProgram;
44 ErrorMessages: TObjectList<TErrorMessage>;
45 CompiledFolder: string;
46
47 Targets: TTargets;
48 Analyzers: TAnalyzers;
49 Convertors: TObjectList<TObject>;
50 Executors: TObjectList<TObject>;
51 API: TCompilerAPI;
52 TargetFolder: string;
53 MainSource: string;
54 ModuleManager: TModuleManager;
55 procedure ErrorMessage(Text: string; Position: TPoint; FileName: string);
56 constructor Create; virtual;
57 destructor Destroy; override;
58 procedure Init; virtual;
59 procedure Compile;
60 property OnErrorMessage: TErrorMessageEvent read FOnErrorMessage
61 write FOnErrorMessage;
62 property Analyzer: TAnalyzer read FAnalyzer write SetAnalyzer;
63 property Target: TTarget read FTarget write SetTarget;
64 property OnLoadSource: TGetSourceEvent read FOnLoadSource write FOnLoadSource;
65 property OnSaveTarget: TWriteTargetEvent read FOnSaveTarget write FOnSaveTarget;
66 end;
67
68
69implementation
70
71uses
72 AnalyzerPascal;
73
74resourcestring
75 SNothingToAnalyze = 'Nothing to analyze';
76 SRewritingExistedTarget = 'Rewriting existing target file %s';
77
78{ TSourceFileManager }
79
80function TSourceFileManager.LoadStringFromFile(FileName: string): string;
81var
82 F: TFileStream;
83begin
84 try
85 F := TFileStream.Create(UTF8Decode(FileName), fmOpenRead);
86 SetLength(Result, F.Size);
87 if F.Size > 0 then
88 F.Read(Result[1], F.Size);
89 finally
90 F.Free;
91 end;
92end;
93
94procedure TSourceFileManager.SaveStringToFile(FileName: string; Content: string);
95var
96 F: TFileStream;
97begin
98 try
99 ForceDirectories(ExtractFileDir(FileName));
100 if FileExists(FileName) then
101 F := TFileStream.Create(UTF8Decode(FileName), fmOpenWrite)
102 else F := TFileStream.Create(UTF8Decode(FileName), fmCreate);
103 F.Size := 0;
104 if Length(Content) > 0 then
105 F.Write(Content[1], Length(Content));
106 finally
107 F.Free;
108 end;
109end;
110
111function TSourceFileManager.GetFileContent(Name: string; var Content: string): Boolean;
112var
113 I: Integer;
114begin
115 I := 0;
116 while (I < Files.Count) and (ExtractFileName(Files[I]) <> Name) do Inc(I);
117 if I < Files.Count then begin
118 if FileExists(Files[I]) then begin
119 Content := LoadStringFromFile(Files[I]);
120 Result := True;
121 end else Result := False;
122 end else Result := False;
123end;
124
125function TSourceFileManager.SetFileContent(Name: string; const Content: string
126 ): Boolean;
127var
128 I: Integer;
129 F: TFileStream;
130begin
131 I := 0;
132 while (I < Files.Count) and (ExtractFileName(Files[I]) <> Name) do Inc(I);
133 if I >= Files.Count then begin
134 SaveStringToFile(Name, Content);
135 Result := True;
136 Files.Add(Name);
137 end else begin
138 Result := False;
139 //ErrorMessage(Format(SRewritingExistedTarget, [Name]), Point(0, 0), '');
140 end;
141end;
142
143constructor TSourceFileManager.Create;
144begin
145 Files := TStringList.Create;
146end;
147
148destructor TSourceFileManager.Destroy;
149begin
150 FreeAndNil(Files);
151 inherited;
152end;
153
154{ TCompiler }
155
156procedure TCompiler.Compile;
157begin
158 Analyzer.OnGetSource := OnLoadSource;
159 AnalyzeAll;
160 if Assigned(Target.Producer) then
161 Target.Producer.OnWriteTarget := OnSaveTarget;
162 ProduceAll;
163end;
164
165constructor TCompiler.Create;
166begin
167 Targets := TTargets.Create;
168 Analyzers := TAnalyzers.Create;
169 Convertors := TObjectList<TObject>.Create;
170 Executors := TObjectList<TObject>.Create;
171 API := TCompilerAPI.Create;
172 API.Compiler := Self;
173 AbstractCode := TProgram.Create;
174 ErrorMessages := TObjectList<TErrorMessage>.Create;
175 CompiledFolder := 'Compiled';
176 ModuleManager := TModuleManager.Create(nil);
177 ModuleManager.API := API;
178end;
179
180procedure TCompiler.Init;
181begin
182 ErrorMessages.Clear;
183 AbstractCode.Clear;
184end;
185
186destructor TCompiler.Destroy;
187begin
188 FreeAndNil(ModuleManager);
189 FreeAndNil(AbstractCode);
190 FreeAndNil(ErrorMessages);
191 FreeAndNil(Targets);
192 FreeAndNil(Analyzers);
193 FreeAndNil(Executors);
194 FreeAndNil(Convertors);
195 inherited;
196end;
197
198procedure TCompiler.ErrorMessage(Text: string; Position: TPoint; FileName: string);
199var
200 NewMessage: TErrorMessage;
201begin
202 NewMessage := TErrorMessage.Create;
203 NewMessage.Text := Text;
204 NewMessage.Position := Position;
205 NewMessage.FileName := FileName;
206 ErrorMessages.Add(NewMessage);
207 if Assigned(FOnErrorMessage) then FOnErrorMessage(Text, Position, FileName);
208end;
209
210procedure TCompiler.SetAnalyzer(const AValue: TAnalyzer);
211begin
212 if FAnalyzer = AValue then exit;
213 FAnalyzer := AValue;
214 if Assigned(Analyzer) then begin
215 Analyzer.OnErrorMessage := ErrorMessage;
216 Analyzer.OnGetSource := OnLoadSource;
217 end;
218end;
219
220procedure TCompiler.AnalyzeAll;
221begin
222 if MainSource <> '' then begin
223 Analyzer.FileName := MainSource;
224 Analyzer.OnGetSource(ExtractFileName(Analyzer.FileName), Analyzer.SourceCode2);
225 Analyzer.Process;
226 Analyzer.ParseModule(AbstractCode);
227 end else raise Exception.Create(SNothingToAnalyze);
228end;
229
230procedure TCompiler.ProduceAll;
231var
232 NewModule: TSourceModule;
233 ProducedCode: TStringList;
234 I: Integer;
235 TargetFileName: string;
236begin
237 if Assigned(Target.Producer) then
238 try
239 ProducedCode := TStringList.Create;
240 with AbstractCode do
241 for I := 0 to Modules.Count - 1 do begin
242 Target.Producer.Produce(TSourceModule(Modules[I]));
243 Target.Producer.AssignToStringList(ProducedCode);
244 TargetFileName := TargetFolder + DirectorySeparator + TSourceModule(Modules[I]).TargetFile;
245 if Assigned(Target.Producer.OnWriteTarget) then
246 Target.Producer.OnWriteTarget(TargetFileName, ProducedCode.Text);
247 end;
248 finally
249 ProducedCode.Free;
250 end;
251end;
252
253procedure TCompiler.SetTarget(AValue: TTarget);
254begin
255 if FTarget = AValue then Exit;
256 FTarget := AValue;
257 if Assigned(FTarget) then begin
258 FTarget.Compiler := Self;
259 if Assigned(FTarget.Producer) then
260 FTarget.Producer.OnWriteTarget := OnSaveTarget;
261 end;
262end;
263
264end.
Note: See TracBrowser for help on using the repository browser.