]> git.donarmstrong.com Git - lilypond.git/commitdiff
resurrect graphing support
authorJoe Neeman <joeneeman@gmail.com>
Thu, 1 Feb 2007 16:17:40 +0000 (18:17 +0200)
committerJoe Neeman <joeneeman@gmail.com>
Thu, 1 Feb 2007 16:17:40 +0000 (18:17 +0200)
lily/context.cc
lily/grob-property.cc
lily/include/context.hh
lily/include/grob.hh
lily/include/lily-guile-macros.hh
lily/include/prob.hh
lily/prob.cc
ly/graphviz.ly [new file with mode: 0644]
scm/graphviz.scm

index 7e5ea8ae2ac0c83ee84e30de36f38f8d10590e34..f5543c01050be8e69c2cb62cfb5a1742570683f4 100644 (file)
@@ -460,6 +460,13 @@ Context::add_alias (SCM sym)
   aliases_ = scm_cons (sym, aliases_);
 }
 
+/* we don't (yet) instrument context properties */
+void
+Context::instrumented_set_property (SCM sym, SCM val, const char*, int, const char*)
+{
+  internal_set_property (sym, val);
+}
+
 void
 Context::internal_set_property (SCM sym, SCM val)
 {
index 7bf13062a59d38523ba31cf8b8da99fb8ced07e7..1473157209dc7be9c9139e6f1a923ffd5f42e508 100644 (file)
@@ -27,9 +27,11 @@ LY_DEFINE (ly_set_grob_modification_callback, "ly:set-grob-modification-callback
           1, 0, 0, (SCM cb),
           "Specify a procedure that will be called every time lilypond modifies "
           "a grob property. The callback will receive as arguments "
-          "the grob that is being modified, the name of the C++ file in which "
-          "the modification was requested, the line number in the C++ file in "
-          "which the modification was requested, the property to be changed and "
+          "the grob that is being modified, "
+          "the name of the C++ file in which the modification was requested, "
+          "the line number in the C++ file in which the modification was requested, "
+          "the name of the function in which the modification was requested, "
+          "the property to be changed and "
           "the new value for the property.")
 {
   LY_ASSERT_TYPE (ly_is_procedure, cb, 1);
@@ -37,6 +39,22 @@ LY_DEFINE (ly_set_grob_modification_callback, "ly:set-grob-modification-callback
   modification_callback = cb;
   return SCM_UNSPECIFIED;
 }
+
+void
+Grob::instrumented_set_property (SCM sym, SCM v,
+                                char const *file,
+                                int line,
+                                char const *fun)
+{
+  if (ly_is_procedure (modification_callback))
+    scm_apply_0 (modification_callback,
+                scm_list_n (self_scm (),
+                            scm_from_locale_string (file),
+                            scm_from_int (line),
+                            scm_from_locale_string (fun),
+                            sym, v, SCM_UNDEFINED));
+  internal_set_property (sym, v);
+}
 #endif
 
 SCM
@@ -51,43 +69,6 @@ Grob::get_property_alist_chain (SCM def) const
 
 extern void check_interfaces_for_property (Grob const *me, SCM sym);
 
-#if 0
-
-/*
-  We can't change signatures depending on NDEBUG, since NDEBUG comes
-  over the command line and may be different per .cc file.  This
-  should be done through the macro expansion of get_property ().
- */
-void
-Grob::internal_set_property (SCM sym, SCM v, char const *file, int line, char const *fun)
-{
-  SCM grob_p = ly_lily_module_constant ("ly:grob?");
-  SCM grob_list_p = ly_lily_module_constant ("grob-list?");
-  SCM type = scm_object_property (sym, ly_symbol2scm ("backend-type?"));
-
-  if (type == grob_p
-      || type == grob_list_p
-      || (unsmob_grob (v) && ly_symbol2scm ("cause") != sym))
-    {
-      scm_display (scm_list_2 (sym, type), scm_current_output_port ());
-      assert (0);
-    }
-  
-  internal_set_value_on_alist (&mutable_property_alist_,
-                              sym, v);
-
-
-  if (ly_is_procedure (modification_callback))
-    scm_apply_0 (modification_callback,
-                scm_list_n (self_scm (),
-                            scm_from_locale_string (file),
-                            scm_from_int (line),
-                            scm_from_locale_string (fun),
-                            sym, v, SCM_UNDEFINED));
-}
-#else
-
-
 void
 Grob::internal_set_property (SCM sym, SCM v)
 {
@@ -95,7 +76,6 @@ Grob::internal_set_property (SCM sym, SCM v)
                               sym, v);
 
 }
-#endif
 
 void
 Grob::internal_set_value_on_alist (SCM *alist, SCM sym, SCM v)
index 39babf7b669751f9c2204b0701ace74159c621bf..7cd01bf5bbcba61632295be7d9a949d08e77b60c 100644 (file)
@@ -85,6 +85,7 @@ public:
   Context *where_defined (SCM name_sym, SCM *value) const;
   void unset_property (SCM var_sym);
 
+  void instrumented_set_property (SCM, SCM, const char*, int, const char*);
   void internal_set_property (SCM var_sym, SCM value);
 
   Context *create_context (Context_def *, string, SCM);
index d134068568b6810e271203eb1d7b7fac1749a572..73d58a8c2c26a78762593864158b23307bbcd1fc 100644 (file)
@@ -84,6 +84,7 @@ public:
   SCM internal_get_object (SCM symbol) const;
   void internal_set_object (SCM sym, SCM val);
   void internal_del_property (SCM symbol);
+  void instrumented_set_property (SCM, SCM, char const*, int, char const*);
   void internal_set_property (SCM sym, SCM val);
 
   /* messages */  
index 6b0a60a2f041271bded2b8d938afb3acaeacc7c7..86d2517dee175fac6e1e8f7abd51d853900a3acd 100644 (file)
@@ -195,7 +195,7 @@ void ly_check_name (string cxx, string fname);
   TODO: include modification callback support here, perhaps
   through intermediate Grob::instrumented_set_property( .. __LINE__ ).
  */
-#define set_property(x, y) internal_set_property (ly_symbol2scm (x), y)  
+#define set_property(x, y) instrumented_set_property (ly_symbol2scm (x), y, __FILE__, __LINE__, __FUNCTION__)
 #else
 #define set_property(x, y) internal_set_property (ly_symbol2scm (x), y)
 #endif
index 839edd4abacdff4c1be17a8cabd93267d66ef271..b01fb4d42d6e8acc0ea9d389499c2c5f2ba037ca 100644 (file)
@@ -42,6 +42,7 @@ public:
   SCM type () const { return type_; }
   SCM get_property_alist (bool mutble) const;
   SCM internal_get_property (SCM sym) const;
+  void instrumented_set_property (SCM, SCM, const char*, int, const char*);
   void internal_set_property (SCM sym, SCM val);
 };
 DECLARE_UNSMOB(Prob,prob);
index ce51546d8e0f83f50582e840cecb25b9b09988de..4e068fa4d45301a7b19daea13b277e55e7795353 100644 (file)
@@ -157,6 +157,13 @@ Prob::internal_get_property (SCM sym) const
   return (s == SCM_BOOL_F) ? SCM_EOL : scm_cdr (s);
 }
 
+/* We don't (yet) instrument probs */
+void
+Prob::instrumented_set_property (SCM sym, SCM val, const char*, int, const char*)
+{
+  internal_set_property (sym, val);
+}
+
 void
 Prob::internal_set_property (SCM sym, SCM val) 
 {
diff --git a/ly/graphviz.ly b/ly/graphviz.ly
new file mode 100644 (file)
index 0000000..65b6538
--- /dev/null
@@ -0,0 +1,53 @@
+\version "2.11.15"
+
+#(define last-grob-action '())
+
+#(define sym-blacklist
+  '(cause font))
+
+#(define sym-whitelist
+  '(control-points))
+
+#(define file-line-blacklist
+  '())
+
+#(define file-line-whitelist
+  '())
+
+#(define graph (make-graph "graph.dot"))
+
+% an event is relevant if
+% (it is on some whitelist or all whitelists are empty)
+% and
+% (it isn't on any blacklist)
+
+#(define (relevant? grob file line prop)
+  (let ((file-line `(,file . ,line)))
+   (and
+    (or
+     (= 0 (length file-line-whitelist) (length sym-whitelist))
+     (memq prop sym-whitelist)
+     (member file-line file-line-whitelist))
+    (and
+     (not (memq prop sym-blacklist))
+     (not (member file-line file-line-blacklist))))))
+
+#(define (grob-mod grob file line func prop val)
+  (let* ((prev (assv grob last-grob-action))
+         (val-str0 (format "~a" val))
+         (val-str (string-take val-str0 (min 50 (string-length val-str0))))
+        (label (format "~a\\n~a:~a\\n~a <- ~a" grob file line prop val-str))
+        (node-id (make-node graph label file)))
+   (if (relevant? grob file line prop)
+    (begin
+     (if (pair? prev)
+      (add-edge graph (cdr prev) node-id))
+     (set! last-grob-action (assv-set! last-grob-action grob node-id))))))
+
+#(define (grob-create grob file line func)
+  (let* ((label (format "~a\\n~a:~a" grob file line))
+        (node-id (make-node graph label file)))
+   (set! last-grob-action (assv-set! last-grob-action grob node-num))))
+
+#(ly:set-grob-modification-callback grob-mod)
+#(ly:set-grob-creation-callback grob-create)
index d3a858fcef4fb6437578cf2f7f32bfcd6ed8a9b2..d361302fede7623a2164a8f90f7409d6fd34bb03 100644 (file)
@@ -1,6 +1,13 @@
+;;;; graphviz.scm -- utilities for creating graphviz output
+;;;;
+;;;;  source file of the GNU LilyPond music typesetter
+;;;;
+;;;; (c) 2007 Joe Neeman <joeneeman@gmail.com>
+
+
 (define-module (scm graphviz)
   #:use-module (lily)
-  #:export (make-graph add-node add-edge))
+  #:export (make-graph add-node add-edge add-cluster))
 
 (define (make-graph filename)
   (let ((empty-graph (list->vector (list filename '() '() '()))))
 (define (edges g) (vector-ref g 2))
 (define (clusters g) (vector-ref g 3))
 
-(define (add-node graph label)
-  (let ((ns (nodes graph)))
-    (vector-set! graph 1 (cons `(,(length ns) . ,label) ns))
-    (length ns)))
+(define (add-cluster graph node-id cluster-name)
+  (let ((cs (clusters g))
+       (cluster (assq cluster-name cs))
+       (already-in-cluster (if cluster
+                               (cdr cluster)
+                               '())))
+    (vector-set! graph 3 (assq-set! cluster-name
+                                   (cons node-id already-in-cluster)
+                                   cs))))
+
+(define (add-node graph label . cluster-name)
+  (let ((ns (nodes graph))
+        (id (length ns)))
+    (vector-set! graph 1 (cons `(,id . ,label) ns))
+    (if (and (not (null? cluster-name))
+            (string? (car cluster-name)))
+       (add-cluster graph id (car cluster-name)))
+    id))
 
 (define (add-edge graph node1 node2)
   (vector-set! graph 2 (cons `(,node1 . ,node2) (edges graph))))
   (let ((out (open-file (filename graph) "w"))
        (ns (nodes graph))
        (es (edges graph))
-       (cc (clusters graph)))
+       (cs (clusters graph)))
     (ly:message (format "writing graph ~s..." (filename graph)))
     (display "digraph G {\nrankdir=\"LR\"\nnode [shape=rectangle]\n" out)
     (map (lambda (n) (display (format "~a [label=\"~a\"]\n" (car n) (cdr n)) out))
         ns)
     (map (lambda (e) (display (format "~a -> ~a\n" (car e) (cdr e)) out))
         es)
+    (map (lambda (c)
+         (display (format "subgraph cluster_~a {\nlabel= \"~a\"\ncolor=blue\n"
+                          (string-filter char-alphabetic? (car c))
+                          (car c))
+                  out)
+         (map (lambda (n) (display (format "~a\n" n) out)) (cdr c))
+         (display "}\n" out))
+        cs)
     (display "}" out)))
-  
\ No newline at end of file