taste-backend-skeletons.adb 9.18 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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
   end Generate;

   function Parameter_Template (Param : ASN1_Parameter) return Translate_Set is
     (+Assoc ("Type", Param.Sort) & Assoc ("Name", Param.Name)
     & Assoc ("Direction", Param.Direction'Img));

   function Interface_Template (TI : Taste_Interface)
                                return Interface_As_Template
   is
      use Template_Vectors;
      Result : Interface_As_Template;
   begin
      Result.Header :=  +Assoc ("Name",             TI.Name)
                        & Assoc ("Parent_Function", TI.Parent_Function);
      for Each of TI.Params loop
         Result.Params := Result.Params & Parameter_Template (Each);
      end loop;
      return Result;
   end Interface_Template;

   function Func_Template (F : Taste_Terminal_Function) return Func_As_Template
   is
      use Interface_Vectors;
194
      use Ctxt_Params;
Maxime Perrotin's avatar
Maxime Perrotin committed
195
196
197
      Result      : Func_As_Template;
      List_Of_PIs : Tag;
      List_Of_RIs : Tag;
Maxime Perrotin's avatar
Maxime Perrotin committed
198
      Timers      : Tag;
Maxime Perrotin's avatar
Maxime Perrotin committed
199
200
   begin
      Result.Header := +Assoc ("Name", F.Name)
201
202
        & Assoc ("Language", Language_Spelling (F))
        & Assoc ("Has_Context", (Length (F.Context_Params) > 0));
Maxime Perrotin's avatar
Maxime Perrotin committed
203
204
      for Each of F.Provided loop
         Result.Provided := Result.Provided & Interface_Template (Each);
Maxime Perrotin's avatar
Maxime Perrotin committed
205
         List_Of_PIs := List_Of_PIs & Each.Name;
Maxime Perrotin's avatar
Maxime Perrotin committed
206
207
208
      end loop;
      for Each of F.Required loop
         Result.Required := Result.Required & Interface_Template (Each);
Maxime Perrotin's avatar
Maxime Perrotin committed
209
         List_Of_RIs := List_Of_RIs & Each.Name;
Maxime Perrotin's avatar
Maxime Perrotin committed
210
      end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
211
212
213
      for Each of F.Timers loop
         Timers := Timers & Each;
      end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
214
215
      Result.Header := Result.Header
        & Assoc ("List_Of_PIs", List_Of_PIs)
Maxime Perrotin's avatar
Maxime Perrotin committed
216
217
        & Assoc ("List_Of_RIs", List_Of_RIs)
        & Assoc ("Timers", Timers);
Maxime Perrotin's avatar
Maxime Perrotin committed
218
219
220
221
222
      return Result;
   end Func_Template;

   function Interface_View_Template (IV : Complete_Interface_View)
                                     return IV_As_Template is
223
224
      use Func_Maps;
      use Ada.Strings.Unbounded;
Maxime Perrotin's avatar
Maxime Perrotin committed
225
226
227
      Result : IV_As_Template;
   begin
      for Each of IV.Flat_Functions loop
228
229
         Result.Funcs.Insert (Key      => To_String (Each.Name),
                              New_Item => Func_Template (Each));
Maxime Perrotin's avatar
Maxime Perrotin committed
230
231
232
233
234
      end loop;
      return Result;
   end Interface_View_Template;

end TASTe.Backend.Skeletons;