Skip to content

Commit

Permalink
feat: adding depth information to env-diff, remove env names for unus…
Browse files Browse the repository at this point in the history
…ed (#817)
  • Loading branch information
EagleoutIce authored May 23, 2024
2 parents 7353771 + 9b94071 commit 12938f6
Show file tree
Hide file tree
Showing 8 changed files with 25 additions and 33 deletions.
3 changes: 1 addition & 2 deletions src/dataflow/environments/append.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ function uniqueMergeValues(old: IdentifierDefinition[], value: readonly Identifi

function appendIEnvironmentWith(base: IEnvironment | undefined, next: IEnvironment | undefined): IEnvironment {
guard(base !== undefined && next !== undefined, 'can not append environments with undefined')
guard(base.name === next.name, 'cannot overwrite environments with different names')
const map = new Map(base.memory)
for(const [key, value] of next.memory) {
const old = map.get(key)
Expand All @@ -29,7 +28,7 @@ function appendIEnvironmentWith(base: IEnvironment | undefined, next: IEnvironme

const parent = base.parent === BuiltInEnvironment ? BuiltInEnvironment : appendIEnvironmentWith(base.parent, next.parent)

const out = new Environment(base.name, parent)
const out = new Environment(parent)
out.memory = map
return out
}
Expand Down
2 changes: 1 addition & 1 deletion src/dataflow/environments/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function cloneEnvironment(environment: IEnvironment | undefined, recurseParents:
} else if(environment.id === BuiltInEnvironment.id) {
return BuiltInEnvironment
}
const clone = new Environment(environment.name, recurseParents ? cloneEnvironment(environment.parent, recurseParents) : environment.parent)
const clone = new Environment(recurseParents ? cloneEnvironment(environment.parent, recurseParents) : environment.parent)
clone.memory = new Map(JSON.parse(JSON.stringify([...environment.memory])) as [Identifier, IdentifierDefinition[]][])
return clone
}
Expand Down
20 changes: 10 additions & 10 deletions src/dataflow/environments/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,22 @@ function diffMemory<Report extends WriteableDifferenceReport>(a: IEnvironment, b
}
}

export function diffEnvironment<Report extends WriteableDifferenceReport>(a: IEnvironment | undefined, b: IEnvironment | undefined, info: GenericDifferenceInformation<Report>): void {
export function diffEnvironment<Report extends WriteableDifferenceReport>(a: IEnvironment | undefined, b: IEnvironment | undefined, info: GenericDifferenceInformation<Report>, depth: number): void {
if(a === undefined || b === undefined) {
if(a !== b) {
info.report.addComment(`${info.position}Different environments. ${info.leftname}: ${a !== undefined ? 'present' : 'undefined'} vs. ${info.rightname}: ${b !== undefined ? 'present' : 'undefined'}`)
info.report.addComment(`${info.position}[at level: ${depth}] Different environments. ${info.leftname}: ${a !== undefined ? 'present' : 'undefined'} vs. ${info.rightname}: ${b !== undefined ? 'present' : 'undefined'}`)
}
return
}
if(a.name !== b.name) {
info.report.addComment(`${info.position}Different environment names. ${info.leftname}: ${a.name} vs. ${info.rightname}: ${b.name}`)
}
if(a.memory.size !== b.memory.size) {
info.report.addComment(`${info.position}Different environment sizes. ${info.leftname}: ${a.memory.size} vs. ${info.rightname}: ${b.memory.size}`)
info.report.addComment(`${info.position}[at level: ${depth}] Different number of definitions in environment. ${info.leftname}: ${a.memory.size} vs. ${info.rightname}: ${b.memory.size}`)
setDifference(new Set([...a.memory.keys()]), new Set([...b.memory.keys()]), {
...info,
position: `${info.position}Key comparison. `
position: `${info.position}[at level: ${depth}] Key comparison. `
})
}
diffMemory(a, b, info)
diffEnvironment(a.parent, b.parent, { ...info, position: `${info.position}Parents of ${a.id} & ${b.id}. ` })
diffMemory(a, b, { ...info, position: `${info.position}[at level: ${depth}] ` })
diffEnvironment(a.parent, b.parent, { ...info, position: `${info.position}Parents of ${a.id} & ${b.id}. ` }, depth--)
}

export function diffEnvironmentInformation<Report extends WriteableDifferenceReport>(a: REnvironmentInformation | undefined, b: REnvironmentInformation | undefined, info: GenericDifferenceInformation<Report>): void {
Expand All @@ -85,5 +82,8 @@ export function diffEnvironmentInformation<Report extends WriteableDifferenceRep
}
return
}
diffEnvironment(a.current, b.current, info)
if(a.level !== b.level) {
info.report.addComment(`${info.position}Different environment levels: ${info.leftname}: ${a.level} vs. ${info.rightname}: ${b.level}. Using max to report level for further errors.`)
}
diffEnvironment(a.current, b.current, info, Math.max(a.level, b.level))
}
23 changes: 9 additions & 14 deletions src/dataflow/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,23 @@ export function makeAllMaybe(references: readonly IdentifierReference[] | undefi

export interface IEnvironment {
/** unique and internally generated identifier -- will not be used for comparison but assists debugging for tracking identities */
readonly id: string
readonly name: string
readonly id: string
/** Lexical parent of the environment, if any (can be manipulated by R code) */
parent: IEnvironment
parent: IEnvironment
/**
* Maps to exactly one definition of an identifier if the source is known, otherwise to a list of all possible definitions
*/
memory: Map<Identifier, IdentifierDefinition[]>
memory: Map<Identifier, IdentifierDefinition[]>
}

let environmentIdCounter = 0

export class Environment implements IEnvironment {
readonly name: string
readonly id: string = `${environmentIdCounter++}`
parent: IEnvironment
memory: Map<Identifier, IdentifierDefinition[]>
readonly id: string = `${environmentIdCounter++}`
parent: IEnvironment
memory: Map<Identifier, IdentifierDefinition[]>

constructor(name: string, parent: IEnvironment) {
this.name = name
constructor(parent: IEnvironment) {
this.parent = parent
this.memory = new Map()
}
Expand All @@ -86,15 +83,13 @@ export interface REnvironmentInformation {


/* the built-in environment is the root of all environments */
export const BuiltInEnvironment = new Environment('built-in', undefined as unknown as IEnvironment)
export const BuiltInEnvironment = new Environment(undefined as unknown as IEnvironment)

BuiltInEnvironment.memory = BuiltInMemory

export const GLOBAL_ENV_NAME = 'global'

export function initializeCleanEnvironments(): REnvironmentInformation {
return {
current: new Environment(GLOBAL_ENV_NAME, BuiltInEnvironment),
current: new Environment(BuiltInEnvironment),
level: 0
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/dataflow/environments/overwrite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ function anyIsMaybeOrEmpty(values: readonly IdentifierDefinition[]): boolean {

export function overwriteIEnvironmentWith(base: IEnvironment | undefined, next: IEnvironment | undefined, includeParent = true): IEnvironment {
guard(base !== undefined && next !== undefined, 'can not overwrite environments with undefined')
guard(base.name === next.name, 'cannot overwrite environments with different names')
const map = new Map(base.memory)
for(const [key, values] of next.memory) {
const hasMaybe = anyIsMaybeOrEmpty(values)
Expand All @@ -44,7 +43,7 @@ export function overwriteIEnvironmentWith(base: IEnvironment | undefined, next:
parent = base.parent
}

const out = new Environment(base.name, parent)
const out = new Environment(parent)
out.memory = map
return out
}
Expand Down
2 changes: 1 addition & 1 deletion src/dataflow/environments/scoping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { guard } from '../../util/assert'
/** Add a new local environment scope to the stack, returns the modified variant - sharing the original environments in the stack (no deep-clone) */
export function pushLocalEnvironment(base: REnvironmentInformation): REnvironmentInformation {
return {
current: new Environment('local', base.current),
current: new Environment(base.current),
level: base.level + 1
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/util/mermaid/dfg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function printEnvironmentToLines(env: IEnvironment | undefined): string[] {
} else if(env.id === BuiltInEnvironment.id) {
return ['Built-in']
}
const lines = [...printEnvironmentToLines(env.parent), `${env.id}--${env.name}${'-'.repeat(40)}`]
const lines = [...printEnvironmentToLines(env.parent), `${env.id}${'-'.repeat(40)}`]
const longestName = Math.max(...[...env.memory.keys()].map(x => x.length))
for(const [name, defs] of env.memory.entries()) {
const printName = `${name}:`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@ describe('Initialization', () => {
const clean = initializeCleanEnvironments()
expect(clean.current,'there should be a current environment').to.be.not.undefined
expect(clean.current.memory.size, 'the current environment should have no memory').to.be.equal(0)
expect(clean.current.name, 'the current environment must have the correct scope name').to.be.equal('global')
expect(clean.level, 'the level of the clean environment is predefined as 0').to.be.equal(0)
})
it(label('Clean creation should create independent new environments', ['lexicographic-scope'], ['other']), () => {
const clean = initializeCleanEnvironments()
clean.current.parent = new Environment('test', clean.current.parent)
clean.current.parent = new Environment(clean.current.parent)

const second = initializeCleanEnvironments()
expect(second.current.parent.id, 'the new one should have a parent, the built-in environment').to.be.equal(BuiltInEnvironment.id)
Expand Down

2 comments on commit 12938f6

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"artificial" Benchmark Suite

Benchmark suite Current: 12938f6 Previous: eddce74 Ratio
Retrieve AST from R code 244.7254340909091 ms 282.3815673181818 ms 0.87
Normalize R AST 31.421613318181816 ms 36.45953090909091 ms 0.86
Produce dataflow information 58.26043640909091 ms 66.17186054545455 ms 0.88
Total per-file 1286.2050521818182 ms 1557.712024590909 ms 0.83
Static slicing 1.2570418805240613 ms (1.1425773976962845) 1.4160048835200516 ms (1.1715105189277293) 0.89
Reconstruct code 0.4137467890927814 ms (0.23376711796226005) 0.48975330853571625 ms (0.2799126163528146) 0.84
Total per-slice 1.687925648850196 ms (1.213445445295694) 1.9280102618968917 ms (1.2491682419110006) 0.88
failed to reconstruct/re-parse 0 # 0 # 1
times hit threshold 0 # 0 # 1
reduction (characters) 0.797431685913541 # 0.797431685913541 # 1
reduction (normalized tokens) 0.7740577588998524 # 0.7740577588998524 # 1

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"social-science" Benchmark Suite

Benchmark suite Current: 12938f6 Previous: eddce74 Ratio
Retrieve AST from R code 242.34150752000002 ms 236.60308994 ms 1.02
Normalize R AST 32.41840752 ms 31.77161632 ms 1.02
Produce dataflow information 82.71765928 ms 81.86384715999999 ms 1.01
Total per-file 2680.60582752 ms 2674.55292236 ms 1.00
Static slicing 5.380358936303224 ms (10.09515912236199) 5.448939336693711 ms (10.154387662460568) 0.99
Reconstruct code 0.3820987914183793 ms (0.2085420929275099) 0.35616079097800935 ms (0.1827576285958724) 1.07
Total per-slice 5.771546395290787 ms (10.171619610503063) 5.814113487370482 ms (10.211794878365124) 0.99
failed to reconstruct/re-parse 2 # 2 # 1
times hit threshold 0 # 0 # 1
reduction (characters) 0.9244759792036856 # 0.9241844105867956 # 1.00
reduction (normalized tokens) 0.8924953600737399 # 0.8924953600737399 # 1

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.