Project

General

Profile

Download (16.1 KB) Statistics
| Branch: | Tag: | Revision:
1
(********************************************************************)
2
(*                                                                  *)
3
(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
4
(*  Copyright 2012 -    --   ONERA - CNRS - INPT - LIFL             *)
5
(*                                                                  *)
6
(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
7
(*  under the terms of the GNU Lesser General Public License        *)
8
(*  version 2.1.                                                    *)
9
(*                                                                  *)
10
(*  This file was originally from the Prelude compiler              *)
11
(*                                                                  *)
12
(********************************************************************)
13

    
14
open Utils
15
(** Types definitions and a few utility functions on types. *)
16

    
17
module type BASIC_TYPES = sig
18
  type t
19

    
20
  val pp : Format.formatter -> t -> unit
21

    
22
  val pp_c : Format.formatter -> t -> unit
23

    
24
  val is_scalar_type : t -> bool
25

    
26
  val is_numeric_type : t -> bool
27

    
28
  val is_int_type : t -> bool
29

    
30
  val is_real_type : t -> bool
31

    
32
  val is_bool_type : t -> bool
33

    
34
  val is_dimension_type : t -> bool
35

    
36
  val type_int_builder : t
37

    
38
  val type_real_builder : t
39

    
40
  val type_bool_builder : t
41

    
42
  val type_string_builder : t
43

    
44
  val unify : t -> t -> unit
45

    
46
  val is_unifiable : t -> t -> bool
47
end
48

    
49
module type S = sig
50
  module BasicT : BASIC_TYPES
51

    
52
  type basic_type = BasicT.t
53

    
54
  type t = { mutable tdesc : type_desc; tid : int }
55

    
56
  and type_desc =
57
    | Tconst of ident
58
    (* type constant *)
59
    | Tbasic of basic_type
60
    | Tclock of t
61
    (* A type expression explicitely tagged as carrying a clock *)
62
    | Tarrow of t * t
63
    | Ttuple of t list
64
    | Tenum of ident list
65
    | Tstruct of (ident * t) list
66
    | Tarray of Dimension.t * t
67
    | Tstatic of Dimension.t * t
68
    (* a type carried by a dimension expression *)
69
    | Tlink of t
70
    (* During unification, make links instead of substitutions *)
71
    | Tvar
72
    (* Monomorphic type variable *)
73
    | Tunivar
74
  (* Polymorphic type variable *)
75

    
76
  type error =
77
    | Unbound_value of ident
78
    | Already_bound of ident
79
    | Already_defined of ident
80
    | Undefined_var of ISet.t
81
    | Declared_but_undefined of ident
82
    | Unbound_type of ident
83
    | Not_a_dimension
84
    | Not_a_constant
85
    | Assigned_constant of ident
86
    | WrongArity of int * int
87
    | WrongMorphism of int * int
88
    | Type_mismatch of ident
89
    | Type_clash of t * t
90
    | Poly_imported_node of ident
91

    
92
  exception Unify of t * t
93

    
94
  exception Error of Location.t * error
95

    
96
  val is_real_type : t -> bool
97

    
98
  val is_int_type : t -> bool
99

    
100
  val is_bool_type : t -> bool
101

    
102
  val is_const_type : t -> ident -> bool
103

    
104
  val is_static_type : t -> bool
105

    
106
  val is_array_type : t -> bool
107

    
108
  val is_dimension_type : t -> bool
109

    
110
  val is_address_type : t -> bool
111

    
112
  val is_generic_type : t -> bool
113

    
114
  val pp : Format.formatter -> t -> unit
115

    
116
  val repr : t -> t
117

    
118
  val dynamic_type : t -> t
119

    
120
  val type_desc : t -> type_desc
121

    
122
  val new_var : unit -> t
123

    
124
  val new_univar : unit -> t
125

    
126
  val new_ty : type_desc -> t
127

    
128
  val type_int : type_desc
129

    
130
  val type_real : type_desc
131

    
132
  val type_bool : type_desc
133

    
134
  val type_string : type_desc
135

    
136
  val array_element_type : t -> t
137

    
138
  val type_list_of_type : t -> t list
139

    
140
  val pp_node_ty : Format.formatter -> t -> unit
141

    
142
  val get_clock_base_type : t -> t option
143

    
144
  val get_static_value : t -> Dimension.t option
145

    
146
  val types_of_tuple_type : t -> t list
147

    
148
  val is_tuple_type : t -> bool
149

    
150
  val type_of_type_list : t list -> t
151

    
152
  val split_arrow : t -> t * t
153

    
154
  val unclock_type : t -> t
155

    
156
  val bottom : t
157

    
158
  val map_tuple_type : (t -> t) -> t -> t
159

    
160
  val array_base_type : t -> t
161

    
162
  val array_type_dimension : t -> Dimension.t
163

    
164
  val pp_error : Format.formatter -> error -> unit
165

    
166
  val struct_field_type : t -> ident -> t
167

    
168
  val array_type_multi_dimension : t -> Dimension.t list
169
end
170

    
171
module Basic : BASIC_TYPES = struct
172
  type t = Tstring | Tint | Treal | Tbool | Trat
173
  (* Actually unused for now. Only place where it can appear is in a clock
174
     declaration *)
175

    
176
  let type_string_builder = Tstring
177

    
178
  let type_int_builder = Tint
179

    
180
  let type_real_builder = Treal
181

    
182
  let type_bool_builder = Tbool
183

    
184
  open Format
185

    
186
  let pp fmt t =
187
    match t with
188
    | Tint ->
189
      fprintf fmt "int"
190
    | Treal ->
191
      fprintf fmt "real"
192
    | Tstring ->
193
      fprintf fmt "string"
194
    | Tbool ->
195
      fprintf fmt "bool"
196
    | Trat ->
197
      fprintf fmt "rat"
198

    
199
  let pp_c = pp
200

    
201
  let is_scalar_type t =
202
    match t with Tbool | Tint | Treal -> true | _ -> false
203

    
204
  let is_numeric_type t = match t with Tint | Treal -> true | _ -> false
205

    
206
  let is_int_type t = t = Tint
207

    
208
  let is_real_type t = t = Treal
209

    
210
  let is_bool_type t = t = Tbool
211

    
212
  let is_dimension_type t = match t with Tint | Tbool -> true | _ -> false
213

    
214
  let is_unifiable b1 b2 = b1 == b2
215

    
216
  let unify _ _ = ()
217
end
218

    
219
module Make (BasicT : BASIC_TYPES) = struct
220
  module BasicT = BasicT
221

    
222
  type basic_type = BasicT.t
223

    
224
  type t = { mutable tdesc : type_desc; tid : int }
225

    
226
  and type_desc =
227
    | Tconst of ident
228
    (* type constant *)
229
    | Tbasic of basic_type
230
    | Tclock of t
231
    (* A type expression explicitely tagged as carrying a clock *)
232
    | Tarrow of t * t
233
    | Ttuple of t list
234
    | Tenum of ident list
235
    | Tstruct of (ident * t) list
236
    | Tarray of Dimension.t * t
237
    | Tstatic of Dimension.t * t
238
    (* a type carried by a dimension expression *)
239
    | Tlink of t
240
    (* During unification, make links instead of substitutions *)
241
    | Tvar
242
    (* Monomorphic type variable *)
243
    | Tunivar
244
  (* Polymorphic type variable *)
245

    
246
  type error =
247
    | Unbound_value of ident
248
    | Already_bound of ident
249
    | Already_defined of ident
250
    | Undefined_var of ISet.t
251
    | Declared_but_undefined of ident
252
    | Unbound_type of ident
253
    | Not_a_dimension
254
    | Not_a_constant
255
    | Assigned_constant of ident
256
    | WrongArity of int * int
257
    | WrongMorphism of int * int
258
    | Type_mismatch of ident
259
    | Type_clash of t * t
260
    | Poly_imported_node of ident
261

    
262
  exception Unify of t * t
263

    
264
  exception Error of Location.t * error
265

    
266
  let mk_basic t = Tbasic t
267

    
268
  (* Pretty-print*)
269
  open Format
270

    
271
  let rec pp_struct_ty_field pp_basic fmt (label, ty) =
272
    fprintf fmt "%a : %a" pp_print_string label (pp_ty_param pp_basic) ty
273

    
274
  and pp_ty_param pp_basic fmt ty =
275
    let pp_ty = pp_ty_param pp_basic in
276
    match ty.tdesc with
277
    | Tvar ->
278
      fprintf fmt "_%s" (name_of_type ty.tid)
279
    | Tbasic t ->
280
      pp_basic fmt t
281
    | Tclock t ->
282
      fprintf fmt "%a%s" pp_ty t (if !Options.kind2_print then "" else " clock")
283
    | Tstatic (_, t) ->
284
      pp_ty fmt t
285
    (* fprintf fmt "(%a:%a)" Dimension.pp_dimension d pp_ty t *)
286
    | Tconst t ->
287
      fprintf fmt "%s" t
288
    | Tarrow (ty1, ty2) ->
289
      fprintf fmt "%a -> %a" pp_ty ty1 pp_ty ty2
290
    | Ttuple tylist ->
291
      fprintf
292
        fmt
293
        "(%a)"
294
        (pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt " * ") pp_ty)
295
        tylist
296
    | Tenum taglist ->
297
      fprintf fmt "enum {%a }" (pp_comma_list pp_print_string) taglist
298
    | Tstruct fieldlist ->
299
      fprintf
300
        fmt
301
        "struct {%a }"
302
        (pp_print_list ~pp_sep:pp_print_semicolon (pp_struct_ty_field pp_basic))
303
        fieldlist
304
    | Tarray (e, ty) ->
305
      fprintf fmt "%a^%a" pp_ty ty Dimension.pp e
306
    | Tlink ty ->
307
      pp_ty fmt ty
308
    | Tunivar ->
309
      fprintf fmt "'%s" (name_of_type ty.tid)
310

    
311
  let pp = pp_ty_param BasicT.pp
312

    
313
  let rec pp_node_struct_ty_field fmt (label, ty) =
314
    fprintf fmt "%a : %a" pp_print_string label pp_node_ty ty
315

    
316
  and pp_node_ty fmt ty =
317
    match ty.tdesc with
318
    | Tvar ->
319
      (*Format.eprintf "DEBUG:Types.pp_node@.";*)
320
      fprintf fmt "_%s" (name_of_type ty.tid)
321
    | Tbasic t ->
322
      BasicT.pp fmt t
323
    | Tclock t ->
324
      fprintf
325
        fmt
326
        "%a%s"
327
        pp_node_ty
328
        t
329
        (if !Options.kind2_print then "" else " clock")
330
    | Tstatic (_, t) ->
331
      fprintf fmt "%a" pp_node_ty t
332
    | Tconst t ->
333
      fprintf fmt "%s" t
334
    | Tarrow (ty1, ty2) ->
335
      fprintf fmt "%a -> %a" pp_node_ty ty1 pp_node_ty ty2
336
    | Ttuple tylist ->
337
      fprintf
338
        fmt
339
        "(%a)"
340
        (pp_print_list
341
           ~pp_sep:(fun fmt () -> pp_print_string fmt "")
342
           pp_node_ty)
343
        tylist
344
    | Tenum taglist ->
345
      fprintf fmt "enum {%a }" (pp_comma_list pp_print_string) taglist
346
    | Tstruct fieldlist ->
347
      fprintf
348
        fmt
349
        "struct {%a }"
350
        (pp_print_list ~pp_sep:pp_print_semicolon pp_node_struct_ty_field)
351
        fieldlist
352
    | Tarray (e, ty) ->
353
      fprintf fmt "%a^%a" pp_node_ty ty Dimension.pp e
354
    | Tlink ty ->
355
      pp_node_ty fmt ty
356
    | Tunivar ->
357
      fprintf fmt "'%s" (name_of_type ty.tid)
358

    
359
  let pp_error fmt = function
360
    | Unbound_value id ->
361
      fprintf fmt "Unknown value %s@." id
362
    | Unbound_type id ->
363
      fprintf fmt "Unknown type %s@." id
364
    | Already_bound id ->
365
      fprintf fmt "%s is already declared@." id
366
    | Already_defined id ->
367
      fprintf fmt "Multiple definitions of variable %s@." id
368
    | Not_a_constant ->
369
      fprintf fmt "This expression is not a constant@."
370
    | Assigned_constant id ->
371
      fprintf fmt "The constant %s cannot be assigned@." id
372
    | Not_a_dimension ->
373
      fprintf fmt "This expression is not a valid dimension@."
374
    | WrongArity (ar1, ar2) ->
375
      fprintf fmt "Expecting %d argument(s), found %d@." ar1 ar2
376
    | WrongMorphism (ar1, ar2) ->
377
      fprintf
378
        fmt
379
        "Expecting %d argument(s) for homomorphic extension, found %d@."
380
        ar1
381
        ar2
382
    | Type_mismatch id ->
383
      fprintf fmt "Definition and declaration of type %s don't agree@." id
384
    | Undefined_var vset ->
385
      fprintf
386
        fmt
387
        "No definition provided for variable(s): %a@."
388
        (pp_comma_list pp_print_string)
389
        (ISet.elements vset)
390
    | Declared_but_undefined id ->
391
      fprintf fmt "%s is declared but not defined@." id
392
    | Type_clash (ty1, ty2) ->
393
      Utils.reset_names ();
394
      fprintf fmt "Expected type %a, got type %a@." pp ty1 pp ty2
395
    | Poly_imported_node _ ->
396
      fprintf fmt "Imported nodes cannot have a polymorphic type@."
397

    
398
  let new_id = ref (-1)
399

    
400
  let rec bottom : t = { tdesc = Tlink bottom; tid = -666 }
401

    
402
  let new_ty desc =
403
    incr new_id;
404
    { tdesc = desc; tid = !new_id }
405

    
406
  let new_var () = new_ty Tvar
407

    
408
  let new_univar () = new_ty Tunivar
409

    
410
  let rec repr = function { tdesc = Tlink t'; _ } -> repr t' | t -> t
411

    
412
  let get_static_value ty =
413
    match (repr ty).tdesc with Tstatic (d, _) -> Some d | _ -> None
414

    
415
  (* XXX: UNUSED *)
416
  (* let get_field_type ty label =
417
   *   match (repr ty).tdesc with
418
   *   | Tstruct fl -> (
419
   *     try Some (List.assoc label fl) with Not_found -> None)
420
   *   | _ ->
421
   *     None *)
422

    
423
  let is_static_type ty =
424
    match (repr ty).tdesc with Tstatic _ -> true | _ -> false
425

    
426
  (* XXX: UNUSED *)
427
  (* let rec is_scalar_type ty =
428
   *   match (repr ty).tdesc with
429
   *   | Tstatic (_, ty) ->
430
   *     is_scalar_type ty
431
   *   | Tbasic t ->
432
   *     BasicT.is_scalar_type t
433
   *   | _ ->
434
   *     false *)
435

    
436
  (* XXX: UNUSED *)
437
  (* let rec is_numeric_type ty =
438
   *   match (repr ty).tdesc with
439
   *   | Tstatic (_, ty) ->
440
   *     is_numeric_type ty
441
   *   | Tbasic t ->
442
   *     BasicT.is_numeric_type t
443
   *   | _ ->
444
   *     false *)
445

    
446
  let rec is_real_type ty =
447
    match (repr ty).tdesc with
448
    | Tstatic (_, ty) ->
449
      is_real_type ty
450
    | Tbasic t ->
451
      BasicT.is_real_type t
452
    | _ ->
453
      false
454

    
455
  let rec is_int_type ty =
456
    match (repr ty).tdesc with
457
    | Tstatic (_, ty) ->
458
      is_int_type ty
459
    | Tbasic t ->
460
      BasicT.is_int_type t
461
    | _ ->
462
      false
463

    
464
  let rec is_bool_type ty =
465
    match (repr ty).tdesc with
466
    | Tstatic (_, ty) ->
467
      is_bool_type ty
468
    | Tbasic t ->
469
      BasicT.is_bool_type t
470
    | _ ->
471
      false
472

    
473
  let rec is_const_type ty c =
474
    match (repr ty).tdesc with
475
    | Tstatic (_, ty) ->
476
      is_const_type ty c
477
    | Tconst c' ->
478
      c = c'
479
    | _ ->
480
      false
481

    
482
  let get_clock_base_type ty =
483
    match (repr ty).tdesc with Tclock ty -> Some ty | _ -> None
484

    
485
  let unclock_type ty =
486
    let ty = repr ty in
487
    match ty.tdesc with Tclock ty' -> ty' | _ -> ty
488

    
489
  let rec is_dimension_type ty =
490
    match (repr ty).tdesc with
491
    | Tbasic t ->
492
      BasicT.is_dimension_type t
493
    | Tclock ty' | Tstatic (_, ty') ->
494
      is_dimension_type ty'
495
    | _ ->
496
      false
497

    
498
  let dynamic_type ty =
499
    let ty = repr ty in
500
    match ty.tdesc with Tstatic (_, ty') -> ty' | _ -> ty
501

    
502
  let types_of_tuple_type ty =
503
    match (repr ty).tdesc with Ttuple ts -> ts | _ -> []
504

    
505
  let is_tuple_type ty =
506
    match (repr ty).tdesc with Ttuple _ -> true | _ -> false
507

    
508
  let map_tuple_type f ty =
509
    let ty = dynamic_type ty in
510
    match ty.tdesc with
511
    | Ttuple ty_list ->
512
      { ty with tdesc = Ttuple (List.map f ty_list) }
513
    | _ ->
514
      f ty
515

    
516
  let rec is_struct_type ty =
517
    match (repr ty).tdesc with
518
    | Tstruct _ ->
519
      true
520
    | Tstatic (_, ty') ->
521
      is_struct_type ty'
522
    | _ ->
523
      false
524

    
525
  let struct_field_type ty field =
526
    match (dynamic_type ty).tdesc with
527
    | Tstruct fields -> (
528
      try List.assoc field fields with Not_found -> assert false)
529
    | _ ->
530
      assert false
531

    
532
  let rec is_array_type ty =
533
    match (repr ty).tdesc with
534
    | Tarray _ ->
535
      true
536
    | Tstatic (_, ty') ->
537
      is_array_type ty' (* looks strange !? *)
538
    | _ ->
539
      false
540

    
541
  let array_type_dimension ty =
542
    match (dynamic_type ty).tdesc with
543
    | Tarray (d, _) ->
544
      d
545
    | _ ->
546
      eprintf "internal error: Types.array_type_dimension %a@." pp ty;
547
      assert false
548

    
549
  let rec array_type_multi_dimension ty =
550
    match (dynamic_type ty).tdesc with
551
    | Tarray (d, ty') ->
552
      d :: array_type_multi_dimension ty'
553
    | _ ->
554
      []
555

    
556
  let array_element_type ty =
557
    match (dynamic_type ty).tdesc with
558
    | Tarray (_, ty') ->
559
      ty'
560
    | _ ->
561
      eprintf "internal error: Types.array_element_type %a@." pp ty;
562
      assert false
563

    
564
  let rec array_base_type ty =
565
    let ty = repr ty in
566
    match ty.tdesc with
567
    | Tarray (_, ty') | Tstatic (_, ty') ->
568
      array_base_type ty'
569
    | _ ->
570
      ty
571

    
572
  let is_address_type ty =
573
    is_array_type ty || is_struct_type ty || (is_real_type ty && !Options.mpfr)
574

    
575
  let rec is_generic_type ty =
576
    match (dynamic_type ty).tdesc with
577
    | Tarray (d, ty') ->
578
      (not (Dimension.is_const d)) || is_generic_type ty'
579
    | _ ->
580
      false
581

    
582
  (** Splits [ty] into the [lhs,rhs] of an arrow type. Expects an arrow type
583
      (ensured by language syntax) *)
584
  let rec split_arrow ty =
585
    match (repr ty).tdesc with
586
    | Tarrow (tin, tout) ->
587
      tin, tout
588
    | Tstatic (_, ty') ->
589
      split_arrow ty'
590
    (* Functions are not first order, I don't think the var case needs to be
591
       considered here *)
592
    | _ ->
593
      eprintf "type %a is not a map@.Unable to split@.@?" pp ty;
594
      assert false
595

    
596
  (** Returns the type corresponding to a type list. *)
597
  let type_of_type_list = function [ t ] -> t | tyl -> new_ty (Ttuple tyl)
598

    
599
  let rec type_list_of_type ty =
600
    match (repr ty).tdesc with
601
    | Tstatic (_, ty) ->
602
      type_list_of_type ty
603
    | Ttuple tl ->
604
      tl
605
    | _ ->
606
      [ ty ]
607

    
608
  (* XXX: UNUSED *)
609
  (** [is_polymorphic ty] returns true if [ty] is polymorphic. *)
610
  (* let rec is_polymorphic ty =
611
   *   match ty.tdesc with
612
   *   | Tenum _ | Tvar | Tbasic _ | Tconst _ ->
613
   *     false
614
   *   | Tclock ty ->
615
   *     is_polymorphic ty
616
   *   | Tarrow (ty1, ty2) ->
617
   *     is_polymorphic ty1 || is_polymorphic ty2
618
   *   | Ttuple tl ->
619
   *     List.exists (fun t -> is_polymorphic t) tl
620
   *   | Tstruct fl ->
621
   *     List.exists (fun (_, t) -> is_polymorphic t) fl
622
   *   | Tlink t' ->
623
   *     is_polymorphic t'
624
   *   | Tarray (d, ty) | Tstatic (d, ty) ->
625
   *     Dimension.is_polymorphic d || is_polymorphic ty
626
   *   | Tunivar ->
627
   *     true *)
628

    
629
  (* XXX: UNUSED *)
630
  (* let mktyptuple nb typ =
631
   *   let array = Array.make nb typ in
632
   *   Ttuple (Array.to_list array) *)
633

    
634
  let type_desc t = t.tdesc
635

    
636
  let type_int = mk_basic BasicT.type_int_builder
637

    
638
  let type_real = mk_basic BasicT.type_real_builder
639

    
640
  let type_bool = mk_basic BasicT.type_bool_builder
641

    
642
  let type_string = mk_basic BasicT.type_string_builder
643
end
644

    
645
include Make (Basic)
646

    
647
(* Local Variables: *)
648
(* compile-command:"make -C .." *)
649
(* End: *)
(89-89/99)