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
         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
38
         Exists (Path & "makefile.tmplt")               and then
Maxime Perrotin's avatar
Maxime Perrotin committed
39
40
         Exists (Path & "body-filename.tmplt")          and then
         Exists (Path & "header-filename.tmplt"));
Maxime Perrotin's avatar
Maxime Perrotin committed
41

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

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

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

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

Maxime Perrotin's avatar
Maxime Perrotin committed
166
167
168
   function Parameter_Template (Param : ASN1_Parameter; TI : Taste_Interface)
       return Translate_Set
   is
Maxime Perrotin's avatar
Maxime Perrotin committed
169
     (+Assoc ("Type", Param.Sort) & Assoc ("Name", Param.Name)
Maxime Perrotin's avatar
Maxime Perrotin committed
170
     & Assoc ("Interface_Kind", TI.RCM'Img)
Maxime Perrotin's avatar
Maxime Perrotin committed
171
172
173
174
175
176
     & 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
177
178
179
180
      Result           : Interface_As_Template;
      Param_Names      : Vector_Tag;
      Param_Types      : Vector_Tag;
      Param_Directions : Vector_Tag;
Maxime Perrotin's avatar
Maxime Perrotin committed
181
   begin
Maxime Perrotin's avatar
Maxime Perrotin committed
182
      Result.Header :=  +Assoc  ("Name",            TI.Name)
Maxime Perrotin's avatar
Maxime Perrotin committed
183
                        & Assoc ("Kind",            TI.RCM'Img)
Maxime Perrotin's avatar
Maxime Perrotin committed
184
185
                        & Assoc ("Parent_Function", TI.Parent_Function);
      for Each of TI.Params loop
Maxime Perrotin's avatar
Maxime Perrotin committed
186
187
188
189
         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
190
      end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
191
192
193
194
      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
195
196
197
198
199
200
      return Result;
   end Interface_Template;

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

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

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

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

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

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