| 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.
|
|---|