<commit_before>(define (head-exprs expr)
  (node-match expr
    ((@ds-apply rator rands) (cons rator rands))
    ((@ds-begin head) (list head))
    ((@ds-if test) (list test))
    ((@ds-set expr) (list expr))
    ((@ds-asm actuals) actuals)
    (else '())))

(define (tail-exprs expr)
  (node-match expr
    ((@ds-begin tail) (list tail))
    ((@ds-if true false) (list true false))
    (else '())))

(define simple?
  (let ((non-simple-types (list @ds-apply @ds-if)))
    (lambda (expr)
      (and (not (memq (node-type expr) non-simple-types))
	   (every simple? (head-exprs expr))
	   (every simple? (tail-exprs expr))))))

(define (initial-expr expr)
  (let loop ((heads (head-exprs expr)))
    (cond
     ((null? heads) expr)		; expr is its own initial expression
     ((simple? (car heads))
      (loop (cdr heads)))		; this head-expr is not an initial-expr
     (else
      (initial-expr (car heads))))))	; this head-expr may be an initial-expr

(define (subst-expr expr what with)
  (if (eq? what with)
      expr
      (node-fold ds-child-attrs
		 (lambda (node k)
		   (cond
		    ((eq? node what) with)
		    (else (k node))))
		 expr)))

(define (expr-references* node mode)
  ;; Icky: treats %cps-value and %cps-exp together
  (let walk ((node node))
    (node-match node
      ((@cps-apply rator rands) (apply lset-union eq? (walk rator) (map walk rands)))
      ((@cps-exp-begin head tail) (lset-union eq? (walk head) (walk tail)))
      ((@cps-exp-if test true false) (lset-union eq? (walk test) (walk true) (walk false)))

      ((@cps-lit) '())
      ((@cps-void) '())
      ((@cps-var name) (case mode
			 ((child-captures) '())
			 ((updates) '())
			 ((references) (list name))))
      ((@cps-lambda formals expr expr-references expr-updates)
       (lset-difference eq?
			(case mode
			  ((child-captures) expr-references)
			  ((updates) expr-updates)
			  ((references) expr-references))
			(map @arginfo-name formals)))
      ((@cps-asm actuals) (apply lset-union eq? (map walk actuals)))
      ((@cps-backend) '())
      ((@cps-set name expr) (case mode
			      ((child-captures) '())<commit_msg>Fix bug in capture analysis: mutated, captured variables were sometimes not boxed<commit_after>(define (head-exprs expr)
  (node-match expr
    ((@ds-apply rator rands) (cons rator rands))
    ((@ds-begin head) (list head))
    ((@ds-if test) (list test))
    ((@ds-set expr) (list expr))
    ((@ds-asm actuals) actuals)
    (else '())))

(define (tail-exprs expr)
  (node-match expr
    ((@ds-begin tail) (list tail))
    ((@ds-if true false) (list true false))
    (else '())))

(define simple?
  (let ((non-simple-types (list @ds-apply @ds-if)))
    (lambda (expr)
      (and (not (memq (node-type expr) non-simple-types))
	   (every simple? (head-exprs expr))
	   (every simple? (tail-exprs expr))))))

(define (initial-expr expr)
  (let loop ((heads (head-exprs expr)))
    (cond
     ((null? heads) expr)		; expr is its own initial expression
     ((simple? (car heads))
      (loop (cdr heads)))		; this head-expr is not an initial-expr
     (else
      (initial-expr (car heads))))))	; this head-expr may be an initial-expr

(define (subst-expr expr what with)
  (if (eq? what with)
      expr
      (node-fold ds-child-attrs
		 (lambda (node k)
		   (cond
		    ((eq? node what) with)
		    (else (k node))))
		 expr)))

(define (expr-references* node mode)
  ;; Icky: treats %cps-value and %cps-exp together
  (let walk ((node node))
    (node-match node
      ((@cps-apply rator rands) (apply lset-union eq? (walk rator) (map walk rands)))
      ((@cps-exp-begin head tail) (lset-union eq? (walk head) (walk tail)))
      ((@cps-exp-if test true false) (lset-union eq? (walk test) (walk true) (walk false)))

      ((@cps-lit) '())
      ((@cps-void) '())
      ((@cps-var name) (case mode
			 ((child-captures) (list name))
			 ((updates) '())
			 ((references) (list name))))
      ((@cps-lambda formals expr expr-references expr-updates)
       (lset-difference eq?
			(case mode
			  ((child-captures) expr-references)
			  ((updates) expr-updates)
			  ((references) expr-references))
			(map @arginfo-name formals)))
      ((@cps-asm actuals) (apply lset-union eq? (map walk actuals)))
      ((@cps-backend) '())
      ((@cps-set name expr) (case mode
			      ((child-captures) '())
{'fraction_non_alphanumeric': 0.1778445883441258, 'fraction_numerical': 0.0, 'mean_word_length': 2.892889288928893, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7438774', 'n_tokens_mistral': 1608, 'n_tokens_neox': 1520, 'n_words': 457}