@@ -44,60 +44,57 @@ setMethod("eval_code", signature = c(object = "qenv.error"), function(object, co
4444 if (identical(trimws(code ), " " ) || length(code ) == 0 ) {
4545 return (object )
4646 }
47+ code <- paste(split_code(code ), collapse = " \n " )
48+
49+ object @ .xData <- rlang :: env_clone(object @ .xData , parent = parent.env(object @ .xData ))
4750 parsed_code <- parse(text = code , keep.source = TRUE )
48- object @ .xData <- rlang :: env_clone(object @ .xData , parent = parent.env(.GlobalEnv ))
49- if (length(parsed_code ) == 0 ) {
50- # empty code, or just comments
51- attr(code , " dependency" ) <- extract_dependency(parsed_code ) # in case comment contains @linksto tag
52- object @ code <- c(object @ code , stats :: setNames(list (code ), sample.int(.Machine $ integer.max , size = 1 )))
53- return (object )
54- }
55- code_split <- split_code(paste(code , collapse = " \n " ))
56- for (i in seq_along(code_split )) {
57- current_code <- code_split [[i ]]
58- current_call <- parse(text = current_code , keep.source = TRUE )
59- # Using withCallingHandlers to capture warnings and messages.
60- # Using tryCatch to capture the error and abort further evaluation.
61- x <- withCallingHandlers(
62- tryCatch(
63- {
64- eval(current_call , envir = object @ .xData )
65- if (! identical(parent.env(object @ .xData ), parent.env(.GlobalEnv ))) {
66- # needed to make sure that @.xData is always a sibling of .GlobalEnv
67- # could be changed when any new package is added to search path (through library or require call)
68- parent.env(object @ .xData ) <- parent.env(.GlobalEnv )
69- }
70- NULL
71- },
72- error = function (e ) {
51+
52+ old <- evaluate :: inject_funs(
53+ library = function (... ) {
54+ x <- library(... )
55+ if (! identical(parent.env(object @ .xData ), parent.env(.GlobalEnv ))) {
56+ parent.env(object @ .xData ) <- parent.env(.GlobalEnv )
57+ }
58+ invisible (x )
59+ }
60+ )
61+ out <- evaluate :: evaluate(
62+ code ,
63+ envir = object @ .xData ,
64+ stop_on_error = 1 ,
65+ output_handler = evaluate :: new_output_handler(value = identity )
66+ )
67+ out <- evaluate :: trim_intermediate_plots(out )
68+
69+ evaluate :: inject_funs(old ) # remove library() override
70+
71+ new_code <- list ()
72+ for (this in out ) {
73+ if (inherits(this , " source" )) {
74+ this_code <- gsub(" \n $" , " " , this $ src )
75+ attr(this_code , " dependency" ) <- extract_dependency(parse(text = this_code , keep.source = TRUE ))
76+ new_code <- c(new_code , stats :: setNames(list (this_code ), sample.int(.Machine $ integer.max , size = 1 )))
77+ } else {
78+ last_code <- new_code [[length(new_code )]]
79+ if (inherits(this , " error" )) {
80+ return (
7381 errorCondition(
7482 message = sprintf(
7583 " %s \n when evaluating qenv code:\n %s" ,
76- cli :: ansi_strip(conditionMessage(e )),
77- current_code
84+ cli :: ansi_strip(conditionMessage(this )),
85+ last_code
7886 ),
7987 class = c(" qenv.error" , " try-error" , " simpleError" ),
80- trace = unlist(c(object @ code , list (current_code )))
88+ trace = unlist(c(object @ code , list (new_code )))
8189 )
82- }
83- ),
84- warning = function (w ) {
85- attr(current_code , " warning" ) <<- cli :: ansi_strip(sprintf(" > %s\n " , conditionMessage(w )))
86- invokeRestart(" muffleWarning" )
87- },
88- message = function (m ) {
89- attr(current_code , " message" ) <<- cli :: ansi_strip(sprintf(" > %s" , conditionMessage(m )))
90- invokeRestart(" muffleMessage" )
90+ )
9191 }
92- )
93-
94- if (! is.null(x )) {
95- return (x )
92+ attr(last_code , " outputs" ) <- c(attr(last_code , " outputs" ), list (this ))
93+ new_code [[length(new_code )]] <- last_code
9694 }
97- attr(current_code , " dependency" ) <- extract_dependency(current_call )
98- object @ code <- c(object @ code , stats :: setNames(list (current_code ), sample.int(.Machine $ integer.max , size = 1 )))
9995 }
10096
97+ object @ code <- c(object @ code , new_code )
10198 lockEnvironment(object @ .xData , bindings = TRUE )
10299 object
103100}
0 commit comments