1 | unit ProducerGCC;
|
---|
2 |
|
---|
3 | interface
|
---|
4 |
|
---|
5 | uses
|
---|
6 | SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,
|
---|
7 | SourceCodePascal, Producer, StrUtils;
|
---|
8 |
|
---|
9 | type
|
---|
10 |
|
---|
11 | { TProducerGCCC }
|
---|
12 |
|
---|
13 | TProducerGCCC = class(TProducer)
|
---|
14 | private
|
---|
15 | function TranslateType(Name: string): string;
|
---|
16 | function TranslateOperator(Name: string): string;
|
---|
17 | procedure Emit(AText: string);
|
---|
18 | procedure EmitLn(AText: string = '');
|
---|
19 | procedure GenerateUses(UsedModules: TUsedModules);
|
---|
20 | procedure GenerateModule(Module: TSourceModule);
|
---|
21 | procedure GenerateCommonBlock(CommonBlock: TCommonBlock;
|
---|
22 | LabelPrefix: string);
|
---|
23 | procedure GenerateType(AType: TType);
|
---|
24 | procedure GenerateTypes(Types: TTypes);
|
---|
25 | procedure GenerateProgram(ProgramBlock: TProgram);
|
---|
26 | procedure GenerateFunctions(Functions: TFunctions;
|
---|
27 | Prefix: string = '');
|
---|
28 | procedure GenerateBeginEnd(BeginEnd: TBeginEnd);
|
---|
29 | procedure GenerateVariableList(VariableList: TVariables);
|
---|
30 | procedure GenerateVariable(Variable: TVariable);
|
---|
31 | procedure GenerateCommand(Command: TCommand);
|
---|
32 | procedure GenerateWhileDo(WhileDo: TWhileDo);
|
---|
33 | procedure GenerateForToDo(ForToDo: TForToDo);
|
---|
34 | procedure GenerateIfThenElse(IfThenElse: TIfThenElse);
|
---|
35 | procedure GenerateAssignment(Assignment: TAssignment);
|
---|
36 | procedure GenerateFunctionCall(FunctionCall: TFunctionCall);
|
---|
37 | function GenerateExpression(Expression: TExpression): string;
|
---|
38 | public
|
---|
39 | TextSource: TStringList;
|
---|
40 | IndentationLength: Integer;
|
---|
41 | Indetation: Integer;
|
---|
42 | procedure AssignToStringList(Target: TStringList); override;
|
---|
43 | procedure Produce(Module: TSourceModule); override;
|
---|
44 | constructor Create;
|
---|
45 | destructor Destroy; override;
|
---|
46 | end;
|
---|
47 |
|
---|
48 |
|
---|
49 | implementation
|
---|
50 |
|
---|
51 | { TProducerGCCC }
|
---|
52 |
|
---|
53 | constructor TProducerGCCC.Create;
|
---|
54 | begin
|
---|
55 | TextSource := TStringList.Create;
|
---|
56 | IndentationLength := 2;
|
---|
57 | {$IFDEF Windows}
|
---|
58 | CompilerPath := 'c:\Program Files\MinGW\bin\gcc.exe -o %1:s';
|
---|
59 | {$ENDIF}
|
---|
60 | {$IFDEF Linux}
|
---|
61 | CompilerPath := '/usr/bin/gcc';
|
---|
62 | {$ENDIF}
|
---|
63 | end;
|
---|
64 |
|
---|
65 | destructor TProducerGCCC.Destroy;
|
---|
66 | begin
|
---|
67 | FreeAndNil(TextSource);
|
---|
68 | inherited;
|
---|
69 | end;
|
---|
70 |
|
---|
71 | function TProducerGCCC.TranslateType(Name: string): string;
|
---|
72 | begin
|
---|
73 | if Name = 'Byte' then Result := 'uint8'
|
---|
74 | else if Name = 'ShortInt' then Result := 'int8'
|
---|
75 | else if Name = 'Word' then Result := 'int16'
|
---|
76 | else if Name = 'SmallInt' then Result := 'int16'
|
---|
77 | else if Name = 'Cardinal' then Result := 'uint32'
|
---|
78 | else if Name = 'Integer' then Result := 'int32'
|
---|
79 | else if Name = 'Void' then Result := 'void'
|
---|
80 | else Result := Name;
|
---|
81 | end;
|
---|
82 |
|
---|
83 | function TProducerGCCC.TranslateOperator(Name: string): string;
|
---|
84 | begin
|
---|
85 | if Name = '=' then Result := '=='
|
---|
86 | else if Name = 'shl' then Result := '<<'
|
---|
87 | else if Name = 'shr' then Result := '>>'
|
---|
88 | else if Name = 'not' then Result := '!'
|
---|
89 | else if Name = 'mod' then Result := '^'
|
---|
90 | else if Name = ':=' then Result := '='
|
---|
91 | else if Name = '@' then Result := '*'
|
---|
92 | else if Name = 'and' then Result := '&'
|
---|
93 | else if Name = 'or' then Result := '|'
|
---|
94 | else if Name = 'xor' then Result := '^'
|
---|
95 | else Result := Name;
|
---|
96 | end;
|
---|
97 |
|
---|
98 | procedure TProducerGCCC.EmitLn(AText: string = '');
|
---|
99 | begin
|
---|
100 | Emit(AText);
|
---|
101 | TextSource.Add('');
|
---|
102 | end;
|
---|
103 |
|
---|
104 | procedure TProducerGCCC.Emit(AText: string);
|
---|
105 | begin
|
---|
106 | with TextSource do begin
|
---|
107 | if Count = 0 then Add('');
|
---|
108 | if Strings[Count - 1] = '' then
|
---|
109 | Strings[Count - 1] := Strings[Count - 1] + DupeString(' ', IndentationLength * Indetation);
|
---|
110 | Strings[Count - 1] := Strings[Count - 1] + AText;
|
---|
111 | end;
|
---|
112 | end;
|
---|
113 |
|
---|
114 | procedure TProducerGCCC.GenerateUses(UsedModules: TUsedModules);
|
---|
115 | var
|
---|
116 | I: Integer;
|
---|
117 | begin
|
---|
118 | for I := 0 to UsedModules.Count - 1 do
|
---|
119 | EmitLn('#include "' + TUsedModule(UsedModules[I]).Name + '.h"');
|
---|
120 | EmitLn;
|
---|
121 | end;
|
---|
122 |
|
---|
123 | procedure TProducerGCCC.GenerateModule(Module: TSourceModule);
|
---|
124 | begin
|
---|
125 | Module.TargetFile := Module.Name + '.c';
|
---|
126 | EmitLn('#include "platform.h"');
|
---|
127 | EmitLn;
|
---|
128 | if Module is TModuleProgram then begin
|
---|
129 | TModuleProgram(Module).Body.Name := 'main';
|
---|
130 | GenerateUses(TModuleProgram(Module).UsedModules);
|
---|
131 | GenerateCommonBlock(TModuleProgram(Module).Body, '');
|
---|
132 | end else
|
---|
133 | if Module is TModuleUnit then begin
|
---|
134 | GenerateUses(TModuleProgram(Module).UsedModules);
|
---|
135 | GenerateCommonBlock(TModuleUnit(Module).Body, '');
|
---|
136 | end;
|
---|
137 | end;
|
---|
138 |
|
---|
139 | procedure TProducerGCCC.Produce(Module: TSourceModule);
|
---|
140 | begin
|
---|
141 | inherited;
|
---|
142 | TextSource.Clear;
|
---|
143 | GenerateModule(Module);
|
---|
144 | end;
|
---|
145 |
|
---|
146 | procedure TProducerGCCC.GenerateProgram(ProgramBlock: TProgram);
|
---|
147 | var
|
---|
148 | I: Integer;
|
---|
149 | begin
|
---|
150 | Indetation := 0;
|
---|
151 | with ProgramBlock do
|
---|
152 | for I := 0 to Modules.Count - 1 do
|
---|
153 | GenerateModule(TSourceModule(Modules[I]));
|
---|
154 | end;
|
---|
155 |
|
---|
156 | procedure TProducerGCCC.GenerateFunctions(Functions: TFunctions;
|
---|
157 | Prefix: string = '');
|
---|
158 | var
|
---|
159 | I: Integer;
|
---|
160 | J: Integer;
|
---|
161 | Line: string;
|
---|
162 | begin
|
---|
163 | for I := 0 to Functions.Count - 1 do
|
---|
164 | with TFunction(Functions[I]) do
|
---|
165 | if not Internal then begin
|
---|
166 | if (FunctionType = ftFunction) and Assigned(ResultType) then
|
---|
167 | Line := TranslateType(ResultType.Name) + ' '
|
---|
168 | else Line := 'void ';
|
---|
169 | Line := Line + Prefix + Name + '(';
|
---|
170 | if Parameters.Count > 0 then
|
---|
171 | for J := 0 to Parameters.Count - 1 do begin
|
---|
172 | Line := Line + TranslateType(TParameter(Parameters[J]).ValueType.Name) +
|
---|
173 | ' ' + TParameter(Parameters[J]).Name;
|
---|
174 | if J < Parameters.Count - 1 then Line := Line + ', ';
|
---|
175 | end;
|
---|
176 | Line := Line + ')';
|
---|
177 | EmitLn(Line);
|
---|
178 | GenerateBeginEnd(Code);
|
---|
179 | EmitLn;
|
---|
180 | end;
|
---|
181 | end;
|
---|
182 |
|
---|
183 | procedure TProducerGCCC.GenerateBeginEnd(BeginEnd: TBeginEnd);
|
---|
184 | var
|
---|
185 | I: Integer;
|
---|
186 | begin
|
---|
187 | EmitLn('{');
|
---|
188 | Inc(Indetation);
|
---|
189 |
|
---|
190 | // Variables
|
---|
191 | if BeginEnd.Parent is TCommonBlock then begin
|
---|
192 | GenerateVariableList(BeginEnd.CommonBlock.Variables);
|
---|
193 | end;
|
---|
194 |
|
---|
195 | // Commands
|
---|
196 | for I := 0 to BeginEnd.Commands.Count - 1 do
|
---|
197 | GenerateCommand(TCommand(BeginEnd.Commands[I]));
|
---|
198 |
|
---|
199 | Dec(Indetation);
|
---|
200 | EmitLn('}');
|
---|
201 | end;
|
---|
202 |
|
---|
203 | procedure TProducerGCCC.GenerateVariableList(VariableList: TVariables);
|
---|
204 | var
|
---|
205 | I: Integer;
|
---|
206 | begin
|
---|
207 | for I := 0 to VariableList.Count - 1 do
|
---|
208 | GenerateVariable(TVariable(VariableList[I]));
|
---|
209 | // EmitLn;
|
---|
210 | end;
|
---|
211 |
|
---|
212 | procedure TProducerGCCC.GenerateVariable(Variable: TVariable);
|
---|
213 | begin
|
---|
214 | with Variable do
|
---|
215 | EmitLn(TranslateType(ValueType.Name) + ' ' + Name + ';');
|
---|
216 | end;
|
---|
217 |
|
---|
218 | procedure TProducerGCCC.GenerateCommand(Command: TCommand);
|
---|
219 | begin
|
---|
220 | if Command is TBeginEnd then GenerateBeginEnd(TBeginEnd(Command))
|
---|
221 | else if Command is TWhileDo then GenerateWhileDo(TWhileDo(Command))
|
---|
222 | else if Command is TForToDo then GenerateForToDo(TForToDo(Command))
|
---|
223 | else if Command is TIfThenElse then GenerateIfThenElse(TIfThenElse(Command))
|
---|
224 | else if Command is TAssignment then GenerateAssignment(TAssignment(Command))
|
---|
225 | else if Command is TFunctionCall then GenerateFunctionCall(TFunctionCall(Command));
|
---|
226 | end;
|
---|
227 |
|
---|
228 | procedure TProducerGCCC.GenerateWhileDo(WhileDo: TWhileDo);
|
---|
229 | begin
|
---|
230 | EmitLn('while (' + GenerateExpression(WhileDo.Condition) + ')');
|
---|
231 | if Assigned(WhileDo.Command) then GenerateCommand(WhileDo.Command);
|
---|
232 | end;
|
---|
233 |
|
---|
234 | procedure TProducerGCCC.GenerateForToDo(ForToDo: TForToDo);
|
---|
235 | begin
|
---|
236 | with ForToDo do begin
|
---|
237 | if Assigned(ControlVariable) then
|
---|
238 | EmitLn('for(' + ControlVariable.Name + ' = ' +
|
---|
239 | GenerateExpression(Start) + '; ' + ControlVariable.Name + ' < ' +
|
---|
240 | GenerateExpression(Stop) + '; ' + ControlVariable.Name + '++)');
|
---|
241 | GenerateCommand(Command);
|
---|
242 | end;
|
---|
243 | end;
|
---|
244 |
|
---|
245 | procedure TProducerGCCC.GenerateIfThenElse(IfThenElse: TIfThenElse);
|
---|
246 | begin
|
---|
247 | EmitLn('if(' + GenerateExpression(IfThenElse.Condition) + ')');
|
---|
248 | GenerateCommand(IfThenElse.Command);
|
---|
249 | if Assigned(IfThenElse.ElseCommand) then begin
|
---|
250 | EmitLn('else ');
|
---|
251 | GenerateCommand(IfThenElse.ElseCommand);
|
---|
252 | end;
|
---|
253 | end;
|
---|
254 |
|
---|
255 | procedure TProducerGCCC.GenerateAssignment(Assignment: TAssignment);
|
---|
256 | begin
|
---|
257 | if Assignment.Target.Name = 'Result' then EmitLn('return(' + GenerateExpression(Assignment.Source) + ');')
|
---|
258 | else EmitLn(Assignment.Target.Name + ' = ' + GenerateExpression(Assignment.Source) + ';');
|
---|
259 | end;
|
---|
260 |
|
---|
261 | procedure TProducerGCCC.GenerateFunctionCall(FunctionCall: TFunctionCall);
|
---|
262 | var
|
---|
263 | Line: string;
|
---|
264 | I: Integer;
|
---|
265 | begin
|
---|
266 | with FunctionCall do begin
|
---|
267 | Line := FunctionRef.Name + '(';
|
---|
268 | if ParameterExpression.Count > 0 then begin
|
---|
269 | for I := 0 to ParameterExpression.Count - 1 do begin
|
---|
270 | Line := Line + GenerateExpression(TExpression(ParameterExpression[I]));
|
---|
271 | if I < ParameterExpression.Count - 1 then Line := Line + ', ';
|
---|
272 | end;
|
---|
273 | end;
|
---|
274 | Line := Line + ');';
|
---|
275 | EmitLn(Line);
|
---|
276 | end;
|
---|
277 | end;
|
---|
278 |
|
---|
279 | function TProducerGCCC.GenerateExpression(Expression: TExpression): string;
|
---|
280 | begin
|
---|
281 | case Expression.NodeType of
|
---|
282 | ntConstant: begin
|
---|
283 | if VarType(Expression.Value) = varString then
|
---|
284 | Result := '"' + Expression.Value + '"'
|
---|
285 | else Result := Expression.Value;
|
---|
286 | end;
|
---|
287 | ntVariable: Result := Expression.Variable.Name;
|
---|
288 | ntFunction: Result := Expression.FunctionCall.FunctionRef.Name;
|
---|
289 | ntOperator: begin
|
---|
290 | Result := GenerateExpression(TExpression(Expression.SubItems.First))
|
---|
291 | + ' ' + TranslateOperator(Expression.OperatorName) + ' ' +
|
---|
292 | GenerateExpression(TExpression(Expression.SubItems.Last));
|
---|
293 | end;
|
---|
294 | ntNone: ;
|
---|
295 | end;
|
---|
296 | end;
|
---|
297 |
|
---|
298 | procedure TProducerGCCC.AssignToStringList(Target: TStringList);
|
---|
299 | begin
|
---|
300 | Target.Assign(TextSource);
|
---|
301 | end;
|
---|
302 |
|
---|
303 | procedure TProducerGCCC.GenerateCommonBlock(CommonBlock: TCommonBlock; LabelPrefix: string);
|
---|
304 | var
|
---|
305 | I: Integer;
|
---|
306 | LabelName: string;
|
---|
307 | begin
|
---|
308 | with CommonBlock do begin
|
---|
309 | GenerateTypes(Types);
|
---|
310 | GenerateFunctions(Functions);
|
---|
311 | EmitLn('void ' + Name + '()');
|
---|
312 | GenerateBeginEnd(Code);
|
---|
313 | end;
|
---|
314 | end;
|
---|
315 |
|
---|
316 | procedure TProducerGCCC.GenerateType(AType: TType);
|
---|
317 | var
|
---|
318 | I: Integer;
|
---|
319 | begin
|
---|
320 | if Assigned(AType) then begin
|
---|
321 | if AType is TTypeRecord then begin
|
---|
322 | EmitLn('struct');
|
---|
323 | EmitLn('{');
|
---|
324 | Inc(Indetation);
|
---|
325 | GenerateVariableList(TTypeRecord(AType).CommonBlock.Variables);
|
---|
326 | Dec(Indetation);
|
---|
327 | EmitLn('} ' + TranslateType(AType.Name) + ';');
|
---|
328 | EmitLn;
|
---|
329 | GenerateFunctions(TTypeRecord(AType).CommonBlock.Functions, AType.Name + '_');
|
---|
330 | end else
|
---|
331 | if AType is TTypeArray then begin
|
---|
332 | GenerateType(TTypeArray(AType).ItemType);
|
---|
333 | EmitLn('* ');
|
---|
334 |
|
---|
335 | (* if Assigned(TTypeArray(AType).IndexType) then begin
|
---|
336 | Emit(AType.Name + '[');
|
---|
337 | Emit('[');
|
---|
338 | GenerateType(TTypeArray(AType).IndexType);
|
---|
339 | Emit(']');
|
---|
340 | end;
|
---|
341 | Emit(' of ');
|
---|
342 | if Assigned(TTypeArray(AType).ItemType) then*)
|
---|
343 | Emit(TranslateType(AType.Name));
|
---|
344 | end else
|
---|
345 | if AType is TTypePointer then begin
|
---|
346 | if Assigned(AType.UsedType) then begin
|
---|
347 | Emit(AType.UsedType.Name);
|
---|
348 | Emit(' *');
|
---|
349 | end;
|
---|
350 | Emit(TranslateType(AType.Name));
|
---|
351 | end else begin
|
---|
352 | if Assigned(AType.UsedType) then begin
|
---|
353 | //GenerateType(AType.UsedType);
|
---|
354 | Emit(AType.UsedType.Name);
|
---|
355 | Emit(' ');
|
---|
356 | end;
|
---|
357 | Emit(TranslateType(AType.Name));
|
---|
358 | end;
|
---|
359 | end;
|
---|
360 | end;
|
---|
361 |
|
---|
362 | procedure TProducerGCCC.GenerateTypes(Types: TTypes);
|
---|
363 | var
|
---|
364 | I: Integer;
|
---|
365 | begin
|
---|
366 | if Types.Count > 0 then begin
|
---|
367 | Inc(Indetation);
|
---|
368 | for I := 0 to Types.Count - 1 do
|
---|
369 | with TType(Types[I]) do
|
---|
370 | if (not Internal) then begin
|
---|
371 | Emit('typedef ');
|
---|
372 | GenerateType(TType(Types[I]));
|
---|
373 | EmitLn(';');
|
---|
374 | end;
|
---|
375 | Dec(Indetation);
|
---|
376 | EmitLn('');
|
---|
377 | end;
|
---|
378 | end;
|
---|
379 |
|
---|
380 | end.
|
---|