taste-backend-skeletons.adb 11.6 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

      --  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
Maxime Perrotin's avatar
Maxime Perrotin committed
34
35
36
37
38
39
         Exists (Path & "interface-header.tmplt")       and then
         Exists (Path & "interface-body.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"));
Maxime Perrotin's avatar
Maxime Perrotin committed
40

Maxime Perrotin's avatar
Maxime Perrotin committed
41
42
43
44
      function Process_Interfaces (Interfaces : Interface_Vectors.Vector;
                                   Path       : String;
                                   Target     : Output) return Tag
      is
Maxime Perrotin's avatar
Maxime Perrotin committed
45
46
47
48
         Result : Tag;
         Tmplt_Sign  : constant String :=
            Path & "interface-" & (if Target = Header then "header"
                                                      else "body") & ".tmplt";
Maxime Perrotin's avatar
Maxime Perrotin committed
49
50
      begin
         for Each of Interfaces loop
Maxime Perrotin's avatar
Maxime Perrotin committed
51
            Result := Result & String'(Parse (Tmplt_Sign, Each.Header));
Maxime Perrotin's avatar
Maxime Perrotin committed
52
         end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
53
         return Result;
Maxime Perrotin's avatar
Maxime Perrotin committed
54
      end Process_Interfaces;
55
56
57
58
59
60
61
62
63
64
65
66
67

      --  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
68
69
70
71
72
73
74
75
76
77
      --  Return a Tag list of ASN.1 Files for the skeleton headers
      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;

Maxime Perrotin's avatar
Maxime Perrotin committed
78
   begin
79
      Put_Info ("=== Generate skeletons ===");
Maxime Perrotin's avatar
Maxime Perrotin committed
80
81
82
83
      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
84
            Proceed    : constant Boolean := Is_Template_Present (Path);
Maxime Perrotin's avatar
Maxime Perrotin committed
85
            Hdr_Tmpl   : constant Translate_Set := +Assoc ("Name", Each.Name);
Maxime Perrotin's avatar
Maxime Perrotin committed
86

Maxime Perrotin's avatar
Maxime Perrotin committed
87
88
            Func_Tmpl  : constant Func_As_Template :=
              Template.Funcs.Element (To_String (Each.Name));
Maxime Perrotin's avatar
Maxime Perrotin committed
89
90
91

            Func_Hdr   : constant Translate_Set :=
              (if Proceed then Func_Tmpl.Header
92
93
94
95
96
               & 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
97
               & Assoc ("ASN1_Files", Get_ASN1_File_List)
Maxime Perrotin's avatar
Maxime Perrotin committed
98
99
100
101
102
103
104
105
106
107
               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",
Maxime Perrotin's avatar
Maxime Perrotin committed
108
                       Process_Interfaces (Func_Tmpl.Required, Path, Code))
Maxime Perrotin's avatar
Maxime Perrotin committed
109
110
               else Null_Set);
            Body_Text   : constant String :=
111
112
113
114
115
                            (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
116
                            & "/" & To_Lower (To_String (Each.Name))
117
                            & "/" & Language
Maxime Perrotin's avatar
Maxime Perrotin committed
118
119
120
121
122
123
124
125
126
127
128
                            & "/" & "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
129
         begin
Maxime Perrotin's avatar
Maxime Perrotin committed
130
            if Proceed then
Maxime Perrotin's avatar
Maxime Perrotin committed
131
               --  Create directory tree (output/function/language/src)
132
               Create_Path (Output_Src);
133
               Put_Info ("Generating " & Header_File);
Maxime Perrotin's avatar
Maxime Perrotin committed
134
135
136
137
138
139
               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
140
                  Put_Info ("Generating " & Body_File);
Maxime Perrotin's avatar
Maxime Perrotin committed
141
142
143
144
145
                  Create (File => Output,
                          Mode => Out_File,
                          Name => Output_Src & Body_File);
                  Put_Line (Output, Body_Text);
                  Close (Output);
146
147
               else
                  Put_Info (Body_File & " already exists, ignoring");
Maxime Perrotin's avatar
Maxime Perrotin committed
148
               end if;
Maxime Perrotin's avatar
Maxime Perrotin committed
149
            else
150
               Put_Info ("Ignoring function " & To_String (Each.Name));
Maxime Perrotin's avatar
Maxime Perrotin committed
151
            end if;
Maxime Perrotin's avatar
Maxime Perrotin committed
152
         exception
153
154
            when E : End_Error
               | Text_IO.Use_Error =>
Maxime Perrotin's avatar
Maxime Perrotin committed
155
156
157
158
159
160
               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);
161
162
         end;
      end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
163
164
   end Generate;

Maxime Perrotin's avatar
Maxime Perrotin committed
165
166
167
   function Parameter_Template (Param : ASN1_Parameter; TI : Taste_Interface)
       return Translate_Set
   is
Maxime Perrotin's avatar
Maxime Perrotin committed
168
     (+Assoc ("Type", Param.Sort) & Assoc ("Name", Param.Name)
Maxime Perrotin's avatar
Maxime Perrotin committed
169
     & Assoc ("Interface_Kind", TI.RCM'Img)
Maxime Perrotin's avatar
Maxime Perrotin committed
170
171
172
173
174
175
     & Assoc ("Direction", Param.Direction'Img));

   function Interface_Template (TI : Taste_Interface)
                                return Interface_As_Template
   is
      use Template_Vectors;
Maxime Perrotin's avatar
Maxime Perrotin committed
176
177
178
179
      Result           : Interface_As_Template;
      Param_Names      : Vector_Tag;
      Param_Types      : Vector_Tag;
      Param_Directions : Vector_Tag;
Maxime Perrotin's avatar
Maxime Perrotin committed
180
   begin
Maxime Perrotin's avatar
Maxime Perrotin committed
181
      Result.Header :=  +Assoc  ("Name",            TI.Name)
Maxime Perrotin's avatar
Maxime Perrotin committed
182
                        & Assoc ("Kind",            TI.RCM'Img)
Maxime Perrotin's avatar
Maxime Perrotin committed
183
184
                        & Assoc ("Parent_Function", TI.Parent_Function);
      for Each of TI.Params loop
Maxime Perrotin's avatar
Maxime Perrotin committed
185
186
187
188
         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
189
      end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
190
191
192
193
      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
194
195
196
197
198
199
      return Result;
   end Interface_Template;

   function Func_Template (F : Taste_Terminal_Function) return Func_As_Template
   is
      use Interface_Vectors;
200
      use Ctxt_Params;
Maxime Perrotin's avatar
Maxime Perrotin committed
201
202
203
204
205
206
207
208
209
210
211
      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;
      Interface_Tmplt    : Interface_As_Template;
Maxime Perrotin's avatar
Maxime Perrotin committed
212
213
   begin
      Result.Header := +Assoc ("Name", F.Name)
214
215
        & Assoc ("Language", Language_Spelling (F))
        & Assoc ("Has_Context", (Length (F.Context_Params) > 0));
216

217
      --  Add list of all PI names (both synchronous and asynchronous)
Maxime Perrotin's avatar
Maxime Perrotin committed
218
      for Each of F.Provided loop
Maxime Perrotin's avatar
Maxime Perrotin committed
219
220
221
222
         Interface_Tmplt := Interface_Template (Each);
         Interface_Tmplt.Header := Interface_Tmplt.Header
                                   & Assoc ("Direction", "PI");
         Result.Provided := Result.Provided & Interface_Tmplt;
223
224
225
         List_Of_PIs     := List_Of_PIs & Each.Name;
         case Each.RCM is
            when Cyclic_Operation | Sporadic_Operation =>
Maxime Perrotin's avatar
Maxime Perrotin committed
226
               List_Of_ASync_PIs := List_Of_ASync_PIs & Each.Name;
227
            when others =>
Maxime Perrotin's avatar
Maxime Perrotin committed
228
               List_Of_Sync_PIs := List_Of_Sync_PIs & Each.Name;
229
         end case;
Maxime Perrotin's avatar
Maxime Perrotin committed
230
      end loop;
231

232
      --  Add list of all RI names (both synchronous and asynchronous)
Maxime Perrotin's avatar
Maxime Perrotin committed
233
      for Each of F.Required loop
Maxime Perrotin's avatar
Maxime Perrotin committed
234
235
236
237
         Interface_Tmplt := Interface_Template (Each);
         Interface_Tmplt.Header := Interface_Tmplt.Header
                                   & Assoc ("Direction", "RI");
         Result.Required := Result.Required & Interface_Tmplt;
238
239
240
         List_Of_RIs     := List_Of_RIs & Each.Name;
         case Each.RCM is
            when Cyclic_Operation | Sporadic_Operation =>
Maxime Perrotin's avatar
Maxime Perrotin committed
241
               List_Of_ASync_RIs := List_Of_ASync_RIs & Each.Name;
242
            when others =>
Maxime Perrotin's avatar
Maxime Perrotin committed
243
               List_Of_Sync_RIs := List_Of_Sync_RIs & Each.Name;
244
         end case;
Maxime Perrotin's avatar
Maxime Perrotin committed
245
      end loop;
246
247

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

      --  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
259
      Result.Header := Result.Header
Maxime Perrotin's avatar
Maxime Perrotin committed
260
261
262
263
264
265
266
267
268
269
270
        & 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
271
272
273
274
275
      return Result;
   end Func_Template;

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