-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinsertReturn.R
104 lines (89 loc) · 2.84 KB
/
insertReturn.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
insertReturn =
# Checks to see if we need to enclose the final expression
# within a call to return()
#
# insertReturn(quote(return(x + 1)) )
# insertReturn(quote(x + 1))
# insertReturn(quote({ x = 2; x + 1} ))
# insertReturn(quote({ x = 2; return(x + 1)} ))
# insertReturn(quote(while(TRUE) { return(x + 1) } ))
# insertReturn(quote(while(TRUE) { x + 1 } ))
# insertReturn(quote(if(x < 10) 20 else 40 ))
# insertReturn(quote(if(x < 10) { x= 3; sqrt(x) } else 40 ))
# insertReturn(quote(if(x < 10) { x= 3; sqrt(x) } else { x = 100; sqrt(x)} ))
#
#XXX Need to handle while, if
function(expr, nested = FALSE, isVoid = FALSE, ...)
UseMethod("insertReturn")
`insertReturn.{` =
function(expr, nested = FALSE, isVoid = FALSE, ...)
{
expr[[length(expr)]] = insertReturn(expr[[length(expr)]], nested)
expr
}
insertReturn.name =
function(expr, nested = FALSE, isVoid = FALSE, ...)
{
substitute(return(x), list(x = expr))
}
`insertReturn.call` =
function(expr, nested = FALSE, isVoid = FALSE, env = NULL, ...)
{
#XXXX rework this strategy
if(!is.null(env) && !is.null(getSApplyType(expr, env)))
return(expr)
if(nested || expr[[1]] != as.name('return')) {
substitute(return(x), list(x = expr))
} else
expr
}
insertReturn.if =
function(expr, nested = FALSE, isVoid = FALSE, ...)
{
expr[[3]] = insertReturn(expr[[3]], nested = TRUE)
if(length(expr) == 4)
expr[[4]] = insertReturn(expr[[4]], nested = TRUE)
expr
}
insertReturn.numeric = insertReturn.logical = insertReturn.character =
insertReturn.integer = `insertReturn.(` = # should check for (return(x+1))
function(expr, nested = FALSE, isVoid = FALSE, ...) {
k = call('return')
k[[2]] = expr
k
}
insertReturn.while =
function(expr, nested = FALSE, isVoid = FALSE, ...)
{
expr[[3]] = insertReturn(expr[[3]], nested = TRUE)
expr
}
`insertReturn.=` = `insertReturn.<-` =
function(expr, nested = FALSE, isVoid = FALSE, ..., value = NULL)
{
substitute(return(x), list(x = expr))
}
`insertReturn.function` =
function(expr, nested = FALSE, isVoid = FALSE, ...)
{
# body(expr) = insertReturn(body(expr))
b = body(expr)
if(class(b) == "{") {
b[[length(b)]] = if(FALSE && isSelect(b[[length(b)]])) #XXX we had no FALSE && here. Why did we want that?
substitute(return(x), list(x = b[[length(b)]]))
else
insertReturn(b[[length(b)]])
} else {
b = if(isSelect(b))
substitute(return(x), list(x = b))
else
insertReturn(b)
}
# Add a return() if the last expression is if() { ... } with no else
# Do we really want to do this?
last = b[[length(b)]]
if(is.call(last) && as.character(last[[1]]) == "if" && length(last) == 3)
b[[ length(b) + 1L ]] = quote(return( ))
body(expr) = b
expr
}