From 0bca9d53705b7a093757b9b63ba3c4a5c6ad7355 Mon Sep 17 00:00:00 2001
From: ploc <ploc@garoche.net>
Date: Wed, 14 Mar 2018 18:58:05 -0700
Subject: [PATCH] Recursive resolution of dependencies

---
 include/simulink_math_fcn.c          | 97 ++--------------------------
 include/simulink_math_fcn.lusi       | 68 ++-----------------
 src/backends/C/c_backend_makefile.ml | 11 +++-
 src/compiler_common.ml               |  9 ++-
 4 files changed, 25 insertions(+), 160 deletions(-)

diff --git a/include/simulink_math_fcn.c b/include/simulink_math_fcn.c
index 84b3354f..723f3929 100644
--- a/include/simulink_math_fcn.c
+++ b/include/simulink_math_fcn.c
@@ -1,80 +1,12 @@
 #include "simulink_math_fcn.h"
 #include <math.h>
 
-/* function exp_scalar_real (x: real) returns (y: real) prototype C lib m; */
-double exp_scalar_real (double x) {
-  return exp(x);
-}
-
-
-/* function log_scalar_real (x: real) returns (y: real) prototype C lib m; */
-double log_scalar_real (double x) {
-  return log(x);
-}
-/* function _10u_scalar_real (x: real) returns (y: real) prototype C lib m; */
-double _10u_scalar_real (double x) {
-  return pow(10.,x);
-}
-
-/* function log10_scalar_real (x: real) returns (y: real) prototype C lib m; */
-double log10_scalar_real (double x) {
-  return log10(x);
-}
-
-/* function magnitude_2_scalar_real (x: real) returns (y: real) prototype C lib m; */
-double magnitude_2_scalar_real (double x) {
-  return pow(fabs(x), 2.);
-}
 
-/* function square_scalar_real (x: real) returns (y: real) prototype C lib m; */
-double square_scalar_real (double x) {
-  return pow(x, 2.);
-}
-
-/* function pow_scalar_real (x,y: real) returns (z: real) prototype C lib m; */
-double pow_scalar_real (double x, double y) {
-  return pow(x, y);
-}
-
-/* function conj_scalar_real (x: real) returns (y: real) prototype C lib m; */
-double conj_scalar_real (double x) {
-  return x; // identity for real
-}
-
-/* function reciprocal_scalar_real (x: real) returns (y: real) prototype C lib m; */
-double reciprocal_scalar_real (double x) {
-  return 1./x; 
-}
-
-/* function hypot_scalar_real (x,y: real) returns (z: real) prototype C lib m; */
-double hypot_scalar_real (double x, double y) {
-  return sqrt(x*x + y*y); 
-}
-
-
-
-/*
-  mod function produces a result that is either zero or has the same sign as the divisor.
-  rem function produces a result that is either zero or has the same sign as the dividend.
-  mod(a,0) returns a
-  rem(a,0) returns NaN.
-
-function rem_scalar_real_int_int_int (x,y: int) returns (z: int) prototype C lib m;
-function rem_scalar_real_double_double_double (x,y: double) returns (z: double) prototype C lib m;
-function rem_scalar_real_double_int_double (x: double; y: int) returns (z: double) prototype C lib m;
-function rem_scalar_real_int_double_double (x: int; y: double) returns (z: double) prototype C lib m;
-
-function mod_scalar_real_int_int_int (x,y: int) returns (z: int) prototype C lib m;
-function mod_scalar_real_double_double_double (x,y: double) returns (z: double) prototype C lib m;
-function mod_scalar_real_double_int_double (x: double; y: int) returns (z: double) prototype C lib m;
-function mod_scalar_real_int_double_double (x: int; y: double) returns (z: double) prototype C lib m;
-*/
-
-int rem_scalar_real_int_int_int (int x, int y) {
+int rem_int (int x, int y) {
   return x%y;
 }
 
-int mod_scalar_real_int_int_int (int x, int y) {
+int mod_int (int x, int y) {
   int tmp;
   if (y == 0) { return x; };
   tmp = x%y;
@@ -86,11 +18,11 @@ int mod_scalar_real_int_int_int (int x, int y) {
   }
 }
 
-double rem_scalar_real_double_double_double (double x, double y) {
+double rem_real (double x, double y) {
   return fmod(x, y);
 }
 
-double mod_scalar_real_double_double_double (double x, double y) {
+double mod_real (double x, double y) {
   double tmp = 0.;
   if (y == 0.) { return x; };
   tmp = fmod(x, y);
@@ -101,24 +33,3 @@ double mod_scalar_real_double_double_double (double x, double y) {
     return tmp;
   }
 }
-
-double rem_scalar_real_double_int_double (double x, int y) {
-  return rem_scalar_real_double_double_double (x, (double)y);
-}
-
-double rem_scalar_real_int_double_double (int x, double y) {
-  return rem_scalar_real_double_double_double ((double)x, y);
-}
-
-
-double mod_scalar_real_double_int_double (double x, int y) {
-  return (mod_scalar_real_double_double_double (x, (double)y));
-}
-
-double mod_scalar_real_int_double_double (int x, double y) {
-  return (mod_scalar_real_double_double_double ((double)x, y));
-}
-
-/* function transpose_scalar_real (x: real) returns (y: real) prototype C lib m; */
-
-/* function hermitian_scalar_real (x: real) returns (y: real) prototype C lib m; */
diff --git a/include/simulink_math_fcn.lusi b/include/simulink_math_fcn.lusi
index 1f926509..46679d2e 100644
--- a/include/simulink_math_fcn.lusi
+++ b/include/simulink_math_fcn.lusi
@@ -1,63 +1,5 @@
-(*
-Mathematical functions in Simulink Math Function blocks
-
-All these functions can be applied to scalar value. All but transpose and
-hermitian can be also applied as element-wise operations on vector, matrices
-inputs. transpose and hermitian are applied on vector and matrices as regular
-(non element-wise) operations.
-
-The Lustre library provides only scalar functions for all cases, and, in the future,
-the matrix versions of them.
-
-exp: 
-log
-10^u
-log10
-magnitude^2
-square
-pow
-conj
-reciprocal
-hypot
-rem
-mod
-transpose
-hermitian
-
-For the moment, we focus only on theoretical types: real, complex.
-A future version can be specialized for concrete datatypes (single, double,
-(u)intXX).
-
-*)
-
--- open <math>
-function fmod (x,y: real) returns (z: real) prototype C lib m;
-
-function exp_scalar_real (x: real) returns (y: real) prototype C lib m;
-function log_scalar_real (x: real) returns (y: real) prototype C lib m;
-function _10u_scalar_real (x: real) returns (y: real) prototype C lib m;
-function log10_scalar_real (x: real) returns (y: real) prototype C lib m;
-
--- complex modulus: |x|^2
-function magnitude_2_scalar_real (x: real) returns (y: real) prototype C lib m;
-function square_scalar_real (x: real) returns (y: real) prototype C lib m;
-function pow_scalar_real (x,y: real) returns (z: real) prototype C lib m;
-function conj_scalar_real (x: real) returns (y: real) prototype C lib m;
-function reciprocal_scalar_real (x: real) returns (y: real) prototype C lib m;
-function hypot_scalar_real (x,y: real) returns (z: real) prototype C lib m;
-
-function rem_scalar_real_int_int_int (x,y: int) returns (z: int) prototype C lib m;
-function rem_scalar_real_double_double_double (x,y: real) returns (z: real) prototype C lib m;
-function rem_scalar_real_double_int_double (x: real; y: int) returns (z: real) prototype C lib m;
-function rem_scalar_real_int_double_double (x: int; y: real) returns (z: real) prototype C lib m;
-
-function mod_scalar_real_int_int_int (x,y: int) returns (z: int) prototype C lib m;
-function mod_scalar_real_double_double_double (x,y: real) returns (z: real) prototype C lib m;
-function mod_scalar_real_double_int_double (x: real; y: int) returns (z: real) prototype C lib m;
-function mod_scalar_real_int_double_double (x: int; y: real) returns (z: real) prototype C lib m;
-
-(*
--- function transpose_scalar_real (x: real) returns (y: real) prototype C lib m;
--- function hermitian_scalar_real (x: real) returns (y: real) prototype C lib m;
--- function exp_matrix_real (const i,j: int; x: real^i^j) returns (y: real^i^j) prototype C lib m;
-*)
+#open <lustrec_math>
+function rem_int (x,y: int) returns (z: int) prototype C;
+function rem_real (x,y: real) returns (z: real) prototype C;
+function mod_int (x,y: int) returns (z: int) prototype C;
+function mod_real (x,y: real) returns (z: real) prototype C;
diff --git a/src/backends/C/c_backend_makefile.ml b/src/backends/C/c_backend_makefile.ml
index 7cca5d53..4edf3d59 100644
--- a/src/backends/C/c_backend_makefile.ml
+++ b/src/backends/C/c_backend_makefile.ml
@@ -13,6 +13,12 @@ open Format
 open LustreSpec
 open Corelang
 
+let pp_dep fmt (Dep(b,id,tops,stateful)) =
+  Format.fprintf fmt "%b, %s, {%a}, %b"
+    b id Printers.pp_prog tops stateful
+  
+let pp_deps fmt deps = Format.fprintf fmt "@[<v 0>%a@ @]" (Utils.fprintf_list ~sep:"@ ," pp_dep) deps
+
 let header_has_code header =
   List.exists 
     (fun top -> 
@@ -39,8 +45,11 @@ let lib_dependencies dep =
     (fun accu (Dep (_, _, header, _)) -> Utils.list_union (header_libs header) accu) [] dep
     
 let fprintf_dependencies fmt (dep: dep_t list) =
+  (* Format.eprintf "Deps: %a@." pp_deps dep; *)
   let compiled_dep = compiled_dependencies dep in
-  List.iter (fun s -> (* Format.eprintf "Adding dependency: %s@." s;  *)
+  (* Format.eprintf "Compiled Deps: %a@." pp_deps compiled_dep; *)
+ 
+  List.iter (fun s -> Format.eprintf "Adding dependency: %s@." s;  
     fprintf fmt "\t${GCC} -I${INC} -c %s@." s)
     (("${INC}/io_frontend.c"):: (* IO functions when a main function is computed *)
 	(List.map 
diff --git a/src/compiler_common.ml b/src/compiler_common.ml
index 351f8229..6b40068d 100644
--- a/src/compiler_common.ml
+++ b/src/compiler_common.ml
@@ -232,7 +232,7 @@ let is_stateful topdecl =
   | _ -> false
 
 
-let import_dependencies prog =
+let rec import_dependencies prog =
   Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 4>.. extracting dependencies");
   let dependencies = Corelang.get_dependencies prog in
   let deps =
@@ -240,13 +240,16 @@ let import_dependencies prog =
     (fun (compilation_dep, type_env, clock_env) dep ->
       let (local, s) = Corelang.dependency_of_top dep in
       let basename = Options_management.name_dependency (local, s) in
-      Log.report ~level:1 (fun fmt -> Format.fprintf fmt "@ Library %s" basename);
+      Log.report ~level:1 (fun fmt -> Format.fprintf fmt "@ Library %s@ " basename);
       let lusic = Modules.import_dependency dep.top_decl_loc (local, s) in
       (*Log.report ~level:1 (fun fmt -> Format.fprintf fmt "");*)
+      let lusic_deps, type_env', clock_env' = import_dependencies lusic.Lusic.contents in
+      let type_env = Env.overwrite type_env type_env' in
+      let clock_env = Env.overwrite clock_env clock_env' in
       let (lusi_type_env, lusi_clock_env) = get_envs_from_top_decls lusic.Lusic.contents in
       let is_stateful = List.exists is_stateful lusic.Lusic.contents in
       let new_dep = Dep (local, s, lusic.Lusic.contents, is_stateful ) in
-      new_dep::compilation_dep,
+      new_dep::lusic_deps@compilation_dep,
       Env.overwrite type_env lusi_type_env,
       Env.overwrite clock_env lusi_clock_env)
     ([], Basic_library.type_env, Basic_library.clock_env)
-- 
GitLab