J-Bobを作ってみよう(8) 簡易プロファイラ
関数の呼び出し回数が見えるようにしてみようかと
env
に覚えるようにしておいて、japply
かなにかのタイミングで更新すればよさそう
リストのままだと更新しづらい(気がする)から、structにしてみようか
こういうの「純粋」なやりかたではどうやるのかな
まず動きはそのまま内部表現だけ変えます
+(struct fentry (name vars body) #:transparent)
- (set! env (cons (list name args body) env)))
+ (set! env (cons (fentry name args body) env)))
(jeval
(let* ((f (findfunc name))
- (vars (cadr f)))
- (subst (caddr f) vars args))))
+ (vars (fentry-vars f)))
+ (subst (fentry-body f) vars args))))
#transparent
がないと、画面に表示させても中身がわかりません
> (fentry 'tcons '(x y) '(cons x y))
#<fentry>
#transparent
にすれば
> (fentry 'tcons '(x y) '(cons x y))
(fentry 'tcons '(x y) '(cons x y))
と表示されます
>> (show-env)
'()
#<void>
>> (defun double (x) (+ x x))
#<void>
>> (show-env)
(list (fentry 'double '(x) '(+ x x) 0))
#<void>
>> (double '2)
4
>> (show-env)
(list (fentry 'double '(x) '(+ x x) 1))
#<void>
>> (double '3)
6
>> (show-env)
(list (fentry 'double '(x) '(+ x x) 2))
#<void>
できてますね
数が数えられたらあとは少し見やすくしてやるくらいでいいかな
こんな感じ
(define (reset-env) (set! env '()))
(define (show-env) (pretty-print env))
(define (reset-profile)
(for ((e env))
(set-fentry-count! e 0)))
(define (profile)
(map (λ (e) (list (fentry-name e) (fentry-count e))) env))
(define (show-profile)
(pretty-print (sort (profile) > #:key cadr)))
(define op0s '(reset-env env show-env reset-profile profile show-profile))
(define (op0 op)
(cond ((eq? op 'reset-env) (reset-env))
((eq? op 'env) env)
((eq? op 'show-env) (show-env))
((eq? op 'reset-profile) (reset-profile))
((eq? op 'profile) (profile))
((eq? op 'show-profile) (show-profile))))
(define (jeval e)
(cond
((string? e) e)
(else
(let ((op (car e)))
(cond ((member op op0s) (op0 op))
:
pretty-print
っていうステキな関数があることを知りました
さて動かしてみますと
> (repl)
>> (reset-env)
#<void>
>> (defun len (x) (if (atom x) '0 (+ '1 (len (cdr x)))))
#<void>
>> (len '(a b c))
3
>> (show-profile)
'((len 4))
#<void>
大丈夫