taste-backend-code_generators.adb 23.7 KB
Newer Older
Maxime Perrotin's avatar
Maxime Perrotin committed
1
with Text_IO; use Text_IO;
2
with Ada.Characters.Handling,
3
     Ada.Containers.Ordered_Sets,
Maxime Perrotin's avatar
Maxime Perrotin committed
4
     Ada.Exceptions,
5
     Ada.Directories,
6
     GNAT.Directory_Operations,  --  for Dir_Nme
Maxime Perrotin's avatar
Maxime Perrotin committed
7
8
     TASTE.Parser_Utils,
     TASTE.Deployment_View;
9

10
use Ada.Characters.Handling,
11
    Ada.Containers,
Maxime Perrotin's avatar
Maxime Perrotin committed
12
    Ada.Exceptions,
13
    Ada.Directories,
14
    GNAT.Directory_Operations,
Maxime Perrotin's avatar
Maxime Perrotin committed
15
16
    TASTE.Parser_Utils,
    TASTE.Deployment_View;
Maxime Perrotin's avatar
Maxime Perrotin committed
17

18
--  This package covers the generation of code for all supported languages
Maxime Perrotin's avatar
Maxime Perrotin committed
19
20
21
22
23
--  There is no code that is specific to one particular language. The package
--  looks for a sub-directory with the name of the language and checks that all
--  skeleton-related template files are present. Then it fills the Template
--  mappings and generate the corresponding code.

Maxime Perrotin's avatar
Maxime Perrotin committed
24
package body TASTE.Backend.Code_Generators is
Maxime Perrotin's avatar
Maxime Perrotin committed
25
   procedure Generate (Model : TASTE_Model) is
26
      All_CP_Files     : Tag;  --  List of Context Parameters ASN.1 files
27
28
      Template         : constant IV_As_Template :=
                                Interface_View_Template (Model.Interface_View);
29
30
      DV : constant Deployment_View_Holder :=
          Model.Deployment_View;
Maxime Perrotin's avatar
Maxime Perrotin committed
31
      --  Path to the input templates files
32
33
      Prefix           : constant String :=
        Model.Configuration.Binary_Path.Element & "/templates/";
34

35
36
      Prefix_Skeletons  : constant String := Prefix & "skeletons/";
      Prefix_Wrappers   : constant String := Prefix & "glue/language_wrappers";
Maxime Perrotin's avatar
Maxime Perrotin committed
37

38
      --  Return a Tag list of ASN.1 Modules for the headers
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
      function Get_Module_List return Tag is
         Result : Tag;
      begin
         for Each of Model.Data_View.ASN1_Files loop
            for Module of Each.Modules loop
               Result := Result & Module.Name;
            end loop;
         end loop;
         return Result;
      end Get_Module_List;

      --  Return a Tag list of ASN.1 Files
      function Get_ASN1_File_List return Tag is
         Result : Tag;
      begin
         for Each of Model.Data_View.ASN1_Files loop
            Result := Result & Each.Path;
         end loop;
         return Result;
      end Get_ASN1_File_List;

60
61
62
63
64
65
66
67
68
69
      --  Return a Tag list of ACN Files
      function Get_ACN_File_List return Tag is
         Result : Tag;
      begin
         for Each of Model.Data_View.ACN_Files loop
            Result := Result & Each;
         end loop;
         return Result;
      end Get_ACN_File_List;

70
71
      --  Generate a global Makefile (processing all functions)
      procedure Generate_Global_Makefile is
72
73
         package Languages_Set is new Ordered_Sets (Unbounded_String);
         use Languages_Set;
74
         Output_File      : File_Type;
75
76
         Languages        : Set;
         Unique_Languages : Tag;
77
78
79
         Functions_Tag,
         Language_Tag,
         Has_Context_Param_Tag,
80
81
82
         Is_Type_Tag,
         Is_FPGA_Tag,
         CPU_Platform_Tag : Vector_Tag;
83
         Content_Set      : Translate_Set;
84
85
         Tmplt            : constant String := Prefix_Skeletons
                                               & "makefile.tmplt";
86
87
      begin
         if not Exists (Tmplt) then
Maxime Perrotin's avatar
Maxime Perrotin committed
88
            raise ACG_Error with "Missing makefile.tmplt";
89
         end if;
90
91
         for Each of Model.Interface_View.Flat_Functions loop
            Languages := Languages or To_Set (US (Language_Spelling (Each)));
92
93
            Functions_Tag := Functions_Tag & Each.Name;
            Language_Tag  := Language_Tag & Language_Spelling (Each);
Maxime Perrotin's avatar
Maxime Perrotin committed
94
            Is_Type_Tag   := Is_Type_Tag & Each.Is_Type;
95
96
            Has_Context_Param_Tag := Has_Context_Param_Tag
              & (not Each.Context_Params.Is_Empty);
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

            if Each.User_Properties.Contains
                ("TASTE_IV_Properties::FPGA_Configurations")
            then
               Is_FPGA_Tag := Is_FPGA_Tag & True;
            else
               Is_FPGA_Tag := Is_FPGA_Tag & False;
            end if;

            if not DV.Is_Empty then
               for Each_Node of Model.Deployment_View.Element.Nodes loop
                  for Each_Partition of  Each_Node.Partitions loop
                     if Each_Partition.Bound_Functions.Contains
                      (To_String (Each.Name))
                     then
                        CPU_Platform_Tag := CPU_Platform_Tag
                         & Each_Node.CPU_Platform'Img;
                     end if;
                  end loop;
               end loop;
            end if;
118
         end loop;
119
120
121
         for Each of Languages loop
            Unique_Languages := Unique_Languages & To_String (Each);
         end loop;
122
         Content_Set := Model.Configuration.To_Template
123
           & Assoc ("Function_Names",    Functions_Tag)
124
125
126
127
           & Assoc ("Language",          Language_Tag)
           & Assoc ("Is_Type",           Is_Type_Tag)
           & Assoc ("CP_Files",          All_CP_Files)
           & Assoc ("Has_Context_Param", Has_Context_Param_Tag)
128
129
           & Assoc ("Is_FPGA",           Is_FPGA_Tag)
           & Assoc ("CPU_Platform",      CPU_Platform_Tag)
130
131
132
133
           & Assoc ("Unique_Languages",  Unique_Languages)
           & Assoc ("ASN1_Files",        Get_ASN1_File_List)
           & Assoc ("ACN_Files",         Get_ACN_File_List)
           & Assoc ("ASN1_Modules",      Get_Module_List);
134

135
         Put_Debug ("Generating global Makefile");
136
137
         Create (File => Output_File,
                 Mode => Out_File,
138
                 Name => Model.Configuration.Output_Dir.Element & "/Makefile");
139
         Document_Template (Templates_Skeletons_Makefile, Content_Set);
140
141
142
         Put_Line (Output_File, Parse (Tmplt, Content_Set));
         Close (Output_File);
      end Generate_Global_Makefile;
143

Maxime Perrotin's avatar
Maxime Perrotin committed
144
145
146
      --  Render a set of interfaces by applying a template
      --  Result is an unbounded string, allowing each interface to use
      --  multiple lines (combined with 'Indent)
Maxime Perrotin's avatar
Maxime Perrotin committed
147
      function Process_Interfaces (Interfaces : Template_Vectors.Vector;
Maxime Perrotin's avatar
Maxime Perrotin committed
148
                                   Path       : String) return Unbounded_String
Maxime Perrotin's avatar
Maxime Perrotin committed
149
      is
Maxime Perrotin's avatar
Maxime Perrotin committed
150
         Result      : Unbounded_String := Null_Unbounded_String;
151
         Tmplt_Sign  : constant String := Path & "interface.tmplt";
Maxime Perrotin's avatar
Maxime Perrotin committed
152
         Doc_Done    : Boolean := False;
Maxime Perrotin's avatar
Maxime Perrotin committed
153
154
      begin
         for Each of Interfaces loop
Maxime Perrotin's avatar
Maxime Perrotin committed
155
156
157
158
159
160
161
162
163
164
165
            declare
               Tmplt :  constant Translate_Set :=
                  Join_Sets (Model.Configuration.To_Template, Each);
            begin
               if not Doc_Done then
                  --  Template documentation (done once)
                  Document_Template (Templates_Skeletons_Sub_Interface, Tmplt);
                  Doc_Done := True;
               end if;
               Result := Result & US (String'(Parse (Tmplt_Sign, Tmplt)));
            end;
Maxime Perrotin's avatar
Maxime Perrotin committed
166
         end loop;
167
         return Strip_String (Result);
Maxime Perrotin's avatar
Maxime Perrotin committed
168
      end Process_Interfaces;
169

Maxime Perrotin's avatar
Maxime Perrotin committed
170
      --  Generate the ASN.1 files translating Context Parameters
171
172
173
174
      procedure Process_Context_Parameters
                               (F           : Taste_Terminal_Function;
                                Output_Lang : String)
      is
175
176
         Output_File : File_Type;
         CP_Tmpl     : constant Translate_Set := CP_Template (F => F);
Maxime Perrotin's avatar
Maxime Perrotin committed
177
178
         CP_Text     : constant String :=
            (Parse (Prefix_Skeletons & "context_parameters.tmplt", CP_Tmpl));
179
180
181
182
         CP_File     : constant String :=
           "Context-" & To_Lower (To_String (F.Name)) & ".asn";
         CP_File_Dash : Unbounded_String;

183
      begin
184
         Document_Template (Templates_Skeletons_Context_Parameters, CP_Tmpl);
185
186
187
188
189
         --  To keep backward compatibility, file name uses dash
         for C of CP_File loop
            CP_File_Dash := CP_File_Dash & (if C = '_' then '-' else C);
         end loop;

190
191
         if not F.Context_Params.Is_Empty then
            Create_Path (Output_Lang);
192
            Put_Debug ("Generating " & To_String (CP_File_Dash));
193
194
            Create (File => Output_File,
                    Mode => Out_File,
195
                    Name => Output_Lang & To_String (CP_File_Dash));
196
197
198
            Put_Line (Output_File, CP_Text);
            Close (Output_File);
            All_CP_Files :=
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
              All_CP_Files & ("../" & Output_Lang & To_String (CP_File_Dash));
            --  If the function is an instance of a function that is in the
            --  library of shared types, we must add its CP here, using the
            --  path to the installed library (known from Model.Configuration)
            if F.Instance_Of.Has_Value
              and then not Model.Interface_View.Flat_Functions.Contains
                (To_String (F.Instance_Of.Unsafe_Just))
            then
               declare
                  Parent      : constant String :=
                    To_Lower (To_String (F.Instance_Of.Unsafe_Just));
                  Parent_Dash : Unbounded_String;
               begin
                  for C of Parent loop
                     Parent_Dash := Parent_Dash & (if C = '_'
                                                   then '-'
                                                   else C);
                  end loop;

                  All_CP_Files := All_CP_Files
                    & (Model.Configuration.Shared_Lib_Dir
                    & "/" & Parent & "/" & Parent & "/" & Language_Spelling (F)
                    & "/" & "Context-" & Parent_Dash & ".asn");
               end;
            end if;
224
225
226
227
228
229
230
         end if;
      exception
         when E : End_Error
         | Text_IO.Use_Error =>
            if Is_Open (Output_File) then
               Close (Output_File);
            end if;
Maxime Perrotin's avatar
Maxime Perrotin committed
231
232
233
            raise ACG_Error with "Generation of code for function "
                                 & To_String (F.Name) & " failed : "
                                 & Exception_Message (E);
234
235
236
237
238
239
240
241
242
243
244
      end Process_Context_Parameters;

      --  Write a header or body file for a function, a corresponding
      --  Makefile, and/or context parameters
      procedure Process_Template (F           : Taste_Terminal_Function;
                                  File_Name   : String := "";
                                  Make_File   : String := "";
                                  Path        : String;
                                  Output_Lang : String;
                                  Output_Sub  : String := "src/") is
         Output_File : File_Type;
245
246
247
248
249
250
         Make_Tmpl   : constant Translate_Set :=
           Function_Makefile_Template
             (Model   => Model,
              F       => F,
              Modules => Get_Module_List,
              Files   => Get_ASN1_File_List);
251
252
253
254
255

         Make_Path   : constant String := Path & "makefile.tmplt";
         Make_Text   : constant String :=
            (if Make_File /= "" and then Exists (Make_Path)
             then Parse (Make_Path, Make_Tmpl) else "");
256

257
         Func_Tmpl   : constant Func_As_Template :=
258
259
                                Template.Funcs.Element (To_String (F.Name));

260
         Func_Map    : constant Translate_Set :=
Maxime Perrotin's avatar
Maxime Perrotin committed
261
262
                         Join_Sets (Model.Configuration.To_Template,
                                    Func_Tmpl.Header)
263
264
                         & Assoc ("Provided_Interfaces",
                                  Process_Interfaces
265
                                     (Func_Tmpl.Provided, Path))
266
267
                         & Assoc ("Required_Interfaces",
                                  Process_Interfaces
268
                                     (Func_Tmpl.Required, Path))
269
270
271
                         & Assoc ("ASN1_Modules", Get_Module_List)
                         & Assoc ("ASN1_Files", Get_ASN1_File_List);

272
273
         Content     : constant String :=
                                    Parse (Path & "function.tmplt", Func_Map);
274

275
         Output_Dir  : constant String := Output_Lang & Output_Sub;
276
      begin
277
         Document_Template (Templates_Skeletons_Sub_Function, Func_Map);
278
         Document_Template (Templates_Skeletons_Sub_Makefile, Make_Tmpl);
279
         --  Create directory tree (output/function/language/src)
280
281
         Create_Path (Output_Dir);
         if File_Name /= "" then
282
            Put_Debug ("Generating " & Output_Dir & File_Name);
283
284
            Create (File => Output_File,
                    Mode => Out_File,
285
286
                    Name => Output_Dir & File_Name);
            Put_Line (Output_File, Content);
287
288
            Close (Output_File);
         end if;
289
         if Make_File /= "" then
290
            Put_Debug ("Generating " & Make_File & " for function "
291
292
293
294
295
296
297
                      & To_String (F.Name));
            Create (File => Output_File,
                    Mode => Out_File,
                    Name => Output_Lang & Make_File);
            Put_Line (Output_File, Make_Text);
            Close (Output_File);
         end if;
298
299
300
301
302
303
      exception
         when E : End_Error
         | Text_IO.Use_Error =>
            if Is_Open (Output_File) then
               Close (Output_File);
            end if;
Maxime Perrotin's avatar
Maxime Perrotin committed
304
305
306
            raise ACG_Error with "Generation of code for function "
                                 & To_String (F.Name) & " failed : "
                                 & Exception_Message (E);
307
      end Process_Template;
308

Maxime Perrotin's avatar
Maxime Perrotin committed
309
      --  Main loop generating output for each function
310
311
312
313
314
315
      --  Prefix is where the templates are located
      --  Output_Base is the output folder defined in the command line
      --  Output_Sub is where the code shall be generated (e.g. "src")
      procedure Generate_From_Templates (Prefix      : String;
                                         Output_Base : String;
                                         Output_Sub  : String := "src/") is
316
      begin
317
         Put_Debug ("== Generate code with templates from " & Prefix & " ==");
318
         for Each of Model.Interface_View.Flat_Functions loop
319
            --  There can be multiple folders containing templates, iterate
320
321
322
323
324
325
            declare
               Language   : constant String := Language_Spelling (Each);
               ST         : Search_Type;
               Current    : Directory_Entry_Type;
               Filter     : constant Filter_Type := (Directory => True,
                                                     others    => False);
326
327
               --  File_Tmpl: to get the output filename from user template
               File_Tmpl  : constant Translate_Set :=
328
329
                 +Assoc  ("Name", Each.Name)
                 & Assoc ("Language", Language);
330
               --  Base output folder where code is generated
331
               --  e.g. output/Ada/src/
332
333
334
335
               Output_Lang : constant String := Output_Base
                  & To_Lower (To_String (Each.Name))
                  & "/" & Language & "/";
               Output_Dir  : constant String := Output_Lang & Output_Sub;
336
337
            begin
               Start_Search (Search    => ST,
338
339
                             Pattern   => "",
                             Directory => Prefix,
340
                             Filter    => Filter);
341

342
               if not More_Entries (ST) then
343
                  Put_Error ("No folders with templates were found");
Maxime Perrotin's avatar
Maxime Perrotin committed
344
               end if;
345
346
347
348
349

               --  Iterate over the folders and process templates. Each folder
               --  shall contain a template named "trigger.tmplt" allowing
               --  the engine to decide if code should be generated or not
               --  based on user-defined critera (e.g. language)
350
351
               while More_Entries (ST) loop
                  Get_Next_Entry (ST, Current);
352
353
354
                  declare
                     --  Path is where the template files are located
                     Path      : constant String := Full_Name (Current);
355

356
357
358
359
                     --  Do_Func is true if there is a template for the
                     --  generation of a function template
                     Do_Func   : constant Boolean :=
                        Exists (Path & "/function-filename.tmplt");
360
361

                     --  Do_Make is true if there is a template for the
362
363
364
                     --  generation of a build script/Makefile template
                     Do_Make   : constant Boolean :=
                        Exists (Path & "/makefile-filename.tmplt");
365

366
367
368
369
370
371
372
373
                     --  File_Name is the output file to generate,
                     --  as parsed from the template file
                     File_Name : constant String :=
                        (if Do_Func
                         then
                            Strip_String (Parse
                               (Path & "/function-filename.tmplt", File_Tmpl))
                         else "");
374

375
                     --  User can define the name of the build script
376
                     --  to generate (typically, for a function, "Makefile")
377
378
379
380
381
382
                     Make_Name : constant String :=
                        (if Do_Make
                         then
                            Strip_String (Parse
                               (Path & "/makefile-filename.tmplt", File_Tmpl))
                         else "");
383

384
385
386
                     --  Present_F is True if the function file already exists
                     Present_F : constant Boolean :=
                        (File_Name /= "" and Exists (Output_Dir & File_Name));
387

388
389
390
                     --  Present_M is True if the Makefile already exists
                     Present_M : constant Boolean :=
                        (Make_Name /= "" and Exists (Output_Dir & Make_Name));
391

392
                     --  Data needed to process trigger.tmplt
393
394
                     --  Includes function attributes (name, zip file, etc)
                     --  and the command line configuration (Use_POHIC, etc.)
395
                     Trig_Tmpl  : constant Translate_Set :=
396
397
398
399
400
                       Join_Sets (Model.Configuration.To_Template,
                                  Template.Funcs.Element
                                    (To_String (Each.Name)).Header)
                       & Assoc ("Filename_Is_Present", Present_F)
                       & Assoc ("Makefile_Is_Present", Present_M);
401

402
403
404
                     --  Trigger is set to True by the template
                     Trigger    : constant Boolean :=
                        (Exists (Path & "/trigger.tmplt")
405
                         and then Strip_String (Parse
406
407
                           (Path & "/trigger.tmplt", Trig_Tmpl)) =
                           String'("TRUE"));
408
                  begin
409
410
411
412
413
414
                     Document_Template
                       (Templates_Skeletons_Sub_Function_Filename, File_Tmpl);
                     Document_Template
                       (Templates_Skeletons_Sub_Makefile_Filename, File_Tmpl);
                     Document_Template
                       (Templates_Skeletons_Sub_Trigger, Trig_Tmpl);
415
                     if Trigger then
416
417
418
419
420
                        --  Possibly create folder to generate the file
                        if File_Name /= "" then
                           Create_Path (Output_Dir & Dir_Separator
                                        & Dir_Name (File_Name));
                        end if;
421
422
423
424
425
426
427
428
429
                        --  Output code and Makefile from this template folder
                        Process_Template (F           => Each,
                                          File_Name   => File_Name,
                                          Make_File   => Make_Name,
                                          Path        => Path & "/",
                                          Output_Lang => Output_Lang,
                                          Output_Sub  => Output_Sub);
                     end if;
                  end;
430
431
               end loop;
               End_Search (ST);
432
433
               Process_Context_Parameters (F           => Each,
                                           Output_Lang => Output_Lang);
434
435
            end;
         end loop;
436
      end Generate_From_Templates;
437
438

   begin
439
440
      Generate_From_Templates (Prefix      => Prefix_Skeletons,
                               Output_Base =>
441
                                  Model.Configuration.Output_Dir.Element & "/",
442
                               Output_Sub  => "src/");
443
444
      Generate_Global_Makefile;
      if Model.Configuration.Glue then
445
446
         Generate_From_Templates (Prefix     => Prefix_Wrappers,
                                  Output_Base =>
447
448
                                    Model.Configuration.Output_Dir.Element
                                       & "/",
449
                                  Output_Sub => "wrappers/");
450
      end if;
Maxime Perrotin's avatar
Maxime Perrotin committed
451
452
   end Generate;

453
454
455
456
457
458
459
   --  Functions that transform the AST into Templates:
   --  * Context Parameters
   --  * Makefile (per function)
   --  * A single interface
   --  * A single taste function
   --  * The complete interface view

460
461
462
463
   --  Context Parameters
   function CP_Template (F : Taste_Terminal_Function) return Translate_Set is
      package Sort_Set is new Ordered_Sets (Unbounded_String);
      use Sort_Set;
464
      Sorts_Set    : Set;
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
      Unique_Sorts : Vector_Tag;
      Corr_Module  : Vector_Tag;
      Names        : Vector_Tag;
      Sorts        : Vector_Tag;
      ASN1_Modules : Vector_Tag;
      Values       : Vector_Tag;
   begin
      for Each of F.Context_Params loop
         if not Sorts_Set.Contains (Each.Sort) then
            --  Build up a set of unique types, needed for the IMPORTS section
            --  in the ASN.1 module
            Sorts_Set.Insert (Each.Sort);
            Unique_Sorts := Unique_Sorts & Each.Sort;
            Corr_Module  := Corr_Module & Each.ASN1_Module;
         end if;
         Names        := Names        & Each.Name;
         Sorts        := Sorts        & Each.Sort;
         ASN1_Modules := ASN1_Modules & Each.ASN1_Module;
         Values       := Values       & Each.Default_Value;
      end loop;
485
486
      return Result : constant Translate_Set :=
        +Assoc ("Name",            F.Name)
487
488
        & Assoc ("Is_Type",        F.Is_Type)
        & Assoc ("Instance_Of",    F.Instance_Of.Value_Or (US ("")))
489
490
491
492
493
494
        & Assoc ("Sort_Set",       Unique_Sorts)
        & Assoc ("Module_Set",     Corr_Module)
        & Assoc ("CP_Name",        Names)
        & Assoc ("CP_Sort",        Sorts)
        & Assoc ("CP_ASN1_Module", ASN1_Modules)
        & Assoc ("CP_Value",       Values);
495
496
   end CP_Template;

497
498
499
   --  A Makefile can be generated for each function
   --  with a rule to edit the function using an IDE, model editor, etc.
   --  (this is defined in the template)
500
501
   function Function_Makefile_Template (Model   : TASTE_Model;
                                        F       : Taste_Terminal_Function;
502
503
                                        Modules : Tag;
                                        Files   : Tag) return Translate_Set
504
   is (Translate_Set'(Properties_To_Template (F.User_Properties)
505
506
507
508
509
510
511
512
513
514
515
516
                      & Assoc ("Name",           F.Name)
                      & Assoc ("ASN1_Files",     Files)
                      & Assoc ("ASN1_Modules",   Modules)
                      & Assoc ("Language",       Language_Spelling (F))
                      & Assoc ("Has_CP",         not F.Context_Params.Is_Empty)
                      & Assoc ("Is_Type",        F.Is_Type)
                      & Assoc ("Shared_Lib_Dir",
                               Model.Configuration.Shared_Lib_Dir)
                      & Assoc ("Is_Shared_Type",
                               F.Instance_Of.Has_Value and then not
                                 Model.Interface_View.Flat_Functions.Contains
                                   (To_String (F.Instance_Of.Unsafe_Just)))
517
                      & Assoc ("Instance_Of",
518
                               F.Instance_Of.Value_Or (US ("")))));
Maxime Perrotin's avatar
Maxime Perrotin committed
519
520
521
522
523
524

   function Interface_View_Template (IV : Complete_Interface_View)
                                     return IV_As_Template is
      Result : IV_As_Template;
   begin
      for Each of IV.Flat_Functions loop
525
         Result.Funcs.Insert (Key      => To_String (Each.Name),
526
                              New_Item => Each.Function_To_Template);
Maxime Perrotin's avatar
Maxime Perrotin committed
527
      end loop;
528
529
530
531
532
      for C of IV.Connections loop
         Result.Callers  := Result.Callers  & C.Caller;
         Result.Callees  := Result.Callees  & C.Callee;
         Result.RI_Names := Result.RI_Names & C.RI_Name;
         Result.PI_Names := Result.PI_Names & C.PI_Name;
533
      end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
534
535
      return Result;
   end Interface_View_Template;
536

Maxime Perrotin's avatar
Maxime Perrotin committed
537
end TASTE.Backend.Code_Generators;