Project

General

Profile

Download (21.9 KB) Statistics
| Branch: | Tag: | Revision:
1
(********************************************************************)
2
(*                                                                  *)
3
(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
4
(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
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
(********************************************************************)
11

    
12
open Lustre_types
13
open Machine_code_types
14
open Machine_code_common
15
open Spec_types
16
open Spec_common
17
open Corelang
18
open Clocks
19
open Causality
20
open Utils
21

    
22
exception NormalizationError
23

    
24
(* Questions:
25

    
26
   - where are used the mconst. They contain initialization of constant in
27
   nodes. But they do not seem to be used by c_backend *)
28

    
29
(* translate_<foo> : vars -> context -> <foo> -> machine code/expression *)
30
(* the context contains  m : state aka memory variables  *)
31
(*                      si : initialization instructions *)
32
(*                       j : node aka machine instances  *)
33
(*                       d : local variables             *)
34
(*                       s : step instructions           *)
35

    
36
(* Machine processing requires knowledge about variables and local variables.
37
   Local could be memories while other could not. *)
38
type machine_env = { is_local : string -> bool; get_var : string -> var_decl }
39

    
40
let build_env inputs locals outputs =
41
  let all = List.sort_uniq VDeclModule.compare (locals @ inputs @ outputs) in
42
  {
43
    is_local = (fun id -> List.exists (fun v -> v.var_id = id) locals);
44
    get_var =
45
      (fun id ->
46
        try List.find (fun v -> v.var_id = id) all
47
        with Not_found ->
48
          (* Format.eprintf "Impossible to find variable %s in set %a@.@?" * id
49
             * VSet.pp all; *)
50
          raise Not_found);
51
  }
52

    
53
(****************************************************************)
54
(* Basic functions to translate to machine values, instructions *)
55
(****************************************************************)
56

    
57
let translate_ident env id =
58
  (* Format.eprintf "trnaslating ident: %s@." id; *)
59
  (* id is a var that shall be visible here , ie. in vars *)
60
  try
61
    let var_id = env.get_var id in
62
    vdecl_to_val var_id
63
  with Not_found -> (
64
    (* id is a constant *)
65
    try
66
      let vdecl =
67
        Corelang.var_decl_of_const
68
          (const_of_top (Hashtbl.find Corelang.consts_table id))
69
      in
70
      vdecl_to_val vdecl
71
    with Not_found -> (
72
      (* id is a tag, getting its type in the list of declared enums *)
73
      try id_to_tag id
74
      with Not_found ->
75
        Format.eprintf "internal error: Machine_code.translate_ident %s@.@?" id;
76
        assert false))
77

    
78
(* specialize predefined (polymorphic) operators wrt their instances, so that
79
   the C semantics is preserved *)
80
let specialize_to_c expr =
81
  match expr.expr_desc with
82
  | Expr_appl (id, e, r) ->
83
    if
84
      List.exists
85
        (fun e -> Types.is_bool_type e.expr_type)
86
        (expr_list_of_expr e)
87
    then
88
      let id = match id with "=" -> "equi" | "!=" -> "xor" | _ -> id in
89
      { expr with expr_desc = Expr_appl (id, e, r) }
90
    else expr
91
  | _ ->
92
    expr
93

    
94
let specialize_op expr =
95
  match !Options.output with Options.OutC -> specialize_to_c expr | _ -> expr
96

    
97
let rec translate_expr env expr =
98
  let expr = specialize_op expr in
99
  let translate_expr = translate_expr env in
100
  let value_desc =
101
    match expr.expr_desc with
102
    | Expr_const v ->
103
      Cst v
104
    | Expr_ident x ->
105
      (translate_ident env x).value_desc
106
    | Expr_array el ->
107
      Array (List.map translate_expr el)
108
    | Expr_access (t, i) ->
109
      Access (translate_expr t, translate_expr (expr_of_dimension i))
110
    | Expr_power (e, n) ->
111
      Power (translate_expr e, translate_expr (expr_of_dimension n))
112
    | Expr_when (e1, _, _) ->
113
      (translate_expr e1).value_desc
114
    | Expr_appl (id, e, _) when Basic_library.is_expr_internal_fun expr ->
115
      let nd = node_from_name id in
116
      Fun (node_name nd, List.map translate_expr (expr_list_of_expr e))
117
    | Expr_ite (g, t, e) when Backends.is_functional () ->
118
      (* special treatment depending on the active backend. For functional ones,
119
         like horn backend, ite are preserved in expression. While they are
120
         removed for C or Java backends. *)
121
      Fun ("ite", [ translate_expr g; translate_expr t; translate_expr e ])
122
    | _ ->
123
      Format.eprintf
124
        "Normalization error for backend %t: %a@."
125
        Options.pp_output
126
        Printers.pp_expr
127
        expr;
128
      raise NormalizationError
129
  in
130
  mk_val value_desc expr.expr_type
131

    
132
let translate_guard env expr =
133
  match expr.expr_desc with
134
  | Expr_ident x ->
135
    translate_ident env x
136
  | _ ->
137
    Format.eprintf "internal error: translate_guard %a@." Printers.pp_expr expr;
138
    assert false
139

    
140
let rec translate_act env (y, expr) =
141
  let translate_act = translate_act env in
142
  let translate_guard = translate_guard env in
143
  let translate_expr = translate_expr env in
144
  let lustre_eq = Corelang.mkeq Location.dummy ([ y.var_id ], expr) in
145
  match expr.expr_desc with
146
  | Expr_ite (c, t, e) ->
147
    let c = translate_guard c in
148
    let t, spec_t = translate_act (y, t) in
149
    let e, spec_e = translate_act (y, e) in
150
    mk_conditional ~lustre_eq c [ t ] [ e ], mk_conditional_tr c spec_t spec_e
151
  | Expr_merge (x, hl) ->
152
    let var_x = env.get_var x in
153
    let hl, spec_hl =
154
      List.(
155
        split
156
          (map
157
             (fun (t, h) ->
158
               let h, spec_h = translate_act (y, h) in
159
               (t, [ h ]), (t, spec_h))
160
             hl))
161
    in
162
    mk_branch' ~lustre_eq var_x hl, mk_branch_tr var_x spec_hl
163
  | _ ->
164
    let e = translate_expr expr in
165
    mk_assign ~lustre_eq y e, mk_assign_tr y e
166

    
167
let get_memory env mems eq =
168
  match eq.eq_lhs, eq.eq_rhs.expr_desc with
169
  | ([ x ], Expr_pre _ | [ x ], Expr_fby _) when env.is_local x ->
170
    let var_x = env.get_var x in
171
    VSet.add var_x mems
172
  | _ ->
173
    mems
174

    
175
let get_memories env = List.fold_left (get_memory env) VSet.empty
176

    
177
(* Datastructure updated while visiting equations *)
178
type machine_ctx = {
179
  (* memories *)
180
  m : ISet.t;
181
  (* Reset instructions *)
182
  si : instr_t list;
183
  (* Instances *)
184
  j : (Lustre_types.top_decl * Dimension.t list) IMap.t;
185
  (* Step instructions *)
186
  s : instr_t list;
187
  (* Memory pack spec *)
188
  mp : (int * mc_formula_t) list;
189
  (* Transition spec *)
190
  t :
191
    (var_decl list
192
    (* vars *)
193
    * ISet.t (* memory footprint *)
194
    * ident IMap.t
195
    (* memory instances footprint *)
196
    * mc_formula_t)
197
    (* formula *)
198
    list;
199
}
200

    
201
let ctx_init =
202
  { m = ISet.empty; si = []; j = IMap.empty; s = []; mp = []; t = [] }
203

    
204
(****************************************************************)
205
(* Main function to translate equations into this machine context we are
206
   building *)
207
(****************************************************************)
208

    
209
let mk_control v l inst = mkinstr (MBranch (vdecl_to_val v, [ l, [ inst ] ]))
210

    
211
let control_on_clock env ck inst =
212
  let rec aux ((fspec, inst) as acc) ck =
213
    match (Clocks.repr ck).cdesc with
214
    | Con (ck, cr, l) ->
215
      let id = Clocks.const_of_carrier cr in
216
      let v = env.get_var id in
217
      aux
218
        ( (fun spec -> Imply (Equal (Var v, Tag (l, v.var_type)), fspec spec)),
219
          mk_control v l inst )
220
        ck
221
    | _ ->
222
      acc
223
  in
224
  let fspec, inst = aux ((fun spec -> spec), inst) ck in
225
  fspec, inst
226

    
227
let reset_instance env i r c =
228
  match r with
229
  | Some r ->
230
    let r = translate_guard env r in
231
    let _, inst =
232
      control_on_clock
233
        env
234
        c
235
        (mk_conditional r [ mkinstr (MSetReset i) ] [ mkinstr (MNoReset i) ])
236
    in
237
    Some r, [ inst ]
238
  | None ->
239
    None, []
240

    
241
let translate_eq env ctx nd inputs locals outputs i eq =
242
  let stateless = fst (get_stateless_status_node nd) in
243
  let id = nd.node_id in
244
  let translate_expr = translate_expr env in
245
  let translate_act = translate_act env in
246
  let locals_pi = Lustre_live.inter_live_i_with id (i - 1) locals in
247
  let outputs_pi = Lustre_live.inter_live_i_with id (i - 1) outputs in
248
  let locals_i = Lustre_live.inter_live_i_with id i locals in
249
  let outputs_i = Lustre_live.inter_live_i_with id i outputs in
250
  let pred_mp ctx a =
251
    let j = try fst (List.hd ctx.mp) with _ -> 0 in
252
    match a with
253
    | Some a -> (i, And [ mk_memory_pack ~i:j id; a ]) :: ctx.mp
254
    | None -> ctx.mp
255
  in
256
  let pred_t ctx a =
257
    ( inputs @ locals_i @ outputs_i,
258
      ctx.m,
259
      IMap.map (fun (td, _) -> node_name td) ctx.j,
260
      Exists
261
        ( Lustre_live.existential_vars id i eq (locals @ outputs),
262
          And
263
            [
264
              mk_transition
265
                ~i:(i - 1)
266
                stateless
267
                id
268
                (vdecls_to_vals (inputs @ locals_pi @ outputs_pi));
269
              a;
270
            ] ) )
271
    :: ctx.t
272
  in
273
  let control_on_clock ck inst spec_mp spec_t ctx =
274
    let fspec, inst = control_on_clock env ck inst in
275
    {
276
      ctx with
277
      s =
278
        {
279
          inst with
280
          instr_spec =
281
            (if fst (get_stateless_status_node nd) || spec_mp = None then []
282
            else [ mk_memory_pack ~i id ])
283
            @ [
284
                mk_transition
285
                  ~i
286
                  stateless
287
                  id
288
                  (vdecls_to_vals (inputs @ locals_i @ outputs_i));
289
              ];
290
        }
291
        :: ctx.s;
292
      mp = pred_mp ctx spec_mp;
293
      t = pred_t ctx (fspec spec_t);
294
    }
295
  in
296
  let reset_instance = reset_instance env in
297
  let mkinstr' = mkinstr ~lustre_eq:eq in
298
  let ctl ?(ck = eq.eq_rhs.expr_clock) instr =
299
    control_on_clock ck (mkinstr' instr)
300
  in
301

    
302
  (* Format.eprintf "translate_eq %a with clock %a@." Printers.pp_node_eq eq
303
     Clocks.print_ck eq.eq_rhs.expr_clock; *)
304
  match eq.eq_lhs, eq.eq_rhs.expr_desc with
305
  | [ x ], Expr_arrow (e1, e2) ->
306
    let var_x = env.get_var x in
307
    let td = Arrow.arrow_top_decl () in
308
    let inst = new_instance td eq.eq_rhs.expr_tag in
309
    let c1 = translate_expr e1 in
310
    let c2 = translate_expr e2 in
311
    assert (c1.value_desc = Cst (Const_tag "true"));
312
    assert (c2.value_desc = Cst (Const_tag "false"));
313
    let ctx =
314
      ctl
315
        (MStep ([ var_x ], inst, [ c1; c2 ]))
316
        (Some (mk_memory_pack ~inst (node_name td)))
317
        (mk_transition ~inst false (node_name td) [ vdecl_to_val var_x ])
318
        { ctx with j = IMap.add inst (td, []) ctx.j }
319
    in
320
    { ctx with si = mkinstr (MSetReset inst) :: ctx.si }
321
  | [ x ], Expr_pre e when env.is_local x ->
322
    let var_x = env.get_var x in
323
    let e = translate_expr e in
324
    ctl
325
      (MStateAssign (var_x, e))
326
      (Some (mk_state_variable_pack var_x))
327
      (mk_state_assign_tr var_x e)
328
      { ctx with m = ISet.add x ctx.m }
329
  | [ x ], Expr_fby (e1, e2) when env.is_local x ->
330
    let var_x = env.get_var x in
331
    let e2 = translate_expr e2 in
332
    let ctx =
333
      ctl
334
        (MStateAssign (var_x, e2))
335
        (Some (mk_state_variable_pack var_x))
336
        (mk_state_assign_tr var_x e2)
337
        { ctx with m = ISet.add x ctx.m }
338
    in
339
    {
340
      ctx with
341
      si = mkinstr' (MStateAssign (var_x, translate_expr e1)) :: ctx.si;
342
    }
343
  | p, Expr_appl (f, arg, r)
344
    when not (Basic_library.is_expr_internal_fun eq.eq_rhs) ->
345
    let var_p = List.map env.get_var p in
346
    let el = expr_list_of_expr arg in
347
    let vl = List.map translate_expr el in
348
    let node_f = node_from_name f in
349
    let call_f = node_f, NodeDep.filter_static_inputs (node_inputs node_f) el in
350
    let i = new_instance node_f eq.eq_rhs.expr_tag in
351
    let env_cks =
352
      List.fold_right
353
        (fun arg cks -> arg.expr_clock :: cks)
354
        el
355
        [ eq.eq_rhs.expr_clock ]
356
    in
357
    let call_ck =
358
      Clock_calculus.compute_root_clock (Clock_predef.ck_tuple env_cks)
359
    in
360
    let r, reset_inst = reset_instance i r call_ck in
361
    let stateless = Stateless.check_node node_f in
362
    let inst = if stateless then None else Some i in
363
    let mp =
364
      if stateless then None else Some (mk_memory_pack ?inst (node_name node_f))
365
    in
366
    let ctx =
367
      ctl
368
        ~ck:call_ck
369
        (MStep (var_p, i, vl))
370
        mp
371
        (mk_transition
372
           ?r
373
           ?inst
374
           stateless
375
           (node_name node_f)
376
           (vl @ vdecls_to_vals var_p))
377
        {
378
          ctx with
379
          j = IMap.add i call_f ctx.j;
380
          s = (if stateless then [] else reset_inst) @ ctx.s;
381
        }
382
    in
383
    (*Clocks.new_var true in Clock_calculus.unify_imported_clock (Some call_ck)
384
      eq.eq_rhs.expr_clock eq.eq_rhs.expr_loc; Format.eprintf "call %a: %a:
385
      %a@," Printers.pp_expr eq.eq_rhs Clocks.print_ck (Clock_predef.ck_tuple
386
      env_cks) Clocks.print_ck call_ck;*)
387
    {
388
      ctx with
389
      si = (if stateless then ctx.si else mkinstr (MSetReset i) :: ctx.si);
390
    }
391
  | [ x ], _ -> (
392
    try
393
      let var_x = env.get_var x in
394
      let instr, spec = translate_act (var_x, eq.eq_rhs) in
395
      control_on_clock eq.eq_rhs.expr_clock instr None spec ctx
396
    with Not_found ->
397
      Format.eprintf "ERROR: node %s, eq %a@." id Printers.pp_node_eq eq;
398
      raise Not_found)
399
  | _ ->
400
    Format.eprintf
401
      "internal error: Machine_code.translate_eq %a@?"
402
      Printers.pp_node_eq
403
      eq;
404
    assert false
405

    
406
let constant_equations locals =
407
  List.fold_left
408
    (fun eqs vdecl ->
409
      if vdecl.var_dec_const then
410
        {
411
          eq_lhs = [ vdecl.var_id ];
412
          eq_rhs = desome vdecl.var_dec_value;
413
          eq_loc = vdecl.var_loc;
414
        }
415
        :: eqs
416
      else eqs)
417
    []
418
    locals
419

    
420
let translate_eqs env ctx nd inputs locals outputs eqs =
421
  List.fold_left
422
    (fun (ctx, i) eq ->
423
      let ctx = translate_eq env ctx nd inputs locals outputs i eq in
424
      ctx, i + 1)
425
    (ctx, 1)
426
    eqs
427
  |> fst
428

    
429
(****************************************************************)
430
(* Processing nodes *)
431
(****************************************************************)
432

    
433
let process_asserts nd =
434
  let exprl = List.map (fun assert_ -> assert_.assert_expr) nd.node_asserts in
435
  if Backends.is_functional () then [], [], exprl
436
  else
437
    (* Each assert(e) is associated to a fresh variable v and declared as v=e;
438
       assert (v); *)
439
    let _, vars, eql, assertl =
440
      List.fold_left
441
        (fun (i, vars, eqlist, assertlist) expr ->
442
          let loc = expr.expr_loc in
443
          let var_id = nd.node_id ^ "_assert_" ^ string_of_int i in
444
          let assert_var =
445
            mkvar_decl
446
              loc
447
              ~orig:false
448
              (* fresh var *)
449
              ( var_id,
450
                mktyp loc Tydec_bool,
451
                mkclock loc Ckdec_any,
452
                false,
453
                (* not a constant *)
454
                None,
455
                (* no default value *)
456
                Some nd.node_id )
457
          in
458
          assert_var.var_type <- Type_predef.type_bool
459
          (* Types.new_ty (Types.Tbool) *);
460
          let eq = mkeq loc ([ var_id ], expr) in
461
          ( i + 1,
462
            assert_var :: vars,
463
            eq :: eqlist,
464
            { expr with expr_desc = Expr_ident var_id } :: assertlist ))
465
        (1, [], [], [])
466
        exprl
467
    in
468
    vars, eql, assertl
469

    
470
let translate_core env nd sorted_eqs inputs locals outputs =
471
  let constant_eqs = constant_equations locals in
472

    
473
  (* Compute constants' instructions *)
474
  let ctx0 = translate_eqs env ctx_init nd inputs locals outputs constant_eqs in
475
  assert (ctx0.si = []);
476
  assert (IMap.is_empty ctx0.j);
477

    
478
  (* Compute ctx for all eqs *)
479
  let ctx = translate_eqs env ctx_init nd inputs locals outputs sorted_eqs in
480

    
481
  ctx, ctx0.s
482

    
483
let zero = mk_val (Cst (Const_int 0)) Type_predef.type_int
484

    
485
let memory_pack_0 nd =
486
  {
487
    mpname = nd;
488
    mpindex = Some 0;
489
    mpformula =
490
      And [ StateVarPack ResetFlag; Equal (Memory ResetFlag, Val zero) ];
491
  }
492

    
493
let memory_pack_toplevel nd i =
494
  {
495
    mpname = nd;
496
    mpindex = None;
497
    mpformula =
498
      Ternary
499
        (Memory ResetFlag, StateVarPack ResetFlag, mk_memory_pack ~i nd.node_id);
500
  }
501

    
502
let transition_0 nd =
503
  {
504
    tname = nd;
505
    tindex = Some 0;
506
    tvars = nd.node_inputs;
507
    tformula =
508
      (if fst (get_stateless_status_node nd) then True
509
      else StateVarPack ResetFlag);
510
    tmem_footprint = ISet.empty;
511
    tinst_footprint = IMap.empty;
512
  }
513

    
514
let transition_toplevel nd i =
515
  let stateless = fst (get_stateless_status_node nd) in
516
  let tr =
517
    mk_transition
518
      stateless
519
      nd.node_id
520
      ~i
521
      (vdecls_to_vals (nd.node_inputs @ nd.node_outputs))
522
  in
523
  {
524
    tname = nd;
525
    tindex = None;
526
    tvars = nd.node_inputs @ nd.node_outputs;
527
    tformula =
528
      (if fst (get_stateless_status_node nd) then tr
529
      else ExistsMem (nd.node_id, Predicate (ResetCleared nd.node_id), tr));
530
    tmem_footprint = ISet.empty;
531
    tinst_footprint = IMap.empty;
532
  }
533

    
534
let translate_eexpr env e =
535
  try
536
    List.fold_right
537
      (fun (qt, xs) f ->
538
        match qt with
539
        | Lustre_types.Exists ->
540
          Exists (xs, f)
541
        | Lustre_types.Forall ->
542
          Forall (xs, f))
543
      e.eexpr_quantifiers
544
      (Value (translate_expr env e.eexpr_qfexpr))
545
  with NormalizationError ->
546
    Format.eprintf "Normalization error: %a@." Printers.pp_eexpr e;
547
    raise NormalizationError
548

    
549
let translate_contract env c =
550
  {
551
    mc_pre = And (List.map (translate_eexpr env) c.Lustre_types.assume);
552
    mc_post = And (List.map (translate_eexpr env) c.Lustre_types.guarantees);
553
    mc_proof = c.proof;
554
  }
555

    
556
let translate_spec env = function
557
  | Contract c ->
558
    Contract (translate_contract env c)
559
  | NodeSpec s ->
560
    NodeSpec s
561

    
562
let translate_decl nd sch =
563
  let stateless = fst (get_stateless_status_node nd) in
564
  (* Format.eprintf "Translating node %s@." nd.node_id; *)
565
  (* Extracting eqs, variables ..  *)
566
  let eqs, auts = get_node_eqs nd in
567
  assert (auts = []);
568

    
569
  (* Automata should be expanded by now *)
570

    
571
  (* In case of non functional backend (eg. C), additional local variables have
572
     to be declared for each assert *)
573
  let new_locals, assert_instrs, nd_node_asserts = process_asserts nd in
574

    
575
  (* Build the env: variables visible in the current scope *)
576
  let locals = nd.node_locals @ new_locals in
577
  (* let locals = VSet.of_list locals_list in *)
578
  (* let inout_vars = nd.node_inputs @ nd.node_outputs in *)
579
  let env = build_env nd.node_inputs locals nd.node_outputs in
580

    
581
  (* Format.eprintf "Node content is %a@." Printers.pp_node nd; *)
582

    
583
  (* Computing main content *)
584
  (* Format.eprintf "ok1@.@?"; *)
585
  let schedule = sch.Scheduling_type.schedule in
586
  (* Format.eprintf "ok2@.@?"; *)
587
  let sorted_eqs, unused =
588
    Scheduling.sort_equations_from_schedule eqs schedule
589
  in
590

    
591
  (* Format.eprintf "ok3@.locals=%a@.inout:%a@?"
592
   *   VSet.pp locals
593
   *   VSet.pp inout_vars
594
   * ; *)
595
  let equations = assert_instrs @ sorted_eqs in
596
  let mems = get_memories env equations in
597
  (* Removing computed memories from locals. We also removed unused
598
     variables. *)
599
  let locals =
600
    List.filter
601
      (fun v -> (not (VSet.mem v mems)) && not (List.mem v.var_id unused))
602
      locals
603
  in
604
  (* Compute live sets for spec *)
605
  Lustre_live.set_live_of nd.node_id nd.node_outputs locals equations;
606

    
607
  (* Translate equations *)
608
  let ctx, ctx0_s =
609
    translate_core env nd equations nd.node_inputs locals nd.node_outputs
610
  in
611

    
612
  (* Format.eprintf "ok4@.@?"; *)
613

    
614
  (* Build the machine *)
615
  let mmap = IMap.bindings ctx.j in
616
  let mmemory_packs =
617
    let i = try fst (List.hd ctx.mp) with _ -> 0 in
618
    i,
619
    memory_pack_0 nd
620
    :: List.map
621
         (fun (i, f) -> { mpname = nd; mpindex = Some i; mpformula = red f })
622
         (List.rev ctx.mp)
623
    @ [ memory_pack_toplevel nd i ]
624
  in
625
  let mtransitions =
626
    transition_0 nd
627
    :: List.mapi
628
         (fun i (tvars, tmem_footprint, tinst_footprint, f) ->
629
           {
630
             tname = nd;
631
             tindex = Some (i + 1);
632
             tvars;
633
             tformula = red f;
634
             tmem_footprint;
635
             tinst_footprint;
636
           })
637
         (List.rev ctx.t)
638
    @ [ transition_toplevel nd (List.length ctx.t) ]
639
  in
640
  let clear_reset =
641
    mkinstr
642
      ~instr_spec:
643
        ((if fst (get_stateless_status_node nd) then []
644
         else [ mk_memory_pack ~i:0 nd.node_id ])
645
        @ [
646
            mk_transition
647
              ~i:0
648
              stateless
649
              nd.node_id
650
              (vdecls_to_vals nd.node_inputs);
651
          ])
652
      MClearReset
653
  in
654
  let mnode_spec = Utils.option_map (translate_spec env) nd.node_spec in
655
  {
656
    mname = nd;
657
    mmemory = VSet.elements mems;
658
    mcalls = mmap;
659
    minstances =
660
      List.filter (fun (_, (n, _)) -> not (Stateless.check_node n)) mmap;
661
    minit = List.rev ctx.si;
662
    mconst = List.rev ctx0_s;
663
    mstatic = List.filter (fun v -> v.var_dec_const) nd.node_inputs;
664
    mstep =
665
      {
666
        step_inputs = nd.node_inputs;
667
        step_outputs = nd.node_outputs;
668
        step_locals = locals;
669
        step_checks =
670
          List.map
671
            (fun d ->
672
              d.Dimension.dim_loc, translate_expr env (expr_of_dimension d))
673
            nd.node_checks;
674
        step_instrs =
675
          clear_reset
676
          ::
677
          (* special treatment depending on the active backend. For horn
678
             backend, common branches are not merged while they are in C or Java
679
             backends. *)
680
          (if !Backends.join_guards then join_guards_list (List.rev ctx.s)
681
          else List.rev ctx.s);
682
        step_asserts = List.map (translate_expr env) nd_node_asserts;
683
      };
684
    (* Processing spec: there is no processing performed here. Contract have
685
       been processed already. Either one of the other machine is a cocospec
686
       node, or the current one is a cocospec node. Contract do not contain any
687
       statement or import. *)
688
    mspec = { mnode_spec; mtransitions; mmemory_packs };
689
    mannot = nd.node_annot;
690
    msch = Some sch;
691
    mis_contract = nd.node_iscontract;
692
  }
693

    
694
(** takes the global declarations and the scheduling associated to each node *)
695
let translate_prog decls node_schs =
696
  let nodes = get_nodes decls in
697
  let machines =
698
    List.map
699
      (fun decl ->
700
        let node = node_of_top decl in
701
        let sch = IMap.find node.node_id node_schs in
702
        translate_decl node sch)
703
      nodes
704
  in
705
  machines
706

    
707
(* Local Variables: *)
708
(* compile-command:"make -C .." *)
709
(* End: *)
(46-46/99)