taste-backend-skeletons.adb 11.7 KB
Newer Older
Maxime Perrotin's avatar
Maxime Perrotin committed
1
with Text_IO; use Text_IO;
2
with Ada.Strings.Unbounded,
3
     Ada.Characters.Handling,
Maxime Perrotin's avatar
Maxime Perrotin committed
4
     Ada.Exceptions,
5
6
     Ada.Directories,
     TASTE.Parser_Utils;
7

8
use Ada.Characters.Handling,
Maxime Perrotin's avatar
Maxime Perrotin committed
9
    Ada.Exceptions,
10
11
    Ada.Directories,
    TASTE.Parser_Utils;
Maxime Perrotin's avatar
Maxime Perrotin committed
12

Maxime Perrotin's avatar
Maxime Perrotin committed
13
14
15
16
17
18
--  This package covers the generation of skeletons for all supported languages
--  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
19
20
package body TASTE.Backend.Skeletons is
   procedure Generate (Model : TASTE_Model) is
Maxime Perrotin's avatar
Maxime Perrotin committed
21
      Template : constant IV_As_Template :=
Maxime Perrotin's avatar
Maxime Perrotin committed
22
        Interface_View_Template (Model.Interface_View);
Maxime Perrotin's avatar
Maxime Perrotin committed
23

24
25
      Prefix : constant String := Model.Configuration.Binary_Path.all
        & "templates/skeletons/";
Maxime Perrotin's avatar
Maxime Perrotin committed
26

27
      use Ada.Strings.Unbounded;
Maxime Perrotin's avatar
Maxime Perrotin committed
28
      type Output is (Header, Code);
Maxime Perrotin's avatar
Maxime Perrotin committed
29
30
31
32
33
34
35
36
37
38
39
40
41

      --  Function checking that all templates files are available to support
      --  a given language (based on the directory name).
      function Is_Template_Present (Path : String) return Boolean is
        (Exists (Path) and then Kind (Path) = Directory and then
         Exists (Path & "interface-signature.tmplt") and then
         Exists (Path & "header.tmplt") and then
         Exists (Path & "body.tmplt") and then
         Exists (Path & "body-filename.tmplt") and then
         Exists (Path & "header-filename.tmplt") and then
         Exists (Path & "interface-body-parameter.tmplt") and then
         Exists (Path & "interface-header-parameter.tmplt"));

Maxime Perrotin's avatar
Maxime Perrotin committed
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
      function Process_Interfaces (Interfaces : Interface_Vectors.Vector;
                                   Path       : String;
                                   Target     : Output) return Tag
      is
         Interfaces_Tag : Tag;
         Tmplt_Param : constant String :=
           Path & "interface-" & (if Target = Header then "header" else "body")
           & "-parameter.tmplt";
         Tmplt_Sign  : constant String := Path & "interface-signature.tmplt";
      begin
         for Each of Interfaces loop
            declare
               Pool   : Translate_Set := Each.Header;
               Params : Tag;
            begin
               for Param of Each.Params loop
58
                  declare
Maxime Perrotin's avatar
Maxime Perrotin committed
59
                     P : constant String := Parse (Tmplt_Param, Param);
60
                  begin
Maxime Perrotin's avatar
Maxime Perrotin committed
61
                     Params := Params & P;
62
                  end;
Maxime Perrotin's avatar
Maxime Perrotin committed
63
64
               end loop;
               Pool := Pool & Assoc ("Parameters", Params);
Maxime Perrotin's avatar
Maxime Perrotin committed
65
               declare
Maxime Perrotin's avatar
Maxime Perrotin committed
66
                  New_Interface : constant String := Parse (Tmplt_Sign, Pool);
Maxime Perrotin's avatar
Maxime Perrotin committed
67
               begin
Maxime Perrotin's avatar
Maxime Perrotin committed
68
                  Interfaces_Tag := Interfaces_Tag & New_Interface;
Maxime Perrotin's avatar
Maxime Perrotin committed
69
               end;
Maxime Perrotin's avatar
Maxime Perrotin committed
70
71
72
73
            end;
         end loop;
         return Interfaces_Tag;
      end Process_Interfaces;
74
75
76
77
78
79
80
81
82
83
84
85
86

      --  Return a Tag list of ASN.1 Modules for the skeleton headers
      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;

Maxime Perrotin's avatar
Maxime Perrotin committed
87
   begin
88
      Put_Info ("=== Generate skeletons ===");
Maxime Perrotin's avatar
Maxime Perrotin committed
89
90
91
92
      for Each of Model.Interface_View.Flat_Functions loop
         declare
            Language   : constant String := Language_Spelling (Each);
            Path       : constant String := Prefix & To_Lower (Language) & "/";
Maxime Perrotin's avatar
Maxime Perrotin committed
93
            Proceed    : constant Boolean := Is_Template_Present (Path);
Maxime Perrotin's avatar
Maxime Perrotin committed
94
            Hdr_Tmpl   : constant Translate_Set := +Assoc ("Name", Each.Name);
Maxime Perrotin's avatar
Maxime Perrotin committed
95

Maxime Perrotin's avatar
Maxime Perrotin committed
96
97
            Func_Tmpl  : constant Func_As_Template :=
              Template.Funcs.Element (To_String (Each.Name));
Maxime Perrotin's avatar
Maxime Perrotin committed
98
99
100

            Func_Hdr   : constant Translate_Set :=
              (if Proceed then Func_Tmpl.Header
101
102
103
104
105
               & Assoc ("Provided_Interfaces",
                 Process_Interfaces (Func_Tmpl.Provided, Path, Header))
               & Assoc ("Required_Interfaces",
                 Process_Interfaces (Func_Tmpl.Required, Path, Header))
               & Assoc ("ASN1_Modules", Get_Module_List)
Maxime Perrotin's avatar
Maxime Perrotin committed
106
107
108
109
110
111
112
113
114
115
116
117
118
               else Null_Set);

            Header_Text : constant String :=
             (if Proceed then Parse (Path & "header.tmplt", Func_Hdr) else "");

            Func_Body  : constant Translate_Set :=
              (if Proceed then Func_Tmpl.Header
              & Assoc ("Provided_Interfaces",
                       Process_Interfaces (Func_Tmpl.Provided, Path, Code))
              & Assoc ("Required_Interfaces",
                 Process_Interfaces (Func_Tmpl.Required, Path, Code))
               else Null_Set);
            Body_Text   : constant String :=
119
120
121
122
123
                            (if Proceed
                             then Parse (Path & "body.tmplt", Func_Body)
                             else "");
            Output_Src  : constant String :=
                            Model.Configuration.Output_Dir.all
Maxime Perrotin's avatar
Maxime Perrotin committed
124
                            & "/" & To_Lower (To_String (Each.Name))
125
                            & "/" & Language
Maxime Perrotin's avatar
Maxime Perrotin committed
126
127
128
129
130
131
132
133
134
135
136
                            & "/" & "src" & "/";
            --  Get header and body filenames from templates
            Header_File : constant String :=
                            (if Proceed then Parse
                               (Path & "header-filename.tmplt", Hdr_Tmpl)
                             else "");
            Body_File   : constant String :=
                            (if Proceed then Parse
                               (Path & "body-filename.tmplt", Hdr_Tmpl)
                             else "");
            Output      : File_Type;
Maxime Perrotin's avatar
Maxime Perrotin committed
137
         begin
Maxime Perrotin's avatar
Maxime Perrotin committed
138
            if Proceed then
Maxime Perrotin's avatar
Maxime Perrotin committed
139
               --  Create directory tree (output/function/language/src)
140
               Create_Path (Output_Src);
141
               Put_Info ("Generating " & Header_File);
Maxime Perrotin's avatar
Maxime Perrotin committed
142
143
144
145
146
147
               Create (File => Output,
                       Mode => Out_File,
                       Name => Output_Src & Header_File);
               Put_Line (Output, Header_Text);
               Close (Output);
               if not Exists (Output_Src & Body_File) then
148
                  Put_Info ("Generating " & Body_File);
Maxime Perrotin's avatar
Maxime Perrotin committed
149
150
151
152
153
                  Create (File => Output,
                          Mode => Out_File,
                          Name => Output_Src & Body_File);
                  Put_Line (Output, Body_Text);
                  Close (Output);
154
155
               else
                  Put_Info (Body_File & " already exists, ignoring");
Maxime Perrotin's avatar
Maxime Perrotin committed
156
               end if;
Maxime Perrotin's avatar
Maxime Perrotin committed
157
            else
158
               Put_Info ("Ignoring function " & To_String (Each.Name));
Maxime Perrotin's avatar
Maxime Perrotin committed
159
            end if;
Maxime Perrotin's avatar
Maxime Perrotin committed
160
         exception
161
162
            when E : End_Error
               | Text_IO.Use_Error =>
Maxime Perrotin's avatar
Maxime Perrotin committed
163
164
165
166
167
168
               if Is_Open (Output) then
                  Close (Output);
               end if;
               raise Skeleton_Error with "Generation of skeleton for function "
                 & To_String (Each.Name) & " failed : "
                 & Exception_Message (E);
169
170
         end;
      end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
171
172
   end Generate;

Maxime Perrotin's avatar
Maxime Perrotin committed
173
174
175
   function Parameter_Template (Param : ASN1_Parameter; TI : Taste_Interface)
       return Translate_Set
   is
Maxime Perrotin's avatar
Maxime Perrotin committed
176
     (+Assoc ("Type", Param.Sort) & Assoc ("Name", Param.Name)
Maxime Perrotin's avatar
Maxime Perrotin committed
177
     & Assoc ("Interface_Kind", TI.RCM'Img)
Maxime Perrotin's avatar
Maxime Perrotin committed
178
179
     & Assoc ("Direction", Param.Direction'Img));

Maxime Perrotin's avatar
Maxime Perrotin committed
180
181
182
   --  MP: With the vector tags Param_Names/Types/Directions it should be
   --  possible to completely avoid the templates specific to params
   --  (Result.Params is probably unnecessary now) to be confirmed
Maxime Perrotin's avatar
Maxime Perrotin committed
183
184
185
186
   function Interface_Template (TI : Taste_Interface)
                                return Interface_As_Template
   is
      use Template_Vectors;
Maxime Perrotin's avatar
Maxime Perrotin committed
187
188
189
190
      Result           : Interface_As_Template;
      Param_Names      : Vector_Tag;
      Param_Types      : Vector_Tag;
      Param_Directions : Vector_Tag;
Maxime Perrotin's avatar
Maxime Perrotin committed
191
   begin
Maxime Perrotin's avatar
Maxime Perrotin committed
192
      Result.Header :=  +Assoc  ("Name",            TI.Name)
Maxime Perrotin's avatar
Maxime Perrotin committed
193
                        & Assoc ("Kind",            TI.RCM'Img)
Maxime Perrotin's avatar
Maxime Perrotin committed
194
195
                        & Assoc ("Parent_Function", TI.Parent_Function);
      for Each of TI.Params loop
Maxime Perrotin's avatar
Maxime Perrotin committed
196
197
198
199
         Result.Params    := Result.Params & Parameter_Template (Each, TI);
         Param_Names      := Param_Names & Each.Name;
         Param_Types      := Param_Types & Each.Sort;
         Param_Directions := Param_Directions & Each.Direction'Img;
Maxime Perrotin's avatar
Maxime Perrotin committed
200
      end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
201
202
203
204
      Result.Header := Result.Header
                       & Assoc ("Param_Names",      Param_Names)
                       & Assoc ("Param_Types",      Param_Types)
                       & Assoc ("Param_Directions", Param_Directions);
Maxime Perrotin's avatar
Maxime Perrotin committed
205
206
207
208
209
210
      return Result;
   end Interface_Template;

   function Func_Template (F : Taste_Terminal_Function) return Func_As_Template
   is
      use Interface_Vectors;
211
      use Ctxt_Params;
Maxime Perrotin's avatar
Maxime Perrotin committed
212
213
214
215
216
217
218
219
220
221
      Result            : Func_As_Template;
      List_Of_PIs       : Tag;
      List_Of_RIs       : Tag;
      List_Of_Sync_PIs  : Tag;
      List_Of_ASync_PIs : Tag;
      List_Of_Sync_RIs  : Tag;
      List_Of_ASync_RIs : Tag;
      Timers            : Tag;
      Property_Names    : Vector_Tag;
      Property_Values   : Vector_Tag;
Maxime Perrotin's avatar
Maxime Perrotin committed
222
223
   begin
      Result.Header := +Assoc ("Name", F.Name)
224
225
        & Assoc ("Language", Language_Spelling (F))
        & Assoc ("Has_Context", (Length (F.Context_Params) > 0));
226

227
      --  Add list of all PI names (both synchronous and asynchronous)
Maxime Perrotin's avatar
Maxime Perrotin committed
228
229
      for Each of F.Provided loop
         Result.Provided := Result.Provided & Interface_Template (Each);
230
231
232
         List_Of_PIs     := List_Of_PIs & Each.Name;
         case Each.RCM is
            when Cyclic_Operation | Sporadic_Operation =>
Maxime Perrotin's avatar
Maxime Perrotin committed
233
               List_Of_ASync_PIs := List_Of_ASync_PIs & Each.Name;
234
            when others =>
Maxime Perrotin's avatar
Maxime Perrotin committed
235
               List_Of_Sync_PIs := List_Of_Sync_PIs & Each.Name;
236
         end case;
Maxime Perrotin's avatar
Maxime Perrotin committed
237
      end loop;
238

239
      --  Add list of all RI names (both synchronous and asynchronous)
Maxime Perrotin's avatar
Maxime Perrotin committed
240
241
      for Each of F.Required loop
         Result.Required := Result.Required & Interface_Template (Each);
242
243
244
         List_Of_RIs     := List_Of_RIs & Each.Name;
         case Each.RCM is
            when Cyclic_Operation | Sporadic_Operation =>
Maxime Perrotin's avatar
Maxime Perrotin committed
245
               List_Of_ASync_RIs := List_Of_ASync_RIs & Each.Name;
246
            when others =>
Maxime Perrotin's avatar
Maxime Perrotin committed
247
               List_Of_Sync_RIs := List_Of_Sync_RIs & Each.Name;
248
         end case;
Maxime Perrotin's avatar
Maxime Perrotin committed
249
      end loop;
250
251

      --  Add list of timers (names)
Maxime Perrotin's avatar
Maxime Perrotin committed
252
253
254
      for Each of F.Timers loop
         Timers := Timers & Each;
      end loop;
255
256
257
258
259
260
261
262

      --  Add all user-defined properties
      for Each of F.User_Properties loop
         Property_Names  := Property_Names & Each.Name;
         Property_Values := Property_Values & Each.Value;
      end loop;

      --  Setup the mapping for the template
Maxime Perrotin's avatar
Maxime Perrotin committed
263
      Result.Header := Result.Header
Maxime Perrotin's avatar
Maxime Perrotin committed
264
265
266
267
268
269
270
271
272
273
274
        & Assoc ("List_Of_PIs",       List_Of_PIs)
        & Assoc ("List_Of_RIs",       List_Of_RIs)
        & Assoc ("List_Of_Sync_PIs",  List_Of_Sync_PIs)
        & Assoc ("List_Of_Sync_RIs",  List_Of_Sync_RIs)
        & Assoc ("List_Of_ASync_PIs", List_Of_ASync_PIs)
        & Assoc ("List_Of_ASync_RIs", List_Of_ASync_RIs)
        & Assoc ("Property_Names",    Property_Names)
        & Assoc ("Property_Values",   Property_Values)
        & Assoc ("Is_Type",           F.Is_Type)
        & Assoc ("Instance_Of",       F.Instance_Of.Value_Or (US ("")))
        & Assoc ("Timers",            Timers);
Maxime Perrotin's avatar
Maxime Perrotin committed
275
276
277
278
279
      return Result;
   end Func_Template;

   function Interface_View_Template (IV : Complete_Interface_View)
                                     return IV_As_Template is
280
281
      use Func_Maps;
      use Ada.Strings.Unbounded;
Maxime Perrotin's avatar
Maxime Perrotin committed
282
283
284
      Result : IV_As_Template;
   begin
      for Each of IV.Flat_Functions loop
285
286
         Result.Funcs.Insert (Key      => To_String (Each.Name),
                              New_Item => Func_Template (Each));
Maxime Perrotin's avatar
Maxime Perrotin committed
287
288
289
      end loop;
      return Result;
   end Interface_View_Template;
290
end TASTE.Backend.Skeletons;