Skip to content

Commit

Permalink
Handling namespaces for user-defined transformations
Browse files Browse the repository at this point in the history
At least, I think I am handling it... probably need some more testing. This resolves #9.
  • Loading branch information
mailund committed Feb 27, 2018
1 parent 2609132 commit ca6215d
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 45 deletions.
8 changes: 4 additions & 4 deletions R/loop-transformation.R
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,8 @@ simplify_returns_call <- function(call_expr, info) {
"return" = {
call_expr[[2]] <- simplify_returns(call_args[[1]], info)
if (rlang::is_lang(call_expr[[2]]) && rlang::call_name(call_expr[[2]]) == "return") {
call_expr <- call_expr[[2]]
}
call_expr <- call_expr[[2]]
}
},

# For all other calls we transform the arguments inside a call context.
Expand Down Expand Up @@ -362,8 +362,8 @@ handle_recursive_returns_call <- function(call_expr, info) {
"return" = {
call_expr[[2]] <- handle_recursive_returns(call_args[[1]], info)
if (rlang::is_lang(call_expr[[2]]) && rlang::call_name(call_expr[[2]]) == info$fun_name) {
call_expr <- translate_recursive_call(call_expr[[2]], info)
}
call_expr <- translate_recursive_call(call_expr[[2]], info)
}
},

# For all other calls we just recurse
Expand Down
13 changes: 10 additions & 3 deletions R/user-defined-transformations.R
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,22 @@ user_transform_rec <- function(expr, env = rlang::caller_env()) {
} else {
stopifnot(rlang::is_lang(expr))

fun_name <- rlang::call_name(expr)
if (!exists(fun_name, where = env)) {
# see if we can figure out which function we are dealing with...
fun_name <- as.character(expr[[1]])
if (length(grep("::", fun_name)) > 0) {
# the function name explicitly uses a namespace, so we get the
# actual function like this:
fun <- eval(expr[[1]])
} else if (exists(fun_name, where = env)) {
# otherwise, check if we have the function in scope
fun <- get(fun_name, envir = env)
} else {
error_msg <- glue::glue(
"The function {fun_name} was not found in the provided scope."
)
stop(simpleError(error_msg, call = expr))
}

fun <- get(fun_name, envir = env)
args <- rlang::call_args(expr)
for (i in seq_along(args)) {
expr[[i + 1]] <- user_transform(args[[i]], env)
Expand Down
40 changes: 2 additions & 38 deletions experiments.R
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,7 @@ llength <- function(llist, acc = 0) {
CONS(car, cdr) -> llength(cdr, acc + 1))
}

llength_tr <- function (llist, acc = 0) {
.tailr_env <- rlang::get_env()
callCC(function(escape) {
repeat {
if (!rlang::is_null(..match_env <- test_pattern(llist,
NIL)))
with(..match_env, escape(acc))

else if (!rlang::is_null(..match_env <-
test_pattern(llist, CONS(car, cdr))))
with(..match_env, {
.tailr_env$.tailr_llist <- cdr
.tailr_env$.tailr_acc <- acc + 1
.tailr_env$llist <- .tailr_env$.tailr_llist
.tailr_env$acc <- .tailr_env$.tailr_acc
})
}
})
}
llength_tr <- loop_transform(llength)

make_llist <- function(n) {
l <- NIL
Expand All @@ -91,25 +73,7 @@ make_llist <- function(n) {
}
l
}
test_llist <- make_llist(100)
test_llist <- make_llist(10)
microbenchmark::microbenchmark(llength(test_llist),
llength_tr(test_llist))




arguments <- list(n = quote(n - 1), acc = quote(n * acc))
vars <- names(arguments)
tmp_assignments <- vector("list", length = length(arguments))
final_assignments <- vector("list", length = length(arguments))
for (i in seq_along(arguments)) {
tmp_var <- parse(text = paste(".tailr_env$.tailr_", vars[i], sep = ""))[[1]]
local_var <- parse(text = paste(".tailr_env$", vars[i], sep = ""))[[1]]
tmp_assignments[[i]] <- rlang::expr(!!tmp_var <- !!arguments[[i]])
final_assignments[[i]] <- rlang::expr(!!local_var <- !!tmp_var)
}
as.call(c(
rlang::sym("{"),
tmp_assignments,
final_assignments
))

0 comments on commit ca6215d

Please sign in to comment.