1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
(**
Table des infos sources : une couche au dessus de AstV6 pour mieux
ranger les packages et les modèles et faciliter la résolution des
identificateurs.
1) expansion des modèles
2) pour chaque package instancié, 2 tables de symboles :
- une pour la vision "exportée"
- une pour la vision interne. Chaque table de symbole, 3 "espaces"
de noms (par nature d'items, type/const/node)
Ces tables sont destinées à résoudre les références simples, elle
associent à une string :
- la definition syntaxique de l'item associé s'il est local
- l'identificateur absolu (package+nom) si il est externe
*)
open Lxm
open AstV6
open AstCore
open Lv6errors
let dbg = (Lv6Verbose.get_flag "ast")
(** Package manager
Un package manager (pack_mng) contient les infos ``source'' du
package + DEUX tables de symboles, correspondant aux deux contextes
possibles de compilation :
- compilation du provide
- compilation du body
En effet, un identificateur de type, de constante ou de noeud
n'est pas interprété de la même manière suivant qu'il apparaît
dans la partie provide ou body.
Il contient aussi une table des items exportés pour faciliter le
traitement des "use" du package. C'est une correspondance
nature + nom simple -> nom complet
(c.a.d. ??? + AstV6.item_ident -> Lv6Id.long)
*)
type pack_mng = {
pm_lxm : Lxm.t;
pm_raw_src : AstV6.pack_info;
pm_actual_src : AstV6.pack_given;
pm_user_items : (AstCore.item_ident, Lv6Id.long Lxm.srcflagged) Hashtbl.t;
pm_body_stab : AstTabSymbol.t;
pm_provide_stab : AstTabSymbol.t option;
}
(** TYPE PRINCIPAL : t
Packages et modèles sont rangés dans des tables, ce qui permet
notamment de traiter les erreurs de multi-déclarations
(st_raw_mod_tab et st_raw_pack_tab)
Les instances de modeles sont traitées pour n'avoir plus que des
``pack_given'' (i.e. pack avec provide + body)
À chaque package (éventuellement expansé) est associé un manager
pour faciliter l'accès à ses infos (pack_mng)
*)
type t = {
st_list : AstV6.pack_or_model list ;
st_raw_mod_tab : (Lv6Id.t , model_info srcflagged) Hashtbl.t ;
st_raw_pack_tab : (Lv6Id.pack_name , pack_info srcflagged) Hashtbl.t ;
st_pack_mng_tab : (Lv6Id.pack_name , pack_mng) Hashtbl.t;
}
let (pack_list:t -> Lv6Id.pack_name list) =
fun this ->
Hashtbl.fold (fun n _p l -> n::l) this.st_pack_mng_tab []
let (pack_body_env: t -> Lv6Id.pack_name -> AstTabSymbol.t) =
fun this p ->
try
(Hashtbl.find this.st_pack_mng_tab p).pm_body_stab
with Not_found ->
print_string ("*** Error: can not find package '" ^
(Lv6Id.pack_name_to_string p) ^ "' in the following packages: ");
Hashtbl.iter
(fun pn _pm -> print_string ("\n***\t '"^(Lv6Id.pack_name_to_string pn)^ "'"))
this.st_pack_mng_tab;
print_string "\n";
flush stdout;
exit 2
let pack_prov_env (this: t) (p: Lv6Id.pack_name)
: AstTabSymbol.t option =
try (Hashtbl.find this.st_pack_mng_tab p).pm_provide_stab
with Not_found ->
None
(** Insert an item in the lexeme table. Raise [Compile_error] if already defined. *)
let put_in_tab
(what: string)
(tab : ('a, 'b Lxm.srcflagged) Hashtbl.t)
(key : 'a)
(value : 'b Lxm.srcflagged)
=
try
let plxm = (Hashtbl.find tab key).src in
let msg =
Printf.sprintf "%s already declared in %s" what (Lxm.position plxm)
in
raise (Lv6errors.Compile_error (value.src, msg))
with
Not_found -> Hashtbl.add tab key value
let init_user_items (this: pack_mng) = (
let pname = Lv6Id.pack_name_of_string (Lxm.str this.pm_lxm) in
let export_const (s:Lv6Id.t) (xci: AstCore.const_info srcflagged) =
Lv6Verbose.printf ~flag:dbg " export const %s\n" (Lv6Id.to_string s);
put_in_tab "const" this.pm_user_items
(ConstItem s)
(Lxm.flagit (Lv6Id.make_long pname s) xci.src)
in
let export_type (s: Lv6Id.t) (xti: AstCore.type_info srcflagged) =
( match (xti.it) with
| EnumType (_, ecl) -> (
let treat_enum_const ec =
let s = ec.it in
let lxm = ec.src in
Lv6Verbose.printf ~flag:dbg " export enum const %s\n" (Lv6Id.to_string s);
put_in_tab "const" this.pm_user_items
(ConstItem s)
(Lxm.flagit (Lv6Id.make_long pname s) lxm)
in
List.iter treat_enum_const ecl
)
| ExternalType _
| AliasedType _
| StructType _
| ArrayType _
-> ()
);
Lv6Verbose.printf ~flag:dbg " export type %s\n" (Lv6Id.to_string s);
put_in_tab "type" this.pm_user_items
(TypeItem s)
(Lxm.flagit (Lv6Id.make_long pname s) xti.src)
in
let export_node (s: Lv6Id.t) (xoi: AstCore.node_info srcflagged) =
Lv6Verbose.printf ~flag:dbg " export node %s\n" (Lv6Id.to_string s);
put_in_tab "node" this.pm_user_items
(NodeItem (s,xoi.it.static_params))
(Lxm.flagit (Lv6Id.make_long pname s) xoi.src)
in
let pg = this.pm_actual_src in
match pg.pg_provides with
| None ->
Hashtbl.iter export_type pg.pg_body.pk_type_table ;
Hashtbl.iter export_const pg.pg_body.pk_const_table ;
Hashtbl.iter export_node pg.pg_body.pk_node_table ;
| Some spflg ->
let treat_prov x =
let lxm = x.src in
let s = Lxm.id lxm in
match (x.it) with
TypeInfo xti -> export_type s (Lxm.flagit xti lxm)
| ConstInfo xci -> export_const s (Lxm.flagit xci lxm)
| NodeInfo xoi -> export_node s (Lxm.flagit xoi lxm)
in
List.iter treat_prov spflg
)
let create_pack_mng
(pdata : AstV6.pack_info srcflagged)
(pgiven : AstV6.pack_given)
= (
let ppstab = match pgiven.pg_provides with
None -> None
| Some _ -> Some (AstTabSymbol.create ())
in
let res =
{
pm_lxm = pdata.src ;
pm_raw_src = pdata.it;
pm_actual_src = pgiven;
pm_user_items = Hashtbl.create 50;
pm_provide_stab = ppstab;
pm_body_stab = AstTabSymbol.create ();
}
in
init_user_items res;
res
)
let rec (create : AstV6.pack_or_model list -> t) =
fun sl ->
let res = {
st_list = sl ;
st_raw_mod_tab = Hashtbl.create 50;
st_raw_pack_tab = Hashtbl.create 50;
st_pack_mng_tab = Hashtbl.create 50;
}
in
Lv6Verbose.printf ~flag:dbg "*** AstTab.create pass 1\n";
init_raw_tabs res sl ;
Lv6Verbose.printf ~flag:dbg "*** AstTab.create pass 2\n";
let init_pack_mng pname pdata = (
Lv6Verbose.printf ~flag:dbg " init pack %s\n" (Lv6Id.pack_name_to_string pname);
let pg = AstInstanciateModel.f res.st_raw_mod_tab pdata in
Hashtbl.add res.st_pack_mng_tab
pname
(create_pack_mng pdata pg)
) in
Hashtbl.iter init_pack_mng res.st_raw_pack_tab ;
Lv6Verbose.printf ~flag:dbg "*** AstTab.create pass 3\n";
Hashtbl.iter (init_pack_mng_stabs res) res.st_pack_mng_tab ;
Lv6Verbose.printf ~flag:dbg "*** AstTab.create done\n";
res
and
init_raw_tabs (this : t) (sl : AstV6.pack_or_model list) =
let treat_ns ns =
match ns with
| AstV6.NSPack pi ->
let lxm = pi.Lxm.src in
let nme = (Lv6Id.pack_name_of_string (Lxm.str lxm)) in
put_in_tab "package" this.st_raw_pack_tab nme pi
| AstV6.NSModel mi ->
let lxm = mi.Lxm.src in
let nme = (Lxm.id lxm) in
put_in_tab "model" this.st_raw_mod_tab nme mi
in
List.iter treat_ns sl
and
init_pack_mng_stabs (this: t) (pname: Lv6Id.pack_name) (pm: pack_mng) = (
let pg = pm.pm_actual_src in
Lv6Verbose.printf ~flag:dbg " init symbol tables for pack %s\n"
(Lv6Id.pack_name_to_string pname);
let treat_uses (px:Lv6Id.pack_name srcflagged) = (
let pname = px.it in
let lxm = px.src in
let pum =
try Hashtbl.find this.st_pack_mng_tab pname
with Not_found -> raise(Compile_error(lxm, "unknown package"))
in
let fill_used_item
(ii: AstCore.item_ident)
(iks: Lv6Id.long Lxm.srcflagged) =
(match ii with
| ConstItem n -> (
AstTabSymbol.add_import_const pm.pm_body_stab px.it n iks.it;
match pm.pm_provide_stab with
Some pt -> AstTabSymbol.add_import_const pt px.it n iks.it
| None -> ()
)
| TypeItem n -> (
AstTabSymbol.add_import_type pm.pm_body_stab n iks.it;
match pm.pm_provide_stab with
Some pt -> AstTabSymbol.add_import_type pt n iks.it
| None -> ()
)
| NodeItem (n,sparams) -> (
AstTabSymbol.add_import_node pm.pm_body_stab n iks.it sparams;
match pm.pm_provide_stab with
Some pt -> AstTabSymbol.add_import_node pt n iks.it sparams
| None -> ()
)
)
in
Hashtbl.iter fill_used_item pum.pm_user_items
)
in
List.iter treat_uses pg.pg_uses ;
Hashtbl.iter (AstTabSymbol.add_type pm.pm_body_stab pname) pg.pg_body.pk_type_table;
Hashtbl.iter (AstTabSymbol.add_const pm.pm_body_stab pname) pg.pg_body.pk_const_table;
Hashtbl.iter (AstTabSymbol.add_node pm.pm_body_stab) pg.pg_body.pk_node_table;
match pg.pg_provides with
| None -> ()
| Some spflg -> (
let pptab = match pm.pm_provide_stab with
Some pt -> pt
| None -> assert false
in
let treat_prov x =
let lxm = x.src in
let s = Lxm.id lxm in
match (x.it) with
| TypeInfo xti -> AstTabSymbol.add_type pptab pname s (Lxm.flagit xti lxm)
| ConstInfo xci -> AstTabSymbol.add_const pptab pname s (Lxm.flagit xci lxm)
| NodeInfo xoi -> AstTabSymbol.add_node pptab s (Lxm.flagit xoi lxm)
in
List.iter treat_prov spflg
)
)
let (dump : t -> unit) =
fun x ->
let p = prerr_string in
p "*** « Syntax table dump:\n";
p " \t - Package or model list:\n\t\t";
List.iter
(fun pm -> p (AstV6.pack_or_model_to_string pm); p "\n\t\t")
x.st_list ;
p "\n\t - Raw model table: ";
Hashtbl.iter
(fun id _mi -> p ((Lv6Id.to_string id) ^ " "))
x.st_raw_mod_tab;
p "\n\t - Raw Package table: ";
Hashtbl.iter
(fun pn _pi -> p ((Lv6Id.pack_name_to_string pn) ^ " "))
x.st_raw_pack_tab;
p "\n\t - Package manager table: ";
Hashtbl.iter
(fun pn _pm -> p ((Lv6Id.pack_name_to_string pn) ^ " "))
x.st_pack_mng_tab;
p "\nEnd of Syntax table dump. »\n"