Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
136f0c8
refactor(env): remove unused working dir ref
MaxAtoms Nov 17, 2025
8737bb5
feat(analyzer): add environment context
MaxAtoms Nov 17, 2025
880fcb2
feat(analyzer): add built-in env
MaxAtoms Nov 17, 2025
f5c30e5
feat(dataflow): use built-in env from context
MaxAtoms Nov 18, 2025
b12af76
Merge remote-tracking branch 'origin/main' into 2027-env-into-ctx
MaxAtoms Nov 18, 2025
d133410
refactor(dataflow): update documentation
MaxAtoms Nov 19, 2025
d04f153
feat(analyzer): add read-only env context
MaxAtoms Nov 20, 2025
cf9f6ef
feat(analyzer): add getters for child envs
MaxAtoms Nov 20, 2025
cc708bb
Merge remote-tracking branch 'origin/main' into 2027-env-into-ctx
MaxAtoms Nov 20, 2025
02a4fbe
Merge branch 'main' into 2027-env-into-ctx
EagleoutIce Nov 24, 2025
8258d47
docs(analyzer): add env ctx to analyzer wiki
MaxAtoms Nov 24, 2025
fb201de
feat-fix(analyzer): create empty built-in env only once
MaxAtoms Nov 24, 2025
4a6e13a
wip(environment): always use built-in env from analyzer
MaxAtoms Nov 24, 2025
4dc16d5
feat(analyzer): provide getter for empty built-in env
MaxAtoms Nov 24, 2025
b36e1ff
wip(environment): fix access to env in static slicer
MaxAtoms Nov 24, 2025
8d85e5d
wip(environment): pass down env
MaxAtoms Nov 24, 2025
74b4e6f
wip(environment): remove env from dataflow graph
MaxAtoms Nov 25, 2025
f4dbf8c
wip(environment): fix references to clean env
MaxAtoms Nov 25, 2025
9838800
fixup! wip(environment): fix references to clean env
MaxAtoms Nov 25, 2025
7d5306c
wip(environment): clean-up
MaxAtoms Nov 25, 2025
b0a6841
Merge remote-tracking branch 'origin/main' into 2027-env-into-ctx
MaxAtoms Nov 25, 2025
f62e4cd
refactor: fix method order
MaxAtoms Nov 25, 2025
b0dd2a7
tests-fix: remove tmp describe.only
MaxAtoms Nov 25, 2025
640a931
feat(analyzer): calculate fingerprint of clean env only once
MaxAtoms Nov 25, 2025
a5201e5
Merge remote-tracking branch 'origin/main' into 2027-env-into-ctx
MaxAtoms Nov 27, 2025
9b2ce21
lint-fix: indentation
MaxAtoms Nov 27, 2025
7e02ee0
Merge branch 'main' into 2027-env-into-ctx
EagleoutIce Dec 1, 2025
c26ef1c
docs-fix(analyzer): use new ctx methods
MaxAtoms Dec 1, 2025
b6b8165
refactor(dataflow): use contextFromInput
MaxAtoms Dec 1, 2025
3d40666
refactor(analyzer): use config as default
MaxAtoms Dec 1, 2025
cc26437
refactor(df-graph): add default cleanEnv
MaxAtoms Dec 1, 2025
c150603
refactor(linter): consolidate params
MaxAtoms Dec 1, 2025
c1016e3
refactor: nits
MaxAtoms Dec 1, 2025
2f612fa
test-fix(slicing): only use analyzer results
MaxAtoms Dec 1, 2025
3353158
refactor(slicing): make ctx optional
MaxAtoms Dec 1, 2025
fea85c5
refactor(df-graph): introduce addVertex delegate
MaxAtoms Dec 1, 2025
6f20325
refactor(analyzer): rename env ctx methods
MaxAtoms Dec 1, 2025
b1e0e41
refactor(analyzer): return built-in env as readonly
MaxAtoms Dec 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions src/dataflow/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import type { DataflowGraph } from '../graph/graph';
import { resolveByName } from './resolve-by-name';
import type { ControlDependency } from '../info';
import { jsonReplacer } from '../../util/json';
import { getDefaultBuiltInDefinitions } from './built-in-config';
import { getBuiltInDefinitions, getDefaultBuiltInDefinitions } from './built-in-config';
import type { BuiltInMemory } from './built-in';
import type { FlowrConfigOptions } from '../../config';

/**
* Marks the reference as maybe (i.e., as controlled by a set of {@link IdentifierReference#controlDependencies|control dependencies}).
Expand Down Expand Up @@ -100,11 +101,6 @@ export class Environment implements IEnvironment {
}
}

export interface WorkingDirectoryReference {
readonly path: string
readonly controlDependencies: ControlDependency[] | undefined
}

/**
* An environment describes a ({@link IEnvironment#parent|scoped}) mapping of names to their definitions ({@link BuiltIns}).
*
Expand Down Expand Up @@ -133,12 +129,39 @@ export interface REnvironmentInformation {
}

/**
* Initialize a new {@link REnvironmentInformation|environment} with the built-ins.
* Create a new built-in {@link IEnvironment|environment}.
* @param memory - Optional built-in memory to use.
* @param fullBuiltIns - Whether to use the full built-in definitions or an empty built-in environment.
*/
export function initializeCleanEnvironments(memory?: BuiltInMemory, fullBuiltIns = true): REnvironmentInformation {
export function createBuiltInEnv(memory?: BuiltInMemory, fullBuiltIns = true): IEnvironment {
const builtInEnv = new Environment(undefined as unknown as IEnvironment, true);
builtInEnv.memory = memory ?? (fullBuiltIns ? getDefaultBuiltInDefinitions().builtInMemory : getDefaultBuiltInDefinitions().emptyBuiltInMemory);
return builtInEnv;
}

/**
* Create a new built-in {@link IEnvironment|environment} according to the given configuration options.
*/
export function createBuiltInEnvFromConfig(config: FlowrConfigOptions): IEnvironment {
const builtInsConfig = config.semantics.environment.overwriteBuiltIns;
const builtIns = getBuiltInDefinitions(builtInsConfig.definitions, builtInsConfig.loadDefaults);
return createBuiltInEnv(builtIns.builtInMemory);
}

/**
* Initialize a new {@link REnvironmentInformation|environment} on top of the built-ins.
*/
export function initializeCleanEnvironments(memory?: BuiltInMemory, fullBuiltIns = true): REnvironmentInformation {
return {
current: new Environment(createBuiltInEnv(memory, fullBuiltIns)),
level: 0
};
}

/**
* Initialize a new {@link REnvironmentInformation|environment} on top of the given built-ins.
*/
export function initializeCleanEnvFromBuiltIn(builtInEnv: IEnvironment): REnvironmentInformation {
return {
current: new Environment(builtInEnv),
level: 0
Expand Down
11 changes: 3 additions & 8 deletions src/dataflow/extractor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { DataflowInformation } from './info';
import { type DataflowProcessorInformation, type DataflowProcessors , processDataflowFor } from './processor';
import { type DataflowProcessorInformation, type DataflowProcessors, processDataflowFor } from './processor';
import { processUninterestingLeaf } from './internal/process/process-uninteresting-leaf';
import { processSymbol } from './internal/process/process-symbol';
import { processFunctionCall } from './internal/process/functions/call/default-call-handling';
Expand All @@ -12,7 +12,6 @@ import { wrapArgumentsUnnamed } from './internal/process/functions/call/argument
import { rangeFrom } from '../util/range';
import type { NormalizedAst, ParentInformation } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
import { RType } from '../r-bridge/lang-4.x/ast/model/type';
import { initializeCleanEnvironments } from './environments/environment';
import { standaloneSourceFile } from './internal/process/functions/call/built-in/built-in-source';
import type { DataflowGraph } from './graph/graph';
import { extractCfgQuick } from '../control-flow/extract-cfg';
Expand All @@ -23,9 +22,9 @@ import {
import type { KnownParserType, Parser } from '../r-bridge/parser';
import { updateNestedFunctionCalls } from './internal/process/functions/call/built-in/built-in-function-definition';
import type { ControlFlowInformation } from '../control-flow/control-flow-graph';
import { getBuiltInDefinitions } from './environments/built-in-config';
import type { FlowrAnalyzerContext } from '../project/context/flowr-analyzer-context';
import { FlowrFile } from '../project/context/flowr-file';
import { initializeCleanEnvFromBuiltIn } from './environments/environment';

/**
* The best friend of {@link produceDataFlowGraph} and {@link processDataflowFor}.
Expand Down Expand Up @@ -97,9 +96,6 @@ export function produceDataFlowGraph<OtherInfo>(
completeAst: NormalizedAst<OtherInfo & ParentInformation>,
ctx: FlowrAnalyzerContext
): DataflowInformation & { cfgQuick: ControlFlowInformation | undefined } {
const builtInsConfig = ctx.config.semantics.environment.overwriteBuiltIns;
const builtIns = getBuiltInDefinitions(builtInsConfig.definitions, builtInsConfig.loadDefaults);
const env = initializeCleanEnvironments(builtIns.builtInMemory);

// we freeze the files here to avoid endless modifications during processing
const files = [...completeAst.ast.files];
Expand All @@ -109,8 +105,7 @@ export function produceDataFlowGraph<OtherInfo>(
const dfData: DataflowProcessorInformation<OtherInfo & ParentInformation> = {
parser,
completeAst,
environment: env,
builtInEnvironment: env.current.parent,
environment: initializeCleanEnvFromBuiltIn(ctx.env.builtInEnvironment),
processors,
controlDependencies: undefined,
referenceChain: [files[0].filePath],
Expand Down
2 changes: 1 addition & 1 deletion src/dataflow/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export interface DataflowInformation extends DataflowCfgInformation {
* This is to be used as a "starting point" when processing leaf nodes during the dataflow extraction.
* @see {@link DataflowInformation}
*/
export function initializeCleanDataflowInformation<T>(entryPoint: NodeId, data: Pick<DataflowProcessorInformation<T>, 'environment' | 'builtInEnvironment' | 'completeAst'>): DataflowInformation {
export function initializeCleanDataflowInformation<T>(entryPoint: NodeId, data: Pick<DataflowProcessorInformation<T>, 'environment' | 'completeAst'>): DataflowInformation {
return {
unknownReferences: [],
in: [],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type DataflowProcessorInformation , processDataflowFor } from '../../../../../processor';
import { type DataflowInformation , ExitPointType } from '../../../../../info';
import { type DataflowProcessorInformation, processDataflowFor } from '../../../../../processor';
import { type DataflowInformation, ExitPointType } from '../../../../../info';
import {
getAllFunctionCallTargets,
linkCircularRedefinitionsWithinALoop,
Expand All @@ -12,14 +12,17 @@ import { guard } from '../../../../../../util/assert';
import { dataflowLogger } from '../../../../../logger';
import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
import { type RFunctionArgument , EmptyArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
import {
EmptyArgument,
type RFunctionArgument
} from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
import { type DataflowFunctionFlowInformation , DataflowGraph } from '../../../../../graph/graph';
import { type IdentifierReference , isReferenceType, ReferenceType } from '../../../../../environments/identifier';
import { type DataflowFunctionFlowInformation, DataflowGraph } from '../../../../../graph/graph';
import { type IdentifierReference, isReferenceType, ReferenceType } from '../../../../../environments/identifier';
import { overwriteEnvironment } from '../../../../../environments/overwrite';
import { VertexType } from '../../../../../graph/vertex';
import { popLocalEnvironment, pushLocalEnvironment } from '../../../../../environments/scoping';
import { type REnvironmentInformation , initializeCleanEnvironments } from '../../../../../environments/environment';
import { initializeCleanEnvironments, type REnvironmentInformation } from '../../../../../environments/environment';
import { resolveByName } from '../../../../../environments/resolve-by-name';
import { EdgeType } from '../../../../../graph/edge';
import { expensiveTrace } from '../../../../../../util/log';
Expand Down Expand Up @@ -264,7 +267,7 @@ export function updateNestedFunctionCalls(
}

function prepareFunctionEnvironment<OtherInfo>(data: DataflowProcessorInformation<OtherInfo & ParentInformation>) {
let env = initializeCleanEnvironments(data.builtInEnvironment.memory);
let env = initializeCleanEnvironments(data.ctx.env.builtInEnvironment.memory);
for(let i = 0; i < data.environment.level + 1 /* add another env */; i++) {
env = pushLocalEnvironment(env);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import type { DataflowProcessorInformation } from '../../../../../processor';
import type { DataflowInformation } from '../../../../../info';
import { processKnownFunctionCall } from '../known-call-handling';
import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
import { type RFunctionArgument , EmptyArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
import {
EmptyArgument,
type RFunctionArgument
} from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
import { dataflowLogger } from '../../../../../logger';
Expand Down Expand Up @@ -44,7 +47,7 @@ export function processRm<OtherInfo>(

let env = res.environment;
for(const name of names) {
env = remove(name, env, data.builtInEnvironment);
env = remove(name, env, data.ctx.env.builtInEnvironment);
}

return {
Expand Down
6 changes: 1 addition & 5 deletions src/dataflow/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
ParentInformation,
RNodeWithParent
} from '../r-bridge/lang-4.x/ast/model/processing/decorate';
import type { IEnvironment, REnvironmentInformation } from './environments/environment';
import type { REnvironmentInformation } from './environments/environment';
import type { RNode } from '../r-bridge/lang-4.x/ast/model/model';
import type { KnownParserType, Parser } from '../r-bridge/parser';
import type { FlowrAnalyzerContext } from '../project/context/flowr-analyzer-context';
Expand Down Expand Up @@ -36,10 +36,6 @@ export interface DataflowProcessorInformation<OtherInfo> {
* The chain of control-flow {@link NodeId}s that lead to the current node (e.g., of known ifs).
*/
readonly controlDependencies: ControlDependency[] | undefined
/**
* The built-in environment
*/
readonly builtInEnvironment: IEnvironment;
/**
* The flowr context used for environment seeding, files, and precision control, ...
*/
Expand Down
12 changes: 10 additions & 2 deletions src/project/context/flowr-analyzer-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type { FlowrConfigOptions } from '../../config';
import { defaultConfigOptions } from '../../config';
import type { FlowrFileProvider } from './flowr-file';
import { FlowrInlineTextFile } from './flowr-file';
import { FlowrAnalyzerEnvironmentContext } from './flowr-analyzer-environment-context';

/**
* This is a read-only interface to the {@link FlowrAnalyzerContext}.
Expand All @@ -41,6 +42,10 @@ export interface ReadOnlyFlowrAnalyzerContext {
* The dependencies context provides access to the identified dependencies and their versions.
*/
readonly deps: ReadOnlyFlowrAnalyzerDependenciesContext;
/**
* The environment context provides access to the R environment information used during analysis.
*/
readonly env: FlowrAnalyzerEnvironmentContext;
/**
* The configuration options used by the analyzer.
*/
Expand All @@ -60,8 +65,10 @@ export interface ReadOnlyFlowrAnalyzerContext {
* If you are just interested in inspecting the context, you can use {@link ReadOnlyFlowrAnalyzerContext} instead (e.g., via {@link inspect}).
*/
export class FlowrAnalyzerContext implements ReadOnlyFlowrAnalyzerContext {
public readonly files: FlowrAnalyzerFilesContext;
public readonly deps: FlowrAnalyzerDependenciesContext;
public readonly files: FlowrAnalyzerFilesContext;
public readonly deps: FlowrAnalyzerDependenciesContext;
public readonly env: FlowrAnalyzerEnvironmentContext;

public readonly config: FlowrConfigOptions;

constructor(config: FlowrConfigOptions, plugins: ReadonlyMap<PluginType, readonly FlowrAnalyzerPlugin[]>) {
Expand All @@ -70,6 +77,7 @@ export class FlowrAnalyzerContext implements ReadOnlyFlowrAnalyzerContext {
this.files = new FlowrAnalyzerFilesContext(loadingOrder, (plugins.get(PluginType.ProjectDiscovery) ?? []) as FlowrAnalyzerProjectDiscoveryPlugin[],
(plugins.get(PluginType.FileLoad) ?? []) as FlowrAnalyzerFilePlugin[]);
this.deps = new FlowrAnalyzerDependenciesContext(this, (plugins.get(PluginType.DependencyIdentification) ?? []) as FlowrAnalyzerPackageVersionsPlugin[]);
this.env = new FlowrAnalyzerEnvironmentContext(this);
}

/** delegate request addition */
Expand Down
20 changes: 20 additions & 0 deletions src/project/context/flowr-analyzer-environment-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { FlowrAnalyzerContext } from './flowr-analyzer-context';
import type { IEnvironment } from '../../dataflow/environments/environment';
import { createBuiltInEnvFromConfig } from '../../dataflow/environments/environment';

/**
* This context is responsible for providing the built-in environment.
*/
export class FlowrAnalyzerEnvironmentContext {
public readonly name = 'flowr-analyzer-environment-context';
private readonly builtInEnv: IEnvironment;

constructor(ctx: FlowrAnalyzerContext) {
this.builtInEnv = createBuiltInEnvFromConfig(ctx.config);
}

public get builtInEnvironment(): IEnvironment {
return this.builtInEnv;
}
}

Loading