# File src/library/methods/R/languageEl.R # Part of the R package, https://www.R-project.org # # Copyright (C) 1995-2014 The R Core Team # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # A copy of the GNU General Public License is available at # https://www.R-project.org/Licenses/ languageEl <- ## extract an element of a language object, consistently ## for different kinds of objects. ## ## The 1st., etc. elements of a function are the corresponding ## formal arguments, with the default expression if any as value. ## ## The first element of a call is the name or the function object being ## called. The 2nd, 3rd, etc. elements are the 1st, 2nd, etc. arguments expressions. ## Note that the form of the extracted name is different for R and S-Plus. ## When the name (the first element) of a call is replaced, the languageEl replacement ## function coerces a character string to the internal form for each system. ## ## The 1st, 2nd, 3rd elements of an `if' expression are the test, first, and second branch. ## ## The 1st element of a `for' object is the name (symbol) being used in the loop, ## the second is the expression for the range of the loop, the third is the body of the loop. ## ## The first element of a `while' object is the loop test, and the second the body of ## the loop. function(object, which) { data <- as.list(object) if(is.character(which)) data[[which]] else if(typeof(object) == "language") { if(isGrammarSymbol(data[[1L]])) data[[which + 1]] else data[[which]] ## other calls } else data[[which]] } "languageEl<-" <- ## replace an element of a language object, see "languageEl" for meaning. function(object, which, value) { data <- as.list(object) n <- length(data) type <- typeof(object) if(type == "closure") { ev <- environment(object) if(is.character(which)) { if(is.na(match(which, names(data)))) { body <- data[[n]] data <- data[-n] data[[which]] <- value data[[n+1]] <- body } else data[[which]] <- value } else { if(which < 1 || which > n) stop("invalid index for function argument") ## we don't warn if this is used to replace the body (which == n) ## but maybe we should. data[[which]] <- value } object <- as.function(data) environment(object) <- ev object } else if(type == "language") { if(is.character(which)) data[[which]] <- value else if(isGrammarSymbol(data[[1L]])) data[[which+1]] <- value else { if(identical(which, 1) && is.character(value)) value <- as.symbol(value) data[[which]] <- value } as.call(data) } else { object[[which]] <- value object } } isGrammarSymbol <- function(symbol) { if(typeof(symbol) != "symbol") FALSE else switch(as.character(symbol), ## the grammatical constructions "{" =, "if" = , "for"= , "while" = , "repeat" = , "return" = , "next" = , "break" = , "<-" = , "<<-" = TRUE, FALSE) }