source: trunk/Compiler/Modules/DynamicC/ProducerDynamicC.pas

Last change on this file was 77, checked in by chronos, 6 months ago
  • Modified: Compiler targets moved into modules.
File size: 11.0 KB
Line 
1unit ProducerDynamicC;
2
3interface
4
5uses
6 SysUtils, Variants, Classes, Graphics, Controls, Forms,
7 Dialogs, StdCtrls, SourceCodePascal, Producer, StrUtils;
8
9type
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
44implementation
45
46{ TProducerC }
47
48constructor TProducerDynamicC.Create;
49begin
50 {$IFDEF Windows}
51 CompilerPath := 'c:\Program Files\Dynamic C Rabbit 9.62\Dcrab_9.62.exe';
52 {$ENDIF}
53end;
54
55destructor TProducerDynamicC.Destroy;
56begin
57 FreeAndNil(TextSource);
58 inherited;
59end;
60
61function TProducerDynamicC.TranslateType(Name: string): string;
62begin
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;
71end;
72
73function TProducerDynamicC.TranslateOperator(Name: string): string;
74begin
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;
86end;
87
88procedure TProducerDynamicC.GenerateUses(UsedModules: TUsedModules);
89var
90 I: Integer;
91begin
92 for I := 0 to UsedModules.Count - 1 do
93 EmitLn('#use "' + TUsedModule(UsedModules[I]).Name + '.lib"');
94 EmitLn;
95end;
96
97procedure TProducerDynamicC.GenerateModule(Module: TSourceModule);
98begin
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;
132end;
133
134procedure TProducerDynamicC.Produce(Module: TSourceModule);
135begin
136 inherited;
137 TextSource.Clear;
138 GenerateModule(Module);
139end;
140
141procedure TProducerDynamicC.GenerateProgram(ProgramBlock: TProgram);
142var
143 I: Integer;
144begin
145 Indentation := 0;
146 with ProgramBlock do
147 for I := 0 to Modules.Count - 1 do
148 GenerateModule(TSourceModule(Modules[I]));
149end;
150
151procedure TProducerDynamicC.GenerateFunctions(Functions: TFunctions;
152 Prefix: string = ''; HeaderOnly: Boolean = False);
153var
154 I: Integer;
155 J: Integer;
156 Line: string;
157begin
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;
176end;
177
178procedure TProducerDynamicC.GenerateBeginEnd(BeginEnd: TBeginEnd);
179var
180 I: Integer;
181begin
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('}');
196end;
197
198procedure TProducerDynamicC.GenerateVariableList(VariableList: TVariables);
199var
200 I: Integer;
201begin
202 for I := 0 to VariableList.Count - 1 do
203 GenerateVariable(TVariable(VariableList[I]));
204// EmitLn;
205end;
206
207procedure TProducerDynamicC.GenerateVariable(Variable: TVariable);
208begin
209 with Variable do
210 EmitLn(TranslateType(ValueType.Name) + ' ' + Name + ';');
211end;
212
213procedure TProducerDynamicC.GenerateCommand(Command: TCommand);
214begin
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)) + ';');
221end;
222
223procedure TProducerDynamicC.GenerateWhileDo(WhileDo: TWhileDo);
224begin
225 EmitLn('while (' + GenerateExpression(WhileDo.Condition) + ')');
226 if Assigned(WhileDo.Command) then GenerateCommand(WhileDo.Command);
227end;
228
229procedure TProducerDynamicC.GenerateForToDo(ForToDo: TForToDo);
230begin
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;
238end;
239
240procedure TProducerDynamicC.GenerateIfThenElse(IfThenElse: TIfThenElse);
241begin
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;
248end;
249
250procedure TProducerDynamicC.GenerateAssignment(Assignment: TAssignment);
251begin
252 if Assignment.Target.Name = 'Result' then EmitLn('return(' + GenerateExpression(Assignment.Source) + ');')
253 else EmitLn(Assignment.Target.Name + ' = ' + GenerateExpression(Assignment.Source) + ';');
254end;
255
256function TProducerDynamicC.GenerateFunctionCall(FunctionCall: TFunctionCall): string;
257var
258 Line: string;
259 I: Integer;
260begin
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;
272end;
273
274function TProducerDynamicC.GenerateExpression(Expression: TExpression): string;
275begin
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;
297end;
298
299procedure TProducerDynamicC.AssignToStringList(Target: TStringList);
300begin
301 Target.Assign(TextSource);
302end;
303
304procedure TProducerDynamicC.GenerateCommonBlock(CommonBlock: TCommonBlock; LabelPrefix: string);
305var
306 I: Integer;
307 LabelName: string;
308begin
309 with CommonBlock do begin
310 EmitLn('void ' + Name + '()');
311 GenerateBeginEnd(Code);
312 end;
313end;
314
315procedure TProducerDynamicC.GenerateType(AType: TType);
316var
317 I: Integer;
318begin
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;
359end;
360
361procedure TProducerDynamicC.GenerateTypes(Types: TTypes);
362var
363 I: Integer;
364begin
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;
377end;
378
379end.
Note: See TracBrowser for help on using the repository browser.