@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
215 lines (214 loc) • 11 kB
TypeScript
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 {};