From de2a5f14b4e5e1e691e40202adb89e3b66560f78 Mon Sep 17 00:00:00 2001
From: Erwan Jahier <jahier@imag.fr>
Date: Fri, 15 Feb 2008 11:50:57 +0100
Subject: [PATCH] Resolve the inconsistant use of node and oper identifiers in
 the code.

To do that, we :

(1) totally remove  (in the  ocaml code) the  use of "oper",  and use
"node" instead.  Indeed, a node  is a memoryfull operator, as opposed
to function that are memoryless operators.  However, lus2lic does not
really care about memoryless  and memoryfull information. Therefore I
prefer  to use  node everywhere,  and to  flag node_info  to indicate
whether it has memories or not.

(2) change the syntaxTreeCore type to make it more general. Indeed,
    the distinction between functions and nodes was

    - redundant:  extern nodes  and (extern)  functions  were handled
    differently (NodeExtern versus ExtNode (was named FUNC before)).

    - and  incomplete:   it  was  not  possible   to  provide  static
      parameters to function, nor to define functions with body, etc.

Now a  function is  just a memoryless  node. The check  that function
indeed use no memory will be done later.

(3) also,  change  the  parser   so  that  functions  with  body  are
    accepted.

(4) in order  to do it step by  step, I add the  "extern" keyword" so
    that extern nodes and functions are more easy to parse. I will
    remove it later.
---
 src/compile.ml              |   4 +-
 src/compiledData.ml         | 108 +++++++------
 src/expandPack.ml           |   8 +-
 src/lazyCompiler.ml         |  38 +++--
 src/lexer.mll               |   3 +
 src/main.ml                 |   4 +-
 src/parser.mly              | 121 +++++++++++----
 src/symbolTab.ml            |   4 +-
 src/syntaxTab.ml            |  14 +-
 src/syntaxTreeCore.ml       |  30 ++--
 src/syntaxTreeDump.ml       |  39 +++--
 src/test/Makefile           |   3 +
 src/test/func_with_body.lus |  12 ++
 src/test/t0.lus             |   2 +-
 src/test/test.res.exp       | 301 ++++++++++++++++++++----------------
 15 files changed, 419 insertions(+), 272 deletions(-)
 create mode 100644 src/test/func_with_body.lus

diff --git a/src/compile.ml b/src/compile.ml
index 157b1cee..2adae980 100644
--- a/src/compile.ml
+++ b/src/compile.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 11/02/2008 (at 09:36) by Erwan Jahier> *)
+(** Time-stamp: <modified the 15/02/2008 (at 11:37) by Erwan Jahier> *)
 
 
 open Lxm
@@ -31,7 +31,7 @@ let (doit : SyntaxTree.pack_or_model list -> Ident.idref -> unit) =
 	"-- MAIN NODE: \"%s\"\n" (CompiledData.string_of_node_key main_node_key);
 
       (* Pour chaque package, on a un solveur de références
-	 globales, pour les types, const et oper :
+	 globales, pour les types, const et node :
 	 - les références pointées (p::n) sont recherchées
 	 directement dans la syntax_tab puisqu'il n'y a pas 
 	 d'ambiguité
diff --git a/src/compiledData.ml b/src/compiledData.ml
index 16b8899c..a6e79b9a 100644
--- a/src/compiledData.ml
+++ b/src/compiledData.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 14/02/2008 (at 17:43) by Erwan Jahier> *)
+(** Time-stamp: <modified the 15/02/2008 (at 11:45) by Erwan Jahier> *)
 
 (** 
 
@@ -51,7 +51,7 @@
 	- eq_eff :
 	version compilée de eq_info 
 
-	- func_eff :
+	- ext_node_eff :
 	déclaration de fonction chéckée 
 	(info conservée dans la table des symboles pour résoudre les call)
 
@@ -59,15 +59,15 @@
 	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.
+	- node_half_eff : (N.B. utilise dans pack_env)
+	union de ext_node_eff et node_half_eff.
 
-	- oper_eff :
+	- node_eff :
 	dénotation d'opération,
-	peut être fonction, predef ou template,
+	peut être externe, predef ou utilisateur,
 	construit à partir de node_exp.
 
-	- node_eff :
+	- user_node_eff :
 	noeud/template + arguments statiques effectifs,
 
 	- static_arg_eff :
@@ -76,7 +76,7 @@
 	- 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
+	(initialisation) et dans CheckNode pour la partie node/template qui
 	est faite à la demande.
 
 	- local_env :
@@ -93,7 +93,7 @@
 	- 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_node_key : pretty-print d'un node_key
 	_ string_of_slice_eff :
 
 ----------------------------------------------------------------------*)
@@ -224,36 +224,37 @@ and clock_eff =
     BaseClockEff
   | VarClockEff of var_eff
 (*---------------------------------------------------------------------
-Type : oper_half_eff
+Type : node_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
+	(ext_node_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
+and node_half_eff = 
+    ExtNodeRef of ext_node_eff
   | NodeRef of node_half_eff
 (*---------------------------------------------------------------------
-Type : func_eff
+Type : ext_node_eff
 -----------------------------------------------------------------------
-	Construit à partir de func_info
+	Construit à partir de ext_ node_info
 ----------------------------------------------------------------------*)
-and func_eff = {
-  fe_name : Ident.t ;
-  fe_in_types  : type_eff list ;
-  fe_out_types : type_eff list
+and ext_node_eff = {
+  fe_name : Ident.t;
+  fe_in_types  : type_eff list;
+  fe_out_types : type_eff list;
+  fe_has_memory : bool;
 }
 (*---------------------------------------------------------------------
-Type : node_half_eff
+Type : user_node_half_eff
 -----------------------------------------------------------------------
 	correspond à un noeud half-checked : on conserve simplement
 	la node_info (on pourra sophistiquer plus tard)
 ----------------------------------------------------------------------*)
-and node_half_eff = SyntaxTreeCore.user_node_info srcflagged
+and user_node_half_eff = SyntaxTreeCore.user_node_info srcflagged
 (*---------------------------------------------------------------------
-Type : node_eff
+Type : user_node_eff
 -----------------------------------------------------------------------
 	correspond à une instance de template (ou, cas limite,
 	de noeud sans param statique). La clé est un couple ident/liste
@@ -264,7 +265,7 @@ Type : node_eff
 	(et pas du clock-checking)
 
 ----------------------------------------------------------------------*)
-and node_eff = {
+and user_node_eff = {
   nf_key : node_key ;
   nf_in_types  : type_eff list ;
   nf_out_types : type_eff list ;
@@ -272,6 +273,7 @@ and node_eff = {
   nf_out_formal_clocks : int option list ;
   nf_asserts : val_eff list;
   nf_eqs : eq_eff list;
+  nf_has_memory : bool;
 }
 (*---------------------------------------------------------------------
 Type : XXX_key
@@ -293,29 +295,29 @@ Type : static_arg_eff
 and static_arg_eff =
   | ConstStaticArgEff of (Ident.t * const_eff)
   | TypeStaticArgEff  of (Ident.t * type_eff)
-  | OperStaticArgEff  of (Ident.t * oper_eff)
+  | NodeStaticArgEff  of (Ident.t * node_eff)
 (*---------------------------------------------------------------------
-Type : oper_eff
+Type : node_eff
 -----------------------------------------------------------------------
 	Version chéckée des node_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
+	Union entre opérateur prédéfini, user_ext_node_eff et user_node_eff
 ----------------------------------------------------------------------*)
-and oper_eff =
-    PredefOper of predef_node 
-  | FuncOper of func_eff
-  | NodeOper of node_eff
+and node_eff =
+  | PredefEff of predef_node 
+  | ExtNodeEff of ext_node_eff
+  | UserNodeEff of user_node_eff
 (*---------------------------------------------------------------------
-Type : oper_alias
+Type : node_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é
+	parfaitement défini (node_eff), ou sur un noeud half_checké
 ----------------------------------------------------------------------*)
-and oper_alias =
-    CheckedOper of oper_eff
+and node_alias =
+    CheckedNode of node_eff
   | HalfCheckedNode of node_half_eff
 
 
@@ -334,8 +336,9 @@ type 'a check_flag =
   | Checked of 'a
   | Incorrect
 
-type
-world_env = {
+
+
+type world_env = {
   wenv_src : SyntaxTree.pack_or_model list;
   wenv_mod_srcs : (Ident.t, SyntaxTree.model_info srcflagged) Hashtbl.t ;
   wenv_pack_srcs :  (Ident.t, SyntaxTree.pack_info srcflagged) Hashtbl.t ;
@@ -350,7 +353,7 @@ and pack_env = {
   (* penv_src : SyntaxTree.package ; *)
   penv_type_table  : (Ident.t, type_eff check_flag)   Hashtbl.t ;
   penv_const_table : (Ident.t, const_eff check_flag)  Hashtbl.t ;
-  penv_oper_table  : (Ident.t, oper_half_eff) Hashtbl.t ;
+  penv_oper_table  : (Ident.t, node_half_eff) Hashtbl.t ;
   penv_node_table : (node_key, node_eff check_flag) Hashtbl.t
 }
 (*---------------------------------------------------------------------
@@ -362,7 +365,7 @@ and local_env = {
   lenv_globals : pack_env ;
   lenv_types : (Ident.t, type_eff) Hashtbl.t ;
   lenv_vals : (Ident.t, val_eff) Hashtbl.t ; 
-  lenv_opers : (Ident.t, oper_eff) Hashtbl.t ; 
+  lenv_nodes : (Ident.t, node_eff) Hashtbl.t ; 
 }
 
 (* Utilitaires liés aux node_key *)
@@ -501,11 +504,14 @@ let rec string_of_node_key (nkey: node_key) = (
     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) -> (
+      | NodeStaticArgEff  (id, opeff) -> (
 	  match opeff with
-	    | PredefOper posop -> sprintf "operator %s" (SyntaxTreeDump.op2string posop)
-	    | FuncOper feff -> sprintf "func %s" (Ident.to_string feff.fe_name)
-	    | NodeOper neff -> sprintf "node %s" (string_of_node_key neff.nf_key)
+	    | PredefEff posop -> 
+		sprintf "operator %s" (SyntaxTreeDump.op2string posop)
+	    | ExtNodeEff feff -> 
+		sprintf "extern node %s" (Ident.to_string feff.fe_name)
+	    | UserNodeEff neff -> 
+		sprintf "node %s" (string_of_node_key neff.nf_key)
 	) 
   in
     match nkey with
@@ -515,7 +521,7 @@ let rec string_of_node_key (nkey: node_key) = (
 	    sprintf "%s<<%s>>" (Ident.string_of_long ik) (String.concat ", " astrings)
 )
 
-let (string_of_node_eff: node_eff -> string) =
+let (string_of_user_node_eff: user_node_eff -> string) =
   fun neff -> 
     (string_of_node_key neff.nf_key) ^ 
       "(" ^
@@ -524,6 +530,22 @@ let (string_of_node_eff: node_eff -> string) =
       (String.concat ", " (List.map string_of_type_eff neff.nf_out_types)) ^
       ") on clock XXX\n"
 
+let (string_of_ext_node_eff: ext_node_eff -> string) =
+  fun neff -> 
+    "extern " ^ (Ident.to_string neff.fe_name) ^ 
+      "(" ^
+      (String.concat ", " (List.map string_of_type_eff neff.fe_in_types)) ^
+      ") returns (" ^
+      (String.concat ", " (List.map string_of_type_eff neff.fe_out_types)) ^
+      ")\n"
+
+let (string_of_node_eff: node_eff -> string) =
+  fun neff -> 
+    match neff with
+      | PredefEff pn -> SyntaxTreeDump.op2string  pn
+      | ExtNodeEff eneff -> string_of_ext_node_eff eneff 
+      | UserNodeEff uneff -> string_of_user_node_eff uneff
+
 let string_of_clock (ck : clock_eff) = (
   match ck with
       BaseClockEff -> "<base>"
diff --git a/src/expandPack.ml b/src/expandPack.ml
index d5be0b92..00f12c54 100644
--- a/src/expandPack.ml
+++ b/src/expandPack.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 11/02/2008 (at 09:37) by Erwan Jahier> *)
+(** Time-stamp: <modified the 15/02/2008 (at 10:36) by Erwan Jahier> *)
 
 open Lxm
 open SyntaxTree
@@ -81,7 +81,7 @@ let (doit:
 			put_in_tab "const" ctab s y ;
 			newdefs := (ConstItem s)::!newdefs
 		  ) 
-		| StaticParamNode (s,inl,outl) -> (
+		| StaticParamNode (s,inl,outl,has_memory) -> (
 		    let ne = match (a.it) with
 			StaticArgIdent idr -> (
 			  Lxm.flagit (CallUsrDef (idr,[])) a.src
@@ -94,12 +94,14 @@ let (doit:
 		      uni_name = s;
 		      uni_static_params = [] ;
 		      uni_def = NodeAlias (Some(inl,outl), ne) ;
+		      uni_has_mem = has_memory;
+		      uni_is_safe = true;
 		    } in
 		    let x = Lxm.flagit (NodeInfo ni) p.src in
 		      newprov := x::!newprov ;
 		      let y = Lxm.flagit ni p.src in
 			put_in_tab "node" otab s y ;
-			newdefs := (OperItem s)::!newdefs
+			newdefs := (NodeItem s)::!newdefs
 		  ) 
 	  ) in
 	    try (
diff --git a/src/lazyCompiler.ml b/src/lazyCompiler.ml
index b9b84831..39efb721 100644
--- a/src/lazyCompiler.ml
+++ b/src/lazyCompiler.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 14/02/2008 (at 17:49) by Erwan Jahier> *)
+(** Time-stamp: <modified the 15/02/2008 (at 11:37) by Erwan Jahier> *)
 
 
 open Lxm
@@ -89,7 +89,7 @@ fun tbl ->
    (10) [solve_const_idref] solves constant reference (w.r.t. short/long ident)
 
 
-    nb: for x in {type, const, oper}, there are several functions that returns [x_eff]:
+    nb: for x in {type, const, node}, there are several functions that returns [x_eff]:
     - [x_check]
         o takes an x_key
         o lookups its (syntaxic) definition (x_info) via the symbolTab.t
@@ -469,6 +469,8 @@ and (node_check_do: t -> CompiledData.node_key -> Lxm.t -> SymbolTab.t ->
       - creer une sorte d'environnement local de compilation, qui
       permette de gerer les espaces de noms propres aux noeuds
       (variables, constantes, flots, types) 
+      cf CompiledData.local_env pack_env, et world_env
+      
     *)
     let id_solver = {
       id2const = solve_const_idref this symbols pack_name;
@@ -476,8 +478,8 @@ and (node_check_do: t -> CompiledData.node_key -> Lxm.t -> SymbolTab.t ->
       id2node  = solve_node_idref  this symbols pack_name;
     } 
     in
-    let make_node_eff itl otl =
-      {
+    let make_user_node_eff itl otl hm =
+      UserNodeEff {
 	nf_key = nk;
 	nf_in_types = itl;
 	nf_out_types = otl;
@@ -485,6 +487,7 @@ and (node_check_do: t -> CompiledData.node_key -> Lxm.t -> SymbolTab.t ->
 	nf_out_formal_clocks = []; (* XXX finish me! *)
 	nf_asserts = []; (* XXX finish me! *)
 	nf_eqs = []; (* XXX finish me! *)
+	nf_has_memory = hm;
       }
     in
       match node_def.it with
@@ -498,24 +501,33 @@ and (node_check_do: t -> CompiledData.node_key -> Lxm.t -> SymbolTab.t ->
 (* 		   id_solver.id2node idref (check_static_arg static_args) lxm *)
 
 	       | NodeAlias (Some (vi_il, vi_ol), _) 
-	       | NodeExtern(vi_il, vi_ol) -> 
+	       | NodeAbstract(vi_il, vi_ol) -> 
 		   let aux vi = EvalType.f id_solver vi.it.va_type in
-		     make_node_eff (List.map aux vi_il) (List.map aux vi_ol)
+		     make_user_node_eff 
+		       (List.map aux vi_il) (List.map aux vi_ol) n.uni_has_mem
 
 	       | NodeBody nb ->
 		   let aux id =
 		     let vi = Hashtbl.find nb.nbdy_vartable id in
 		       EvalType.f id_solver vi.it.va_type
 		   in
-		     make_node_eff
+		     (* ??? c'est vraiment ca qu'il faut faire ??? *)
+		     make_user_node_eff
 		       (List.map aux nb.nbdy_inlist)
 		       (List.map aux nb.nbdy_outlist)
+		       n.uni_has_mem
 	    )
 	| ExtNode en ->
 	    let aux (_,texp) = EvalType.f id_solver texp in
-	      make_node_eff
-		(List.map aux en.eni_inputs)
-		(List.map aux en.eni_outputs)
+	      ExtNodeEff {
+		fe_name = en.eni_name;
+		fe_in_types =(List.map aux en.eni_inputs);
+		fe_out_types = (List.map aux en.eni_outputs);
+		fe_has_memory = en.eni_has_mem;
+	      }
+		
+		
+		
 		
 		
 (** builds and node_key and calls [node_check] *)
@@ -570,7 +582,7 @@ and (node_check_interface:
 (* 	    try *)
 (* 	      let sargs = [] in (* ok? *) *)
 (* 	      let neff = id_solver.id2node idref id_solver sargs sa.src in *)
-(* 		OperStaticArgEff (id, NodeOper neff) *)
+(* 		NodeStaticArgEff (id, NodeEff neff) *)
 (* 	    with Compile_error _ -> *)
 (* 	    try *)
 (* 	      let teff = id_solver.id2type idref sa.src in *)
@@ -599,7 +611,7 @@ and (node_check_interface:
 (*  *)
 (* 	| StaticArgNode (CallUsrDef (idref, s_args)) ->  *)
 (* 	    let neff = id_solver.id2node idref id_solver s_args sa.src in *)
-(* 	      OperStaticArgEff (id, NodeOper neff) *)
+(* 	      NodeStaticArgEff (id, NodeEff neff) *)
 (*     in *)
 (*  *)
 (*       SymbolTab.add_ *)
@@ -656,7 +668,7 @@ let test_nodes pack_name this id ni_f =
 	flush stdout
     (* too difficult to test such node easily, so we skip it *)
     | None ->
-	test_item this "oper" node_check_interface CompiledData.string_of_node_key
+	test_item this "node" node_check_interface CompiledData.string_of_node_key
 	  string_of_node_eff (fun id -> (Ident.make_long pack_name id, [])) id ni_f
 
 
diff --git a/src/lexer.mll b/src/lexer.mll
index c6a846b9..6c22d68b 100644
--- a/src/lexer.mll
+++ b/src/lexer.mll
@@ -20,6 +20,8 @@ let handle_lexical_error fn lexbuf = (
 
 (* table des mots-clé *)
 let keywords = Hashtbl.create 50 ;;
+Hashtbl.add keywords "extern"     (function x -> TK_EXTERN x) ;;
+
 Hashtbl.add keywords "and"        (function x -> TK_AND x) ;;
 Hashtbl.add keywords "assert"     (function x -> TK_ASSERT x) ;;
 Hashtbl.add keywords "bool"       (function x -> TK_BOOL x) ;;
@@ -72,6 +74,7 @@ let token_code tk = (
 	match tk with
 		  TK_EOF           -> ("TK_EOF" , Lxm.dummy )
 		| TK_ERROR     lxm -> ("TK_ERROR" , lxm)
+		| TK_EXTERN    lxm -> ("TK_EXTERN" , lxm)
 		| TK_AND       lxm -> ("TK_AND" , lxm)
 		| TK_ARROW     lxm -> ("TK_ARROW" , lxm)
 		| TK_ASSERT    lxm -> ("TK_ASSERT" , lxm)
diff --git a/src/main.ml b/src/main.ml
index 2c90a6ed..ef655029 100644
--- a/src/main.ml
+++ b/src/main.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 11/02/2008 (at 09:57) by Erwan Jahier> *)
+(** Time-stamp: <modified the 15/02/2008 (at 11:39) by Erwan Jahier> *)
 
 (** Here follows a description of the different modules used by this lus2lic compiler.
 
@@ -19,7 +19,7 @@ which results into a parse tree containing raw source expressions.
    syntaxTab.mli/ml
       syntaxTabUtil.ml/mli
       expandPack.mli/ml
-      symbolTab.mli/ml (type/const/oper)
+      symbolTab.mli/ml (type/const/node)
 
 syntaxTab is a kind of layer above syntaxTree to make things easier afterwards.
 
diff --git a/src/parser.mly b/src/parser.mly
index a1d633aa..00ba220d 100644
--- a/src/parser.mly
+++ b/src/parser.mly
@@ -6,7 +6,7 @@ open SyntaxTreeCore
 (* les var locales pour ranger les resultat intermédaire *)
 let const_table = Hashtbl.create 50 
 let type_table  = Hashtbl.create 50
-let oper_table  = Hashtbl.create 50
+let node_table  = Hashtbl.create 50
 let def_list    = ref []
 
 (* Interface avec SyntaxTree *)
@@ -138,6 +138,7 @@ let treat_struct_type
 (* Traitement d'un noeud externe *)
 (*********************************)
 let treat_external_node
+    (has_memory : bool)
     (ext_nodelxm : Lxm.t)
     (inpars   : ((Lxm.t list) * type_exp) list) (* liste des ins *)
     (outpars  : ((Lxm.t list) * type_exp) list) (* liste des outs *)
@@ -155,18 +156,21 @@ let treat_external_node
     let flat_ins = ParserUtils.flat_flagged_list inpars make_a_param in
       (* fabrique la liste à plat des outputs *)
     let flat_outs = ParserUtils.flat_flagged_list outpars make_a_param in
-      (* fabrique le extern_node_info *)
+      (* fabrique le ext_node_info *)
     let ext_nodestr = Lxm.id ext_nodelxm in
     let en_info = {
       eni_name = ext_nodestr;
       eni_inputs = flat_ins;
-      eni_outputs = flat_outs
+      eni_outputs = flat_outs;
+      eni_has_mem = has_memory;
+      eni_is_safe = true;
     } in
       (* range l'info correspondante dans la table des oper *)
-      SyntaxTree.add_info oper_table "(extern) node" ext_nodelxm (ExtNode en_info) ;
-      def_list := (OperItem ext_nodestr) :: !def_list
+      SyntaxTree.add_info node_table "(extern) node" ext_nodelxm (ExtNode en_info) ;
+      def_list := (NodeItem ext_nodestr) :: !def_list
   )
 
+      
 (********************************************)
 (* Déclarations de vars et params de noeuds *)
 (********************************************)
@@ -196,6 +200,7 @@ let rec clocked_ids_to_var_infos vnat vdefs = (
 )
 
 let treat_node_decl
+    (has_memory : bool)
     (nlxm:   Lxm.t)          (* le lexeme du nom du noeud *)
     (statics: static_param srcflagged list) 
     (indefs:  clocked_ids list) (* descripteur des entrées *)
@@ -258,29 +263,57 @@ let treat_node_decl
     let ninfo = {
       uni_name = nstr;
       uni_static_params = statics;
-      uni_def = nval
+      uni_def = nval;
+      uni_has_mem = has_memory;
+      uni_is_safe = true;
     } in
       (* On met le tout dans la table des oper *)
-      SyntaxTree.add_info oper_table "(extern) node" nlxm (Node (ninfo)) ;
-      def_list := (OperItem nstr) :: !def_list
+      SyntaxTree.add_info node_table "(extern) node" nlxm (Node (ninfo)) ;
+      def_list := (NodeItem nstr) :: !def_list
   )
 let treat_node_alias
-	(nlxm:   Lxm.t)          (* le lexeme du nom du noeud *)
-	(statics: static_param srcflagged list) (* les params statiques formel *)
-	(dyn: node_profile option) (* l'eventuel profil dyn *)
-	(value: node_exp srcflagged)   (* la valeur *)
+    (has_memory : bool)
+    (nlxm:   Lxm.t)          (* le lexeme du nom du noeud *)
+    (statics: static_param srcflagged list) (* les params statiques formel *)
+    (dyn: node_profile option) (* l'eventuel profil dyn *)
+    (value: node_exp srcflagged)   (* la valeur *)
 =
 (
 	let nstr = Lxm.id nlxm in
 	let ninfo = {
 		uni_name = nstr;
 		uni_static_params = statics;
-		uni_def = NodeAlias (dyn, value)
+		uni_def = NodeAlias (dyn, value);
+		uni_has_mem = has_memory;
+		uni_is_safe = true;
 	} in
-	SyntaxTree.add_info oper_table "(extern) node" nlxm (Node (ninfo)) ;
-	def_list := (OperItem nstr) :: !def_list
+	SyntaxTree.add_info node_table "(extern) node" nlxm (Node (ninfo)) ;
+	def_list := (NodeItem nstr) :: !def_list
 )
 
+(**********************************)
+(* Traitement d'un noeud abstrait *)
+(**********************************)
+let treat_abstract_node
+    (has_memory : bool)
+    (lxm : Lxm.t)
+    (inpars   : (((Lxm.t list) * type_exp) list * SyntaxTreeCore.clock_exp) list)
+    (outpars  : (((Lxm.t list) * type_exp) list * SyntaxTreeCore.clock_exp) list)
+    = (* sortie: unit *)
+
+  let invars = clocked_ids_to_var_infos VarInput inpars in
+  let outvars = clocked_ids_to_var_infos VarOutput outpars in
+  let xn = Node {
+    uni_name = Lxm.id lxm;
+    uni_static_params = [];
+    uni_def = NodeAbstract (invars, outvars);
+    uni_has_mem = has_memory;
+    uni_is_safe = true;
+  } in
+    Lxm.flagit
+      (NodeInfo xn)
+      lxm
+
 (* Pour les node proto, c'est un peu plus simple
 car on ne tabule pas les variables : on garde des listes.
 on les met juste "a plat"
@@ -313,6 +346,8 @@ let flat_output_ids (vdefs: clocked_ids list) = (
 
 %token <Lxm.t> TK_ERROR
 
+%token <Lxm.t> TK_EXTERN
+
 %token <Lxm.t> TK_AND
 %token <Lxm.t> TK_ARROW
 %token <Lxm.t> TK_ASSERT
@@ -498,16 +533,12 @@ sxOneProvide:
 	/* noeud abstrait */
 |	TK_NODE sxIdent sxParams TK_RETURNS sxParams 
 	{
-		let invars = clocked_ids_to_var_infos VarInput $3 in
-		let outvars = clocked_ids_to_var_infos VarOutput $5 in
-		let xn = Node {
-			uni_name = Lxm.id $2 ;
-			uni_static_params = [];
-			uni_def = NodeExtern (invars, outvars);
-		} in
-		Lxm.flagit
-		(NodeInfo xn)
-		$2
+		treat_abstract_node true $2 $3 $5
+	}
+	/* fonction abstraite */
+|	TK_FUNCTION sxIdent sxParams TK_RETURNS sxParams 
+	{
+		treat_abstract_node false $2 $3 $5
 	}
 	/* type abstrait ... */
 |	TK_TYPE	sxIdent
@@ -635,11 +666,11 @@ sxPackBody:
 	sxDeclList
 	{
 		let res = SyntaxTree.make_packbody
-			const_table type_table oper_table (List.rev !def_list) in
+			const_table type_table node_table (List.rev !def_list) in
 		(* clean all ... *)
 		Hashtbl.clear const_table ;
 		Hashtbl.clear type_table ;
-		Hashtbl.clear oper_table ;
+		Hashtbl.clear node_table ;
 		def_list := [] ;
 		res
 	}
@@ -796,12 +827,14 @@ sxType:
 	;
 
 
-/* fonctions */
+/* extern nodes */
 
 sxExtNodeDecl:
-	TK_FUNCTION sxIdent sxExtNodeParam TK_RETURNS sxExtNodeParam sxOptSemicol
+  TK_EXTERN TK_FUNCTION sxIdent sxExtNodeParam TK_RETURNS sxExtNodeParam sxOptSemicol
+          { treat_external_node false $3 (List.rev $4) (List.rev $6) }
+| TK_EXTERN TK_NODE     sxIdent sxExtNodeParam TK_RETURNS sxExtNodeParam sxOptSemicol
 	/* WARNING ! il faut remettre les listes à l'endroit */
-			{ treat_external_node $2 (List.rev $3) (List.rev $5) }
+	  { treat_external_node true $3 (List.rev $4) (List.rev $6) }
 	;
 
 
@@ -824,10 +857,17 @@ sxNodeDecl:
 sxLocalNode:
 	TK_NODE sxIdent sxStaticParams sxParams TK_RETURNS sxParams sxOptSemicol
 		sxLocals sxBody sxOptEndNode
-	{ treat_node_decl $2 $3 $4 $6 $8 (fst $9) (snd $9) }
+	{ treat_node_decl true $2 $3 $4 $6 $8 (fst $9) (snd $9) }
+   |	TK_FUNCTION sxIdent sxStaticParams sxParams TK_RETURNS sxParams sxOptSemicol
+		sxLocals sxBody sxOptEndNode
+	{ treat_node_decl false $2 $3 $4 $6 $8 (fst $9) (snd $9) }
 |	TK_NODE sxIdent sxStaticParams sxNodeProfileOpt TK_EQ sxEffectiveNode 
 	    sxOptSemicol 
-	{ treat_node_alias $2 $3 $4 $6 }
+	{ treat_node_alias true $2 $3 $4 $6 }
+;
+|	TK_FUNCTION sxIdent sxStaticParams sxNodeProfileOpt TK_EQ sxEffectiveNode 
+	    sxOptSemicol 
+	{ treat_node_alias false $2 $3 $4 $6 }
 ;
 
 sxNodeProfileOpt :
@@ -864,7 +904,20 @@ sxStaticParam:
 		let xn = StaticParamNode (
 			Lxm.id $2,
 			invars,
-			outvars	
+			outvars,
+		        true
+		) in
+		Lxm.flagit xn $2
+	}
+	|	TK_FUNCTION sxIdent sxParams TK_RETURNS sxParams 
+	{
+		let invars = clocked_ids_to_var_infos VarInput $3 in
+		let outvars = clocked_ids_to_var_infos VarOutput $5 in
+		let xn = StaticParamNode (
+			Lxm.id $2,
+			invars,
+			outvars,
+		        false
 		) in
 		Lxm.flagit xn $2
 	}
@@ -1159,6 +1212,8 @@ sxStaticArgList:
 	    { {src=$1 ; it=StaticArgNode $2.it } }
 	  /* un ident OU une expression simple (à résoudre) */
 	  /* c'est au retour qu'on choisit */
+	| TK_FUNCTION sxEffectiveNode
+	    { {src=$1 ; it=StaticArgFunc $2.it } }
 	| sxSimpleExp
 	    {
 	      match $1 with 
diff --git a/src/symbolTab.ml b/src/symbolTab.ml
index b1a9e1f5..37951f44 100644
--- a/src/symbolTab.ml
+++ b/src/symbolTab.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 11/02/2008 (at 17:44) by Erwan Jahier> *)
+(** Time-stamp: <modified the 15/02/2008 (at 11:40) by Erwan Jahier> *)
 
 (*
 Sous-module pour SyntaxTab 
@@ -37,7 +37,7 @@ let find_const (this: t) (id: Ident.t) lxm =
 
 let find_node (this: t) (id: Ident.t) lxm =
   try Hashtbl.find (this.st_nodes) id
-  with Not_found -> raise (Compile_error(lxm, "unknown operator"))
+  with Not_found -> raise (Compile_error(lxm, "unknown node"))
 
 
 (* Manip de SymbolTab.t *)
diff --git a/src/syntaxTab.ml b/src/syntaxTab.ml
index 1cd4b640..54791cda 100644
--- a/src/syntaxTab.ml
+++ b/src/syntaxTab.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 14/02/2008 (at 17:15) by Erwan Jahier> *)
+(** Time-stamp: <modified the 15/02/2008 (at 11:40) by Erwan Jahier> *)
 
 (** 
     Table des infos sources : une couche au dessus de SyntaxTree pour mieux
@@ -11,7 +11,7 @@
 
     - 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/oper)
+    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 :
@@ -152,14 +152,14 @@ let init_user_items (this: pack_mng) = (
       (TypeItem s)
       (Lxm.flagit (Ident.make_long pname  s) xti.src)
   in
-    (* EXPORTATION D'UN oper_info *)
+    (* EXPORTATION D'UN node_info *)
   let export_node
       (s: Ident.t)
       (xoi: SyntaxTreeCore.node_info srcflagged)
       = (
-	Verbose.printf "       export oper %s\n" (Ident.to_string s);
-	put_in_tab "oper" this.pm_user_items
-	  (OperItem s)
+	Verbose.printf "       export node %s\n" (Ident.to_string s);
+	put_in_tab "node" this.pm_user_items
+	  (NodeItem s)
 	  (Lxm.flagit (Ident.make_long pname  s) xoi.src)
       ) 
   in
@@ -327,7 +327,7 @@ init_pack_mng_stabs (this: t) (pname: Ident.pack_name) (pm: pack_mng) = (
 		    Some pt -> SymbolTab.add_import_type pt n iks.it
 		  | None -> ()
 	      )
-	    | OperItem n -> (
+	    | NodeItem n -> (
 		SymbolTab.add_import_node pm.pm_body_stab n iks.it;
 		match pm.pm_provide_stab with
 		    Some pt -> SymbolTab.add_import_node pt n iks.it
diff --git a/src/syntaxTreeCore.ml b/src/syntaxTreeCore.ml
index 2ee8c0f5..b50a476e 100644
--- a/src/syntaxTreeCore.ml
+++ b/src/syntaxTreeCore.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 14/02/2008 (at 17:11) by Erwan Jahier> *)
+(** Time-stamp: <modified the 15/02/2008 (at 11:45) by Erwan Jahier> *)
 
 
 (** (Raw) Abstract syntax tree of source programs. *)
@@ -24,27 +24,34 @@ and
 and
   node_info =
   | Node    of user_node_info
-  | ExtNode of extern_node_info
+  | ExtNode of ext_node_info
 and
-  extern_node_info = {
+  ext_node_info = {
     eni_name    : Ident.t;
     eni_inputs  : (Ident.t option * type_exp) list;
-    eni_outputs : (Ident.t option * type_exp) list
+    eni_outputs : (Ident.t option * type_exp) list;
+    eni_has_mem : bool;
+    eni_is_safe : bool;
   }
 and
   user_node_info = {
-    uni_name        : Ident.t ;
+    uni_name    : Ident.t ;
     uni_static_params : static_param srcflagged list;
-    uni_def         : node_def
+    uni_def     : node_def;
+    uni_has_mem : bool;
+    uni_is_safe : bool;
   }
 and static_param =
   | StaticParamType  of Ident.t
   | StaticParamConst of (Ident.t * type_exp)
-  | StaticParamNode  of (Ident.t * var_info srcflagged list * var_info srcflagged list)
+  | StaticParamNode  of 
+      (Ident.t * var_info srcflagged list * var_info srcflagged list * has_mem_flag)
+
+and has_mem_flag = bool
 
 and node_profile = (var_info srcflagged list * var_info srcflagged list)
 and node_def =
-  | NodeExtern of node_profile (* XXX rm *)
+  | NodeAbstract of node_profile
   | NodeBody   of node_body
   | NodeAlias  of node_profile option * node_exp srcflagged
 
@@ -188,6 +195,7 @@ and static_arg =
   | StaticArgConst of val_exp
   | StaticArgType  of type_exp
   | StaticArgNode  of node_exp
+  | StaticArgFunc  of node_exp
 
 
 (**********************************************************************************)
@@ -223,7 +231,7 @@ type type_info =
 type item_ident =
   | ConstItem of Ident.t
   | TypeItem  of Ident.t
-  | OperItem  of Ident.t
+  | NodeItem  of Ident.t
       
 type item_info =
     ConstInfo of const_info
@@ -246,3 +254,7 @@ let naryexp lxm op elst = CallByPos( {src = lxm ; it = op }, Oper elst )
 
 
 let bynameexp lxm op nelst = CallByName( {src = lxm ; it = op } , nelst )
+
+let node_info_has_memory = function
+  | Node uni -> uni.uni_has_mem
+  | ExtNode eni -> eni.eni_has_mem
diff --git a/src/syntaxTreeDump.ml b/src/syntaxTreeDump.ml
index 5901d9a5..845434e6 100644
--- a/src/syntaxTreeDump.ml
+++ b/src/syntaxTreeDump.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 11/02/2008 (at 09:37) by Erwan Jahier> *)
+(** Time-stamp: <modified the 15/02/2008 (at 11:45) by Erwan Jahier> *)
 
 
 open Lxm
@@ -78,7 +78,7 @@ let rec packbody (os: Format.formatter) (pkg: SyntaxTree.packbody) =
 	match d with
 	    ConstItem id -> dump_const os (Hashtbl.find pkg.pk_const_table id)
 	  | TypeItem  id -> dump_type os (Hashtbl.find pkg.pk_type_table id)
-	  | OperItem  id -> (
+	  | NodeItem  id -> (
 	      match (Hashtbl.find pkg.pk_node_table id) with
 		| {src = lxm ; it = Node (ninfo) } -> 
 		    dump_node os {src = lxm; it = ninfo}
@@ -91,7 +91,7 @@ let rec packbody (os: Format.formatter) (pkg: SyntaxTree.packbody) =
 			(match d with 
 			     ConstItem id 
 			   | TypeItem  id 
-			   | OperItem  id -> Ident.to_string id
+			   | NodeItem  id -> Ident.to_string id
 			));
 	assert false
     ) ;
@@ -180,7 +180,7 @@ and dump_field (os: Format.formatter) (finfo: field_info) = (
   (**************************)
   (* dump d'une def de func *)
   (**************************)
-and dump_ext_node (os: Format.formatter) (x: extern_node_info srcflagged) = (
+and dump_ext_node (os: Format.formatter) (x: ext_node_info srcflagged) = (
   let lxm = x.src and info = x.it in
     fprintf os "-- %s" (Lxm.details lxm) ;
     fprintf os " (external function)@\n" ;
@@ -246,8 +246,10 @@ and dump_static_param
       | StaticParamType id ->  fprintf os "type %s" (Ident.to_string id)
       | StaticParamConst (id, exp) -> fprintf os "const %s : %a" 
 	  (Ident.to_string id) dump_type_exp exp
-      | StaticParamNode (id, ins, outs) -> (
-	  fprintf os "node %s(@,%a@,)returns(@,%a@,)" (Ident.to_string id)
+      | StaticParamNode (id, ins, outs, has_mem) -> (
+	  fprintf os "%s %s(@,%a@,)returns(@,%a@,)" 
+	    (if has_mem then "node" else "function")
+	    (Ident.to_string id)
 	    dump_line_var_decl_list ins dump_line_var_decl_list outs
 	)
   )
@@ -268,7 +270,9 @@ and dump_node (os: Format.formatter) (x: user_node_info srcflagged) = (
 	NodeBody nbody -> dump_node_body os nbody
       | NodeAlias (_,{it = nexp; src = lxm}) -> 
 	  fprintf os " = @,%a;@\n" dump_node_exp nexp
-      | NodeExtern _ -> assert false
+      | NodeAbstract _ ->
+	  fprintf os " finish me (dump_node: print abstract node)";
+	  assert false
 )
 
 and dump_node_body (os: Format.formatter) (nbody: node_body) = (
@@ -568,21 +572,14 @@ and dump_static_arg_list
 and dump_static_arg
     (os : Format.formatter)
     (sa: static_arg)
-    = (
+    =
       match sa with
-	  StaticArgIdent id -> (
-	    fprintf os "%s" (Ident.string_of_idref id) 
-	  ) |
-	      StaticArgConst ve -> (
-		fprintf os "const %a" dump_val_exp ve
-	      ) |
-		  StaticArgType  te -> (
-		    fprintf os "type %a" dump_type_exp te 
-		  ) |
-		      StaticArgNode  ne -> (
-			fprintf os "node %a" dump_node_exp ne
-		      ) 
-    )
+	| StaticArgIdent id -> fprintf os "%s" (Ident.string_of_idref id) 
+	| StaticArgConst ve -> fprintf os "const %a"    dump_val_exp ve
+	| StaticArgType  te -> fprintf os "type %a"     dump_type_exp te 
+	| StaticArgNode  ne -> fprintf os "node %a"     dump_node_exp ne
+	| StaticArgFunc  ne -> fprintf os "function %a" dump_node_exp ne
+		      
 and dump_slice_info 
     (os : Format.formatter)
     (sl: slice_info)
diff --git a/src/test/Makefile b/src/test/Makefile
index 79ed53dc..ae6d6b21 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -53,6 +53,9 @@ test:
 	echo " " >> test.res; echo -e "$(NL)====> $(LC) heater_control.lus" >> test.res
 	$(LC) heater_control.lus >> test.res 2>&1
 	\
+	echo " " >> test.res; echo -e "$(NL)====> $(LC) func_with_body.lus" >> test.res
+	$(LC) func_with_body.lus >> test.res 2>&1 || true
+	\
 	echo " " >> test.res; echo -e "$(NL)====> $(LC) pfs.lus" >> test.res
 	$(LC) pfs.lus >> test.res 2>&1 || true
 	\
diff --git a/src/test/func_with_body.lus b/src/test/func_with_body.lus
new file mode 100644
index 00000000..074d0a08
--- /dev/null
+++ b/src/test/func_with_body.lus
@@ -0,0 +1,12 @@
+-- an intern function
+function trivial(x : int) returns (y : int);
+let
+	y = 1;
+tel
+
+
+-- and an extern node
+extern node ext(x : int) returns (y : int);
+
+
+
diff --git a/src/test/t0.lus b/src/test/t0.lus
index d0b40e09..82250da4 100644
--- a/src/test/t0.lus
+++ b/src/test/t0.lus
@@ -1,6 +1,6 @@
 -- Test main node load
 
-function max(x : int; y : int) returns (mx: int);
+extern function max(x : int; y : int) returns (mx: int);
 
 node min(x : int; y : int) returns (mn : int);
 let
diff --git a/src/test/test.res.exp b/src/test/test.res.exp
index 2f520306..2a61ba51 100644
--- a/src/test/test.res.exp
+++ b/src/test/test.res.exp
@@ -5,19 +5,19 @@ Non-regression tests
 *** SyntaxTab.create pass 1
 *** SyntaxTab.create pass 2
     init pack inter
-       export oper preced
+       export node preced
        export const n
        export type selType
     init pack mainPack
-       export oper preced
+       export node preced
     init pack pint
-       export oper fby1
+       export node fby1
        export type t
     init pack pbool
-       export oper fby1
+       export node fby1
        export type t
     init pack preal
-       export oper fby1
+       export node fby1
        export type t
 *** SyntaxTab.create pass 3
    init symbol tables for pack inter
@@ -46,21 +46,21 @@ End of Syntax table dump. 
 		type preal::t = real
 	Exported constants:
 	Exported nodes:
-		oper preal::fby1 = preal::fby1(real, real) returns (real) on clock XXX
+		node preal::fby1 = preal::fby1(real, real) returns (real) on clock XXX
 
  * package pbool
 	Exported types:
 		type pbool::t = bool
 	Exported constants:
 	Exported nodes:
-		oper pbool::fby1 = pbool::fby1(bool, bool) returns (bool) on clock XXX
+		node pbool::fby1 = pbool::fby1(bool, bool) returns (bool) on clock XXX
 
  * package pint
 	Exported types:
 		type pint::t = int
 	Exported constants:
 	Exported nodes:
-		oper pint::fby1 = pint::fby1(int, int) returns (int) on clock XXX
+		node pint::fby1 = pint::fby1(int, int) returns (int) on clock XXX
 
  * package mainPack
 	Exported types:
@@ -68,9 +68,9 @@ End of Syntax table dump. 
 	Exported constants:
 		const mainPack::n = inter::n (imported)
 	Exported nodes:
-		oper mainPack::preced = mainPack::preced(inter::selType) returns (inter::selType) on clock XXX
+		node mainPack::preced = mainPack::preced(inter::selType) returns (inter::selType) on clock XXX
 
-		oper mainPack::preced = inter::preced (imported)
+		node mainPack::preced = inter::preced (imported)
  * package inter
 	Exported types:
 		type inter::t = preal::t (imported)
@@ -78,8 +78,8 @@ End of Syntax table dump. 
 	Exported constants:
 		const inter::n = -4
 	Exported nodes:
-		oper inter::fby1 = preal::fby1 (imported)
-		oper inter::preced = inter::preced( {i : int; b : bool; r : real}) returns ( {i : int; b : bool; r : real},  {i : int; b : bool; r : real}) on clock XXX
+		node inter::fby1 = preal::fby1 (imported)
+		node inter::preced = inter::preced( {i : int; b : bool; r : real}) returns ( {i : int; b : bool; r : real},  {i : int; b : bool; r : real}) on clock XXX
 
  
 ----------------------------------------------------------------------
@@ -88,7 +88,7 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 2
     init pack dummy
        export type Toto
-       export oper bibi
+       export node bibi
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -107,7 +107,7 @@ End of Syntax table dump. 
 		type dummy::Toto =  {x : int (1); y : int (2)}
 	Exported constants:
 	Exported nodes:
-		oper dummy::bibi = dummy::bibi(int) returns ( {x : int (1); y : int (2)}) on clock XXX
+		node dummy::bibi = dummy::bibi(int) returns ( {x : int (1); y : int (2)}) on clock XXX
 
  
 ----------------------------------------------------------------------
@@ -115,10 +115,10 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 1
 *** SyntaxTab.create pass 2
     init pack dummy
-       export oper min_4
-       export oper min
-       export oper min_n
-       export oper max
+       export node min_4
+       export node min
+       export node min_n
+       export node max
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -137,7 +137,7 @@ End of Syntax table dump. 
 	Exported constants:
 	Exported nodes:
 
-*** oops: an internal error occurred in file lazyCompiler.ml, line 499, column 5
+*** oops: an internal error occurred in file lazyCompiler.ml, line 500, column 5
 *** when compiling lustre program t0.lus
  
 ----------------------------------------------------------------------
@@ -145,11 +145,11 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 1
 *** SyntaxTab.create pass 2
     init pack dummy
-       export oper fold_left
-       export oper consensus_6_bis
-       export oper consensus_6
-       export oper consensus_bis
-       export oper consensus
+       export node fold_left
+       export node consensus_6_bis
+       export node consensus_6
+       export node consensus_bis
+       export node consensus
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -169,7 +169,7 @@ End of Syntax table dump. 
 	Exported nodes:
  ### skipping fold_left
 
-*** oops: an internal error occurred in file lazyCompiler.ml, line 499, column 5
+*** oops: an internal error occurred in file lazyCompiler.ml, line 500, column 5
 *** when compiling lustre program t2.lus
  
 ----------------------------------------------------------------------
@@ -204,7 +204,7 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 1
 *** SyntaxTab.create pass 2
     init pack dummy
-       export oper trivial
+       export node trivial
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -222,7 +222,7 @@ End of Syntax table dump. 
 	Exported types:
 	Exported constants:
 	Exported nodes:
-		oper dummy::trivial = dummy::trivial(int) returns (int) on clock XXX
+		node dummy::trivial = dummy::trivial(int) returns (int) on clock XXX
 
  
 ----------------------------------------------------------------------
@@ -263,10 +263,10 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 1
 *** SyntaxTab.create pass 2
     init pack dummy
-       export oper main
-       export oper main2
-       export oper consensus
-       export oper c8
+       export node main
+       export node main2
+       export node consensus
+       export node c8
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -284,10 +284,10 @@ End of Syntax table dump. 
 	Exported types:
 	Exported constants:
 	Exported nodes:
-		oper dummy::main = dummy::main(bool^4) returns (bool) on clock XXX
+		node dummy::main = dummy::main(bool^4) returns (bool) on clock XXX
 
 
-*** oops: an internal error occurred in file lazyCompiler.ml, line 499, column 5
+*** oops: an internal error occurred in file lazyCompiler.ml, line 500, column 5
 *** when compiling lustre program consensus.lus
  
 ----------------------------------------------------------------------
@@ -296,7 +296,7 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 2
     init pack dummy
        export type truc
-       export oper toto
+       export node toto
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -315,7 +315,7 @@ End of Syntax table dump. 
 		type dummy::truc =  {a : bool^100; b : int}
 	Exported constants:
 	Exported nodes:
-		oper dummy::toto = dummy::toto(bool) returns ( {a : bool^100; b : int}^3) on clock XXX
+		node dummy::toto = dummy::toto(bool) returns ( {a : bool^100; b : int}^3) on clock XXX
 
  
 ----------------------------------------------------------------------
@@ -323,7 +323,7 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 1
 *** SyntaxTab.create pass 2
     init pack inter
-       export oper preced
+       export node preced
        export const n
        export type selType
        export enum const X
@@ -337,15 +337,15 @@ End of Syntax table dump. 
        export type couleurs
        export const N
        export const X
-       export oper preced
+       export node preced
     init pack pint
-       export oper fby1
+       export node fby1
        export type t
     init pack pbool
-       export oper fby1
+       export node fby1
        export type t
     init pack preal
-       export oper fby1
+       export node fby1
        export type t
 *** SyntaxTab.create pass 3
    init symbol tables for pack inter
@@ -374,21 +374,21 @@ End of Syntax table dump. 
 		type preal::t = real
 	Exported constants:
 	Exported nodes:
-		oper preal::fby1 = preal::fby1(real, real) returns (real) on clock XXX
+		node preal::fby1 = preal::fby1(real, real) returns (real) on clock XXX
 
  * package pbool
 	Exported types:
 		type pbool::t = bool
 	Exported constants:
 	Exported nodes:
-		oper pbool::fby1 = pbool::fby1(bool, bool) returns (bool) on clock XXX
+		node pbool::fby1 = pbool::fby1(bool, bool) returns (bool) on clock XXX
 
  * package pint
 	Exported types:
 		type pint::t = int
 	Exported constants:
 	Exported nodes:
-		oper pint::fby1 = pint::fby1(int, int) returns (int) on clock XXX
+		node pint::fby1 = pint::fby1(int, int) returns (int) on clock XXX
 
  * package mainPack
 	Exported types:
@@ -405,9 +405,9 @@ End of Syntax table dump. 
 		const mainPack::X = 8
 		const mainPack::Y = inter::Y (imported)
 	Exported nodes:
-		oper mainPack::preced = mainPack::preced(inter::selType) returns (inter::selType) on clock XXX
+		node mainPack::preced = mainPack::preced(inter::selType) returns (inter::selType) on clock XXX
 
-		oper mainPack::preced = inter::preced (imported)
+		node mainPack::preced = inter::preced (imported)
  * package inter
 	Exported types:
 		type inter::t = preal::t (imported)
@@ -418,8 +418,8 @@ End of Syntax table dump. 
 		const inter::X = inter::X
 		const inter::Y = inter::Y
 	Exported nodes:
-		oper inter::fby1 = preal::fby1 (imported)
-		oper inter::preced = inter::preced( {i : int; b : bool; r : real}) returns ( {i : int; b : bool; r : real},  {i : int; b : bool; r : real}) on clock XXX
+		node inter::fby1 = preal::fby1 (imported)
+		node inter::preced = inter::preced( {i : int; b : bool; r : real}) returns ( {i : int; b : bool; r : real},  {i : int; b : bool; r : real}) on clock XXX
 
  
 ----------------------------------------------------------------------
@@ -427,19 +427,19 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 1
 *** SyntaxTab.create pass 2
     init pack inter
-       export oper preced
+       export node preced
        export const n
        export type selType
     init pack mainPack
-       export oper preced
+       export node preced
     init pack pint
-       export oper fby1
+       export node fby1
        export type t
     init pack pbool
-       export oper fby1
+       export node fby1
        export type t
     init pack preal
-       export oper fby1
+       export node fby1
        export type t
 *** SyntaxTab.create pass 3
    init symbol tables for pack inter
@@ -468,21 +468,21 @@ End of Syntax table dump. 
 		type preal::t = real
 	Exported constants:
 	Exported nodes:
-		oper preal::fby1 = preal::fby1(real, real) returns (real) on clock XXX
+		node preal::fby1 = preal::fby1(real, real) returns (real) on clock XXX
 
  * package pbool
 	Exported types:
 		type pbool::t = bool
 	Exported constants:
 	Exported nodes:
-		oper pbool::fby1 = pbool::fby1(bool, bool) returns (bool) on clock XXX
+		node pbool::fby1 = pbool::fby1(bool, bool) returns (bool) on clock XXX
 
  * package pint
 	Exported types:
 		type pint::t = int
 	Exported constants:
 	Exported nodes:
-		oper pint::fby1 = pint::fby1(int, int) returns (int) on clock XXX
+		node pint::fby1 = pint::fby1(int, int) returns (int) on clock XXX
 
  * package mainPack
 	Exported types:
@@ -490,9 +490,9 @@ End of Syntax table dump. 
 	Exported constants:
 		const mainPack::n = inter::n (imported)
 	Exported nodes:
-		oper mainPack::preced = mainPack::preced(inter::selType) returns (inter::selType) on clock XXX
+		node mainPack::preced = mainPack::preced(inter::selType) returns (inter::selType) on clock XXX
 
-		oper mainPack::preced = inter::preced (imported)
+		node mainPack::preced = inter::preced (imported)
  * package inter
 	Exported types:
 		type inter::t = preal::t (imported)
@@ -500,8 +500,8 @@ End of Syntax table dump. 
 	Exported constants:
 		const inter::n = -4
 	Exported nodes:
-		oper inter::fby1 = preal::fby1 (imported)
-		oper inter::preced = inter::preced( {i : int; b : bool; r : real}) returns ( {i : int; b : bool; r : real},  {i : int; b : bool; r : real}) on clock XXX
+		node inter::fby1 = preal::fby1 (imported)
+		node inter::preced = inter::preced( {i : int; b : bool; r : real}) returns ( {i : int; b : bool; r : real},  {i : int; b : bool; r : real}) on clock XXX
 
  
 ----------------------------------------------------------------------
@@ -511,8 +511,8 @@ End of Syntax table dump. 
     init pack dummy
        export const A
        export const B
-       export oper map2
-       export oper toto
+       export node map2
+       export node toto
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -537,7 +537,7 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 1
 *** SyntaxTab.create pass 2
     init pack dummy
-       export oper trivial
+       export node trivial
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -555,7 +555,7 @@ End of Syntax table dump. 
 	Exported types:
 	Exported constants:
 	Exported nodes:
-		oper dummy::trivial = dummy::trivial(int) returns (int) on clock XXX
+		node dummy::trivial = dummy::trivial(int) returns (int) on clock XXX
 
  
 ----------------------------------------------------------------------
@@ -563,9 +563,9 @@ End of Syntax table dump. 
 *** SyntaxTab.create pass 1
 *** SyntaxTab.create pass 2
     init pack dummy
-       export oper fold_left
-       export oper consensus
-       export oper bt_void
+       export node fold_left
+       export node consensus
+       export node bt_void
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -621,30 +621,30 @@ End of Syntax table dump. 
        export const BID_VAL
        export const TIME_CROSS_ROLL
        export const CROSS_CH_TOL_YAW
-       export oper Calculate
-       export oper onlyroll
-       export oper Median
-       export oper oneoffour
-       export oper MedianValue3
-       export oper Monitor
-       export oper Allocator
-       export oper Channel
-       export oper min2
-       export oper min4
-       export oper max2
-       export oper max4
-       export oper OlympicAverage
-       export oper InHardoverRange
-       export oper twooffour
-       export oper noneof
-       export oper threeoffour
-       export oper InNominalRange
-       export oper FailDetect
-       export oper abs
-       export oper Average2
-       export oper Average
-       export oper maintain
-       export oper values_nok
+       export node Calculate
+       export node onlyroll
+       export node Median
+       export node oneoffour
+       export node MedianValue3
+       export node Monitor
+       export node Allocator
+       export node Channel
+       export node min2
+       export node min4
+       export node max2
+       export node max4
+       export node OlympicAverage
+       export node InHardoverRange
+       export node twooffour
+       export node noneof
+       export node threeoffour
+       export node InNominalRange
+       export node FailDetect
+       export node abs
+       export node Average2
+       export node Average
+       export node maintain
+       export node values_nok
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -691,53 +691,53 @@ End of Syntax table dump. 
 		const dummy::CROSS_CH_TOL_YAW = 10.000000
 		const dummy::TIME_CROSS_ROLL = 3
 	Exported nodes:
-		oper dummy::Calculate = dummy::Calculate(real, real, real, real, bool, bool, bool, bool) returns (real) on clock XXX
+		node dummy::Calculate = dummy::Calculate(real, real, real, real, bool, bool, bool, bool) returns (real) on clock XXX
 
-		oper dummy::onlyroll = dummy::onlyroll(real, real, real, real, real, real, real, real, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool) returns (real, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, int, int, int, int) on clock XXX
+		node dummy::onlyroll = dummy::onlyroll(real, real, real, real, real, real, real, real, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool) returns (real, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, int, int, int, int) on clock XXX
 
-		oper dummy::Median = dummy::Median(real, real, real, real, bool, bool, bool, bool) returns (real) on clock XXX
+		node dummy::Median = dummy::Median(real, real, real, real, bool, bool, bool, bool) returns (real) on clock XXX
 
-		oper dummy::oneoffour = dummy::oneoffour(bool, bool, bool, bool) returns (bool) on clock XXX
+		node dummy::oneoffour = dummy::oneoffour(bool, bool, bool, bool) returns (bool) on clock XXX
 
-		oper dummy::MedianValue3 = dummy::MedianValue3(real, real, real) returns (real) on clock XXX
+		node dummy::MedianValue3 = dummy::MedianValue3(real, real, real) returns (real) on clock XXX
 
-		oper dummy::Monitor = dummy::Monitor(real, real, bool) returns (real, bool) on clock XXX
+		node dummy::Monitor = dummy::Monitor(real, real, bool) returns (real, bool) on clock XXX
 
-		oper dummy::Allocator = dummy::Allocator(bool, bool, bool, bool, bool) returns (bool, bool, bool, bool) on clock XXX
+		node dummy::Allocator = dummy::Allocator(bool, bool, bool, bool, bool) returns (bool, bool, bool, bool) on clock XXX
 
-		oper dummy::Channel = dummy::Channel(bool, bool, bool, real, real, bool, real, real, real, bool, bool, bool, bool) returns (real, bool, bool, bool, bool, int) on clock XXX
+		node dummy::Channel = dummy::Channel(bool, bool, bool, real, real, bool, real, real, real, bool, bool, bool, bool) returns (real, bool, bool, bool, bool, int) on clock XXX
 
-		oper dummy::min2 = dummy::min2(real, real) returns (real) on clock XXX
+		node dummy::min2 = dummy::min2(real, real) returns (real) on clock XXX
 
-		oper dummy::max2 = dummy::max2(real, real) returns (real) on clock XXX
+		node dummy::max2 = dummy::max2(real, real) returns (real) on clock XXX
 
-		oper dummy::min4 = dummy::min4(real, real, real, real) returns (real) on clock XXX
+		node dummy::min4 = dummy::min4(real, real, real, real) returns (real) on clock XXX
 
-		oper dummy::OlympicAverage = dummy::OlympicAverage(real, real, real, real) returns (real) on clock XXX
+		node dummy::OlympicAverage = dummy::OlympicAverage(real, real, real, real) returns (real) on clock XXX
 
-		oper dummy::max4 = dummy::max4(real, real, real, real) returns (real) on clock XXX
+		node dummy::max4 = dummy::max4(real, real, real, real) returns (real) on clock XXX
 
-		oper dummy::InHardoverRange = dummy::InHardoverRange(real) returns (bool) on clock XXX
+		node dummy::InHardoverRange = dummy::InHardoverRange(real) returns (bool) on clock XXX
 
-		oper dummy::noneof = dummy::noneof(bool, bool, bool, bool) returns (bool) on clock XXX
+		node dummy::noneof = dummy::noneof(bool, bool, bool, bool) returns (bool) on clock XXX
 
-		oper dummy::twooffour = dummy::twooffour(bool, bool, bool, bool) returns (bool) on clock XXX
+		node dummy::twooffour = dummy::twooffour(bool, bool, bool, bool) returns (bool) on clock XXX
 
-		oper dummy::threeoffour = dummy::threeoffour(bool, bool, bool, bool) returns (bool) on clock XXX
+		node dummy::threeoffour = dummy::threeoffour(bool, bool, bool, bool) returns (bool) on clock XXX
 
-		oper dummy::InNominalRange = dummy::InNominalRange(real) returns (bool) on clock XXX
+		node dummy::InNominalRange = dummy::InNominalRange(real) returns (bool) on clock XXX
 
-		oper dummy::FailDetect = dummy::FailDetect(bool, real, bool, bool, bool, real, real, real, bool, bool, bool, bool) returns (bool, bool, int, bool) on clock XXX
+		node dummy::FailDetect = dummy::FailDetect(bool, real, bool, bool, bool, real, real, real, bool, bool, bool, bool) returns (bool, bool, int, bool) on clock XXX
 
-		oper dummy::abs = dummy::abs(real) returns (real) on clock XXX
+		node dummy::abs = dummy::abs(real) returns (real) on clock XXX
 
-		oper dummy::Average2 = dummy::Average2(real, real) returns (real) on clock XXX
+		node dummy::Average2 = dummy::Average2(real, real) returns (real) on clock XXX
 
-		oper dummy::Average = dummy::Average(real, real, real, real, bool, bool, bool, bool) returns (real) on clock XXX
+		node dummy::Average = dummy::Average(real, real, real, real, bool, bool, bool, bool) returns (real) on clock XXX
 
-		oper dummy::values_nok = dummy::values_nok(bool, bool, bool, real, real, real, real) returns (bool) on clock XXX
+		node dummy::values_nok = dummy::values_nok(bool, bool, bool, real, real, real, real) returns (bool) on clock XXX
 
-		oper dummy::maintain = dummy::maintain(int, bool) returns (bool) on clock XXX
+		node dummy::maintain = dummy::maintain(int, bool) returns (bool) on clock XXX
 
  
 ----------------------------------------------------------------------
@@ -749,17 +749,17 @@ End of Syntax table dump. 
        export const TMIN
        export const TMAX
        export const DELTA
-       export oper not_a_sauna2
-       export oper Median
-       export oper heater_control
-       export oper min2
-       export oper max2
-       export oper alloftree
-       export oper not_a_sauna
-       export oper abs
-       export oper noneoftree
-       export oper oneoftree
-       export oper Average
+       export node not_a_sauna2
+       export node Median
+       export node heater_control
+       export node min2
+       export node max2
+       export node alloftree
+       export node not_a_sauna
+       export node abs
+       export node noneoftree
+       export node oneoftree
+       export node Average
 *** SyntaxTab.create pass 3
    init symbol tables for pack dummy
 *** SyntaxTab.create done
@@ -781,27 +781,56 @@ End of Syntax table dump. 
 		const dummy::TMAX = 9.000000
 		const dummy::DELTA = 0.500000
 	Exported nodes:
-		oper dummy::not_a_sauna2 = dummy::not_a_sauna2(real, real, real, real, bool) returns (bool) on clock XXX
+		node dummy::not_a_sauna2 = dummy::not_a_sauna2(real, real, real, real, bool) returns (bool) on clock XXX
 
-		oper dummy::Median = dummy::Median(real, real, real) returns (real) on clock XXX
+		node dummy::Median = dummy::Median(real, real, real) returns (real) on clock XXX
 
-		oper dummy::heater_control = dummy::heater_control(real, real, real, real) returns (bool) on clock XXX
+		node dummy::heater_control = dummy::heater_control(real, real, real, real) returns (bool) on clock XXX
 
-		oper dummy::min2 = dummy::min2(real, real) returns (real) on clock XXX
+		node dummy::min2 = dummy::min2(real, real) returns (real) on clock XXX
 
-		oper dummy::max2 = dummy::max2(real, real) returns (real) on clock XXX
+		node dummy::max2 = dummy::max2(real, real) returns (real) on clock XXX
 
-		oper dummy::not_a_sauna = dummy::not_a_sauna(real, real, real, real, bool) returns (bool) on clock XXX
+		node dummy::not_a_sauna = dummy::not_a_sauna(real, real, real, real, bool) returns (bool) on clock XXX
 
-		oper dummy::alloftree = dummy::alloftree(bool, bool, bool) returns (bool) on clock XXX
+		node dummy::alloftree = dummy::alloftree(bool, bool, bool) returns (bool) on clock XXX
 
-		oper dummy::abs = dummy::abs(real) returns (real) on clock XXX
+		node dummy::abs = dummy::abs(real) returns (real) on clock XXX
 
-		oper dummy::noneoftree = dummy::noneoftree(bool, bool, bool) returns (bool) on clock XXX
+		node dummy::noneoftree = dummy::noneoftree(bool, bool, bool) returns (bool) on clock XXX
 
-		oper dummy::Average = dummy::Average(real, real) returns (real) on clock XXX
+		node dummy::Average = dummy::Average(real, real) returns (real) on clock XXX
 
-		oper dummy::oneoftree = dummy::oneoftree(bool, bool, bool) returns (bool) on clock XXX
+		node dummy::oneoftree = dummy::oneoftree(bool, bool, bool) returns (bool) on clock XXX
+
+ 
+----------------------------------------------------------------------
+====> ../lus2lic -vl 3  func_with_body.lus
+*** SyntaxTab.create pass 1
+*** SyntaxTab.create pass 2
+    init pack dummy
+       export node ext
+       export node trivial
+*** SyntaxTab.create pass 3
+   init symbol tables for pack dummy
+*** SyntaxTab.create done
+*** « Syntax table dump:
+ 	 - Package or model list:
+		func_with_body (pack) 
+		
+	 - Raw model table: 
+	 - Raw Package table: dummy 
+	 - Package manager table: dummy 
+End of Syntax table dump. »
+-- MAIN NODE: "func_with_body::main"
+*** Dump the exported items of the packages.
+ * package dummy
+	Exported types:
+	Exported constants:
+	Exported nodes:
+		node dummy::ext = extern ext(int) returns (int)
+
+		node dummy::trivial = dummy::trivial(int) returns (int) on clock XXX
 
  
 ----------------------------------------------------------------------
-- 
GitLab