source: trunk/Compiler/Modules/Delphi/ProducerDelphi.pas

Last change on this file was 75, checked in by chronos, 6 months ago
  • Modified: Removed U prefix from unit names.
  • Modified: Updated Common package.
File size: 14.8 KB
Line 
1unit ProducerDelphi;
2
3interface
4
5uses
6 SysUtils, Variants, Classes, Graphics, Controls, Forms,
7 Dialogs, SourceCodePascal, Producer, StrUtils, SourceConvertor;
8
9type
10
11 { TProducerPascal }
12
13 TProducerPascal = class(TConvertor)
14 private
15 Producer: TProducer;
16 procedure GenerateUses(UsedModules: TUsedModules);
17 procedure GenerateModule(Module: TSourceModule);
18 procedure GenerateUnit(Module: TSourceModule);
19 procedure GenerateLibrary(Module: TSourceModule);
20 procedure GeneratePackage(Module: TSourceModule);
21 procedure GenerateType(AType: TType; AssignSymbol: Char = ':');
22 procedure GenerateTypes(Types: TTypes);
23 procedure GenerateCommonBlockInterface(CommonBlock: TCommonBlock;
24 LabelPrefix: string);
25 procedure GenerateCommonBlockImplementation(CommonBlock: TCommonBlock;
26 LabelPrefix: string);
27 procedure GenerateFunctions(Functions: TFunctions);
28 procedure GenerateFunction(AFunction: TFunction);
29 procedure GenerateFunctionHead(AFunction: TFunction);
30 procedure GenerateConstants(Constants: TConstants);
31 procedure GenerateConstant(Constant: TConstant);
32 procedure GenerateBeginEnd(BeginEnd: TBeginEnd);
33 procedure GenerateVariableList(Variables: TVariables);
34 procedure GenerateVariable(Variable: TVariable);
35 procedure GenerateCommand(Command: TCommand);
36 procedure GenerateWhileDo(WhileDo: TWhileDo);
37 procedure GenerateForToDo(ForToDo: TForToDo);
38 procedure GenerateIfThenElse(IfThenElse: TIfThenElse);
39 procedure GenerateAssignment(Assignment: TAssignment);
40 procedure GenerateFunctionCall(ConstantCall: TFunctionCall);
41 function GenerateExpression(Expression: TExpression): string;
42 public
43 procedure AssignToStringList(Target: TStringList);
44 procedure Produce(Module: TSourceModule);
45 constructor Create;
46 destructor Destroy; override;
47 end;
48
49
50implementation
51
52{ TProducerPascal }
53
54constructor TProducerPascal.Create;
55begin
56 inherited;
57 Name := 'PascalToDelphi';
58 InputType := TProgram;
59 OutputType := TSourceFileLink;
60
61 Producer := TProducer.Create;
62 {$IFDEF Windows}
63 Producer.CompilerPath := 'c:\Program Files\Embarcadero\RAD Studio\9.0\bin\DCC32.EXE';
64 Producer.CompilerParameters := '"%0:s"';
65 {$ENDIF}
66 {$IFDEF Linux}
67 Producer.CompilerPath := '';
68 {$ENDIF}
69end;
70
71destructor TProducerPascal.Destroy;
72begin
73 FreeAndNil(Producer);
74 inherited;
75end;
76
77procedure TProducerPascal.GenerateUses(UsedModules: TUsedModules);
78var
79 I: Integer;
80 ModuleName: string;
81begin
82 with Producer do begin
83 if UsedModules.Count = 0 then Exit;
84 EmitLn('uses');
85 Inc(Indentation);
86 for I := 0 to UsedModules.Count - 1 do begin
87 if Assigned(TUsedModule(UsedModules[I]).Module) then
88 ModuleName := TUsedModule(UsedModules[I]).Module.Name
89 else ModuleName := '(' + TUsedModule(UsedModules[I]).Name + ')';
90 if UsedModules.ParentModule is TModuleProgram then begin
91 Emit(ModuleName + ' in ''' + ModuleName + '.pas''');
92 if I < UsedModules.Count - 1 then EmitLn(', ');
93 end else begin
94 Emit(ModuleName);
95 if I < UsedModules.Count - 1 then Emit(', ');
96 end;
97 end;
98 EmitLn(';');
99 Dec(Indentation);
100 EmitLn;
101 end;
102end;
103
104procedure TProducerPascal.GenerateModule(Module: TSourceModule);
105begin
106 with Producer do begin
107 Module.TargetFile := Module.Name + '.pas';
108 if Module is TModuleProgram then
109 with TModuleProgram(Module) do begin
110 Module.TargetFile := Module.Name + '.dpr';
111 EmitLn('program ' + Name + ';');
112 EmitLn;
113 EmitLn('{$APPTYPE Console}');
114 EmitLn;
115 GenerateUses(UsedModules);
116 GenerateCommonBlockImplementation(Body, '');
117 EmitLn('.');
118 end else
119 if Module is TModuleUnit then GenerateUnit(Module)
120 else if Module is TModuleLibrary then GenerateLibrary(Module)
121 else if Module is TModulePackage then GeneratePackage(Module);
122 end;
123end;
124
125procedure TProducerPascal.GenerateUnit(Module: TSourceModule);
126begin
127 with Producer do begin
128 EmitLn('unit ' + TModuleUnit(Module).Name + ';');
129 EmitLn;
130 EmitLn('interface');
131 EmitLn;
132 GenerateCommonBlockInterface(TModuleUnit(Module).Body, '.');
133 EmitLn;
134 EmitLn('implementation');
135 EmitLn;
136 GenerateCommonBlockImplementation(TModuleUnit(Module).Body, '.');
137 EmitLn('.');
138 end;
139end;
140
141procedure TProducerPascal.GenerateLibrary(Module: TSourceModule);
142begin
143end;
144
145procedure TProducerPascal.GeneratePackage(Module: TSourceModule);
146begin
147end;
148
149procedure TProducerPascal.GenerateType(AType: TType; AssignSymbol: Char = ':');
150var
151 I: Integer;
152begin
153 with Producer do begin
154 if AType is TTypeRecord then begin
155 EmitLn('record');
156 Inc(Indentation);
157 with TTypeRecord(AType).CommonBlock do
158 for I := 0 to Variables.Count - 1 do begin
159 Emit(TVariable(Variables[I]).Name + ': ');
160 GenerateType(TVariable(Variables[I]).ValueType);
161 EmitLn(';');
162 end;
163 Dec(Indentation);
164 Emit('end');
165 end else
166 if AType is TTypeSubRange then begin
167 Emit(TTypeSubRange(AType).Bottom + '..' + TTypeSubRange(AType).Top);
168 end else
169 if AType is TTypeArray then begin
170 Emit('array ');
171 if Assigned(TTypeArray(AType).IndexType) then begin
172 Emit('[');
173 GenerateType(TTypeArray(AType).IndexType);
174 Emit(']');
175 end;
176 Emit(' of ');
177 if Assigned(TTypeArray(AType).ItemType) then
178 GenerateType(TTypeArray(AType).ItemType);
179 end else
180 if AType is TTypePointer then begin
181 Emit('^' + TTypePointer(AType).UsedType.Name);
182 end else begin
183 Emit(AType.Name);
184 if AType.Name = '' then begin
185 GenerateType(AType.UsedType);
186 end;
187 end;
188 end;
189end;
190
191procedure TProducerPascal.GenerateTypes(Types: TTypes);
192var
193 I: Integer;
194begin
195 with Producer do begin
196 if Types.Count > 0 then begin
197 EmitLn('type');
198 Inc(Indentation);
199 for I := 0 to Types.Count - 1 do
200 with TType(Types[I]) do
201 if (not Internal) then begin
202 Emit(TType(Types[I]).Name + ' = ');
203 GenerateType(TType(Types[I]));
204 EmitLn(';');
205 end;
206 Dec(Indentation);
207 EmitLn;
208 end;
209 end;
210end;
211
212procedure TProducerPascal.Produce(Module: TSourceModule);
213var
214 I: Integer;
215begin
216 inherited;
217 with Producer do begin
218 TextSource.Clear;
219
220 // Check unit names
221 with Module.ParentProgram do
222 for I := 0 to Modules.Count - 1 do
223 if TSourceModule(Modules[I]).Name = 'System' then
224 TSourceModule(Modules[I]).Name := 'System2';
225
226 GenerateModule(Module);
227 end;
228end;
229
230procedure TProducerPascal.GenerateFunctions(Functions: TFunctions);
231var
232 I: Integer;
233begin
234 for I := 0 to Functions.Count - 1 do
235 GenerateFunction(TFunction(Functions[I]));
236end;
237
238procedure TProducerPascal.GenerateFunction(AFunction: TFunction);
239var
240 I: Integer;
241 P: Integer;
242 Line: string;
243begin
244 with Producer do
245 with AFunction do
246 if not Internal then
247 begin
248 GenerateFunctionHead(AFunction);
249 GenerateBeginEnd(Code);
250 EmitLn(';');
251 EmitLn;
252 end;
253end;
254
255procedure TProducerPascal.GenerateFunctionHead(AFunction: TFunction);
256var
257 Line: string;
258 P: Integer;
259begin
260 with Producer, AFunction do begin
261 if FunctionType = ftFunction then
262 Line := 'function ' + Name
263 else Line := 'procedure ' + Name;
264 if Parameters.Count > 0 then begin
265 Line := Line + '(';
266 for P := 0 to Parameters.Count - 1 do begin
267 with TParameter(Parameters[P]) do
268 Line := Line + Name + ': ' + ValueType.Name;
269 if P < (Parameters.Count - 1) then Line := Line + '; ';
270 end;
271 Line := Line + ')';
272 end;
273 if (FunctionType = ftFunction) and Assigned(ResultType) then
274 Line := Line + ': ' + ResultType.Name;
275 EmitLn(Line + ';');
276 end;
277end;
278
279procedure TProducerPascal.GenerateConstants(Constants: TConstants);
280var
281 I: Integer;
282begin
283 with Producer do
284 if Constants.Count > 0 then begin
285 EmitLn('const');
286 Inc(Indentation);
287 for I := 0 to Constants.Count - 1 do
288 GenerateConstant(TConstant(Constants[I]));
289 Dec(Indentation);
290 Emit('');
291 end;
292end;
293
294procedure TProducerPascal.GenerateConstant(Constant: TConstant);
295begin
296 with Producer, Constant do begin
297 Emit(Name);
298 //if Assigned(ValueType) then Emit(': ' + ValueType.Name);
299 EmitLn(' = ' + Value + ';');
300 end;
301end;
302
303procedure TProducerPascal.GenerateBeginEnd(BeginEnd: TBeginEnd);
304var
305 I: Integer;
306begin
307 with Producer do begin
308 EmitLn('begin');
309 Inc(Indentation);
310 // Commands
311 for I := 0 to BeginEnd.Commands.Count - 1 do begin
312 GenerateCommand(TCommand(BeginEnd.Commands[I]));
313 EmitLn(';');
314 end;
315
316 Dec(Indentation);
317 Emit('end');
318 end;
319end;
320
321procedure TProducerPascal.GenerateVariableList(Variables: TVariables);
322var
323 I: Integer;
324begin
325 with Producer do begin
326 EmitLn('var');
327 Inc(Indentation);
328 for I := 0 to Variables.Count - 1 do
329 GenerateVariable(TVariable(Variables[I]));
330 Dec(Indentation);
331 EmitLn;
332 end;
333end;
334
335procedure TProducerPascal.GenerateVariable(Variable: TVariable);
336begin
337 with Producer, Variable do
338 EmitLn(Name + ': ' + ValueType.Name + ';');
339end;
340
341procedure TProducerPascal.GenerateCommand(Command: TCommand);
342begin
343 if Command is TBeginEnd then GenerateBeginEnd(TBeginEnd(Command))
344 else if Command is TWhileDo then GenerateWhileDo(TWhileDo(Command))
345 else if Command is TForToDo then GenerateForToDo(TForToDo(Command))
346 else if Command is TIfThenElse then GenerateIfThenElse(TIfThenElse(Command))
347 else if Command is TAssignment then GenerateAssignment(TAssignment(Command))
348 else if Command is TFunctionCall then GenerateFunctionCall(TFunctionCall(Command));
349end;
350
351procedure TProducerPascal.GenerateWhileDo(WhileDo: TWhileDo);
352begin
353 with Producer do begin
354 Emit('while ' + GenerateExpression(WhileDo.Condition) + ' do ');
355 GenerateCommand(WhileDo.Command);
356 end;
357end;
358
359procedure TProducerPascal.GenerateForToDo(ForToDo: TForToDo);
360begin
361 with Producer, ForToDo do begin
362 if Assigned(ControlVariable) and Assigned(Start) and Assigned(Stop) then
363 Emit('for ' + ControlVariable.Name + ' := ' +
364 GenerateExpression(Start) + ' to ' + GenerateExpression(Stop) + ' do ');
365 GenerateCommand(Command);
366 end;
367end;
368
369procedure TProducerPascal.GenerateIfThenElse(IfThenElse: TIfThenElse);
370begin
371 with Producer do begin
372 Emit('if ' + GenerateExpression(IfThenElse.Condition) + ' then ');
373 GenerateCommand(IfThenElse.Command);
374 if Assigned(IfThenElse.ElseCommand) then begin
375 Emit(' else ');
376 GenerateCommand(IfThenElse.ElseCommand);
377 end;
378 end;
379end;
380
381procedure TProducerPascal.GenerateAssignment(Assignment: TAssignment);
382begin
383 with Producer do begin
384 Emit(Assignment.Target.Name + ' := ' + GenerateExpression(Assignment.Source));
385 end;
386end;
387
388procedure TProducerPascal.GenerateFunctionCall(ConstantCall: TFunctionCall);
389var
390 Line: string;
391 I: Integer;
392begin
393 with Producer do begin
394 with ConstantCall do begin
395 Line := FunctionRef.Name;
396 if ParameterExpression.Count > 0 then begin
397 Line := Line + '(';
398 for I := 0 to ParameterExpression.Count - 1 do begin
399 Line := Line + GenerateExpression(TExpression(ParameterExpression[I]));
400 if I < ParameterExpression.Count - 1 then Line := Line + ', ';
401 end;
402 Line := Line + ')';
403 end;
404 end;
405 Emit(Line);
406 end;
407end;
408
409function TProducerPascal.GenerateExpression(Expression: TExpression): string;
410begin
411 if Assigned(Expression) then begin
412 case Expression.NodeType of
413 ntConstant: begin
414 Result := Expression.Constant.Name;
415 end;
416 ntValue: begin
417 if VarType(Expression.Value) = varString then
418 Result := '''' + Expression.Value + ''''
419 else Result := Expression.Value;
420 end;
421 ntVariable: Result := Expression.Variable.Name;
422 ntFunction: Result := Expression.FunctionCall.FunctionRef.Name;
423 ntOperator: begin
424 Result := GenerateExpression(TExpression(Expression.SubItems.First))
425 + ' ' + Expression.OperatorName + ' ' +
426 GenerateExpression(TExpression(Expression.SubItems.Last));
427 end;
428 ntNone: ;
429 end;
430 if Expression.Braces then Result := '(' + Result + ')';
431 end;
432end;
433
434procedure TProducerPascal.AssignToStringList(Target: TStringList);
435begin
436// Target.Assign(TextSource);
437end;
438
439procedure TProducerPascal.GenerateCommonBlockInterface(CommonBlock: TCommonBlock; LabelPrefix: string);
440var
441 I: Integer;
442 LabelName: string;
443 Section: TCommonBlockSection;
444begin
445 with Producer do begin
446 Inc(Indentation);
447 with CommonBlock do begin
448 for I := 0 to Order.Count - 1 do begin
449 if (Order[I] is TType) and (TType(Order[I]).Exported) then begin
450 if Section <> cbsType then begin
451 EmitLn;
452 Dec(Indentation);
453 EmitLn('type');
454 Inc(Indentation);
455 end;
456 Emit(TType(Order[I]).Name + ' = ');
457 GenerateType(TType(Order[I]));
458 EmitLn(';');
459 Section := cbsType;
460 end else
461 if (Order[I] is TVariable) and (TVariable(Order[I]).Exported) then begin
462 if Section <> cbsVariable then begin
463 EmitLn;
464 Dec(Indentation);
465 EmitLn('var');
466 Inc(Indentation);
467 end;
468 GenerateVariable(TVariable(Order[I]));
469 Section := cbsVariable;
470 end else
471 if (Order[I] is TConstant) and (TConstant(Order[I]).Exported) then begin
472 if Section <> cbsConstant then begin
473 EmitLn;
474 Dec(Indentation);
475 EmitLn('const');
476 Inc(Indentation);
477 end;
478 GenerateConstant(TConstant(Order[I]));
479 Section := cbsConstant;
480 end else
481 if (Order[I] is TFunction) and (TFunction(Order[I]).Exported) then begin
482 GenerateFunctionHead(TFunction(Order[I]));
483 end;
484 end;
485 end;
486 Dec(Indentation);
487 end;
488end;
489
490procedure TProducerPascal.GenerateCommonBlockImplementation(
491 CommonBlock: TCommonBlock; LabelPrefix: string);
492var
493 I: Integer;
494 LabelName: string;
495 Section: TCommonBlockSection;
496begin
497 with Producer do begin
498 Inc(Indentation);
499 with CommonBlock do begin
500 for I := 0 to Order.Count - 1 do begin
501 if (Order[I] is TType) and (not TType(Order[I]).Exported) then begin
502 if Section <> cbsType then begin
503 EmitLn;
504 Dec(Indentation);
505 EmitLn('type');
506 Inc(Indentation);
507 end;
508 Emit(TType(Order[I]).Name + ' = ');
509 GenerateType(TType(Order[I]));
510 EmitLn(';');
511 Section := cbsType;
512 end else
513 if (Order[I] is TVariable) and (not TVariable(Order[I]).Exported) then begin
514 if Section <> cbsVariable then begin
515 EmitLn;
516 Dec(Indentation);
517 EmitLn('var');
518 Inc(Indentation);
519 end;
520 GenerateVariable(TVariable(Order[I]));
521 Section := cbsVariable;
522 end else
523 if (Order[I] is TConstant) and (not TConstant(Order[I]).Exported) then begin
524 if Section <> cbsConstant then begin
525 EmitLn;
526 Dec(Indentation);
527 EmitLn('const');
528 Inc(Indentation);
529 end;
530 GenerateConstant(TConstant(Order[I]));
531 Section := cbsConstant;
532 end else
533 if Order[I] is TFunction then begin
534 GenerateFunction(TFunction(Order[I]));
535 end;
536 end;
537 GenerateBeginEnd(Code);
538 end;
539 Dec(Indentation);
540 end;
541end;
542
543end.
Note: See TracBrowser for help on using the repository browser.