@@ -23,17 +23,9 @@ pre_visit <- function(pd_nested, funs) {
2323 if (length(funs ) == 0L ) {
2424 return (pd_nested )
2525 }
26- pd_nested <- visit_one(pd_nested , funs )
2726
28- children <- pd_nested $ child
29- for (i in seq_along(children )) {
30- child <- children [[i ]]
31- if (! is.null(child )) {
32- children [[i ]] <- pre_visit(child , funs )
33- }
34- }
35- pd_nested $ child <- children
36- pd_nested
27+ fun <- make_visit_one(funs )
28+ pre_visit_one(pd_nested , fun )
3729}
3830
3931# ' @rdname visit
@@ -65,16 +57,8 @@ post_visit <- function(pd_nested, funs) {
6557 return (pd_nested )
6658 }
6759
68- children <- pd_nested $ child
69- for (i in seq_along(children )) {
70- child <- children [[i ]]
71- if (! is.null(child )) {
72- children [[i ]] <- post_visit(child , funs )
73- }
74- }
75- pd_nested $ child <- children
76-
77- visit_one(pd_nested , funs )
60+ fun <- make_visit_one(funs )
61+ post_visit_one(pd_nested , fun )
7862}
7963
8064# ' @rdname visit
@@ -99,19 +83,33 @@ post_visit_one <- function(pd_nested, fun) {
9983
10084# ' Transform a flat parse table with a list of transformers
10185# '
102- # ' Uses [Reduce()] to apply each function of `funs` sequentially to
103- # ' `pd_flat`.
86+ # ' Creates a single transformer function from a list of transformer functions.
87+ # '
88+ # ' @details
89+ # ' For an input of the form `list(f1 = f1, f2 = f2)`, creates a function
90+ # '
91+ # ' ```r
92+ # ' function(pd_flat) {
93+ # ' pd_flat <- f1(pd_flat)
94+ # ' pd_flat <- f2(pd_flat)
95+ # ' pd_flat
96+ # ' }
97+ # ' ```
98+ # '
99+ # ' The function's environment is constructed from `rlang::as_environment(funs)`.
100+ # ' This makes function sequences called by visitors interpretable in profiling.
101+ # '
104102# ' @param pd_flat A flat parse table.
105- # ' @param funs A list of transformer functions.
103+ # ' @param funs A named list of transformer functions.
106104# ' @family visitors
107105# ' @keywords internal
108- visit_one <- function (pd_flat , funs ) {
109- stopifnot( ! is.null (names(funs )))
110- stopifnot(all(names( funs ) != " " ))
111- for ( f in funs ) {
112- pd_flat <- f( pd_flat )
113- }
114- pd_flat
106+ make_visit_one <- function (funs ) {
107+ calls <- map( rlang :: syms (names(funs )), ~ rlang :: expr( pd_flat <- ( !! .x )( pd_flat )))
108+ all_calls <- c( calls , rlang :: expr( pd_flat ))
109+ body <- rlang :: call2( " { " , !!! all_calls )
110+
111+ env <- rlang :: as_environment( funs , rlang :: base_env())
112+ rlang :: new_function( rlang :: pairlist2( pd_flat = ), body , env )
115113}
116114
117115# ' Propagate context to terminals
0 commit comments