2012-01-16 85 views
1

與一個GP項目,我有很多自動生成的口齒不清片段可以看基本上是這樣的:作圖Lisp代碼

(+ 2 (f1 (f2 x y) (f2 x y))) 

總之:一個俏皮話負載。

如何將圖形繪製到函數樹中?最好通過產生斑點或類似的圖形,可以很容易地通過graphviz的被推開,這樣我可以使其弄成這個樣子:

 + 
    /\ 
    / \ 
    2  f1 
     /\ 
     / \ 
    / \ 
    /  \ 
    f2   f2 
    /\  /\ 
/ \ / \ 
    x  y x  y 
+0

你可以在這裏尋找靈感:http://ryepup.unwashedmeme.com/blog/2012/01/03/visualizing-call-graphs-in-lisp-using-swank-and-graphviz/ – 2012-01-16 13:13:27

回答

2

這個怎麼樣(方案[球拍博士):

(define (as-string elm) 
    (cond 
    ((string? elm) (string-append "\\\"" elm "\\\"")) 
    ((number? elm) (number->string elm)) 
    ((symbol? elm) (symbol->string elm)) 
    ((null? elm) "*empty-list*") 
    (else (error "Unrecognized type")))) 

(define (node-name-label names labels) 
    (apply append (map (lambda (a b) 
         (if (list? a) 
          (node-name-label a b) 
          (list (cons a b)))) 
        names labels))) 

(define (node-txt names labels) 
    (apply string-append (map (lambda (x) 
           (let ((name (car x)) (label (cdr x))) 
           (string-append name " [label=\"" (as-string label) "\"];\n"))) 
          (node-name-label names labels)))) 

(define (graph-txt lst) 
    (apply string-append (map (lambda (x) 
           (let ((a (car x)) (b (cdr x))) 
           (string-append a " -- " b ";\n"))) 
          (get-relationships lst)))) 

(define (declare-nodes lst (basename "node")) 
    (map (lambda (x n) 
     (if (and (list? x) (not (empty? x))) 
      (declare-nodes x (string-append basename "_" (number->string n))) 
      (string-append basename "_" (number->string n)))) 
     lst 
     (range 0 (length lst)))) 

(define (get-relationships lst) 
    (if (< (length lst) 2) 
     null 
     (apply append (map (lambda (x) 
          (if (list? x) 
           (cons (cons (car lst) (car x)) (get-relationships x)) 
           (list (cons (car lst) x)))) 
         (cdr lst))))) 

(define (range start end) 
    (if (>= start end) 
     '() 
     (cons start (range (+ 1 start) end)))) 

(define (get-graph code graph-title) 
    (let ((names (declare-nodes code))) 
    (string-append 
    "graph " 
    graph-title 
    " {\n" 
    (node-txt names code) 
    "\n" 
    (graph-txt names) 
    "}"))) 

用法:(display (get-graph '(+ 2 (f1 (f2() y) (f2 x y))) "simple_graph"))生產:

graph simple_graph { 
node_0 [label="+"]; 
node_1 [label="2"]; 
node_2_0 [label="f1"]; 
node_2_1_0 [label="f2"]; 
node_2_1_1 [label="*empty-list*"]; 
node_2_1_2 [label="y"]; 
node_2_2_0 [label="f2"]; 
node_2_2_1 [label="x"]; 
node_2_2_2 [label="y"]; 

node_0 -- node_1; 
node_0 -- node_2_0; 
node_2_0 -- node_2_1_0; 
node_2_1_0 -- node_2_1_1; 
node_2_1_0 -- node_2_1_2; 
node_2_0 -- node_2_2_0; 
node_2_2_0 -- node_2_2_1; 
node_2_2_0 -- node_2_2_2; 
}