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