Capabilities
Qualitative overview of flowR's support for R.
Please keep in mind that the capabilities are a qualitative measure.
Statements like "flowR can fully handle 50/80 capabilities" are discouraged as some capabilities have a vastly different granularity (and different levels of real-world presence).
Missing something? Suggest a capability!
Nothing matches that.
Names and Identifiers
Recognizing the names an R program uses and resolving them to definitions.
20 fully8 partially2 notExpressions
Everything comprising the structure of an R program
CallsIndex AccessOperatorsControl-FlowFunction DefinitionsImportant Built-InsLiteral Values
52 fully20 partially1 notNon-Standard Evaluations/Semantics
Specific support for R's NSE/Reflection semantics
1 fully5 partially1 notObject-Oriented Programming
R's object systems and what their classes and dispatch tell us about a program.
S3S4Class-Based Dependency Attribution
2 fully9 partially1 notR File Structure
The lexical shape of a source file, down to its line endings and encoding.
5 fully4 partially0 notProject
Support for non-R/project files (dependencies, etc.).
Package MetadataDependency ManagersStartup and DiscoveryPre-Processors/external Tooling
9 fully4 partially0 notSystem, I/O, FFI, and Other Files
Everything a program reaches for beyond its own code, from files it reads to calls it makes out of R.
0 fully9 partially0 notTypes
What a value is, how we infer it from the code, and the coercions R applies between types.
0 fully1 partially3 notNames and Identifiers
20 fully8 partially2 not
Recognizing the names an R program uses and resolving them to definitions.
Consider the following R code:
"f" <- function(x) { get("x") }
`y x` <- 2
print(`y x` + f(3))Identifiers of interest are:
- The symbols
x(Normal),f(Quoted), and`y x`(Escaped). - The function calls
<-,function,{,get,+, andprint(Calls, all given with Normal). Especially{is identified as a Grouping of the Function Definitions' body. - The quoted name created by a function call
get(Created).
Besides the parameter x, which is resolved in its Lexicographic Scope, the other identifiers are resolved in the Global Scope.
flowchart LR
10["`**function** (L. 1)
*RFunctionDefinition*`"]
subgraph "flow-10" ["function(x) #123; get(#34;x#34;) #125; (L. 1)"]
1["`**x** (L. 1)
*RSymbol*`"]
8-get-name(["`**#34;x#34;** (L. 1)
*RSymbol*`"])
8[["`base#58;#58;**get** (L. 1)
*RFunctionCall*`"]]
built-in:get["`Built-In:
get`"]
style built-in:get stroke:gray,fill:gray,stroke-width:2px,opacity:.8;
9[["`base#58;#58;**#123;**
*RExpressionList*`"]]
built-in:_["`Built-In:
#123;`"]
style built-in:_ stroke:gray,fill:gray,stroke-width:2px,opacity:.8;
end
0["`**#34;f#34;** (L. 1)
*RString*`"]
11[["`base#58;#58;**#60;#45;** (L. 1)
*RBinaryOp*`"]]
built-in:_-["`Built-In:
#60;#45;`"]
style built-in:_- stroke:gray,fill:gray,stroke-width:2px,opacity:.8;
13{{"`**2** (L. 2)
*RNumber*`"}}
12["`**#96;y x#96;** (L. 2)
*RSymbol*`"]
14[["`base#58;#58;**#60;#45;** (L. 2)
*RBinaryOp*`"]]
16(["`**#96;y x#96;** (L. 3)
*RSymbol*`"])
18{{"`**3** (L. 3)
*RNumber*`"}}
20[["`**f** (L. 3)
*RFunctionCall*`"]]
21[["`base#58;#58;**#43;** (L. 3)
*RBinaryOp*`"]]
built-in:_["`Built-In:
#43;`"]
style built-in:_ stroke:gray,fill:gray,stroke-width:2px,opacity:.8;
23[["`base#58;#58;**print** (L. 3)
*RFunctionCall*`"]]
built-in:print["`Built-In:
print`"]
style built-in:print stroke:gray,fill:gray,stroke-width:2px,opacity:.8;
1 -->|"def-by-on-call"| 18
8-get-name -->|"reads"| 1
8 -->|"reads, returns, arg"| 8-get-name
8 -.->|"reads, calls"| built-in:get
linkStyle 3 stroke:gray;
9 -->|"returns, arg"| 8
9 -.->|"reads, calls"| built-in:_
linkStyle 5 stroke:gray;
10 -.-|function| flow-10
0 -->|"defined-by, flow"| 11
0 -->|"defined-by"| 10
11 -->|"reads, arg"| 10
11 -->|"returns, arg"| 0
11 -.->|"reads, calls"| built-in:_-
linkStyle 11 stroke:gray;
12 -->|"defined-by, flow"| 14
12 -->|"defined-by"| 13
14 -->|"reads, arg"| 13
14 -->|"returns, arg"| 12
14 -.->|"reads, calls"| built-in:_-
linkStyle 16 stroke:gray;
16 -->|"reads"| 12
18 -->|"def-on-call"| 1
20 -->|"reads, arg"| 18
20 -->|"reads"| 0
20 -->|"returns"| 8
20 -->|"calls"| 10
21 -->|"reads, arg"| 16
21 -->|"reads, arg"| 20
21 -.->|"reads, calls"| built-in:_
linkStyle 25 stroke:gray;
23 -->|"reads, returns, arg"| 21
23 -.->|"reads, calls"| built-in:print
linkStyle 27 stroke:gray;R Code of the (simplified) Dataflow Graph
The analysis ran (including parse and normalize, using the tree-sitter engine) within the generation environment. No signature database is mounted for these generated graphs, so library() calls attach no package exports; base-R names are still qualified via the generated base-package store (e.g. acf as stats::acf). We encountered unknown side effects (with ids: 23 (linked)) during the analysis.
"f" <- function(x) { get("x") }
`y x` <- 2
print(`y x` + f(3))- #Form
5 children500
Recognize symbol uses like
a,plot, ... (i.e., "normal variables or function calls").Recognize
"a",'plot', ... R lets a name be quoted so it may hold spaces and the like, but only where it is defined; reaching it as a variable needsgetor backticks.Recognize
`a`,`plot`, ...- #Created
Recognize functions that treat a string argument as the identifier it names, such as
get,get0,mget,exists,match.fun, andassign. A name only known at runtime (get(Sys.getenv("V"))) names no identifier we could link. - #Resolved Name
Recognize a name resolved to a constant string and follow it like a written-out one. Covers literals, variables, and
paste0/paste/file.pathfolded over constants.
- #Resolution
25 children1582
- #Global Scope
For example, tracking a big table of current identifier bindings
- #Lexicographic Scope
For example, support function definition scopes
- #Closures
Two closures from the same factory keep independent state in R. A
<<-in one is over-approximated as reaching the other. - #Closure Capture
Handle ordinary function-factory capture. A closure sees later writes to its enclosing environment, including from a sibling closure.
- #Dynamic Environment Resolution
For example, using
new.envand friends. Coversnew.env,assign/get/localwithenvir=,e$x,attach,with, and env-variable aliasing.8 children440
- #Environment in Control Flow
Track environment assignments and reads across branches and loop bodies, a key built at run time such as
paste0("k", i)included. - #Environment Parent
Specifying a parent for a newly-created environment from a dynamic or unknown expression (
new.env(parent = f())). Such a parent falls back to the default (parent.frame()) instead of resolving. - #Environment Parent (Tracked)
Specifying a parent for a newly-created environment from a tracked environment variable or a constant (
new.env(parent = e),new.env(parent = emptyenv())). - #Environment Alias
Aliasing a tracked environment variable (
alias <- e). An assign to the original variable made AFTER the alias is not reflected through the alias. - #Environment Alias Read
Reading through an aliased tracked environment variable (
alias <- e). Every assign made up to the alias is visible through it. - #With
Evaluating an expression inside a named environment with
with(data, expr). Reads of names the tracked env defines resolve, including through a computeddataargument or a nested call. - #Parent Frame
Reading via
parent.frame()$name, and a write escaping througheval.parent(quote(name <- value)). Works only one call away; storing the frame first drops the binding. - #Dynamic Variable Removal
Support for
rm(list=..., envir=sys.frame(N))removing variables from a specific call frame. Currently handles negative and zero offsets from within depth-1 functions.
- #Environment Sharing
Handling side-effects through environments, which act as reference types and are not copied when modified. A write through a parameter is kept as an unknown side effect of the call; see Environment Alias and Side-Effects in Function Call.
Separating the resolution for functions and symbols.
Handling R's search path. Attached packages sit below
.GlobalEnv, so a global binding shadows an export.library(dplyr) filter <- function(...) "mine" filter(1)Programmatically inspecting or mutating the search path with
search(),searchpaths(), or detaching by position. None of this is modelled;search()reads as an unknown call.Handling R's namespaces (Advanced R). The imports environment a package carries for itself is not modelled.
Resolving calls with
::to their origin. Depends on what the signature database knows; an unresolved name is left unresolved rather than reported.- #Accessing Internal Names
Similar to
::but for internal names. Whether the name was genuinely internal rather than exported is not checked (see Namespace Exports)."C_cor" %in% getNamespaceExports("stats") stats:::C_cor$name - #Namespace Exports
Know which names a package's namespace declares exported versus keeps internal. The
namespace-accessrule checks a::/:::choice against what the signature database records, which omits most internal names to stay small. - #Library Loading
Resolve libraries identified with
library,require,attachNamespace, ... and attach them to the search path. A script binding still shadows an export.library(stats) require(utils) attachNamespace("tools") - #Library Unloading
Undo an attach with
detach,unloadNamespace, ... Neither is modelled, so a name resolved afterdetachstill resolves through it. Manually changing scopes with a plain
localblock. It gets a scope of its own, and a<<-from within reaches out.x <- 1 local({ x <- 2 x }) x- #Local with Explicit Environment
Send
local's body to a specific environment.new.env()andglobalenv()work; inside a function that already binds the name, the write lands in that frame instead. Support for
Recallfact <- function(n) if(n <= 1) 1 else n * Recall(n - 1) fact(5)
Expressions
52 fully20 partially1 not
Everything comprising the structure of an R program
15 children1140
Recognize groups done with
(,{, ... (more precisely, their default mapping to the primitive implementations).Recognize and resolve calls like
f(x),foo::bar(x, y), ...7 children520
- #Unnamed Arguments
Recognize and resolve calls like
f(3),foo::bar(3, c(1,2)), ... Essentially a special form of an unnamed argument as in
foo::bar(3, ,42), ...Recognize and resolve calls like
f(x = 3),foo::bar(x = 3, y = 4), ...- #String Arguments
Recognize and resolve calls like
f('x' = 3),foo::bar('x' = 3, "y" = 4), ... - #Resolve Arguments
Correctly bind arguments (including
pmatch). A formal behind...matches only exactly, and an ambiguous prefix binds nothing. Handle side-effects of arguments (e.g.,
f(x <- 3),f(x = y <- 3), ...). Whether the argument is ever forced is not modelled, sof <- function(a) 1; f(x <- 3)still believesxis 3.- #Side-Effects in Function Call
Handle side-effects of function calls (e.g.,
setXTo(3), ...) achieved via super assignment. A<<-reaches the caller through several call levels; a write through a shared environment is missed.
Recognize and resolve recursive calls like
f(3)inside the definition off, ...- #Anonymous Calls
Recognize and resolve calls like
(function(x) x)(3),factory(0)(), ... Recognize and resolve calls like
x + y,x %>% f(y), ...Handle cases like
print <- function(x) x,`for` <- function(a,b,c) a, ... A redefined name wins wherever the built-in would have been used, with scope and order respected. Only::/:::are exempt.Support functions like
setwdwhich have an impact on the subsequent program. Only the working directory is interpreted; other ambient state is an unknown side effect.- #Working Directory
Track the effective working directory across
setwd, control-flow- and location-sensitive. Interprocedural, sourced, and loop cases are treated as unbounded.
- #Index Access
The bracket, double-bracket, dollar, and slot forms for picking an element out of a container, with names, empty positions, and multiple indices.
7 children700
Detect calls like
x[i],x[i, ,b],x[3][y], ... This does not include the real separation of cells, which is handled extra.Detect calls like
x[[i]],x[[i, b]], ... Similar to single bracket.Detect calls like
x$y,x$"y",x$y$z, ... On a list,$matches the name partially, sol$alreaches an element namedalpha.Detect calls like
x@y,x@y@z, ...Detect calls like
x[i = 3],x[[i=]], ...Detect calls like
x[],x[2,,42], ...Detect calls like
x[i > 3],x[c(1,3)], ...
- #Operators
R's unary, binary, and special operators, the model formula, and every way a name can be bound to a value.
15 children1131
Recognize and resolve calls like
+3,-3, ...- #Binary Operator
Recognize and resolve calls like
3 + 4,3 * 4, ...13 children931
- #Special Operator
Recognize and resolve calls like
3 %in% 4,3 %*% 4, ... Recognize and resolve calls like
y ~ x,y ~ x + z, ... The operands of~are non-standard evaluation, so a barey ~ xreads neither name.11 children821
Handle
x <- 3,x$y <- 3, ...- #Local Right Assignment
signature tests
"1 -> x -> y", "x <- 1 -> y", local define with -> in function, read after
Handle
3 -> x,3 -> x$y, ... - #Local Equal Assignment
Handle
x = 3,x$y = 3, ... At the start of an expression=binds a name, while inside a call it names an argument (f(a = 3)). - #Local Table Assignment
Handle
x[,a:=3,], ... - #Super Left Assignment
Handle
x <<- 42,x$y <<- 42, ... - #Super Right Assignment
signature tests
global define with ->> in function, read after, Manual Max Function
Handle
42 ->> x,42 ->> x$y, ... Handle
x <- 3returning3, e.g., inx <- y <- 3x <- y <- 3 print(x <- 4)- #Assignment Functions
Handle
assign(x, 3),delayedAssign(x, 3), ... What a delayed assignment does when forced is not modelled.assign("x", 3) delayedAssign("y", x * 2) y Handle
x[1:3] <- 3,x$y[1:3] <- 3, ...Handle
x[i] <- 3,x$y <- 3, ... as`[<-`(x, 3), ... A named argument in such a call (g(v, k = 2) <- 3) leaves its argument edge dangling.- #Locked Bindings
Handle
lockBinding(x, 3), ...lockBindingis not recognized as a built-in, so the assignment it should have rejected is analyzed as an ordinary redefinition.
Conditionals, the three loop forms, their jumps, and how an error leaves a computation.
9 children810
Handle
if (x) y else z,if (x) y, ...Handle
for (i in 1:3) print(i), ...- #while loop
signature tests
a loop body is evaluated, Next in while, Endless while loop with variables
Handle
while (x) b, ... Handle
repeat {b; if (x) break}, ...Handle
break(includingbreak()) ...Handle
next(includingnext()) ...Handle
switch(3, "a", "b", "c"), ...Handle
return(3), ... in function definitions- #Exceptions and Errors
signature tests
Call edges for error, Call edges for error with fn, Call edges with may built-in
Handle
try,stop, ... A path where a call throws before a write is not kept open, sotryCatch({ risky(); x <- 2 }, ...)losesx.
- #Function Definitions
Parameters and their defaults,
..., promises, and the value a function hands back.7 children610
- #Normal
Handle
function() 3, ... - #Formals
4 children310
Handle
function(x) x, ...Handle
function(x = 3) x, ...Handle
function(...) 3, ...- #Promises
Handle
function(x = y) { y <- 3; x }, ... We do not model when a promise is forced, nor the writes forcing it performs.
Handle the return of
function() 3, ...Support
\(x) x, ...sapply(1:3, \(x) x^2)
- #Important Built-Ins
The base-R functions we give a meaning of their own rather than treating as opaque calls, the ones that compute on the language included.
13 children2110
Handle
&&,||, ...Handle the native pipe
|>. The left-hand side becomes the first argument or fills the_placeholder.Handle the experimental pipe-bind
=>, which R only enables under_R_USE_PIPEBIND_. Off by default; needsengine.r-shell.pipeBind. Tree-sitter's grammar has no production for it at all.Handle
:,seq, ... by gathering value information using abstract interpretation.seq,seq_len,seq_along, andrepare not folded even for literal arguments.Handle
.Internal,.Primitive, ... The call is kept and its arguments read, but the primitive a.Primitive("sum")names is not resolved to the built-in of that name.Handle
options,getOption, ... Option values are not tracked, sogetOption("digits")does not reach a precedingoptions(digits = 3).Handle
help,?, ...?and??are recognized, but their topic is read as an ordinary variable where R only looks it up, andhelp/help.searchare not known at all.?sum help("sum")6 children060
- #Get Function Structure
Handle
body,formals,args,environmentto access the respective parts of a function. What comes back is opaque, and reading onlyformals(f)keeps all off's body in a slice. - #Modify Function Structure
Handle
body<-,formals<-,environment<-to modify the respective parts of a function. The function is redefined, so a later call reaches the new part as well as the original one. Handle
quote,substitute,bquote, ... A quoted argument is non-standard evaluation;substitutedoes not reach the caller's expression.- #Evaluation
Handle
eval,evalq,eval.parent, ...eval(expr, envir)runs elsewhere, so we mark it an unknown side effect. - #String Templates
Handle
glue::glue("{x}"),cli::cli_alert_info("{.val {x}}"),stringr::str_glue, ... A template aimed at another scope (.envir,.con,glue_data) becomes an unknown side effect. Handle
parse,deparse, ...deparseis not modelled beyond reading its argument.
- #Literal Values
7 children700
Recognize numbers like
3,3.14, the integer3L, hexadecimals such as0xFFand0x1p3, as well as the typed missingsNA_integer_/NA_real_, ...1 child100
- #Complex
Recognize the imaginary literals
1i,4.1i,1e-2i, ... The value survives arithmetic and is told apart from1Land a plain1.
Recognize strings like
"a",'b', ...1 child100
Recognize raw strings like
r"(a)", ...
Recognize the logicals
TRUEandFALSE, ... Their short formsTandFare ordinary bindings and can be reassigned, whileTRUEandFALSEare reserved.- #NULL
Recognize
NULL - #Inf and NaN
Recognize
InfandNaN
Non-Standard Evaluations/Semantics
1 fully5 partially1 not
Specific support for R's NSE/Reflection semantics
- #Data Masking
Handle
subset(d, col > 1), dplyr verbs,ggplot2::aes, data.table:=, ... Which columns exist is unknown to us, so a column shadowing a variable still resolves to the variable.d <- data.frame(x = 1:3) threshold <- 2 subset(d, x > threshold) - #Recycling
Handle recycling of vectors as explained in Advanced R. We do not support recycling.
- #Vectorized Operator or Functions
Handle vectorized operations as explained in Advanced R. Comparisons, the reducing functions, and
ifelsewiden to the unknown value.x <- 1:5 x * 2 ifelse(x > 2, "big", "small") - #Hooks
Handle hooks like
userhooksandon.exit.setHookis not modelled.f <- function() { on.exit(print("bye")) 1 } f() Handle the precedence of operators as explained in the Documentation. We handle the precedence of operators (implicitly with the parser).
- #Attributes
2 children020
- #User-Defined
Handle attributes like
attr,attributes, ... Which attributes an object carries is not part of the value we track. Handle built-in attributes like
dim, ...dim<-,names<-,class<-track shape on a data frame; elsewhere the attribute values are not tracked.
Object-Oriented Programming
2 fully9 partially1 not
R's object systems and what their classes and dispatch tell us about a program.
Classes and methods built on the
classattribute andUseMethoddispatch.3 children120
- #Class Construction
Give an object its class with
structure(..., class =),class<-, oroldClass<-. The class a literal names is tracked and reaches the dispatch that follows it. Route a generic call to the method that runs.
UseMethodlinks to everygeneric.classin scope (heavily over-approximating).Walk the class vector with
NextMethod. It reaches the generic's methods, the one it stands in included, rather than only the next class in the vector.
- #S4
Formal classes and methods declared with
setClass,setGeneric, andsetMethod.3 children111
- #Class Construction
Declare a class with
setClassand build one withnew. Thenewcall is linked to thesetClassthat declared the class, and a slot is read through@like any other access. Route a generic call to the method
setMethodregistered. The generic reaches its methods through the chain they register in, but the signature does not narrow which of them runs.Reach a parent method with
callNextMethod, and inherit throughcontains.callNextMethodis left unresolved, so nothing links it to the method it would call.
- #RC/R5
Reference classes made with
setRefClass, whose objects are mutable.$new()and$method()on an instance are unknown side effects; no call links to the body it runs. - #R6
Handle R6 classes and methods as one unit. We do not support typing, inheritance, private/active bindings, or handling objects fully "as units."
- #R7/S7
Handle R7 classes and methods as one unit, dispatch and inheritance included. Typing is not supported, nor are objects handled fully "as units."
- #Class-Based Dependency Attribution
Attribute the use of a class to the package that owns it, so a class use implies a dependency for library detection and version guessing.
2 children020
R File Structure
5 fully4 partially0 not
The lexical shape of a source file, down to its line endings and encoding.
Recognize comments like
# this is a comment, including a shebang line, ...Recognize
#line n "file"as its own node (r-shell only). It is parsed but never retargets a location; tree-sitter reads it as a comment.- #Semicolons
Recognize and resolve semicolons like
a; b; c, ... - #Newlines
Recognize and resolve newlines like
a\nb\nc; a newline ends an expression unless it is still incomplete. A trailing operator or an unclosed bracket continues on the next line. - #Line Endings
Recognize
\n(Unix),\r\n(Windows), and a lone\r(classic Mac). Normalized at the r-bridge boundary, with both engines. - #Source Encoding
Recognize non-ASCII source, i.e., UTF-8 in string literals, in comments, and in identifiers (plain as well as backtick-escaped). Such names bind and resolve like any other, with both engines.
Recognize a UTF-8 byte-order mark at the start of a file. The tree-sitter engine reads past it, the r-shell engine rejects the same input as unparsable.
- #Syntax Errors
signature tests
unbalanced brace, missing closing parenthesis, valid code has no syntax errors
Handle source that does not parse. The
syntactically-validrule locates the region and offers a fix; the strict parser rejects the file, tree-sitter's lax mode (off by default) drops the region. - #Reserved Words
Reject a syntactic keyword like
`if`or`function`where R's grammar requires an expression. The r-shell engine rejectsif <- 5; tree-sitter's grammar parses it as an ordinary assignment.
Project
9 fully4 partially0 not
Support for non-R/project files (dependencies, etc.).
- #Package Metadata
The files that describe the package itself, what it needs, and what it offers.
5 children410
Read a package's
DESCRIPTION. Its DCF records give the package name, version, R version, dependency fields, andCollateorder.- #NAMESPACE
Read a package's
NAMESPACE. Acts onimport/importFrom,importClassesFrom/importMethodsFromfor S4, andexport/S3method. - #Documentation (`.Rd`)
Read the
.Rdpages underman/, their macros, and the indices beside them. A documented name is tied back to the page that documents it. Read a package's
NEWS/NEWS.md. We parse the versions it announces and what each changed, which is what a version guess is checked against.- #Package Data (`sysdata.rda`)
Read the
R/sysdata.rdaa package keeps its internal data in, and thedata/files it exports. What those bindings hold is not reconstructed.
- #Dependency Managers
The lockfiles and manifests a version manager pins a project's packages with.
5 children410
- #renv
Read the configuration of renv, the most widespread R project-library manager. The library it points at is neither installed nor restored.
- #packrat
Read the configuration of packrat, the predecessor of renv. The
packrat/liblibrary beside it is not loaded. - #rv
Read the configuration of rv, a declarative project manager in the style of cargo. Parses
rproject.tomland the resolvedrv.lock. - #uvr
Read the configuration of uvr, an R project manager modelled on uv. Parses
uvr.tomland theuvr.lockbeside it. - #Installed Library
Read the package library a project installs into (
renv/library,packrat/lib, or the platform library). Their code is not read.
- #Startup and Discovery
What runs before a script does and what counts as part of the project at all.
2 children110
- #Startup Files
Read the files R runs or reads before a script (
.Rprofile,Rprofile.site,.Renviron,Renviron.site). Variables set by an environment file are not interpreted. - #Ignore Files
Read the
.gitignoreand.Rbuildignorethat say which files are not part of the project. Follows gitignore globs and the regular expressionsR CMD builduses.
- #Pre-Processors/external Tooling
The tooling around R code rather than the R in it, such as roxygen2 blocks and woven documents.
1 child010
- #roxygen2
Handle the roxygen2 blocks that precede a definition. What a tag states does not reach name resolution, so an
@importFromleaves the name below it unqualified.
System, I/O, FFI, and Other Files
0 fully9 partially0 not
Everything a program reaches for beyond its own code, from files it reads to calls it makes out of R.
Handle
source,sys.source, ... We are currently working on supporting the inclusion of external files. Currently we can handlesource.source("helpers.R") sys.source("setup.R", envir = environment())- #Handling Binary Files
Handle files dumped with, e.g.,
save, ... The values behind aloaded name are not reconstructed. - #I/O
Handle
read.csv,write.csv, ... What a file contains does not enter the analysis. - #Foreign Function Interface
Handle
.C,.Call,.External,.Fortran, ... The call carries an unknown side effect; the foreign code behind it is not analyzed. Handle
system,system.*, ... An injectable command built from user input is flagged by theproblematic-inputsandunescaped-argumentsrules.- #R-Markdown files
Support R-Markdown files as R sources. Code chunks are extracted; inline
r exprand theparamsobject of the YAML front matter are not. - #Jupyter Notebook
Support Jupyter Notebooks as R sources. Cells are read in document order, not execution order, and the kernel is not checked.
- #Quarto
Support Quarto files as R sources. Code chunks are extracted; inline
r exprand theparamsobject of the YAML front matter are not. Support for Sweave files as R sources. Code chunks are extracted,
\Sexpr{}inline expressions are not.
Types
0 fully1 partially3 not
What a value is, how we infer it from the code, and the coercions R applies between types.
- #Primitive
Recognize and resolve primitive types like
numeric,character, ...typeof,class, andmodeare not evaluated and resolve to the unknown top value. - #Non-Primitive
Recognize and resolve non-primitive/composite types. The type of a list, a data frame, or any other composite is not tracked, so
class(list(1, 2))resolves to the unknown top value. - #Inference
Infer types from the code. A type predicate never narrows a branch, so
if(is.numeric(1)) y <- 1 else y <- "a"still leavesyas both alternatives. - #Coercion
Handle coercion of types. A vector is not unified:
c(1, "a")keeps a number beside a string, and theas.*converters are not evaluated.