@@ -23,17 +23,9 @@ pre_visit <- function(pd_nested, funs) {
23
23
if (length(funs ) == 0 ) {
24
24
return (pd_nested )
25
25
}
26
- pd_nested <- visit_one(pd_nested , funs )
27
26
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 )
37
29
}
38
30
39
31
# ' @rdname visit
@@ -65,16 +57,8 @@ post_visit <- function(pd_nested, funs) {
65
57
return (pd_nested )
66
58
}
67
59
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 )
78
62
}
79
63
80
64
# ' @rdname visit
@@ -99,19 +83,33 @@ post_visit_one <- function(pd_nested, fun) {
99
83
100
84
# ' Transform a flat parse table with a list of transformers
101
85
# '
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
+ # '
104
102
# ' @param pd_flat A flat parse table.
105
- # ' @param funs A list of transformer functions.
103
+ # ' @param funs A named list of transformer functions.
106
104
# ' @family visitors
107
105
# ' @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 )
115
113
}
116
114
117
115
# ' Propagate context to terminals
0 commit comments