UNPKG

@eagleoutice/flowr-dev

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

215 lines (214 loc) 11 kB
import type { DecodedFunction } from '../../project/sigdb/decode'; /** * What a single argument of a call is used for, as a bitmask. * @see {@link BuiltInFnInfo#sig} */ export declare enum ArgProp { /** the result is this argument, handed back unchanged, like `x` in `identity(x)`; this is what draws the `Returns` edge */ Alias = 1, /** the result is computed from the argument's value, like `x` in `sum(x)` */ Value = 2, /** only the shape is used (length, dimensions, names, other attributes), like `x` in `nrow(x)` */ Shape = 4, /** selects a behavior instead of carrying data, like `na.rm` in `sum(x, na.rm = TRUE)` */ Flag = 8, /** names the resource the call reads or writes, like `file` in `write.csv(x, file)` */ Resource = 16, /** what it refers to may be modified, like `envir` in `assign(x, v, envir = e)` */ Written = 32, /** evaluated whenever the call happens, even if the result goes unused, like `x` in `force(x)` */ Forced = 64, /** quoted or evaluated in another frame, like `expr` in `quote(expr)` */ Nse = 128, /** called as a function, like `FUN` in `lapply(x, FUN)` */ Callee = 256, /** only whether it was supplied matters, as with `missing()` */ Presence = 512, /** * the result is one of this argument's values, like `choices` in `match.arg(arg, choices)`. The bounding * argument of a {@link CallProp.Narrows} call; without one such a call yields a value of its own making. */ Bounds = 1024, /** * only atomic data works here, never a closure, as with `e1` in `e1 > e2`. A bare symbol in such an * argument therefore names a variable even when a function of that name is in scope. */ Atomic = 2048, /** the open handle the call acts on, like `con` in `close(con)` */ Handle = 4096 } /** * What the call as a whole does, as a bitmask. The resource bits ({@link CallProp.File} and its neighbors) * say where the call gets its data from, which is what {@link InputProps} collects. * @see {@link BuiltInFnInfo#props} */ export declare enum CallProp { /** computes a result and nothing else, the positive counterpart of `hasUnknownSideEffects` (excludes {@link ImpureProps}) */ Pure = 1, /** * pure on its own, but it runs code it is handed, so whatever that code does happens too. * The parameter it runs is marked {@link ArgProp.Callee} or {@link ArgProp.Nse}, as with `lapply(x, f)`. */ MayPure = 2, /** may signal an error, like `stop()` (see {@link SigDbInferable}) */ Throws = 4, /** returns invisibly, so the result is not auto-printed */ Invisible = 8, /** dispatches on the class of an argument (S3, S4, or S7), a group generic like `+` on either operand */ Generic = 16, /** a method that is reached by dispatch, like `print.foo` (see {@link SigDbInferable}) */ Method = 32, /** binds, rebinds, or removes names outside of its own frame, like `assign` or `library` */ Scope = 64, /** the result may differ between two identical calls for a reason neither `Random` nor `Ambient` covers (see {@link SigDbInferable}) */ NonDet = 128, /** draws from the random number generator, or sets its state (stated instead of `NonDet`) */ Random = 256, /** depends on ambient state like the clock, the locale, environment variables, or global options (stated instead of `NonDet`) */ Ambient = 512, /** touches the file system */ File = 1024, /** produces a temporary path; on its own this touches no file system, so a call that also does states `File` too */ TempFile = 2048, /** * always reaches the network, like `curl::curl_download`. Calls that only do so for some arguments, like * `read.csv` of a URL, are left to the `network-functions` rule, which decides that per call site. */ Network = 4096, /** runs a system command */ Process = 8192, /** calls native code through the foreign function interface, like `.Call` */ Ffi = 16384, /** produces a language object, like `quote` or `deparse` */ Lang = 32768, /** asks the user, like `readline` or a file chooser */ User = 65536, /** draws on a graphics device */ Graphics = 131072, /** talks to a database */ Database = 262144, /** reads the resource its `Resource` arguments name */ Reads = 524288, /** writes the resource its `Resource` arguments name */ Writes = 1048576, /** may emit to standard output, like `print` or a `cat` without a `file`, and follows a `sink` when one is active */ Prints = 2097152, /** * the result is bounded no matter what flows in: a count, an index, a logical, or one of the values of the * argument marked {@link ArgProp.Bounds}. So nothing an argument carries reaches the result, which is what * lets the input-sources query stop tracing at `length(x)` or `match.arg(arg, choices)`. */ Narrows = 4194304, /** * sets ambient state later calls read back: the working directory, environment variables, options, the * locale, the RNG seed. The counterpart of {@link CallProp.Ambient}; a call doing both states both. */ Configures = 8388608, /** ends what an opener started: a graphics device, a connection, a sink. Narrower than {@link CallProp.Graphics}. */ Closes = 16777216, /** yields the paths it matches at run time rather than one it was handed (`list.files`, `Sys.glob`); empty is an answer */ Glob = 33554432, /** hands back what the program was invoked with, as `commandArgs` and the option parsers built on it do */ CommandLine = 67108864, /** hands back a handle the program is expected to close again, like `file` or `DBI::dbConnect` */ Opens = 134217728 } /** * The {@link CallProp} bits that state an effect beyond computing a result, so no {@link CallProp.Pure} * definition may carry any of them. */ export declare const ImpureProps: number; /** * Which {@link CallProp} bits rule each other out, as `[bit, everything stating it forbids]`. A definition * that carries the left bit must carry none of the right ones; a test checks the {@link DefaultBuiltinConfig} * (and any configured built-ins) against this. Every other pair of bits combines freely. */ export declare const ExclusiveCallProps: readonly (readonly [bit: CallProp, forbidden: CallProps])[]; /** * The {@link CallProp} bits of calls that bring in data of their own. A function that states its props and * carries none of these derives its result from its arguments, which is what {@link BuiltInIndex#without} * looks for. */ export declare const InputProps: number; /** * The {@link CallProp} bits the signature database states itself, so {@link fnInfoFromSignature} can read them * off any package function without anyone writing them down. */ export declare const SigDbInferable: number; /** * The {@link CallProp} bits that say a call takes its data from a file, as {@link CallProp.File} alone also * covers the calls that only write one. */ export declare const FileInputProps: number; /** * The {@link CallProp} bits that carry over from a callee to its caller: what the called function does, the * calling one does too. Purity does not travel this way, which is why it is not in here. */ export declare const PropagatedProps: number; /** a bitfield of {@link ArgProp} */ export type ArgProps = number; /** a bitfield of {@link CallProp} */ export type CallProps = number; /** * The formals of a built-in, in the order they are declared in, each with what its argument is used for. * A `...` entry stands for every argument from the position it appears at, and the entries behind it are matched * by their full name only. */ export type FnSig = [name: string, props: ArgProps][]; /** * Utility functions for {@link FnSig|function signatures}. */ export declare const FnSig: { readonly name: "FnSig"; /** The positional view of a signature; see {@link sigLayout}. */ readonly layout: typeof sigLayout; /** The roles of the argument at a position; see {@link argProp}. */ readonly propAt: typeof argProp; /** The positions carrying any of the given roles; see {@link argsWith}. */ readonly posWith: typeof argsWith; }; /** What a call states about itself, as words rather than as a bit mask, for anything showing it to a reader. */ export declare function callPropWords(props: CallProps | undefined): string[]; /** * Semantics of a built-in that hold no matter which processor handles the call. The remaining facts already * have a home: the exit behavior in `cfg`, whether flowR can fold the call in the `evalHandler` of the * definition, and the fallback for everything unmodelled in `hasUnknownSideEffects`. */ export interface BuiltInFnInfo { /** the parameters and what each of their arguments is used for */ readonly sig?: FnSig; /** bitfield of {@link CallProp} */ readonly props?: CallProps; /** keep the environment on the call vertex, for a later pass to look names up in */ readonly keepEnvironment?: boolean; } /** A {@link FnSig} in the form the call processors use it, see {@link sigLayout}. */ export interface SigLayout { /** the props of each declared parameter, in order */ readonly props: readonly ArgProps[]; /** the position of the `...` parameter, `-1` if there is none */ readonly rest: number; /** every bit some parameter carries, so a call can skip the bits nobody uses */ readonly any: ArgProps; /** the position of the {@link ArgProp.Alias} argument, handed back as the result, `-1` if there is none */ readonly alias: number; } /** * The positional view of a {@link FnSig}, computed on first use and cached per signature object, * so declaring a signature costs nothing until a call actually needs it. */ declare function sigLayout(this: void, sig: FnSig): SigLayout; /** The {@link ArgProp} bits of the argument at `index`, with `...` covering every position from where it appears. */ declare function argProp(this: void, { props, rest }: SigLayout, index: number): ArgProps; /** The positions of the first `count` arguments that carry any of `prop`. */ declare function argsWith(this: void, layout: SigLayout, count: number, prop: ArgProps): number[]; /** the callees that make the calling function itself a generic ({@link CallProp.Generic}) */ export declare const DispatchCallees: ReadonlySet<string>; /** * The part of a {@link BuiltInFnInfo} that the signature database already knows: the parameter names in order * (`...` included) with the ones R always forces, plus the properties listed in {@link SigDbProps}. Everything * else the database records (`higher-order`, `deprecated`, `recursive`, ...) has no counterpart here and is * dropped, and anything it cannot see (purity, resources, what an argument is used for) stays unset. */ export declare function fnInfoFromSignature(fn: DecodedFunction): BuiltInFnInfo; export {};