Newer
Older
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
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
(*----------------------------------------------------------------------
module : CompileData
date :
------------------------------------------------------------------------
DESCRIPTION :
Définition des structures de données utilisée pour la compil,
plus des utilitaires pour les mesages d'erreurs, de bug etc.
N.B. on utilise beaucoup l'adjectif "effectif", qui signifie
simplement "correct".
REMARQUE GENERALE :
D'une manière générale, la compil d'une entité syntaxique
"toto" est implémentée par une fonction check_toto, qui
prend en entrée (entr'autre) un toto et renvoie un
toto_eff.
TYPES DE DONNEES :
- type_eff :
dénotation de type effectif, implémente l'équivalence des types,
construit à partir d'une type_exp.
- const_eff :
dénotation de constante effective,
construit à partir d'une val_exp => IL S'AGIT DE LA REPRESENTATION
INTERNE DES CONSTANTES STATIQUES
- var_eff :
déclaration de variable,
construit à partir de var_info.
- val_eff :
union entre const_eff et var_eff.
- slice_eff :
dénotation de tranche de tableau,
construit à partir de slice_info.
- left_eff :
version compilée de left_part
- eq_eff :
version compilée de eq_info
- func_eff :
déclaration de fonction chéckée
(info conservée dans la table des symboles pour résoudre les call)
- node_half_eff : (N.B. utilise dans pack_env)
déclaration de node/template half-chéckée.
(info conservée dans la table des symboles pour résoudre les call)
- oper_half_eff : (N.B. utilise dans pack_env)
union de func_eff et node_half_eff.
- oper_eff :
dénotation d'opération,
peut être fonction, predef ou template,
construit à partir de oper_exp.
- node_eff :
noeud/template + arguments statiques effectifs,
- static_arg_eff :
déclaration d'un static arg
- pack_env :
la "grosse" structure de données qui gère la compilation
des packages => implémentée dans CheckGlobal pour la partie type/const/function
(initialisation) et dans CheckOper pour la partie node/template qui
est faite à la demande.
- local_env :
structure qui gère l'environnement de compilation
d'un noeud/template.
TYPES FONCTIONNEL :
- id_solver (en fait, une structure qui contient plusieurs fonctions,
une pour traiter les constantes, une pour traiter les types)
UTILITAIRES :
- type_of_const_eff : renvoie le type_eff d'une const_eff
- string_of_type_eff : pretty-print d'un type_eff
- string_of_const_eff : pretty-print d'une const_eff
- string_of_oper_key : pretty-print d'un oper_key
_ string_of_slice_eff :
----------------------------------------------------------------------*)
open Printf
open Hashtbl
open Lxm
open CompUtils
open Errors
open Syntaxe
open String
(*---------------------------------------------------------------------
Type : id_solver
-----------------------------------------------------------------------
Joue le rôle d'environnemnt : contient des fonctions
pour résoudre les réferences aux idents.
(voir par exemple EvalConst, EvalType)
N.B. On fournit les constructeurs des id_solver courants, voir :
const_and_type_id_solver
----------------------------------------------------------------------*)
type id_solver = {
id2const : Syntaxe.idref -> Lxm.t -> const_eff ;
id2type : Syntaxe.idref -> Lxm.t -> type_eff ;
}
and fullid = string * string
(*---------------------------------------------------------------------
Type : type_eff
-----------------------------------------------------------------------
Dénotation de type immédiat : l'équivalence sémantique des types
EST l'équivalence structurelle des type_eff.
Par rapport à une type_exp :
- pas d'alias
- taille des tableaux résolues
----------------------------------------------------------------------*)
and type_eff =
Bool_type_eff
| Int_type_eff
| Real_type_eff
| External_type_eff of fullid
| Enum_type_eff of (fullid * (fullid list))
| Array_type_eff of (type_eff * int)
| Struct_type_eff of (fullid * (string * type_eff * const_eff option) list)
(*---------------------------------------------------------------------
Type : slice_eff
-----------------------------------------------------------------------
Dénotation de tranche de tableau correcte :
si A est le tableau d'entrée, alors S est le tableau
de sortie avec :
S[i] = A[first + i*step] pour i = 0 .. width
----------------------------------------------------------------------*)
and slice_eff = {
se_first : int;
se_last : int;
se_step : int;
se_width : int
}
(*---------------------------------------------------------------------
Type : left_eff
-----------------------------------------------------------------------
Version checkée des left_part
(les idents, les index et les tranches sont résolus)
N.B. On conserve aussi le type effectif de chaque noeud
bien qu'il soit possible de le retrouver.
(voir type_of_left_eff)
N.B. On garde aussi l'info source des idents au cas ou.
----------------------------------------------------------------------*)
and left_eff =
LeftEffVar of (var_eff * Lxm.t)
| LeftEffField of (left_eff * string * type_eff)
| LeftEffArray of (left_eff * int * type_eff)
| LeftEffSlice of (left_eff * slice_eff * type_eff)
(*---------------------------------------------------------------------
Type : eq_eff
-----------------------------------------------------------------------
Version checkée des eq_info
N.B. A COMPLETER SANS DOUTE
----------------------------------------------------------------------*)
and eq_eff = {
eqf_left_list : left_eff list ;
}
(*---------------------------------------------------------------------
Type : const_eff
-----------------------------------------------------------------------
Dénotation de constante immédiate
N.B. les const_eff "portent" leur type :
- il est implicite pour bool, int, real,
- explicite pour extern, enum et struct
- pour array c'est le TYPE DES ELEMENTS QU'ON TRIMBALE
VOIR => type_of_const_eff
----------------------------------------------------------------------*)
and const_eff =
(* type predef *)
Bool_const_eff of bool
| Int_const_eff of int
| Real_const_eff of float
(* type atomique non predef : on précise le type *)
| Extern_const_eff of (fullid * type_eff)
| Enum_const_eff of (fullid * type_eff)
(* type structure : liste (champ,valeur) + type structure *)
| Struct_const_eff of ((string * const_eff) list * type_eff)
(* type tableau : liste des valeurs + type des elts + taille *)
| Array_const_eff of (const_eff array * type_eff)
(*---------------------------------------------------------------------
Type: val_eff
-----------------------------------------------------------------------
Une constante ou une variable
=> item de la table des symboles de valeurs
----------------------------------------------------------------------*)
and val_eff =
ConstEff of const_eff
| VarEff of var_eff
(*---------------------------------------------------------------------
Type: var_eff
-----------------------------------------------------------------------
Info associée à un ident de variable
----------------------------------------------------------------------*)
(* ICI à completer/modifier sans doute *)
and var_eff = {
vf_name : string ;
vf_nature : var_nature ;
vf_type : type_eff ;
vf_clock : clock_eff
}
and clock_eff =
BaseClockEff
| VarClockEff of var_eff
(*---------------------------------------------------------------------
Type : oper_half_eff
-----------------------------------------------------------------------
Union des déclarations de node et de function.
N.B. dans le cas des fonctions, on a un info complétement chéckée
(func_eff), par contre pour les nodes on a une info
à peine chéckée, d'où le nom node_half_eff.
=> item de la table des symboles d'opération
----------------------------------------------------------------------*)
and oper_half_eff =
FuncRef of func_eff
| NodeRef of node_half_eff
(*---------------------------------------------------------------------
Type : func_eff
-----------------------------------------------------------------------
Construit à partir de func_info
----------------------------------------------------------------------*)
and func_eff = {
fe_name : string ;
fe_in_types : type_eff list ;
fe_out_types : type_eff list
}
(*---------------------------------------------------------------------
Type : node_half_eff
-----------------------------------------------------------------------
correspond à un noeud half-checked : on conserve simplement
la node_info (on pourra sophistiquer plus tard)
----------------------------------------------------------------------*)
and node_half_eff = Syntaxe.node_info srcflaged
(*---------------------------------------------------------------------
Type : node_eff
-----------------------------------------------------------------------
correspond à une instance de template (ou, cas limite,
de noeud sans param statique). La clé est un couple ident/liste
d'arguments statiques effectifs
N.B. une horloge formelle est soit None (base)
soit l'index d'une entrée (0..nb entrées-1)
Les formal-clocks sont crées au cours du type-checking
(et pas du clock-checking)
----------------------------------------------------------------------*)
and node_eff = {
nf_key : node_key ;
nf_in_types : type_eff list ;
nf_out_types : type_eff list ;
nf_in_formal_clocks : int option list ;
nf_out_formal_clocks : int option list ;
}
(*---------------------------------------------------------------------
Type : XXX_key
-----------------------------------------------------------------------
les clés sont des idents complets en général,
un peu plus compliqué pour les nodes...
----------------------------------------------------------------------*)
and item_key = fullid
and node_key = item_key * static_arg_eff list
(*---------------------------------------------------------------------
Type : static_arg_eff
-----------------------------------------------------------------------
associé à un nom de noeud une liste
de static_arg_eff permet d'identifier de manière unique une
instance de template.
N.B. si la liste d'args est vide, c'est un noeud simple.
----------------------------------------------------------------------*)
and static_arg_eff =
ConstStaticArgEff of (string * const_eff)
| TypeStaticArgEff of (string * type_eff)
| OperStaticArgEff of (string * oper_eff)
(*---------------------------------------------------------------------
Type : oper_eff
-----------------------------------------------------------------------
Version chéckée des oper_exp (expression dénotant une opération).
Utilisée dans les expressions call, mais aussi comme argument statique
ou comme définition de noeud (alias).
Union entre opérateur prédéfini, user_func_eff et node_eff
----------------------------------------------------------------------*)
and oper_eff =
PredefOper of by_pos_op
| FuncOper of func_eff
| NodeOper of node_eff
(*---------------------------------------------------------------------
Type : oper_alias
-----------------------------------------------------------------------
item utilisé pour ``résoudre'' les idents d'operation dans
local_env : dans un local_env, un identificateur utilisé
dans une expression "call" peut pointer sur un opérateur
parfaitement défini (oper_eff), ou sur un noeud half_checké
----------------------------------------------------------------------*)
and oper_alias =
CheckedOper of oper_eff
| HalfCheckedNode of node_half_eff
(*---------------------------------------------------------------------
Type chkflaged
-----------------------------------------------------------------------
Au cours du check, on conserve le statut des idents :
- Checking => en cours de traitement, permet de lever les récursions
- Checked => traité et correct
- BadChecked => déjà marqué comme incorrect (pas besoin d'un nouveau
message d'erreur)
----------------------------------------------------------------------*)
type 'a chkflaged =
Checking
| Checked of 'a
| BadChecked
type
world_env = {
wenv_src : Syntaxe.namespace list;
wenv_mod_srcs : (string, Syntaxe.model_info srcflaged) Hashtbl.t ;
wenv_pack_srcs : (string, Syntaxe.pack_info srcflaged) Hashtbl.t ;
wenv_pack_envs : (string, pack_env) Hashtbl.t ;
}
(*---------------------------------------------------------------------
Type pack_env
-----------------------------------------------------------------------
----------------------------------------------------------------------*)
and pack_env = {
penv_world : world_env ;
(* penv_src : Syntaxe.package ; *)
penv_type_table : (string, type_eff chkflaged) Hashtbl.t ;
penv_const_table : (string, const_eff chkflaged) Hashtbl.t ;
penv_oper_table : (string, oper_half_eff) Hashtbl.t ;
penv_node_table : (node_key, node_eff chkflaged) Hashtbl.t
}
(*---------------------------------------------------------------------
Type local_env
-----------------------------------------------------------------------
----------------------------------------------------------------------*)
and local_env = {
lenv_node_key : node_key ;
lenv_globals : pack_env ;
lenv_types : (string, type_eff) Hashtbl.t ;
lenv_vals : (string, val_eff) Hashtbl.t ;
lenv_opers : (string, oper_eff) Hashtbl.t ;
}
(* Utilitaires liés aux node_key *)
let make_simple_node_key nkey = (nkey, [])
(*---------------------------------------------------------------------
Utilitaire: const_and_type_id_solver
-----------------------------------------------------------------------
Rôle :
comme son nom l'indique
Entrées :
id2const, id2type
Sorties :
id_solver
Effets de bord :
aucun. mais peut générer des Internal à l'usage !
---------------------------------------------------------------------*)
let const_and_type_id_solver
(i2c : Syntaxe.idref -> Lxm.t -> const_eff)
(i2t : Syntaxe.idref -> Lxm.t -> type_eff)
=
{
id2const = i2c ;
id2type = i2t ;
}
(*---------------------------------------------------------------------
Utilitaire: type_of_const_eff
-----------------------------------------------------------------------
Rôle :
comme son nom l'indique
Entrées :
const_eff
Sorties :
type_eff
Effets de bord :
aucun
----------------------------------------------------------------------*)
let type_of_const_eff c =
match c with
Bool_const_eff v -> Bool_type_eff
| Int_const_eff v -> Int_type_eff
| Real_const_eff v -> Real_type_eff
| Extern_const_eff (s, teff) -> teff
| Enum_const_eff (s, teff) -> teff
| Struct_const_eff (fl, teff) -> teff
| Array_const_eff (ct, teff) -> Array_type_eff (teff, Array.length ct)
(*---------------------------------------------------------------------
Utilitaire: type_of_left_eff
-----------------------------------------------------------------------
Rôle :
comme son nom l'indique
Entrées :
left_eff
Sorties :
type_eff
Effets de bord :
aucun
----------------------------------------------------------------------*)
let type_of_left_eff l =
match l with
LeftEffVar (v,lxm) -> v.vf_type
| LeftEffField (l, n, te) -> te
| LeftEffArray (l, i, te) -> te
| LeftEffSlice (l, s, te) -> te
(*---------------------------------------------------------------------
Utilitaire: string_of_type_eff
-----------------------------------------------------------------------
Rôle :
affichage d'une valeur de type (pour debug)
Entrées :
type_eff
Sorties :
string
Effets de bord :
----------------------------------------------------------------------*)
let rec string_of_type_eff = function
Bool_type_eff -> "bool"
| Int_type_eff -> "int"
| Real_type_eff -> "real"
| External_type_eff i -> string_of_fullid i
| Enum_type_eff (i, sl) -> string_of_fullid i
| Array_type_eff (ty, sz) -> sprintf "%s^%d" (string_of_type_eff ty) sz
| Struct_type_eff (i, fl) -> string_of_fullid i
and string_of_type_eff_list = function
[] -> ""
| [x] -> (string_of_type_eff x)
| l -> (
String.concat " * " (List.map string_of_type_eff l)
)
let rec string_of_const_eff = (
function
Bool_const_eff true -> "true"
| Bool_const_eff false -> "false"
| Int_const_eff i -> sprintf "%d" i
| Real_const_eff r -> sprintf "%f" r
| Extern_const_eff (s,t) -> (string_of_fullid s)
| Enum_const_eff (s,t) -> (string_of_fullid s)
| Struct_const_eff (fl, t) -> (
let string_of_field =
function (id, veff) -> id^" = "^(string_of_const_eff veff)
in
let flst = List.map string_of_field fl in
(string_of_type_eff t)^"{"^(String.concat "; " flst)^"}"
)
| Array_const_eff (ctab, t) -> (
let vl = Array.to_list(Array.map string_of_const_eff ctab) in
"["^(String.concat ", " vl)^"]"
)
)
let rec string_of_node_key (nkey: node_key) = (
let arg2string (sa : static_arg_eff) = (
match sa with
ConstStaticArgEff (id, ceff) -> (
sprintf "const %s" (string_of_const_eff ceff)
) |
TypeStaticArgEff (id, teff) -> (
sprintf "type %s" (string_of_type_eff teff)
) |
OperStaticArgEff (id, opeff) -> (
match opeff with
PredefOper posop -> (
sprintf "operator %s" (Dump.op2string posop)
) |
FuncOper feff -> (
sprintf "node %s" feff.fe_name
) |
NodeOper neff -> (
sprintf "node %s" (string_of_node_key neff.nf_key)
)
)
) in
match nkey with
(ik, []) -> (
(string_of_fullid ik)
) |
(ik, salst) -> (
let astrings = List.map arg2string salst in
sprintf "%s<<%s>>"
(string_of_fullid ik)
(String.concat ", " astrings)
)
)
let string_of_clock (ck : clock_eff) = (
match ck with
BaseClockEff -> "<base>"
| VarClockEff veff -> veff.vf_name
)
(*---------------------------------------------------------------------
Une erreur associée à un noeud + 1 lexeme dans le fichier source
----------------------------------------------------------------------*)
exception Compile_node_error of node_key * Lxm.t * string
exception Global_node_error of node_key * string
(*---------------------------------------------------------------------
Formatage standard des erreurs de compil
----------------------------------------------------------------------*)
let node_error_string nkey = (
Printf.sprintf "While checking %s" (string_of_node_key nkey)
)
(*---------------------------------------------------------------------
Message d'erreur (associé à un lexeme) sur stderr
----------------------------------------------------------------------*)
let print_compile_node_error nkey lxm msg = (
Printf.eprintf "%s\n" (node_error_string nkey);
Errors.print_compile_error lxm msg ;
flush stderr
)
let print_global_node_error nkey msg = (
Printf.eprintf "%s\n" (node_error_string nkey);
Errors.print_global_error msg ;
flush stderr
)