From fb0fc02720a5b2211eed4f35a7bc54485d3b7dad Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sat, 18 May 2024 17:13:36 +0200 Subject: [PATCH 01/23] test: start on expanding get/assign slicing tests --- .../slicing/static-program-slices/calls-tests.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/functionality/slicing/static-program-slices/calls-tests.ts b/test/functionality/slicing/static-program-slices/calls-tests.ts index 5adb0f60e2..ab55d4c5d8 100644 --- a/test/functionality/slicing/static-program-slices/calls-tests.ts +++ b/test/functionality/slicing/static-program-slices/calls-tests.ts @@ -438,6 +438,16 @@ cat(4 %a% 5)`) assertSliced(label('using assign as assignment', ['name-normal', 'numbers', 'assignment-functions', 'strings', 'newlines', 'global-scope']), shell, 'assign("x", 42)\nx', ['2@x'], 'assign("x", 42)\nx') + assertSliced(label('function', ['name-normal', 'assignment-functions', 'strings', 'newlines', 'numbers', 'implicit-return', 'normal-definition']), + shell, 'assign("a", function() 1)\na()', ['2@a'], 'assign("a", function() 1)\na()') + assertSliced(label('conditional assign', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'if', 'lambda-syntax', 'numbers', 'call-normal', 'implicit-return', 'assignment-functions', 'strings', 'numbers']), + shell, `a <- \\() 2 +if(y) { + assign("a", function() 1) +} +a()`, ['5@a'], `a <- function() 2 +if(y) { assign("a", function() 1) } +a()`) }) describe('DelayedAssign', () => { assertSliced(label('using delayed-assign as assignment', ['name-normal', 'numbers', 'assignment-functions', 'strings', 'newlines', 'global-scope']), @@ -451,6 +461,8 @@ cat(4 %a% 5)`) assertSliced(label('get-access should work like a symbol-access', ['name-normal', 'numbers','strings', 'newlines', ...OperatorDatabase['<-'].capabilities, 'global-scope']), shell, 'x <- 42\ny <- get("x")', ['2@y'], 'x <- 42\ny <- get("x")') + assertSliced(label('function', ['name-normal', 'strings', 'newlines', 'normal-definition', 'implicit-return', ...OperatorDatabase['<-'].capabilities]), + shell, 'a <- function() 1\nb <- get("a")\nb()', ['3@b'], 'a <- function() 1\nb <- get("a")\nb()') }) }) describe('Redefine built-ins', () => { From e7f984968b6ec1295392c67399f4e65eb14b5fb3 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sat, 18 May 2024 17:25:23 +0200 Subject: [PATCH 02/23] test: additional get/assign tests --- .../static-program-slices/calls-tests.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/functionality/slicing/static-program-slices/calls-tests.ts b/test/functionality/slicing/static-program-slices/calls-tests.ts index ab55d4c5d8..e227664af1 100644 --- a/test/functionality/slicing/static-program-slices/calls-tests.ts +++ b/test/functionality/slicing/static-program-slices/calls-tests.ts @@ -463,6 +463,25 @@ a()`) 'x <- 42\ny <- get("x")') assertSliced(label('function', ['name-normal', 'strings', 'newlines', 'normal-definition', 'implicit-return', ...OperatorDatabase['<-'].capabilities]), shell, 'a <- function() 1\nb <- get("a")\nb()', ['3@b'], 'a <- function() 1\nb <- get("a")\nb()') + assertSliced(label('get in function', ['name-normal', 'function-definitions', 'newlines', 'strings', 'implicit-return']), + shell, `a <- 5 +f <- function() { + get("a") +} +f()`, ['5@f'], `a <- 5 +f <- function() { get("a") } +f()`) + assertSliced(label('get in function argument', ['name-normal', 'formals-default', 'strings', 'implicit-return', ...OperatorDatabase['<-'].capabilities, 'newlines', 'numbers']), + shell, `a <- 5 +f <- function(a = get("a")) { + a +} +f()`, ['5@f'], `f <- function(a=get("a")) { a } +f()`) + }) + describe('Combine get and assign', () => { + assertSliced(label('get in assign', ['name-normal', 'numbers', ...OperatorDatabase['<-'].capabilities, 'assignment-functions', 'strings', 'unnamed-arguments', 'newlines']), + shell, 'b <- 5\nassign("a", get("b"))\nprint(a)', ['3@a'], 'b <- 5\nassign("a", get("b"))\na') }) }) describe('Redefine built-ins', () => { From 31727a89972b3b2eac73555d44f3cdf57dafa296 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sat, 18 May 2024 18:09:17 +0200 Subject: [PATCH 03/23] test: control flow slicing tests --- .../control-flow-tests.ts | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 test/functionality/slicing/static-program-slices/control-flow-tests.ts diff --git a/test/functionality/slicing/static-program-slices/control-flow-tests.ts b/test/functionality/slicing/static-program-slices/control-flow-tests.ts new file mode 100644 index 0000000000..e02de6a8b4 --- /dev/null +++ b/test/functionality/slicing/static-program-slices/control-flow-tests.ts @@ -0,0 +1,57 @@ +import { assertSliced, withShell } from '../../_helper/shell' +import { label } from '../../_helper/label' +import { OperatorDatabase } from '../../../../src/r-bridge/lang-4.x/ast/model/operators' +import type { SupportedFlowrCapabilityId } from '../../../../src/r-bridge/data/get' + +describe('Control flow', withShell(shell => { + describe('Branch Coverage', () => { + assertSliced(label('nested if', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'newlines', 'if', 'unnamed-arguments']), + shell, `x <- 1 +if(x) { + if(y) { + x <- 3 + } else { + x <- 2 + } +} else { + x <- 4 +} +print(x)`, ['11@x'], `if(x) { if(y) { x <- 3 } else + { x <- 2 } } else +{ x <- 4 } +x`) + + const loops: [string, SupportedFlowrCapabilityId[]][] = [ + ['repeat', ['repeat-loop']], + ['while(TRUE)', ['while-loop', 'logical']], + ['for(i in 1:100)', ['for-loop', 'numbers', 'name-normal']] + ] + for(const [loop, caps] of loops){ + describe(loop, () => { + assertSliced(label('Break immediately', [...caps, 'name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments']), + shell, `x <- 1 +${loop} { + x <- 2; + break +} +print(x)`, ['6@x'], 'x <- 2\nx') + assertSliced(label('Break in condition', [...caps, 'name-normal', 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments', 'if']), + shell, `x <- 1 +${loop} { + x <- 2; + if(foo) + break +} +print(x)`, ['7@x'], 'x <- 2\nx') + assertSliced(label('Next', [...caps]), + shell, `x <- 1 +${loop} { + x <- 2; + next; + x <- 3; +} +print(x)`, ['7@x'], 'x <- 2\nx') + }) + } + }) +})) From 697783dd85cfbc684f03c773dcde8f51aa2c07fa Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 20 May 2024 10:50:51 +0200 Subject: [PATCH 04/23] test: fixed up existing tests --- .../control-flow-tests.ts | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/functionality/slicing/static-program-slices/control-flow-tests.ts b/test/functionality/slicing/static-program-slices/control-flow-tests.ts index e02de6a8b4..30685b1108 100644 --- a/test/functionality/slicing/static-program-slices/control-flow-tests.ts +++ b/test/functionality/slicing/static-program-slices/control-flow-tests.ts @@ -7,8 +7,8 @@ describe('Control flow', withShell(shell => { describe('Branch Coverage', () => { assertSliced(label('nested if', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'newlines', 'if', 'unnamed-arguments']), shell, `x <- 1 -if(x) { - if(y) { +if(y) { + if(z) { x <- 3 } else { x <- 2 @@ -16,11 +16,12 @@ if(x) { } else { x <- 4 } -print(x)`, ['11@x'], `if(x) { if(y) { x <- 3 } else +print(x)`, ['11@x'], `if(y) { if(z) { x <- 3 } else { x <- 2 } } else { x <- 4 } x`) + // we don't expect to be smart about loops other than repeat at the moment, see https://github.com/Code-Inspect/flowr/issues/804 const loops: [string, SupportedFlowrCapabilityId[]][] = [ ['repeat', ['repeat-loop']], ['while(TRUE)', ['while-loop', 'logical']], @@ -34,7 +35,7 @@ ${loop} { x <- 2; break } -print(x)`, ['6@x'], 'x <- 2\nx') +print(x)`, ['6@x'], loop == 'repeat' ? 'x <- 2\nx' : `x <- 1\n${loop} x <- 2\nx`) assertSliced(label('Break in condition', [...caps, 'name-normal', 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments', 'if']), shell, `x <- 1 ${loop} { @@ -42,7 +43,12 @@ ${loop} { if(foo) break } -print(x)`, ['7@x'], 'x <- 2\nx') +print(x)`, ['7@x'], loop == 'repeat' ? 'x <- 2\nx' :`x <- 1 +${loop} { + x <- 2 + if(foo) break +} +x`) assertSliced(label('Next', [...caps]), shell, `x <- 1 ${loop} { @@ -50,7 +56,11 @@ ${loop} { next; x <- 3; } -print(x)`, ['7@x'], 'x <- 2\nx') +print(x)`, ['7@x'], loop == 'repeat' ? 'x <- 2\nx' : `x <- 1\n${loop} { + x <- 2 + x <- 3 +} +x`) }) } }) From c2a9cbbdfa140ee2a87b2ef92cc157d8d99bcaf8 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 20 May 2024 11:42:56 +0200 Subject: [PATCH 05/23] test: finished additional slicing tests --- .../static-program-slices/calls-tests.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/functionality/slicing/static-program-slices/calls-tests.ts b/test/functionality/slicing/static-program-slices/calls-tests.ts index e8ccafdcef..d2380ffc67 100644 --- a/test/functionality/slicing/static-program-slices/calls-tests.ts +++ b/test/functionality/slicing/static-program-slices/calls-tests.ts @@ -493,6 +493,30 @@ res <- b()`) describe('Redefine built-ins', () => { assertSliced(label('redefining assignments should work', ['name-quoted', 'name-normal', 'precedence', 'numbers', ...OperatorDatabase['<-'].capabilities, ...OperatorDatabase['='].capabilities, 'redefinition-of-built-in-functions-primitives']), shell, 'x <- 1\n`<-`<-`*`\nx <- 3\ny = x', ['4@y'], 'x <- 1\ny = x') + assertSliced(label('redefine if', ['name-escaped', ...OperatorDatabase['<-'].capabilities, 'numbers', 'formals-dot-dot-dot', 'newlines', 'unnamed-arguments']), + shell, `\`if\` <- function(...) 2 +if(1) + x <- 3 +print(x)`, ['4@x'], 'x <- 3\nx'/*, { expectedOutput: '[1] 2' }*/) + assertSliced(label('named argument with redefine', ['name-escaped', 'name-normal', ...OperatorDatabase['<-'].capabilities, ...OperatorDatabase['*'].capabilities, 'named-arguments', 'newlines', 'numbers']), + shell, `x <- 2 +\`<-\` <- \`*\` +x <- 3 +print(y = x)`, ['4@y'], 'y=x') + assertSliced(label('redefine in local scope', []), + shell, `f <- function() { + x <- 2 + \`<-\` <- \`*\` + x <- 3 +} +y <- f() +print(y)`, ['7@y'], `f <- function() { + x <- 2 + \`<-\` <- \`*\` + x <- 3 + } +y <- f() +y` /* the formatting here seems wild, why five spaces */, { expectedOutput: '[1] 6' }) }) describe('Switch', () => { assertSliced(label('Switch with named arguments', ['switch', ...OperatorDatabase['<-'].capabilities, 'numbers', 'strings', 'named-arguments', 'unnamed-arguments', 'switch', 'function-calls' ]), From fcb443e29bd5651507d489e2487346dfaf51d667 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 20 May 2024 12:34:12 +0200 Subject: [PATCH 06/23] test(wip): start on dataflow tests --- .../atomic/dataflow-atomic-tests.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts index 469b019d0d..b4b9940706 100644 --- a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts @@ -685,4 +685,24 @@ describe('Atomic (dataflow information)', withShell(shell => { ) }) }) + describe('Get and assign', () => { + assertDataflow(label('simple assign', ['assignment-functions', 'strings', 'implicit-return', 'normal-definition', 'newlines', 'call-normal', 'numbers']), + shell, 'assign("a", function() 1)\na()', emptyGraph() + .call('9', 'a', [], { returns: ['3'], reads: ['1'], environment: defaultEnv().defineFunction('a', '1', '7') }) + .calls('9', '5') + .defineVariable('1', '"a"', { definedBy: ['7', '5'] }) + .call('7', 'assign', [argumentInCall('1'), argumentInCall('5')], { onlyBuiltIn: true }) + .defineFunction('5', ['3'], { + entryPoint: '5', + environment: defaultEnv().pushEnv(), + graph: new Set(['3']), + in: [{ nodeId: '3', name: undefined, controlDependencies: [] }], + out: [], + unknownReferences: [] + }) + .constant('3', undefined, false) + ) + assertDataflow(label('simple get', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'implicit-return', 'newlines', 'strings', 'call-normal', 'unnamed-arguments']), + shell, 'a <- function() 1\nget("a")()', emptyGraph()) + }) })) From cf29fe0d9672f8f644934b0faa0c07d6c7f60777 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 20 May 2024 14:45:35 +0200 Subject: [PATCH 07/23] test(wip): additional dataflow tests --- .../atomic/dataflow-atomic-tests.ts | 21 +++++++++- .../dataflow-if-then-tests.ts | 41 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts index b4b9940706..18283bd459 100644 --- a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts @@ -15,6 +15,7 @@ import { BuiltIn } from '../../../../../src/dataflow/environments/built-in' import { OperatorDatabase } from '../../../../../src/r-bridge/lang-4.x/ast/model/operators' import type { FunctionArgument } from '../../../../../src/dataflow/graph/graph' import { EmptyArgument } from '../../../../../src/r-bridge/lang-4.x/ast/model/nodes/r-function-call' +import { UnnamedFunctionCallPrefix } from '../../../../../src/dataflow/internal/process/functions/call/unnamed-call-handling' describe('Atomic (dataflow information)', withShell(shell => { describe('Uninteresting Leafs', () => { @@ -703,6 +704,24 @@ describe('Atomic (dataflow information)', withShell(shell => { .constant('3', undefined, false) ) assertDataflow(label('simple get', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'implicit-return', 'newlines', 'strings', 'call-normal', 'unnamed-arguments']), - shell, 'a <- function() 1\nget("a")()', emptyGraph()) + shell, 'a <- function() 1\nget("a")()', emptyGraph() + .call('9', `${UnnamedFunctionCallPrefix}9`, [], { returns: ['1'], reads: ['8'], environment: defaultEnv().defineFunction('a', '0', '4') }) + .call('4', '<-', [argumentInCall('0'), argumentInCall('3')],{ returns: ['0'], reads: [BuiltIn] }) + .calls('9', '8') + .calls('9', '3') + .call('8', 'get', [argumentInCall('6')], { reads: ['6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineFunction('a', '0', '4') }) + .defineFunction('3', ['1'], { + entryPoint: '0', + environment: defaultEnv().pushEnv(), + graph: new Set(['1']), + in: [{ nodeId: '9', name: 'get("a")', controlDependencies: [] }], + out: [], + unknownReferences: [] + }) + .use('6', '"a"') + .defineVariable('0', 'a', { definedBy: ['4', '3'] }) + .constant('1', undefined, false) + .reads('6', '0') + ) }) })) diff --git a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts index 42015c5fa6..bec151ad9a 100644 --- a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts @@ -202,4 +202,45 @@ describe('Lists with if-then constructs', withShell(shell => { .defineVariable('14', 'y', { definedBy: ['15', '16'] }) ) }) + describe('Get and assign', () => { + assertDataflow(label('assign in condition', ['name-normal', 'lambda-syntax', 'numbers', 'if', 'newlines', 'assignment-functions', 'strings', 'normal-definition', 'implicit-return', 'call-normal']), + shell, `a <- \\() 2 +if(y) { + assign("a", function() 1) +} +a()`, emptyGraph() + .use('5', 'y') + .call('4', '<-', [argumentInCall('0'), argumentInCall('3')], { returns: ['0'], reads: [BuiltIn] }) + .argument('4', ['3', '0']) + .call('15', 'assign', [argumentInCall('9'), argumentInCall('13')], { returns: [], reads: [], environment: defaultEnv().defineFunction('a', '0', '4'), onlyBuiltIn: true }) + .argument('15', ['13', '9']) + .call('16', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependency: ['17'], environment: defaultEnv().defineFunction('a', '0', '4') }) + .argument('16', '8') + .argument('17', '5') + .argument('17', '16') + .call('17', 'if', [argumentInCall('5'), argumentInCall('16'), EmptyArgument], { returns: ['16'], reads: ['5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineFunction('a', '0', '4', ['17']) }) + .call('19', 'a', [], { returns: ['1', '11'], reads: ['9', '0'], environment: defaultEnv().defineFunction('a', '9', '15', ['17']).defineFunction('a', '0', '4', ['17']) }) + .calls('19', ['3', '13']) + .constant('1', undefined, false) + .defineFunction('3', ['1'], { + out: [], + in: [{ nodeId: '1', name: undefined, controlDependencies: [] }], + unknownReferences: [], + entryPoint: '1', + graph: new Set(['1']), + environment: defaultEnv().pushEnv() + }) + .defineVariable('0', 'a', { definedBy: ['3', '4'] }) + .constant('11', undefined, false) + .defineFunction('13', ['11'], { + out: [], + in: [{ nodeId: '11', name: undefined, controlDependencies: [] }], + unknownReferences: [], + entryPoint: '11', + graph: new Set(['11']), + environment: defaultEnv().pushEnv() + }) + .defineVariable('9', '"a"', { definedBy: ['13', '15'], controlDependency: ['17'] }) + ) + }) })) From 882c5e098f0d1b7db26bf1561c9014bbecb90bf7 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 22 May 2024 12:15:20 +0200 Subject: [PATCH 08/23] test: additional dataflow tests --- .../atomic/dataflow-atomic-tests.ts | 2 +- .../dataflow-if-then-tests.ts | 131 ++++++++++++++++++ .../loops/dataflow-for-loop-tests.ts | 4 + 3 files changed, 136 insertions(+), 1 deletion(-) diff --git a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts index 18283bd459..3daa25df5a 100644 --- a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts @@ -692,7 +692,7 @@ describe('Atomic (dataflow information)', withShell(shell => { .call('9', 'a', [], { returns: ['3'], reads: ['1'], environment: defaultEnv().defineFunction('a', '1', '7') }) .calls('9', '5') .defineVariable('1', '"a"', { definedBy: ['7', '5'] }) - .call('7', 'assign', [argumentInCall('1'), argumentInCall('5')], { onlyBuiltIn: true }) + .call('7', 'assign', [argumentInCall('1'), argumentInCall('5')], { returns: ['1'], onlyBuiltIn: true, reads: [BuiltIn] }) .defineFunction('5', ['3'], { entryPoint: '5', environment: defaultEnv().pushEnv(), diff --git a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts index bec151ad9a..66ae2d54e2 100644 --- a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts @@ -201,6 +201,57 @@ describe('Lists with if-then constructs', withShell(shell => { .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: ['13'] }) .defineVariable('14', 'y', { definedBy: ['15', '16'] }) ) + assertDataflow(label('nested if else', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'newlines', 'if', 'unnamed-arguments']), + shell, `x <- 1 +if(y) { + if(z) { + x <- 3 + } else { + x <- 2 + } +} else { + x <- 4 +} +print(x)`, emptyGraph() + .use('3', 'y') + .use('6', 'z', { controlDependencies: ['27'] }) + .use('29', 'x') + .reads('29', ['9', '15', '23']) + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('11', ['10', '9']) + .argument('12', '11') + .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependency: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('17', '<-', [argumentInCall('15'), argumentInCall('16')], { returns: ['15'], reads: [BuiltIn], controlDependency: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('17', ['16', '15']) + .argument('18', '17') + .call('18', '{', [argumentInCall('17')], { returns: ['17'], reads: [BuiltIn], controlDependency: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('19', '6') + .argument('19', '12') + .argument('19', '18') + .call('19', 'if', [argumentInCall('6'), argumentInCall('12'), argumentInCall('18')], { returns: ['12', '18'], reads: ['6', BuiltIn], onlyBuiltIn: true, controlDependency: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('20', '19') + .call('20', '{', [argumentInCall('19')], { returns: ['19'], reads: [BuiltIn], controlDependency: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('25','<-', [argumentInCall('23'), argumentInCall('24')], { returns: ['23'], reads: [BuiltIn], controlDependency: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('25', ['24', '23']) + .argument('26', '25') + .call('26', '{', [argumentInCall('25')], { returns: ['25'], reads: [BuiltIn], controlDependency: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('27', '3') + .argument('27', '20') + .argument('27', '26') + .call('27', 'if', [argumentInCall('3'), argumentInCall('20'), argumentInCall('26')], { returns: ['20', '26'], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('31', '29') + .call('31', 'print', [argumentInCall('29')], { returns: ['29'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '9', '11', ['27']).defineVariable('x', '15', '17', ['27']).defineVariable('x', '23', '25', ['27']) }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .constant('10') + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: ['27'] }) + .constant('16') + .defineVariable('15', 'x', { definedBy: ['16', '17'], controlDependency: ['27'] }) + .constant('24') + .defineVariable('23', 'x', { definedBy: ['24', '25'], controlDependency: ['27'] }) + ) }) describe('Get and assign', () => { assertDataflow(label('assign in condition', ['name-normal', 'lambda-syntax', 'numbers', 'if', 'newlines', 'assignment-functions', 'strings', 'normal-definition', 'implicit-return', 'call-normal']), @@ -242,5 +293,85 @@ a()`, emptyGraph() }) .defineVariable('9', '"a"', { definedBy: ['13', '15'], controlDependency: ['17'] }) ) + assertDataflow(label('assign from get', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'newlines', 'assignment-functions', 'strings', 'unnamed-arguments']), + shell, 'b <- 5\nassign("a", get("b"))\nprint(a)', emptyGraph() + .use('7', '"b"') + .reads('7', '0') + .use('13', 'a') + .reads('13', '4') + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .argument('9', '7') + .call('9', 'get', [argumentInCall('7')], { returns: [], reads: [BuiltIn, '7'], onlyBuiltIn: true, environment: defaultEnv().defineVariable('b', '0', '2') }) + .argument('11', '9') + .call('11', 'assign', [argumentInCall('4'), argumentInCall('9')], { returns: ['4'], reads: [BuiltIn], environment: defaultEnv().defineVariable('b', '0', '2') }) + .argument('11', '4') + .argument('15', '13') + .call('15', 'print', [argumentInCall('13')], { returns: ['13'], reads: [BuiltIn], environment: defaultEnv().defineVariable('b', '0', '2').defineVariable('a', '4', '11') }) + .constant('1') + .defineVariable('0', 'b', { definedBy: ['1', '2'] }) + .defineVariable('4', '"a"', { definedBy: ['9', '11'] }) + ) + assertDataflow(label('get in function', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'empty-arguments', 'newlines', 'implicit-return', 'call-normal']), + shell, `a <- 5 +f <- function() { + get("a") +} +f()`, emptyGraph() + .use('7', '"a"', undefined, false) + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .argument('9', '7') + .call('9', 'get', [argumentInCall('7')], { returns: [], reads: ['7', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().pushEnv() }, false) + .argument('10', '9') + .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) + .call('12', '<-', [argumentInCall('3'), argumentInCall('11')], { returns: ['3'], reads: [BuiltIn], environment: defaultEnv().defineVariable('a', '0', '2') }) + .argument('12', ['11', '3']) + .call('14', 'f', [], { returns: ['10'], reads: ['3', '0'], environment: defaultEnv().defineVariable('a', '0', '2').defineFunction('f', '3', '12') }) + .calls('14', '11') + .constant('1') + .defineVariable('0', 'a', { definedBy: ['1', '2'] }) + .defineFunction('11', ['10'], { + out: [], + in: [{ nodeId: '7', name: 'a', controlDependencies: [] }], + unknownReferences: [], + entryPoint: '10', + graph: new Set(['7', '9', '10']), + environment: defaultEnv().pushEnv() + }) + .defineVariable('3', 'f', { definedBy: ['11', '12'] }) + ) + assertDataflow(label('get in function argument', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'newlines', 'formals-default', 'strings', 'implicit-return']), + shell, `a <- 5 +f <- function(a = get("a")) { + a +} +f()`, emptyGraph() + .use('6', '"a"', undefined, false) + .reads('6', '4') + .use('12', 'a', undefined, false) + .reads('12', '4') + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .argument('8', '6') + .call('8', 'get', [argumentInCall('6')], { returns: [], reads: ['6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().pushEnv() }, false) + .argument('13', '12') + .call('13', '{', [argumentInCall('12')], { returns: ['12'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('a', '4', '9') }, false) + .call('15', '<-', [argumentInCall('3'), argumentInCall('14')], { returns: ['3'], reads: [BuiltIn], environment: defaultEnv().defineVariable('a', '0', '2') }) + .argument('15', ['14', '3']) + .call('17', 'f', [], { returns: ['13'], reads: ['3'], environment: defaultEnv().defineVariable('a', '0', '2').defineFunction('f', '3', '15') }) + .calls('17', '14') + .constant('1') + .defineVariable('0', 'a', { definedBy: ['1', '2'] }) + .defineVariable('4', 'a', { definedBy: ['6', '8'] }, false) + .defineFunction('14', ['13'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '13', + graph: new Set(['4', '6', '8', '12', '13']), + environment: defaultEnv().pushEnv().defineParameter('a', '4', '9') + }) + .defineVariable('3', 'f', { definedBy: ['14', '15'] })) }) })) diff --git a/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts b/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts index ee44793c95..a5b563cd01 100644 --- a/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts @@ -149,4 +149,8 @@ x`, emptyGraph() .constant('8', { controlDependency: ['11'] }) .defineVariable('7', 'i', { definedBy: ['8', '9'], controlDependency: [] }) ) + + describe('Branch coverage', () => { + + }) })) From d953e5b667e35c4526162c25cf81c0e471d299a8 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 22 May 2024 12:23:47 +0200 Subject: [PATCH 09/23] refactor: unify controlDependencies naming --- src/dataflow/environments/diff.ts | 2 +- src/dataflow/graph/diff.ts | 2 +- .../dataflow/dataflow-builder-printer.ts | 8 +- .../_helper/dataflow/dataflowgraph-builder.ts | 26 +++--- .../_helper/dataflow/environment-builder.ts | 4 +- .../functionality/_helper/dataflow/printer.ts | 8 +- .../atomic/dataflow-atomic-tests.ts | 50 +++++----- .../dataflow-if-then-tests.ts | 92 +++++++++---------- .../dataflow-function-definition-tests.ts | 6 +- .../functions/dataflow-source-tests.ts | 4 +- .../loops/dataflow-for-loop-tests.ts | 46 +++++----- .../loops/dataflow-while-loop-tests.ts | 12 +-- 12 files changed, 130 insertions(+), 130 deletions(-) diff --git a/src/dataflow/environments/diff.ts b/src/dataflow/environments/diff.ts index eb4d468ae5..e0c9485c38 100644 --- a/src/dataflow/environments/diff.ts +++ b/src/dataflow/environments/diff.ts @@ -45,7 +45,7 @@ function diffMemory(a: IEnvironment, b info.report.addComment(`${info.position}Different ids for ${key}. ${info.leftname}: ${aVal.nodeId} vs. ${info.rightname}: ${bVal.nodeId}`) } if(!arrayEqual(aVal.controlDependencies, bVal.controlDependencies)) { - info.report.addComment(`${info.position}Different controlDependency for ${key} (${aVal.nodeId}). ${info.leftname}: ${JSON.stringify(aVal.controlDependencies)} vs. ${info.rightname}: ${JSON.stringify(bVal.controlDependencies)}`) + info.report.addComment(`${info.position}Different controlDependencies for ${key} (${aVal.nodeId}). ${info.leftname}: ${JSON.stringify(aVal.controlDependencies)} vs. ${info.rightname}: ${JSON.stringify(bVal.controlDependencies)}`) } if(aVal.definedAt !== bVal.definedAt) { info.report.addComment(`${info.position}Different definition ids (definedAt) for ${key} (${aVal.nodeId}). ${info.leftname}: ${aVal.definedAt} vs. ${info.rightname}: ${bVal.definedAt}`) diff --git a/src/dataflow/graph/diff.ts b/src/dataflow/graph/diff.ts index 4c260cfd9e..49d0b745b6 100644 --- a/src/dataflow/graph/diff.ts +++ b/src/dataflow/graph/diff.ts @@ -226,7 +226,7 @@ export function diffVertices(ctx: DataflowDiffContext): void { } if(!arrayEqual(lInfo.controlDependencies, rInfo.controlDependencies)) { ctx.report.addComment( - `Vertex ${id} differs in controlDependency. ${ctx.leftname}: ${JSON.stringify(lInfo.controlDependencies)} vs ${ctx.rightname}: ${JSON.stringify(rInfo.controlDependencies)}`, + `Vertex ${id} differs in controlDependencies. ${ctx.leftname}: ${JSON.stringify(lInfo.controlDependencies)} vs ${ctx.rightname}: ${JSON.stringify(rInfo.controlDependencies)}`, { tag: 'vertex', id } ) } diff --git a/test/functionality/_helper/dataflow/dataflow-builder-printer.ts b/test/functionality/_helper/dataflow/dataflow-builder-printer.ts index c38babef11..90461eb004 100644 --- a/test/functionality/_helper/dataflow/dataflow-builder-printer.ts +++ b/test/functionality/_helper/dataflow/dataflow-builder-printer.ts @@ -127,13 +127,13 @@ class DataflowBuilderPrinter { if(arg === undefined || arg === EmptyArgument) { return 'EmptyArgument' } else if(isPositionalArgument(arg)) { - const suffix = this.getControlDependencySuffix(this.controlDependencyForArgument(arg.nodeId), ', { ') ?? '' + const suffix = this.getControlDependencySuffix(this.controlDependenciesForArgument(arg.nodeId), ', { ') ?? '' this.handleArgumentArgLinkage(fn, arg.nodeId) return `argumentInCall('${arg.nodeId}'${suffix})` } else { this.coveredVertices.add(arg.nodeId) this.handleArgumentArgLinkage(fn, arg.nodeId) - const suffix = this.getControlDependencySuffix(this.controlDependencyForArgument(arg.nodeId), ', ', '') ?? '' + const suffix = this.getControlDependencySuffix(this.controlDependenciesForArgument(arg.nodeId), ', ', '') ?? '' return `argumentInCall('${arg.nodeId}', { name: '${arg.name}'${suffix} } )` } } @@ -153,7 +153,7 @@ class DataflowBuilderPrinter { } } - private controlDependencyForArgument(id: NodeId): NodeId[] | undefined { + private controlDependenciesForArgument(id: NodeId): NodeId[] | undefined { // we ignore the control dependency of the argument in the call as it is usually separate, and the auto creation // will respect the corresponding node! return this.graph.getVertex(id, true)?.controlDependencies @@ -247,7 +247,7 @@ class DataflowBuilderPrinter { private getControlDependencySuffix(arg: NodeId[] | undefined, prefix: string = '{ ', suffix: string = ' }'): string | undefined { if(arg !== undefined) { - return `${prefix}controlDependency: [${arg.map(id => wrap(id)).join(', ')}]${suffix}` + return `${prefix}controlDependencies: [${arg.map(id => wrap(id)).join(', ')}]${suffix}` } return undefined } diff --git a/test/functionality/_helper/dataflow/dataflowgraph-builder.ts b/test/functionality/_helper/dataflow/dataflowgraph-builder.ts index 82fa28083f..56f2f3370a 100644 --- a/test/functionality/_helper/dataflow/dataflowgraph-builder.ts +++ b/test/functionality/_helper/dataflow/dataflowgraph-builder.ts @@ -40,7 +40,7 @@ export class DataflowGraphBuilder extends DataflowGraph { */ public defineFunction(id: NodeId, exitPoints: readonly NodeId[], subflow: DataflowFunctionFlowInformation, - info?: { environment?: REnvironmentInformation, controlDependency?: NodeId[] }, + info?: { environment?: REnvironmentInformation, controlDependencies?: NodeId[] }, asRoot: boolean = true) { return this.addVertex({ tag: VertexType.FunctionDefinition, @@ -54,7 +54,7 @@ export class DataflowGraphBuilder extends DataflowGraph { unknownReferences: subflow.unknownReferences.map(o => ({ ...o, nodeId: normalizeIdToNumberIfPossible(o.nodeId), controlDependencies: o.controlDependencies?.map(normalizeIdToNumberIfPossible) })) } as DataflowFunctionFlowInformation, exitPoints: exitPoints.map(normalizeIdToNumberIfPossible), - controlDependencies: info?.controlDependency?.map(normalizeIdToNumberIfPossible), + controlDependencies: info?.controlDependencies?.map(normalizeIdToNumberIfPossible), environment: info?.environment }, asRoot) } @@ -71,11 +71,11 @@ export class DataflowGraphBuilder extends DataflowGraph { */ public call(id: NodeId, name: string, args: FunctionArgument[], info?: { - returns?: readonly NodeId[], - reads?: readonly NodeId[], - onlyBuiltIn?: boolean, - environment?: REnvironmentInformation, - controlDependency?: NodeId[] + returns?: readonly NodeId[], + reads?: readonly NodeId[], + onlyBuiltIn?: boolean, + environment?: REnvironmentInformation, + controlDependencies?: NodeId[] }, asRoot: boolean = true) { const onlyBuiltInAuto = info?.reads?.length === 1 && info?.reads[0] === BuiltIn @@ -83,9 +83,9 @@ export class DataflowGraphBuilder extends DataflowGraph { tag: VertexType.FunctionCall, id: normalizeIdToNumberIfPossible(id), name, - args: args.map(a => a === EmptyArgument ? EmptyArgument : { ...a, nodeId: normalizeIdToNumberIfPossible(a.nodeId), controlDependency: undefined }), + args: args.map(a => a === EmptyArgument ? EmptyArgument : { ...a, nodeId: normalizeIdToNumberIfPossible(a.nodeId), controlDependencies: undefined }), environment: info?.environment ?? initializeCleanEnvironments(), - controlDependencies: info?.controlDependency?.map(normalizeIdToNumberIfPossible), + controlDependencies: info?.controlDependencies?.map(normalizeIdToNumberIfPossible), onlyBuiltin: info?.onlyBuiltIn ?? onlyBuiltInAuto ?? false }, asRoot) this.addArgumentLinks(id, args) @@ -131,12 +131,12 @@ export class DataflowGraphBuilder extends DataflowGraph { * (i.e., be a valid entry point), or is it nested (e.g., as part of a function definition) */ public defineVariable(id: NodeId, name: string, - info?: { controlDependency?: NodeId[], definedBy?: NodeId[]}, asRoot: boolean = true) { + info?: { controlDependencies?: NodeId[], definedBy?: NodeId[]}, asRoot: boolean = true) { this.addVertex({ tag: VertexType.VariableDefinition, id: normalizeIdToNumberIfPossible(id), name, - controlDependencies: info?.controlDependency?.map(normalizeIdToNumberIfPossible), + controlDependencies: info?.controlDependencies?.map(normalizeIdToNumberIfPossible), }, asRoot) if(info?.definedBy) { for(const def of info.definedBy) { @@ -177,11 +177,11 @@ export class DataflowGraphBuilder extends DataflowGraph { * @param asRoot - should the vertex be part of the root vertex set of the graph * (i.e., be a valid entry point), or is it nested (e.g., as part of a function definition) */ - public constant(id: NodeId, options?: { controlDependency?: NodeId[] }, asRoot: boolean = true) { + public constant(id: NodeId, options?: { controlDependencies?: NodeId[] }, asRoot: boolean = true) { return this.addVertex({ tag: VertexType.Value, id: normalizeIdToNumberIfPossible(id), - controlDependencies: options?.controlDependency?.map(normalizeIdToNumberIfPossible), + controlDependencies: options?.controlDependencies?.map(normalizeIdToNumberIfPossible), environment: undefined }, asRoot) } diff --git a/test/functionality/_helper/dataflow/environment-builder.ts b/test/functionality/_helper/dataflow/environment-builder.ts index 2d36975393..56bcf7c8ba 100644 --- a/test/functionality/_helper/dataflow/environment-builder.ts +++ b/test/functionality/_helper/dataflow/environment-builder.ts @@ -17,8 +17,8 @@ export function variable(name: string, definedAt: NodeId): IdentifierDefinition * @param nodeId - AST Node ID * @param options - optional allows to give further options */ -export function argumentInCall(nodeId: NodeId, options?: { name?: string, controlDependency?: NodeId[] }): FunctionArgument { - return { nodeId: normalizeIdToNumberIfPossible(nodeId), name: options?.name, controlDependencies: options?.controlDependency?.map(normalizeIdToNumberIfPossible) } +export function argumentInCall(nodeId: NodeId, options?: { name?: string, controlDependencies?: NodeId[] }): FunctionArgument { + return { nodeId: normalizeIdToNumberIfPossible(nodeId), name: options?.name, controlDependencies: options?.controlDependencies?.map(normalizeIdToNumberIfPossible) } } /** * The constant global environment with all pre-defined functions. diff --git a/test/functionality/_helper/dataflow/printer.ts b/test/functionality/_helper/dataflow/printer.ts index 77baa6e6a2..d8eca1d2dd 100644 --- a/test/functionality/_helper/dataflow/printer.ts +++ b/test/functionality/_helper/dataflow/printer.ts @@ -20,13 +20,13 @@ export function wrap(id: string | NodeId | undefined): string { } } -function wrapControlDependency(controlDependency: NodeId[] | undefined): string { - if(controlDependency === undefined) { +function wrapControlDependencies(controlDependencies: NodeId[] | undefined): string { + if(controlDependencies === undefined) { return 'undefined' } else { - return `[${controlDependency.map(wrap).join(', ')}]` + return `[${controlDependencies.map(wrap).join(', ')}]` } } export function wrapReference(ref: IdentifierReference): string { - return `{ nodeId: ${wrap(ref.nodeId)}, name: ${wrap(ref.name)}, controlDependencies: ${wrapControlDependency(ref.controlDependencies)} }` + return `{ nodeId: ${wrap(ref.nodeId)}, name: ${wrap(ref.name)}, controlDependencies: ${wrapControlDependencies(ref.controlDependencies)} }` } diff --git a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts index 3daa25df5a..fceba79f7c 100644 --- a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts @@ -363,7 +363,7 @@ describe('Atomic (dataflow information)', withShell(shell => { .argument('5', '4') .call('5', '<-', [argumentInCall('0'), argumentInCall('4')], { returns: ['0'], reads: [BuiltIn] }) .argument('5', '0') - .constant('2', { controlDependency: [] }) + .constant('2', { controlDependencies: [] }) .defineVariable('0', 'x', { definedBy: ['4', '5'] }) ) @@ -376,7 +376,7 @@ describe('Atomic (dataflow information)', withShell(shell => { .defineVariable('1', 'i', { definedBy: ['4'] }) .constant('2') .constant('3') - .constant('5', { controlDependency: [] }) + .constant('5', { controlDependencies: [] }) .defineVariable('0', 'x', { definedBy: ['7', '8'] }) ) }) @@ -460,7 +460,7 @@ describe('Atomic (dataflow information)', withShell(shell => { .reads('2', ['0', '1']) .call('5', 'if', [argumentInCall('2'), argumentInCall('3'), EmptyArgument], { returns: ['3'], reads: ['2', BuiltIn], onlyBuiltIn: true }) .constant('1') - .constant('3', { controlDependency: ['5'] }) + .constant('3', { controlDependencies: ['5'] }) ) assertDataflow(label('compare cond. symbol in then', ['if', 'logical', 'numbers', 'name-normal', ...OperatorDatabase['>'].capabilities]), shell, 'if (x > 5) y', emptyGraph() @@ -528,13 +528,13 @@ describe('Atomic (dataflow information)', withShell(shell => { .use('0', 'x') .call('2', '>', [argumentInCall('0'), argumentInCall('1')], { returns: [], reads: [BuiltIn] }) .reads('2', ['0', '1']) - .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependency: ['11'] }) - .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['11'] }) + .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependencies: ['11'] }) + .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['11'] }) .call('11', 'if', [argumentInCall('2'), argumentInCall('6'), argumentInCall('10')], { returns: ['6', '10'], reads: [BuiltIn] }) .reads('11', '2') .constant('1') - .constant('5', { controlDependency: ['11'] }) - .constant('9', { controlDependency: ['11'] }) + .constant('5', { controlDependencies: ['11'] }) + .constant('9', { controlDependencies: ['11'] }) ) assertDataflow(label('compare cond. symbol in then', ['if', 'logical', 'numbers', 'name-normal', 'grouping', ...OperatorDatabase['>'].capabilities]), shell, 'if (x > 5) { y } else { 42 }', @@ -544,15 +544,15 @@ describe('Atomic (dataflow information)', withShell(shell => { .call('2', '>', [argumentInCall('0'), argumentInCall('1')], { returns: [], reads: [BuiltIn] }) .reads('2', ['0', '1']) .argument('2', ['1']) - .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependency: ['11'] }) + .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependencies: ['11'] }) .argument('6', '5') - .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['11'] }) + .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['11'] }) .argument('10', '9') .call('11', 'if', [argumentInCall('2'), argumentInCall('6'), argumentInCall('10')], { returns: ['6', '10'], reads: [BuiltIn] }) .argument('11', ['6', '10', '2']) .reads('11', '2') .constant('1') - .constant('9', { controlDependency: ['11'] }) + .constant('9', { controlDependencies: ['11'] }) ) assertDataflow(label('compare cond. symbol in then & else', ['if', 'logical', 'numbers', 'name-normal', 'grouping', ...OperatorDatabase['>'].capabilities]), shell, 'if (x > 5) { y } else { z }', emptyGraph() @@ -561,8 +561,8 @@ describe('Atomic (dataflow information)', withShell(shell => { .use('9', 'z', { controlDependencies: ['11'] }) .call('2', '>', [argumentInCall('0'), argumentInCall('1')], { returns: [], reads: [BuiltIn] }) .reads('2', ['0', '1']) - .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependency: ['11'] }) - .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['11'] }) + .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependencies: ['11'] }) + .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['11'] }) .call('11', 'if', [argumentInCall('2'), argumentInCall('6'), argumentInCall('10')], { returns: ['6', '10'], reads: ['2', BuiltIn], onlyBuiltIn: true }) .constant('1') ) @@ -574,8 +574,8 @@ describe('Atomic (dataflow information)', withShell(shell => { .use('9', 'a', { controlDependencies: ['11'] }) .call('2', '>', [argumentInCall('0'), argumentInCall('1')], { returns: [], reads: [BuiltIn] }) .reads('2', ['0', '1']) - .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependency: ['11'] }) - .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['11'] }) + .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependencies: ['11'] }) + .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['11'] }) .call('11', 'if', [argumentInCall('2'), argumentInCall('6'), argumentInCall('10')], { returns: ['6', '10'], reads: ['2', BuiltIn], onlyBuiltIn: true }) ) assertDataflow(label('all variables, some same', ['if', 'logical', 'name-normal', 'grouping', ...OperatorDatabase['>'].capabilities]), @@ -586,8 +586,8 @@ describe('Atomic (dataflow information)', withShell(shell => { .use('9', 'y', { controlDependencies: ['11'] }) .call('2', '>', [argumentInCall('0'), argumentInCall('1')], { returns: [], reads: [BuiltIn] }) .reads('2', ['0', '1']) - .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependency: ['11'] }) - .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['11'] }) + .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependencies: ['11'] }) + .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['11'] }) .call('11', 'if', [argumentInCall('2'), argumentInCall('6'), argumentInCall('10')], { returns: ['6', '10'], reads: ['2', BuiltIn], onlyBuiltIn: true }) ) assertDataflow(label('all same variables', ['if', 'logical', 'name-normal', 'grouping', ...OperatorDatabase['>'].capabilities]), @@ -598,8 +598,8 @@ describe('Atomic (dataflow information)', withShell(shell => { .use('9', 'x', { controlDependencies: ['11'] }) .call('2', '>', [argumentInCall('0'), argumentInCall('1')], { returns: [], reads: [BuiltIn] }) .reads('2', ['0', '1']) - .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependency: ['11'] }) - .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['11'] }) + .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependencies: ['11'] }) + .call('10', '{', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['11'] }) .call('11', 'if', [argumentInCall('2'), argumentInCall('6'), argumentInCall('10')], { returns: ['6', '10'], reads: ['2', BuiltIn], onlyBuiltIn: true }) ) }) @@ -613,16 +613,16 @@ describe('Atomic (dataflow information)', withShell(shell => { .reads('11', ['0', '6']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .argument('2', ['1', '0']) - .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: ['6'], reads: [BuiltIn], controlDependency: ['10'], environment: defaultEnv().defineVariable('y', '0', '2') }) + .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: ['6'], reads: [BuiltIn], controlDependencies: ['10'], environment: defaultEnv().defineVariable('y', '0', '2') }) .argument('8', ['7', '6']) - .call('9', '(', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependency: ['10'], environment: defaultEnv().defineVariable('y', '0', '2').defineVariable('y', '6', '8', ['10']) }) + .call('9', '(', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependencies: ['10'], environment: defaultEnv().defineVariable('y', '0', '2').defineVariable('y', '6', '8', ['10']) }) .call('10', '&&', [argumentInCall('3'), argumentInCall('9')], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('y', '0', '2').defineVariable('y', '6', '8', ['10']) }) .reads('10', '3') .argument('10', ['3', '9']) .constant('1') .defineVariable('0', 'y', { definedBy: ['1', '2'] }) - .constant('7', { controlDependency: ['10'] }) - .defineVariable('6', 'y', { definedBy: ['7', '8'], controlDependency: ['10'] }) + .constant('7', { controlDependencies: ['10'] }) + .defineVariable('6', 'y', { definedBy: ['7', '8'], controlDependencies: ['10'] }) ) }) @@ -631,20 +631,20 @@ describe('Atomic (dataflow information)', withShell(shell => { assertDataflow(label('simple constant for-loop', ['for-loop', 'numbers', 'name-normal', 'built-in-sequencing', 'grouping']), shell, 'for(i in 1:10) { 1 }', emptyGraph() .call('3', ':', [argumentInCall('1'), argumentInCall('2')], { returns: [], reads: ['1', '2', BuiltIn], onlyBuiltIn: true }) - .call('7', '{', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn], controlDependency: [] }) + .call('7', '{', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn], controlDependencies: [] }) .call('8', 'for', [argumentInCall('0'), argumentInCall('3'), argumentInCall('7')], { returns: [], reads: ['0', '3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('i', '0', '8') }) .nse('8', '7') .defineVariable('0', 'i', { definedBy: ['3'] }) .constant('1') .constant('2') - .constant('6', { controlDependency: [] }) + .constant('6', { controlDependencies: [] }) ) assertDataflow(label('using loop variable in body', ['for-loop', 'numbers', 'name-normal', 'built-in-sequencing', 'grouping']), shell, 'for(i in 1:10) { i }', emptyGraph() .use('6', 'i', { controlDependencies: [] }) .reads('6', '0') .call('3', ':', [argumentInCall('1'), argumentInCall('2')], { returns: [], reads: ['1', '2', BuiltIn], onlyBuiltIn: true }) - .call('7', '{', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn], controlDependency: [] }) + .call('7', '{', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn], controlDependencies: [] }) .call('8', 'for', [argumentInCall('0'), argumentInCall('3'), argumentInCall('7')], { returns: [], reads: ['0', '3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('i', '0', '8') }) .nse('8', '7') .defineVariable('0', 'i', { definedBy: ['3'] }) diff --git a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts index 66ae2d54e2..7c23078fcc 100644 --- a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts @@ -20,20 +20,20 @@ describe('Lists with if-then constructs', withShell(shell => { .use('3', 'x') .reads('3', '0') .call('2', assign, [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) - .call('7', '{', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn], controlDependency: cd, environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('7', '{', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn], controlDependencies: cd, environment: defaultEnv().defineVariable('x', '0', '2') }) if(b.text !== '') { baseGraph - .call('11', '{', [argumentInCall('10')], { returns: ['10'], reads: [BuiltIn], controlDependency: ['12'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('11', '{', [argumentInCall('10')], { returns: ['10'], reads: [BuiltIn], controlDependencies: ['12'], environment: defaultEnv().defineVariable('x', '0', '2') }) .call('12', 'if', [argumentInCall('3'), argumentInCall('7'), argumentInCall('11')], { returns: ['7', '11'], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) - .constant('6', { controlDependency: ['12'] }) - .constant('10', { controlDependency: ['12'] }) + .constant('6', { controlDependencies: ['12'] }) + .constant('10', { controlDependencies: ['12'] }) } else { baseGraph.call('8', 'if', [argumentInCall('3'), argumentInCall('7'), EmptyArgument], { returns: ['7'], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) - .constant('6', { controlDependency: ['8'] }) + .constant('6', { controlDependencies: ['8'] }) } assertDataflow(label('read previous def in cond', [...OperatorDatabase[assign].capabilities, 'name-normal', 'numbers', 'newlines', 'if']), shell, @@ -102,15 +102,15 @@ describe('Lists with if-then constructs', withShell(shell => { .use('0', 'z') .use('14', 'x') .reads('14', ['3', '9']) - .call('5', assign, [argumentInCall('3'), argumentInCall('4')], { returns: ['3'], reads: [BuiltIn], controlDependency: ['13'] }) - .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependency: ['13'] }) - .call('11', assign, [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['13'] }) - .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependency: ['13'] }) + .call('5', assign, [argumentInCall('3'), argumentInCall('4')], { returns: ['3'], reads: [BuiltIn], controlDependencies: ['13'] }) + .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependencies: ['13'] }) + .call('11', assign, [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['13'] }) + .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependencies: ['13'] }) .call('13', 'if', [argumentInCall('0'), argumentInCall('6'), argumentInCall('12')], { returns: ['6', '12'], reads: ['0', BuiltIn], onlyBuiltIn: true }) .constant('4') - .defineVariable('3', 'x', { definedBy: ['4', '5'], controlDependency: ['13'] }) + .defineVariable('3', 'x', { definedBy: ['4', '5'], controlDependencies: ['13'] }) .constant('10') - .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: ['13'] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: ['13'] }) ) }) }) @@ -122,18 +122,18 @@ describe('Lists with if-then constructs', withShell(shell => { .use('18', 'x') .reads('18', ['6', '12']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) - .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: ['6'], reads: [BuiltIn], controlDependency: ['16'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('9', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependency: ['16'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('14', '<-', [argumentInCall('12'), argumentInCall('13')], { returns: ['12'], reads: [BuiltIn], controlDependency: ['16'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('15', '{', [argumentInCall('14')], { returns: ['14'], reads: [BuiltIn], controlDependency: ['16'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: ['6'], reads: [BuiltIn], controlDependencies: ['16'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('9', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependencies: ['16'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('14', '<-', [argumentInCall('12'), argumentInCall('13')], { returns: ['12'], reads: [BuiltIn], controlDependencies: ['16'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('15', '{', [argumentInCall('14')], { returns: ['14'], reads: [BuiltIn], controlDependencies: ['16'], environment: defaultEnv().defineVariable('x', '0', '2') }) .call('16', 'if', [argumentInCall('3'), argumentInCall('9'), argumentInCall('15')], { returns: ['9', '15'], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) .call('19', '<-', [argumentInCall('17'), argumentInCall('18')], { returns: ['17'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '6', '8', ['16']).defineVariable('x', '12', '14', ['16']) }) .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) .constant('7') - .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependency: ['16'] }) + .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependencies: ['16'] }) .constant('13') - .defineVariable('12', 'x', { definedBy: ['13', '14'], controlDependency: ['16'] }) + .defineVariable('12', 'x', { definedBy: ['13', '14'], controlDependencies: ['16'] }) .defineVariable('17', 'y', { definedBy: ['18', '19'] }) ) @@ -142,14 +142,14 @@ describe('Lists with if-then constructs', withShell(shell => { .use('12', 'x') .reads('12', ['6', '0']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) - .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: ['6'], reads: [BuiltIn], controlDependency: ['10'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('9', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependency: ['10'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: ['6'], reads: [BuiltIn], controlDependencies: ['10'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('9', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependencies: ['10'], environment: defaultEnv().defineVariable('x', '0', '2') }) .call('10', 'if', [argumentInCall('3'), argumentInCall('9'), EmptyArgument], { returns: ['9'], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', ['10']) }) .call('13', '<-', [argumentInCall('11'), argumentInCall('12')], { returns: ['11'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '6', '8', ['10']).defineVariable('x', '0', '2', ['10']) }) .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) .constant('7') - .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependency: ['10'] }) + .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependencies: ['10'] }) .defineVariable('11', 'y', { definedBy: ['12', '13'] }) ) @@ -164,11 +164,11 @@ describe('Lists with if-then constructs', withShell(shell => { .reads('27', ['12', '3']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .call('5', '<-', [argumentInCall('3'), argumentInCall('4')], { returns: ['3'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['22'], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('y', '3', '5') }) - .call('14', '<-', [argumentInCall('12'), argumentInCall('13')], { returns: ['12'], reads: [BuiltIn], controlDependency: ['22'], environment: defaultEnv().defineVariable('x', '9', '11').defineVariable('y', '3', '5') }) - .call('15', '{', [argumentInCall('11'), argumentInCall('14')], { returns: ['14'], reads: [BuiltIn], controlDependency: ['22'], environment: defaultEnv().defineVariable('x', '9', '11').defineVariable('y', '3', '5') }) - .call('20', '<-', [argumentInCall('18'), argumentInCall('19')], { returns: ['18'], reads: [BuiltIn], controlDependency: ['22'], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('y', '3', '5') }) - .call('21', '{', [argumentInCall('20')], { returns: ['20'], reads: [BuiltIn], controlDependency: ['22'], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('y', '3', '5') }) + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['22'], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('y', '3', '5') }) + .call('14', '<-', [argumentInCall('12'), argumentInCall('13')], { returns: ['12'], reads: [BuiltIn], controlDependencies: ['22'], environment: defaultEnv().defineVariable('x', '9', '11').defineVariable('y', '3', '5') }) + .call('15', '{', [argumentInCall('11'), argumentInCall('14')], { returns: ['14'], reads: [BuiltIn], controlDependencies: ['22'], environment: defaultEnv().defineVariable('x', '9', '11').defineVariable('y', '3', '5') }) + .call('20', '<-', [argumentInCall('18'), argumentInCall('19')], { returns: ['18'], reads: [BuiltIn], controlDependencies: ['22'], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('y', '3', '5') }) + .call('21', '{', [argumentInCall('20')], { returns: ['20'], reads: [BuiltIn], controlDependencies: ['22'], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('y', '3', '5') }) .call('22', 'if', [argumentInCall('6'), argumentInCall('15'), argumentInCall('21')], { returns: ['15', '21'], reads: ['6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('y', '3', '5') }) .call('25', '<-', [argumentInCall('23'), argumentInCall('24')], { returns: ['23'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '9', '11', ['22']).defineVariable('x', '18', '20', ['22']).defineVariable('y', '12', '14', ['22']).defineVariable('y', '3', '5', ['22']) }) .call('28', '<-', [argumentInCall('26'), argumentInCall('27')], { returns: ['26'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '9', '11', ['22']).defineVariable('x', '18', '20', ['22']).defineVariable('y', '12', '14', ['22']).defineVariable('y', '3', '5', ['22']).defineVariable('w', '23', '25') }) @@ -177,11 +177,11 @@ describe('Lists with if-then constructs', withShell(shell => { .constant('4') .defineVariable('3', 'y', { definedBy: ['4', '5'] }) .constant('10') - .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: ['22'] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: ['22'] }) .constant('13') - .defineVariable('12', 'y', { definedBy: ['13', '14'], controlDependency: ['22'] }) + .defineVariable('12', 'y', { definedBy: ['13', '14'], controlDependencies: ['22'] }) .constant('19') - .defineVariable('18', 'x', { definedBy: ['19', '20'], controlDependency: ['22'] }) + .defineVariable('18', 'x', { definedBy: ['19', '20'], controlDependencies: ['22'] }) .defineVariable('23', 'w', { definedBy: ['24', '25'] }) .defineVariable('26', 'z', { definedBy: ['27', '28'] }) ) @@ -190,15 +190,15 @@ describe('Lists with if-then constructs', withShell(shell => { .use('15', 'x') .reads('15', ['0', '9']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) - .call('6', '{', [], { returns: [], reads: [BuiltIn], controlDependency: ['13'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['13'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependency: ['13'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('6', '{', [], { returns: [], reads: [BuiltIn], controlDependencies: ['13'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['13'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependencies: ['13'], environment: defaultEnv().defineVariable('x', '0', '2') }) .call('13', 'if', [argumentInCall('3'), argumentInCall('6'), argumentInCall('12')], { returns: ['6', '12'], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', ['13']).defineVariable('x', '9', '11', ['13']) }) .call('16', '<-', [argumentInCall('14'), argumentInCall('15')], { returns: ['14'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2', ['13']).defineVariable('x', '9', '11', ['13']) }) .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) .constant('10') - .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: ['13'] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: ['13'] }) .defineVariable('14', 'y', { definedBy: ['15', '16'] }) ) assertDataflow(label('nested if else', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'newlines', 'if', 'unnamed-arguments']), @@ -219,24 +219,24 @@ print(x)`, emptyGraph() .reads('29', ['9', '15', '23']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .argument('2', ['1', '0']) - .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependency: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('11', ['10', '9']) .argument('12', '11') - .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependency: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('17', '<-', [argumentInCall('15'), argumentInCall('16')], { returns: ['15'], reads: [BuiltIn], controlDependency: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependencies: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('17', '<-', [argumentInCall('15'), argumentInCall('16')], { returns: ['15'], reads: [BuiltIn], controlDependencies: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('17', ['16', '15']) .argument('18', '17') - .call('18', '{', [argumentInCall('17')], { returns: ['17'], reads: [BuiltIn], controlDependency: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('18', '{', [argumentInCall('17')], { returns: ['17'], reads: [BuiltIn], controlDependencies: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('19', '6') .argument('19', '12') .argument('19', '18') - .call('19', 'if', [argumentInCall('6'), argumentInCall('12'), argumentInCall('18')], { returns: ['12', '18'], reads: ['6', BuiltIn], onlyBuiltIn: true, controlDependency: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('19', 'if', [argumentInCall('6'), argumentInCall('12'), argumentInCall('18')], { returns: ['12', '18'], reads: ['6', BuiltIn], onlyBuiltIn: true, controlDependencies: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('20', '19') - .call('20', '{', [argumentInCall('19')], { returns: ['19'], reads: [BuiltIn], controlDependency: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('25','<-', [argumentInCall('23'), argumentInCall('24')], { returns: ['23'], reads: [BuiltIn], controlDependency: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('20', '{', [argumentInCall('19')], { returns: ['19'], reads: [BuiltIn], controlDependencies: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('25','<-', [argumentInCall('23'), argumentInCall('24')], { returns: ['23'], reads: [BuiltIn], controlDependencies: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('25', ['24', '23']) .argument('26', '25') - .call('26', '{', [argumentInCall('25')], { returns: ['25'], reads: [BuiltIn], controlDependency: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('26', '{', [argumentInCall('25')], { returns: ['25'], reads: [BuiltIn], controlDependencies: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('27', '3') .argument('27', '20') .argument('27', '26') @@ -246,11 +246,11 @@ print(x)`, emptyGraph() .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) .constant('10') - .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: ['27'] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: ['27'] }) .constant('16') - .defineVariable('15', 'x', { definedBy: ['16', '17'], controlDependency: ['27'] }) + .defineVariable('15', 'x', { definedBy: ['16', '17'], controlDependencies: ['27'] }) .constant('24') - .defineVariable('23', 'x', { definedBy: ['24', '25'], controlDependency: ['27'] }) + .defineVariable('23', 'x', { definedBy: ['24', '25'], controlDependencies: ['27'] }) ) }) describe('Get and assign', () => { @@ -263,9 +263,9 @@ a()`, emptyGraph() .use('5', 'y') .call('4', '<-', [argumentInCall('0'), argumentInCall('3')], { returns: ['0'], reads: [BuiltIn] }) .argument('4', ['3', '0']) - .call('15', 'assign', [argumentInCall('9'), argumentInCall('13')], { returns: [], reads: [], environment: defaultEnv().defineFunction('a', '0', '4'), onlyBuiltIn: true }) + .call('15', 'assign', [argumentInCall('9'), argumentInCall('13')], { returns: ['9'], reads: [BuiltIn], environment: defaultEnv().defineFunction('a', '0', '4'), onlyBuiltIn: true, controlDependencies: ['17'] }) .argument('15', ['13', '9']) - .call('16', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependency: ['17'], environment: defaultEnv().defineFunction('a', '0', '4') }) + .call('16', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependencies: ['17'], environment: defaultEnv().defineFunction('a', '0', '4') }) .argument('16', '8') .argument('17', '5') .argument('17', '16') @@ -291,7 +291,7 @@ a()`, emptyGraph() graph: new Set(['11']), environment: defaultEnv().pushEnv() }) - .defineVariable('9', '"a"', { definedBy: ['13', '15'], controlDependency: ['17'] }) + .defineVariable('9', '"a"', { definedBy: ['13', '15'], controlDependencies: ['17'] }) ) assertDataflow(label('assign from get', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'newlines', 'assignment-functions', 'strings', 'unnamed-arguments']), shell, 'b <- 5\nassign("a", get("b"))\nprint(a)', emptyGraph() diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts index 5f09114ee1..d4bf1bb1d1 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts @@ -368,9 +368,9 @@ describe('Function Definition', withShell(shell => { .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().pushEnv().pushEnv() }, false) .call('8', '<-', [argumentInCall('2'), argumentInCall('7')], { returns: ['2'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineFunction('g', '2', '8') }, false) - .call('16', 'return', [argumentInCall('14')], { returns: ['14'], reads: [BuiltIn], controlDependency: ['18'], environment: defaultEnv().pushEnv().defineFunction('g', '2', '8').defineVariable('y', '9', '11') }, false) + .call('16', 'return', [argumentInCall('14')], { returns: ['14'], reads: [BuiltIn], controlDependencies: ['18'], environment: defaultEnv().pushEnv().defineFunction('g', '2', '8').defineVariable('y', '9', '11') }, false) .call('18', 'if', [argumentInCall('12'), argumentInCall('16'), EmptyArgument], { returns: ['16'], reads: ['12', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().pushEnv().defineFunction('g', '2', '8').defineVariable('y', '9', '11') }, false) - .call('21', '<-', [argumentInCall('19'), argumentInCall('20')], { returns: ['19'], reads: [BuiltIn], controlDependency: [], environment: defaultEnv().pushEnv().defineFunction('g', '2', '8').defineVariable('y', '9', '11') }, false) + .call('21', '<-', [argumentInCall('19'), argumentInCall('20')], { returns: ['19'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().pushEnv().defineFunction('g', '2', '8').defineVariable('y', '9', '11') }, false) .call('23', '{', [argumentInCall('8'), argumentInCall('11'), argumentInCall('18'), argumentInCall('21'), argumentInCall('22')], { returns: ['22'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineFunction('g', '2', '8').defineVariable('y', '9', '11').defineVariable('y', '19', '21', []) }, false) .returns('23', '16') .defineFunction('7', ['6'], { @@ -385,7 +385,7 @@ describe('Function Definition', withShell(shell => { .constant('10', undefined, false) .defineVariable('9', 'y', { definedBy: ['10', '11'] }, false) .constant('20', undefined, false) - .defineVariable('19', 'y', { definedBy: ['20', '21'], controlDependency: [] }, false) + .defineVariable('19', 'y', { definedBy: ['20', '21'], controlDependencies: [] }, false) .defineFunction('24', ['23'], { out: [], in: [{ nodeId: '12', name: 'z', controlDependencies: [] }], diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts index 6e2267c1c8..ba1c045317 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts @@ -53,9 +53,9 @@ describe('source', withShell(shell => { .use('0', 'x') .use('10', 'N') .reads('10', 'simple-1:10-1:15-0') - .call('6', 'source', [argumentInCall('4')], { returns: [], reads: [BuiltIn], controlDependency: ['8'] }) + .call('6', 'source', [argumentInCall('4')], { returns: [], reads: [BuiltIn], controlDependencies: ['8'] }) .call('simple-1:10-1:15-2', '<-', [argumentInCall('simple-1:10-1:15-0'), argumentInCall('simple-1:10-1:15-1')], { returns: ['simple-1:10-1:15-0'], reads: [BuiltIn] }) - .call('7', '{', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn], controlDependency: ['8'] }) + .call('7', '{', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn], controlDependencies: ['8'] }) .call('8', 'if', [argumentInCall('0'), argumentInCall('7'), EmptyArgument], { returns: ['7'], reads: ['0', BuiltIn], onlyBuiltIn: true }) .call('12', 'cat', [argumentInCall('10')], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('N', 'simple-1:10-1:15-0', 'simple-1:10-1:15-2') }) .constant('4') diff --git a/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts b/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts index a5b563cd01..b7a683fe23 100644 --- a/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts @@ -32,16 +32,16 @@ x`, emptyGraph() .use('14', 'x') .reads('14', ['2', '9']) .call('4', '<-', [argumentInCall('2'), argumentInCall('3')], { returns: ['2'], reads: [BuiltIn] }) - .call('6', 'break', [], { returns: [], reads: [BuiltIn], controlDependency: ['8'], environment: defaultEnv().defineVariable('x', '2', '4') }) + .call('6', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: ['8'], environment: defaultEnv().defineVariable('x', '2', '4') }) .call('8', 'if', [argumentInCall('5'), argumentInCall('6'), EmptyArgument], { returns: ['6'], reads: [BuiltIn, '5'], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '2', '4') }) - .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependency: [], environment: defaultEnv().defineVariable('x', '2', '4') }) + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '2', '4') }) .call('12', '{', [argumentInCall('4'), argumentInCall('8'), argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '2', '4').defineVariable('x', '9', '11', []) }) .call('13', 'repeat', [argumentInCall('12')], { returns: [], reads: [BuiltIn] }) .nse('13', '12') .constant('3') .defineVariable('2', 'x', { definedBy: ['3', '4'] }) .constant('10') - .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: [] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] }) ) }) @@ -62,15 +62,15 @@ x`, emptyGraph() .use('11', 'x') .reads('11', '6') .call('3', ':', [argumentInCall('1'), argumentInCall('2')], { returns: [], reads: ['1', '2', BuiltIn], onlyBuiltIn: true }) - .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: ['6'], reads: [BuiltIn], controlDependency: [] }) - .call('9', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependency: [] }) + .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: ['6'], reads: [BuiltIn], controlDependencies: [] }) + .call('9', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependencies: [] }) .call('10', 'for', [argumentInCall('0'), argumentInCall('3'), argumentInCall('9')], { returns: [], reads: ['0', '3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('i', '0', '10') }) .nse('10', '9') .defineVariable('0', 'i', { definedBy: ['3'] }) .constant('1') .constant('2') - .constant('7', { controlDependency: ['10'] }) - .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependency: [] }) + .constant('7', { controlDependencies: ['10'] }) + .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependencies: [] }) ) @@ -79,8 +79,8 @@ x`, emptyGraph() .reads('14', ['0', '9']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .call('6', ':', [argumentInCall('4'), argumentInCall('5')], { returns: [], reads: ['4', '5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependency: [] }) - .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependency: [] }) + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) + .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependencies: [] }) .call('13', 'for', [argumentInCall('3'), argumentInCall('6'), argumentInCall('12')], { returns: [], reads: ['3', '6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('i', '3', '13') }) .nse('13', '12') .constant('1') @@ -88,8 +88,8 @@ x`, emptyGraph() .defineVariable('3', 'i', { definedBy: ['6'] }) .constant('4') .constant('5') - .constant('10', { controlDependency: ['13'] }) - .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: [] }) + .constant('10', { controlDependencies: ['13'] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] }) ) assertDataflow(label('redefinition within loop', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'newlines', 'for-loop']), shell, 'x <- 9\nfor(i in 1:10) { x <- x }\n x', emptyGraph() .use('10', 'x', { controlDependencies: [] }) @@ -98,8 +98,8 @@ x`, emptyGraph() .reads('14', ['0', '9']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .call('6', ':', [argumentInCall('4'), argumentInCall('5')], { returns: [], reads: ['4', '5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependency: [] }) - .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependency: [] }) + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) + .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependencies: [] }) .call('13', 'for', [argumentInCall('3'), argumentInCall('6'), argumentInCall('12')], { returns: [], reads: ['3', '6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('i', '3', '13') }) .nse('13', '12') .constant('1') @@ -107,7 +107,7 @@ x`, emptyGraph() .defineVariable('3', 'i', { definedBy: ['6'] }) .constant('4') .constant('5') - .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: [] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] }) ) assertDataflow(label('double redefinition within loop', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'newlines', 'for-loop', 'semicolons']), shell, 'x <- 9\nfor(i in 1:10) { x <- x; x <- x }\n x', emptyGraph() @@ -119,9 +119,9 @@ x`, emptyGraph() .reads('17', ['0', '9', '12']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .call('6', ':', [argumentInCall('4'), argumentInCall('5')], { returns: [], reads: ['4', '5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependency: [] }) - .call('14', '<-', [argumentInCall('12'), argumentInCall('13')], { returns: ['12'], reads: [BuiltIn], controlDependency: [], environment: defaultEnv().defineVariable('x', '9', '11', ['16']) }) - .call('15', '{', [argumentInCall('11'), argumentInCall('14')], { returns: ['14'], reads: [BuiltIn], controlDependency: [], environment: defaultEnv().defineVariable('x', '9', '11', ['16']) }) + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) + .call('14', '<-', [argumentInCall('12'), argumentInCall('13')], { returns: ['12'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['16']) }) + .call('15', '{', [argumentInCall('11'), argumentInCall('14')], { returns: ['14'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['16']) }) .call('16', 'for', [argumentInCall('3'), argumentInCall('6'), argumentInCall('15')], { returns: [], reads: ['3', '6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('x', '12', '14', []).defineVariable('i', '3', '16') }) .nse('16', '15') .constant('1') @@ -129,8 +129,8 @@ x`, emptyGraph() .defineVariable('3', 'i', { definedBy: ['6'] }) .constant('4') .constant('5') - .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependency: [] }) - .defineVariable('12', 'x', { definedBy: ['13', '14'], controlDependency: [] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] }) + .defineVariable('12', 'x', { definedBy: ['13', '14'], controlDependencies: [] }) ) assertDataflow(label('loop-variable redefined within loop', ['name-normal', 'for-loop', 'semicolons', 'newlines', 'numbers']), shell, 'for(i in 1:10) { i; i <- 12 }\n i', emptyGraph() @@ -139,15 +139,15 @@ x`, emptyGraph() .use('12', 'i') .reads('12', ['0', '7']) .call('3', ':', [argumentInCall('1'), argumentInCall('2')], { returns: [], reads: ['1', '2', BuiltIn], onlyBuiltIn: true }) - .call('9', '<-', [argumentInCall('7'), argumentInCall('8')], { returns: ['7'], reads: [BuiltIn], controlDependency: [] }) - .call('10', '{', [argumentInCall('6'), argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependency: [] }) + .call('9', '<-', [argumentInCall('7'), argumentInCall('8')], { returns: ['7'], reads: [BuiltIn], controlDependencies: [] }) + .call('10', '{', [argumentInCall('6'), argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) .call('11', 'for', [argumentInCall('0'), argumentInCall('3'), argumentInCall('10')], { returns: [], reads: ['0', '3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('i', '0', '11', []).defineVariable('i', '7', '9', []) }) .nse('11', '10') .defineVariable('0', 'i', { definedBy: ['3'] }) .constant('1') .constant('2') - .constant('8', { controlDependency: ['11'] }) - .defineVariable('7', 'i', { definedBy: ['8', '9'], controlDependency: [] }) + .constant('8', { controlDependencies: ['11'] }) + .defineVariable('7', 'i', { definedBy: ['8', '9'], controlDependencies: [] }) ) describe('Branch coverage', () => { diff --git a/test/functionality/dataflow/processing-of-elements/loops/dataflow-while-loop-tests.ts b/test/functionality/dataflow/processing-of-elements/loops/dataflow-while-loop-tests.ts index c6c064d477..56fba26045 100644 --- a/test/functionality/dataflow/processing-of-elements/loops/dataflow-while-loop-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/loops/dataflow-while-loop-tests.ts @@ -10,7 +10,7 @@ describe('While', withShell(shell => { .call('3', 'while', [argumentInCall('0'), argumentInCall('1')], { returns: [], reads: ['0', BuiltIn], onlyBuiltIn: true }) .nse('3', '1') .constant('0') - .constant('1', { controlDependency: [] }) + .constant('1', { controlDependencies: [] }) ) assertDataflow(label('using variable in body', ['while-loop', 'logical', 'name-normal']), shell, 'while (TRUE) x', emptyGraph() .use('1', 'x', { controlDependencies: [] }) @@ -19,13 +19,13 @@ describe('While', withShell(shell => { .constant('0') ) assertDataflow(label('assignment in loop body', ['while-loop', 'logical', 'name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers']), shell, 'while (TRUE) { x <- 3 }', emptyGraph() - .call('5', '<-', [argumentInCall('3'), argumentInCall('4')], { returns: ['3'], reads: [BuiltIn], controlDependency: [] }) - .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependency: [] }) + .call('5', '<-', [argumentInCall('3'), argumentInCall('4')], { returns: ['3'], reads: [BuiltIn], controlDependencies: [] }) + .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], controlDependencies: [] }) .call('7', 'while', [argumentInCall('0'), argumentInCall('6')], { returns: [], reads: ['0', BuiltIn], onlyBuiltIn: true }) .nse('7', '6') .constant('0') - .constant('4', { controlDependency: ['7'] }) - .defineVariable('3', 'x', { definedBy: ['4', '5'], controlDependency: [] }) + .constant('4', { controlDependencies: ['7'] }) + .defineVariable('3', 'x', { definedBy: ['4', '5'], controlDependencies: [] }) ) assertDataflow(label('def compare in loop', ['while-loop', 'grouping', ...OperatorDatabase['<-'].capabilities, 'name-normal', 'infix-calls', 'binary-operator', ...OperatorDatabase['-'].capabilities, ...OperatorDatabase['>'].capabilities, 'precedence']), shell, 'while ((x <- x - 1) > 0) { x }', emptyGraph() .use('3', 'x') @@ -35,7 +35,7 @@ describe('While', withShell(shell => { .call('6', '<-', [argumentInCall('2'), argumentInCall('5')], { returns: ['2'], reads: [BuiltIn] }) .call('7', '(', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn] }) .call('9', '>', [argumentInCall('7'), argumentInCall('8')], { returns: [], reads: [BuiltIn, '7', '8'], onlyBuiltIn: true }) - .call('13', '{', [argumentInCall('12')], { returns: ['12'], reads: [BuiltIn], controlDependency: [], environment: defaultEnv().defineVariable('x', '2', '6') }) + .call('13', '{', [argumentInCall('12')], { returns: ['12'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '2', '6') }) .call('14', 'while', [argumentInCall('9'), argumentInCall('13')], { returns: [], reads: ['9', BuiltIn], onlyBuiltIn: true }) .nse('14', '13') .constant('4') From fb7d76ac3a7fcfbfef93654c597e2de17a850426 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 22 May 2024 13:26:40 +0200 Subject: [PATCH 10/23] test: branch coverage df tests for repeat, for and while --- .../loops/dataflow-for-loop-tests.ts | 293 +++++++++++++++++- .../control-flow-tests.ts | 2 +- 2 files changed, 293 insertions(+), 2 deletions(-) diff --git a/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts b/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts index b7a683fe23..faa43462c0 100644 --- a/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts @@ -151,6 +151,297 @@ x`, emptyGraph() ) describe('Branch coverage', () => { - + describe('repeat', () => { + assertDataflow(label('Break immediately', ['repeat-loop', 'name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments']), + shell, `x <- 1 +repeat { + x <- 2; + break +} +print(x)`, emptyGraph() + .use('12', 'x') + .reads('12', '5') + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('7', '<-', [argumentInCall('5'), argumentInCall('6')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('7', ['6', '5']) + .call('8', 'break', [], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '5', '7') }) + .argument('9', '7') + .argument('9', '8') + .call('9', '{', [argumentInCall('7'), argumentInCall('8')], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '5', '7') }) + .argument('10', '9') + .call('10', 'repeat', [argumentInCall('9')], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .nse('10', '9') + .argument('14', '12') + .call('14', 'print', [argumentInCall('12')], { returns: ['12'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '5', '7') }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .constant('6') + .defineVariable('5', 'x', { definedBy: ['6', '7'] })) + assertDataflow(label('Break in condition', ['repeat-loop', 'name-normal', 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments', 'if']), + shell, `x <- 1 +repeat { + x <- 2; + if(foo) + break +} +print(x)`, emptyGraph() + .use('8', 'foo') + .use('15', 'x') + .reads('15', '5') + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('7', '<-', [argumentInCall('5'), argumentInCall('6')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('7', ['6', '5']) + .call('9', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: ['11'], environment: defaultEnv().defineVariable('x', '5', '7') }) + .argument('11', '8') + .argument('11', '9') + .call('11', 'if', [argumentInCall('8'), argumentInCall('9', { controlDependencies: ['11'] }), EmptyArgument], { returns: ['9'], reads: [BuiltIn, '8'], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '5', '7') }) + .argument('12', '7') + .argument('12', '11') + .call('12', '{', [argumentInCall('7'), argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '5', '7') }) + .argument('13', '12') + .call('13', 'repeat', [argumentInCall('12')], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .nse('13', '12') + .argument('17', '15') + .call('17', 'print', [argumentInCall('15')], { returns: ['15'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '5', '7') }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .constant('6') + .defineVariable('5', 'x', { definedBy: ['6', '7'] })) + assertDataflow(label('Next', ['repeat-loop', 'newlines', 'name-normal', 'numbers', 'next', 'semicolons', 'unnamed-arguments']), + shell, `x <- 1 +repeat { + x <- 2; + next; + x <- 3; +} +print(x)`, emptyGraph() + .use('17', 'x') + .reads('17', '5') + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('7', '<-', [argumentInCall('5'), argumentInCall('6')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('7', ['6', '5']) + .call('8', 'next', [], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '5', '7') }) + .argument('14', '7') + .call('14', '{', [argumentInCall('7')], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('15', '14') + .call('15', 'repeat', [argumentInCall('14')], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .nse('15', '14') + .argument('19', '17') + .call('19', 'print', [argumentInCall('17')], { returns: ['17'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '5', '7') }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .constant('6') + .defineVariable('5', 'x', { definedBy: ['6', '7'] })) + }) + + describe('for', () => { + assertDataflow(label('Break immediately', ['for-loop', 'name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments']), + shell, `x <- 1 +for(i in 1:100) { + x <- 2; + break +} +print(x)`, emptyGraph() + .use('16', 'x') + .reads('16', ['0', '9']) + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('6', ':', [argumentInCall('4'), argumentInCall('5')], { returns: [], reads: ['4', '5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('6', ['4', '5']) + .call('11', '<-', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: ['14'] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) + .argument('11', ['10', '9']) + .call('12', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['14']) }) + .argument('13', '11') + .argument('13', '12') + .call('13', '{', [argumentInCall('11', { controlDependencies: [] }), argumentInCall('12', { controlDependencies: [] })], { returns: ['12'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['14']) }) + .argument('14', '6') + .argument('14', '13') + .call('14', 'for', [argumentInCall('3'), argumentInCall('6'), argumentInCall('13', { controlDependencies: [] })], { returns: [], reads: ['3', '6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('i', '3', '14') }) + .argument('14', '3') + .nse('14', '13') + .argument('18', '16') + .call('18', 'print', [argumentInCall('16')], { returns: ['16'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('i', '3', '14') }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .defineVariable('3', 'i', { definedBy: ['6'] }) + .constant('4') + .constant('5') + .constant('10', { controlDependencies: ['14'] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] })) + assertDataflow(label('Break in condition', ['for-loop', 'name-normal', 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments', 'if']), + shell, `x <- 1 +for(i in 1:100) { + x <- 2; + if(foo) + break +} +print(x)`, emptyGraph() + .use('12', 'foo', { controlDependencies: [] }) + .use('19', 'x') + .reads('19', ['0', '9']) + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('6', ':', [argumentInCall('4'), argumentInCall('5')], { returns: [], reads: ['4', '5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('6', ['4', '5']) + .call('11', '<-', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: ['17', '15'] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) + .argument('11', ['10', '9']) + .call('13', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['17']) }) + .argument('15', '12') + .argument('15', '13') + .call('15', 'if', [argumentInCall('12', { controlDependencies: [] }), argumentInCall('13', { controlDependencies: [] }), EmptyArgument], { returns: ['13'], reads: ['12', BuiltIn], onlyBuiltIn: true, controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['17', '15']) }) + .argument('16', '11') + .argument('16', '15') + .call('16', '{', [argumentInCall('11', { controlDependencies: [] }), argumentInCall('15', { controlDependencies: [] })], { returns: ['15'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['17', '15']) }) + .argument('17', '6') + .argument('17', '16') + .call('17', 'for', [argumentInCall('3'), argumentInCall('6'), argumentInCall('16', { controlDependencies: [] })], { returns: [], reads: ['3', '6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('i', '3', '17') }) + .argument('17', '3') + .nse('17', '16') + .argument('21', '19') + .call('21', 'print', [argumentInCall('19')], { returns: ['19'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('i', '3', '17') }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .defineVariable('3', 'i', { definedBy: ['6'] }) + .constant('4') + .constant('5') + .constant('10', { controlDependencies: ['17', '15'] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] })) + assertDataflow(label('Next', ['for-loop', 'newlines', 'name-normal', 'numbers', 'next', 'semicolons', 'unnamed-arguments']), + shell, `x <- 1 +for(i in 1:100) { + x <- 2; + next; + x <- 3; +} +print(x)`, emptyGraph() + .use('21', 'x') + .reads('21', ['0', '9', '14']) + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('6', ':', [argumentInCall('4'), argumentInCall('5')], { returns: [], reads: ['4', '5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('6', ['4', '5']) + .call('11', '<-', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: ['19'] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) + .argument('11', ['10', '9']) + .call('12', 'next', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['19']) }) + .call('16', '<-', [argumentInCall('14', { controlDependencies: [] }), argumentInCall('15', { controlDependencies: ['19'] })], { returns: ['14'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['19']) }) + .argument('16', ['15', '14']) + .argument('18', '11') + .call('18', '{', [argumentInCall('11', { controlDependencies: [] })], { returns: ['11'], reads: [BuiltIn], controlDependencies: [] }) + .argument('19', '6') + .argument('19', '18') + .call('19', 'for', [argumentInCall('3'), argumentInCall('6'), argumentInCall('18', { controlDependencies: [] })], { returns: [], reads: ['3', '6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('x', '14', '16', []).defineVariable('i', '3', '19') }) + .argument('19', '3') + .nse('19', '18') + .argument('23', '21') + .call('23', 'print', [argumentInCall('21')], { returns: ['21'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('x', '14', '16', []).defineVariable('i', '3', '19') }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .defineVariable('3', 'i', { definedBy: ['6'] }) + .constant('4') + .constant('5') + .constant('10', { controlDependencies: ['19'] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] }) + .constant('15', { controlDependencies: ['19'] }) + .defineVariable('14', 'x', { definedBy: ['15', '16'], controlDependencies: [] })) + }) + + describe('while', () => { + assertDataflow(label('Break immediately', ['while-loop', 'name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments']), + shell, `x <- 1 +while(TRUE) { + x <- 2; + break +} +print(x)`, emptyGraph() + .use('13', 'x') + .reads('13', ['0', '6']) + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('8', '<-', [argumentInCall('6', { controlDependencies: [] }), argumentInCall('7', { controlDependencies: ['11'] })], { returns: ['6'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('8', ['7', '6']) + .call('9', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['11']) }) + .argument('10', '8') + .argument('10', '9') + .call('10', '{', [argumentInCall('8', { controlDependencies: [] }), argumentInCall('9', { controlDependencies: [] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['11']) }) + .argument('11', '10') + .call('11', 'while', [argumentInCall('3'), argumentInCall('10', { controlDependencies: [] })], { returns: [], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['11']) }) + .argument('11', '3') + .nse('11', '10') + .argument('15', '13') + .call('15', 'print', [argumentInCall('13')], { returns: ['13'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '6', '8', []) }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .constant('3') + .constant('7', { controlDependencies: ['11'] }) + .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependencies: [] })) + assertDataflow(label('Break in condition', ['while-loop', 'name-normal', 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments', 'if']), + shell, `x <- 1 +while(TRUE) { + x <- 2; + if(foo) + break +} +print(x)`, emptyGraph() + .use('9', 'foo', { controlDependencies: [] }) + .use('16', 'x') + .reads('16', ['0', '6']) + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('8', '<-', [argumentInCall('6', { controlDependencies: [] }), argumentInCall('7', { controlDependencies: ['14', '12'] })], { returns: ['6'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('8', ['7', '6']) + .call('10', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['14']) }) + .argument('12', '9') + .argument('12', '10') + .call('12', 'if', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: [] }), EmptyArgument], { returns: ['10'], reads: [BuiltIn, '9'], onlyBuiltIn: true, controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['14', '12']) }) + .argument('13', '8') + .argument('13', '12') + .call('13', '{', [argumentInCall('8', { controlDependencies: [] }), argumentInCall('12', { controlDependencies: [] })], { returns: ['12'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['14', '12']) }) + .argument('14', '13') + .call('14', 'while', [argumentInCall('3'), argumentInCall('13', { controlDependencies: [] })], { returns: [], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['14', '12']) }) + .argument('14', '3') + .nse('14', '13') + .argument('18', '16') + .call('18', 'print', [argumentInCall('16')], { returns: ['16'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '6', '8', []) }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .constant('3') + .constant('7', { controlDependencies: ['14', '12'] }) + .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependencies: [] })) + assertDataflow(label('Next', ['while-loop', 'newlines', 'name-normal', 'numbers', 'next', 'semicolons', 'unnamed-arguments']), + shell, `x <- 1 +while(TRUE) { + x <- 2; + next; + x <- 3; +} +print(x)`, emptyGraph() + .use('18', 'x') + .reads('18', ['0', '6', '11']) + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('8', '<-', [argumentInCall('6', { controlDependencies: [] }), argumentInCall('7', { controlDependencies: ['16'] })], { returns: ['6'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('8', ['7', '6']) + .call('9', 'next', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['16']) }) + .call('13', '<-', [argumentInCall('11', { controlDependencies: [] }), argumentInCall('12', { controlDependencies: ['16'] })], { returns: ['11'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['16']) }) + .argument('13', ['12', '11']) + .argument('15', '8') + .call('15', '{', [argumentInCall('8', { controlDependencies: [] })], { returns: ['8'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['16']).defineVariable('x', '11', '13', []) }) + .argument('16', '15') + .call('16', 'while', [argumentInCall('3'), argumentInCall('15', { controlDependencies: [] })], { returns: [], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['16']).defineVariable('x', '11', '13', []) }) + .argument('16', '3') + .nse('16', '15') + .argument('20', '18') + .call('20', 'print', [argumentInCall('18')], { returns: ['18'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '6', '8', []).defineVariable('x', '11', '13', []) }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .constant('3') + .constant('7', { controlDependencies: ['16'] }) + .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependencies: [] }) + .constant('12', { controlDependencies: ['16'] }) + .defineVariable('11', 'x', { definedBy: ['12', '13'], controlDependencies: [] })) + }) }) })) diff --git a/test/functionality/slicing/static-program-slices/control-flow-tests.ts b/test/functionality/slicing/static-program-slices/control-flow-tests.ts index 30685b1108..35946a1988 100644 --- a/test/functionality/slicing/static-program-slices/control-flow-tests.ts +++ b/test/functionality/slicing/static-program-slices/control-flow-tests.ts @@ -49,7 +49,7 @@ ${loop} { if(foo) break } x`) - assertSliced(label('Next', [...caps]), + assertSliced(label('Next', [...caps, 'newlines', 'name-normal', 'numbers', 'next', 'semicolons', 'unnamed-arguments']), shell, `x <- 1 ${loop} { x <- 2; From eefafb00d08df68e08581ab0d140511b97fba186 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 22 May 2024 15:06:59 +0200 Subject: [PATCH 11/23] test: finished up initial batch of dataflow tests --- .../atomic/dataflow-redefine-tests.ts | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 test/functionality/dataflow/processing-of-elements/atomic/dataflow-redefine-tests.ts diff --git a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-redefine-tests.ts b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-redefine-tests.ts new file mode 100644 index 0000000000..4009ce90f2 --- /dev/null +++ b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-redefine-tests.ts @@ -0,0 +1,146 @@ +import { assertDataflow, withShell } from '../../../_helper/shell' +import { label } from '../../../_helper/label' +import { emptyGraph } from '../../../_helper/dataflow/dataflowgraph-builder' +import { OperatorDatabase } from '../../../../../src/r-bridge/lang-4.x/ast/model/operators' +import { argumentInCall, defaultEnv } from '../../../_helper/dataflow/environment-builder' +import { EmptyArgument } from '../../../../../src/r-bridge/lang-4.x/ast/model/nodes/r-function-call' +import { BuiltIn } from '../../../../../src/dataflow/environments/built-in' + +describe('Redefining builtins', withShell(shell => { + assertDataflow(label('if (print)', ['name-escaped', 'formals-dot-dot-dot', 'implicit-return', 'numbers', 'unnamed-arguments', ...OperatorDatabase['<-'].capabilities, 'newlines']), + shell, `\`if\` <- function(...) 2 +if(1) + print(3)`, emptyGraph() + .call('6', '<-', [argumentInCall('0'), argumentInCall('5')], { returns: ['0'], reads: [BuiltIn] }) + .argument('6', ['5', '0']) + .call('11', 'print', [argumentInCall('9')], { returns: ['9'], reads: [BuiltIn], environment: defaultEnv().defineFunction('if', '0', '6') }) + .argument('11', '9') + .definesOnCall('11', '1') + .argument('13', '11') + .call('13', 'if', [argumentInCall('7'), argumentInCall('11'), EmptyArgument], { returns: ['3'], reads: ['0'], environment: defaultEnv().defineFunction('if', '0', '6') }) + .argument('13', '7') + .calls('13', '5') + .defineVariable('1', '...', { definedBy: [] }, false) + .constant('3', undefined, false) + .defineFunction('5', ['3'], { + out: [], + in: [{ nodeId: '3', name: undefined, controlDependencies: [] }], + unknownReferences: [], + entryPoint: '3', + graph: new Set(['1', '3']), + environment: defaultEnv().pushEnv().defineParameter('...', '1', '2') + }) + .defineVariable('0', '`if`', { definedBy: ['5', '6'] }) + .constant('7') + .definesOnCall('7', '1') + .constant('9')) + assertDataflow(label('if (assignment)', ['name-escaped', 'formals-dot-dot-dot', 'implicit-return', 'numbers', 'unnamed-arguments', 'name-normal', ...OperatorDatabase['<-'].capabilities, 'newlines']), + shell, `\`if\` <- function(...) 2 +if(1) + x <- 3 +print(x)`, emptyGraph() + .use('14', 'x') + .reads('14', '8') + .call('6', '<-', [argumentInCall('0'), argumentInCall('5')], { returns: ['0'], reads: [BuiltIn] }) + .argument('6', ['5', '0']) + .call('10', '<-', [argumentInCall('8'), argumentInCall('9')], { returns: ['8'], reads: [BuiltIn], environment: defaultEnv().defineFunction('if', '0', '6') }) + .argument('10', ['9', '8']) + .definesOnCall('10', '1') + .argument('12', '10') + .call('12', 'if', [argumentInCall('7'), argumentInCall('10'), EmptyArgument], { returns: ['3'], reads: ['0'], environment: defaultEnv().defineFunction('if', '0', '6') }) + .argument('12', '7') + .calls('12', '5') + .argument('16', '14') + .call('16', 'print', [argumentInCall('14')], { returns: ['14'], reads: [BuiltIn], environment: defaultEnv().defineFunction('if', '0', '6').defineVariable('x', '8', '10') }) + .defineVariable('1', '...', { definedBy: [] }, false) + .constant('3', undefined, false) + .defineFunction('5', ['3'], { + out: [], + in: [{ nodeId: '3', name: undefined, controlDependencies: [] }], + unknownReferences: [], + entryPoint: '3', + graph: new Set(['1', '3']), + environment: defaultEnv().pushEnv().defineParameter('...', '1', '2') + }) + .defineVariable('0', '`if`', { definedBy: ['5', '6'] }) + .constant('7') + .definesOnCall('7', '1') + .constant('9') + .defineVariable('8', 'x', { definedBy: ['9', '10'] })) + assertDataflow(label('<-', []), + shell, `x <- 2 +\`<-\` <- \`*\` +x <- 3 +print(y = x)`, emptyGraph() + .use('4', '`*`') + .reads('4', BuiltIn) + .use('6', 'x') + .reads('6', '0') + .use('11', 'x') + .reads('11', '0') + .use('12', 'y') + .reads('12', '11') + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .argument('5', '4') + .call('5', '<-', [argumentInCall('3'), argumentInCall('4')], { returns: ['3'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('5', '3') + .argument('8', '6') + .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: [], reads: ['3'], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('<-', '3', '5') }) + .argument('8', '7') + .argument('13', '12') + .call('13', 'print', [argumentInCall('12', { name: 'y' } )], { returns: ['12'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('<-', '3', '5') }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .defineVariable('3', '`<-`', { definedBy: ['4', '5'] }) + .constant('7')) + assertDataflow(label('<- in function', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'normal-definition', 'implicit-return','newlines', ...OperatorDatabase['*'].capabilities, 'call-normal', 'unnamed-arguments']), + shell, `f <- function() { + x <- 2 + \`<-\` <- \`*\` + x <- 3 +} +y <- f() +print(y)`, emptyGraph() + .use('7', '`*`', undefined, false) + .reads('7', BuiltIn) + .use('9', 'x', undefined, false) + .reads('9', '3') + .use('20', 'y') + .reads('20', '15') + .call('5', '<-', [argumentInCall('3'), argumentInCall('4')], { returns: ['3'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) + .argument('5', ['4', '3']) + .argument('8', '7') + .call('8', '<-', [argumentInCall('6'), argumentInCall('7')], { returns: ['6'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineVariable('x', '3', '5') }, false) + .argument('8', '6') + .argument('11', '9') + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: [], reads: ['6'], environment: defaultEnv().pushEnv().defineVariable('x', '3', '5').defineVariable('<-', '6', '8') }, false) + .argument('11', '10') + .argument('12', '5') + .argument('12', '8') + .argument('12', '11') + .call('12', '{', [argumentInCall('5'), argumentInCall('8'), argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineVariable('x', '3', '5').defineVariable('<-', '6', '8') }, false) + .call('14', '<-', [argumentInCall('0'), argumentInCall('13')], { returns: ['0'], reads: [BuiltIn] }) + .argument('14', ['13', '0']) + .call('17', 'f', [], { returns: ['12'], reads: ['0'], environment: defaultEnv().defineFunction('f', '0', '14') }) + .calls('17', '13') + .argument('18', '17') + .call('18', '<-', [argumentInCall('15'), argumentInCall('17')], { returns: ['15'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '14') }) + .argument('18', '15') + .argument('22', '20') + .call('22', 'print', [argumentInCall('20')], { returns: ['20'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '14').defineVariable('y', '15', '18') }) + .constant('4', undefined, false) + .defineVariable('3', 'x', { definedBy: ['4', '5'] }, false) + .defineVariable('6', '`<-`', { definedBy: ['7', '8'] }, false) + .constant('10', undefined, false) + .defineFunction('13', ['12'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '12', + graph: new Set(['4', '3', '5', '7', '6', '8', '9', '10', '11', '12']), + environment: defaultEnv().pushEnv().defineVariable('x', '3', '5').defineVariable('<-', '6', '8') + }) + .defineVariable('0', 'f', { definedBy: ['13', '14'] }) + .defineVariable('15', 'y', { definedBy: ['17', '18'] })) +})) From 0a14c3897482940fc68a8fb08989be1a423f678d Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Thu, 23 May 2024 16:29:40 +0200 Subject: [PATCH 12/23] test: added dead code dataflow tests --- .../dataflow-function-definition-tests.ts | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts index d4bf1bb1d1..322f792dbe 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts @@ -451,4 +451,191 @@ describe('Function Definition', withShell(shell => { .defineVariable('18', 'b', { definedBy: ['19', '20'] }) ) }) + + describe('Dead Code', () => { + assertDataflow(label('simple return', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-named', 'newlines', 'numbers', ...OperatorDatabase['*'].capabilities, 'return', 'unnamed-arguments']), + shell, `f <- function(x) { + x <- 3 * x + return(x) + x <- 2 + return(x) +} + +f(5)`, emptyGraph() + .use('7', 'x', undefined, false) + .reads('7', '1') + .use('11', 'x', undefined, false) + .reads('11', '5') + .argument('8', '7') + .call('8', '*', [argumentInCall('6'), argumentInCall('7')], { returns: [], reads: [BuiltIn, '6', '7'], onlyBuiltIn: true, environment: defaultEnv().pushEnv().defineParameter('x', '1', '2') }, false) + .argument('8', '6') + .argument('9', '8') + .call('9', '<-', [argumentInCall('5'), argumentInCall('8')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('x', '1', '2') }, false) + .argument('9', '5') + .argument('13', '11') + .call('13', 'return', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) + .argument('21', '9') + .argument('21', '13') + .call('21', '{', [argumentInCall('9'), argumentInCall('13')], { returns: ['13'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) + .call('23', '<-', [argumentInCall('0'), argumentInCall('22')], { returns: ['0'], reads: [BuiltIn] }) + .argument('23', ['22', '0']) + .call('27', 'f', [argumentInCall('25')], { returns: ['21'], reads: ['0'], environment: defaultEnv().defineFunction('f', '0', '23') }) + .argument('27', '25') + .calls('27', '22') + .defineVariable('1', 'x', { definedBy: [] }, false) + .constant('6', undefined, false) + .defineVariable('5', 'x', { definedBy: ['8', '9'] }, false) + .defineFunction('22', ['21'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '21', + graph: new Set(['1', '6', '7', '8', '5', '9', '11', '13', '21']), + environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') + }) + .defineVariable('0', 'f', { definedBy: ['22', '23'] }) + .constant('25') + .definesOnCall('25', '1')) + // this is potentially incorrect, see https://github.com/Code-Inspect/flowr/issues/816 + assertDataflow(label('return in if',['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-named', 'newlines', 'numbers', ...OperatorDatabase['*'].capabilities, 'return', 'unnamed-arguments', 'if']), + shell, `f <- function(x) { + x <- 3 * x + if(k) + return(x) + else + return(1) + x <- 2 + return(x) +} + +f(5)`, emptyGraph() + .use('7', 'x', undefined, false) + .reads('7', '1') + .use('10', 'k', undefined, false) + .use('12', 'x', undefined, false) + .reads('12', '5') + .use('26', 'x', undefined, false) + .reads('26', ['5', '22']) + .argument('8', '7') + .call('8', '*', [argumentInCall('6'), argumentInCall('7')], { returns: [], reads: [BuiltIn, '6', '7'], onlyBuiltIn: true, environment: defaultEnv().pushEnv().defineParameter('x', '1', '2') }, false) + .argument('8', '6') + .argument('9', '8') + .call('9', '<-', [argumentInCall('5'), argumentInCall('8')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('x', '1', '2') }, false) + .argument('9', '5') + .argument('14', '12') + .call('14', 'return', [argumentInCall('12')], { returns: ['12'], reads: [BuiltIn], controlDependencies: ['21'], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) + .call('19', 'return', [argumentInCall('17')], { returns: ['17'], reads: [BuiltIn], controlDependencies: ['21'], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) + .argument('19', '17') + .argument('21', '10') + .argument('21', '14') + .argument('21', '19') + .call('21', 'if', [argumentInCall('10'), argumentInCall('14', { controlDependencies: ['21'] }), argumentInCall('19', { controlDependencies: ['21'] })], { returns: ['14', '19'], reads: ['10', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) + .call('24', '<-', [argumentInCall('22', { controlDependencies: [] }), argumentInCall('23')], { returns: ['22'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) + .argument('24', ['23', '22']) + .argument('28', '26') + .call('28', 'return', [argumentInCall('26')], { returns: ['26'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9').defineVariable('x', '22', '24', []) }, false) + .argument('29', '9') + .argument('29', '21') + .argument('29', '24') + .argument('29', '28') + .call('29', '{', [argumentInCall('9'), argumentInCall('21'), argumentInCall('24', { controlDependencies: [] }), argumentInCall('28', { controlDependencies: [] })], { returns: ['28', '14', '19'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9').defineVariable('x', '22', '24', []) }, false) + .call('31', '<-', [argumentInCall('0'), argumentInCall('30')], { returns: ['0'], reads: [BuiltIn] }) + .argument('31', ['30', '0']) + .call('35', 'f', [argumentInCall('33')], { returns: ['29'], reads: ['0'], environment: defaultEnv().defineFunction('f', '0', '31') }) + .argument('35', '33') + .calls('35', '30') + .defineVariable('1', 'x', { definedBy: [] }, false) + .constant('6', undefined, false) + .defineVariable('5', 'x', { definedBy: ['8', '9'] }, false) + .constant('17', undefined, false) + .constant('23', undefined, false) + .defineVariable('22', 'x', { definedBy: ['23', '24'], controlDependencies: [] }, false) + .defineFunction('30', ['29'], { + out: [], + in: [{ nodeId: '10', name: 'k', controlDependencies: [] }], + unknownReferences: [], + entryPoint: '29', + graph: new Set(['1', '6', '7', '8', '5', '9', '10', '12', '14', '17', '19', '21', '23', '22', '24', '26', '28', '29']), + environment: defaultEnv().pushEnv().defineParameter('x', '1', '2').defineVariable('x', '5', '9').defineVariable('x', '22', '24', []) + }) + .defineVariable('0', 'f', { definedBy: ['30', '31'] }) + .constant('33') + .definesOnCall('33', '1')) + }) + + describe('Side Effects', () => { + assertDataflow(label('global definition', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-named', 'numbers', 'implicit-return', ...OperatorDatabase['*'].capabilities, ...OperatorDatabase['<<-'].capabilities, 'lambda-syntax', 'unnamed-arguments', ...OperatorDatabase['+'].capabilities, 'side-effects-in-function-call']), + shell, `f <- function(x) 2 * x + +m <- function(g) { + f <<- g +} + +m(\\(x) x + 1) + +f(3)`, emptyGraph() + .use('4', 'x', undefined, false) + .reads('4', '1') + .use('15', 'g', undefined, false) + .reads('15', '10') + .use('23', 'x', undefined, false) + .reads('23', '21') + .argument('5', '4') + .call('5', '*', [argumentInCall('3'), argumentInCall('4')], { returns: [], reads: ['3', '4', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().pushEnv().defineParameter('x', '1', '2') }, false) + .argument('5', '3') + .call('8', '<-', [argumentInCall('0'), argumentInCall('7')], { returns: ['0'], reads: [BuiltIn] }) + .argument('8', ['7', '0']) + .argument('16', '15') + .call('16', '<<-', [argumentInCall('14'), argumentInCall('15')], { returns: ['14'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('g', '10', '11') }, false) + .argument('16', '14') + .argument('17', '16') + .call('17', '{', [argumentInCall('16')], { returns: ['16'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('g', '10', '11') }, false) + .call('19', '<-', [argumentInCall('9'), argumentInCall('18')], { returns: ['9'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '8') }) + .argument('19', ['18', '9']) + .argument('25', '23') + .call('25', '+', [argumentInCall('23'), argumentInCall('24')], { returns: [], reads: ['23', '24', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().pushEnv().defineParameter('x', '21', '22') }, false) + .argument('25', '24') + .call('29', 'm', [argumentInCall('27')], { returns: ['17'], reads: ['9'], environment: defaultEnv().defineFunction('f', '0', '8').defineFunction('m', '9', '19') }) + .argument('29', '27') + .calls('29', '18') + .call('33', 'f', [argumentInCall('31')], { returns: ['25'], reads: ['14'], environment: defaultEnv().defineVariable('f', '14', '16').defineFunction('m', '9', '19') }) + .argument('33', '31') + .calls('33', '27') + .defineVariable('1', 'x', { definedBy: [] }, false) + .constant('3', undefined, false) + .defineFunction('7', ['5'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '5', + graph: new Set(['1', '3', '4', '5']), + environment: defaultEnv().pushEnv().defineParameter('x', '1', '2') + }) + .defineVariable('0', 'f', { definedBy: ['7', '8'] }) + .defineVariable('10', 'g', { definedBy: [] }, false) + .defineVariable('14', 'f', { definedBy: ['15', '16'] }, false) + .sideEffectOnCall('14', '29') + .defineFunction('18', ['17'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '17', + graph: new Set(['10', '15', '14', '16', '17']), + environment: defaultEnv().pushEnv().defineVariable('f', '14', '16') + }, { environment: defaultEnv().defineVariable('f', '14', '16') }) + .defineVariable('9', 'm', { definedBy: ['18', '19'] }) + .defineVariable('21', 'x', { definedBy: [] }, false) + .constant('24', undefined, false) + .defineFunction('27', ['25'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '25', + graph: new Set(['21', '23', '24', '25']), + environment: defaultEnv().pushEnv().defineParameter('x', '21', '22') + }) + .definesOnCall('27', '10') + .constant('31') + .definesOnCall('31', '21')) + }) })) From 286fba99b81b2585fc69750ec05936c862a93eec Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Thu, 23 May 2024 16:35:20 +0200 Subject: [PATCH 13/23] test: added dead code slicing tests --- .../control-flow-tests.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/functionality/slicing/static-program-slices/control-flow-tests.ts b/test/functionality/slicing/static-program-slices/control-flow-tests.ts index 35946a1988..c1e01ac1af 100644 --- a/test/functionality/slicing/static-program-slices/control-flow-tests.ts +++ b/test/functionality/slicing/static-program-slices/control-flow-tests.ts @@ -63,5 +63,40 @@ print(x)`, ['7@x'], loop == 'repeat' ? 'x <- 2\nx' : `x <- 1\n${loop} { x`) }) } + assertSliced(label('dead code (return)', ['name-normal', 'formals-named', 'newlines', ...OperatorDatabase['<-'].capabilities, ...OperatorDatabase['*'].capabilities, 'numbers', 'return', 'unnamed-arguments', 'comments']), + shell, `f <- function(x) { + x <- 3 * x + return(x) + # alles drunter soll natürlich weg + x <- 2 + return(x) +} + +f(5)`, ['9@f'],`f <- function(x) { + x <- 3 * x + return(x) + } +f(5)`) + // this is incorrect, see https://github.com/Code-Inspect/flowr/issues/816 + assertSliced(label('dead code (return in if)', ['name-normal', 'formals-named', 'newlines', ...OperatorDatabase['<-'].capabilities, ...OperatorDatabase['*'].capabilities, 'numbers', 'if', 'return', 'unnamed-arguments', 'comments']), + shell, `f <- function(x) { + x <- 3 * x + if(k) + return(x) + else + return(1) + # alles drunter soll natürlich weg + x <- 2 + return(x) +} + +f(5)`, ['12@f'], `f <- function(x) { + x <- 3 * x + if(k) return(x) else + return(1) + x <- 2 + return(x) + } +f(5)`) }) })) From ec0537d163e4d925d2b02aaab73bb59a09d5cdf7 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 May 2024 15:14:44 +0200 Subject: [PATCH 14/23] refactor(test): updated tests to new features --- .../dataflow/dataflow-builder-printer.ts | 4 +- .../dataflow/environment-builder-printer.ts | 4 +- .../dataflow-if-then-tests.ts | 37 +++++----- .../dataflow-function-definition-tests.ts | 27 +++----- .../loops/dataflow-for-loop-tests.ts | 68 +++++++++---------- .../control-flow-tests.ts | 3 - 6 files changed, 64 insertions(+), 79 deletions(-) diff --git a/test/functionality/_helper/dataflow/dataflow-builder-printer.ts b/test/functionality/_helper/dataflow/dataflow-builder-printer.ts index b90e82656c..d57f7aaabf 100644 --- a/test/functionality/_helper/dataflow/dataflow-builder-printer.ts +++ b/test/functionality/_helper/dataflow/dataflow-builder-printer.ts @@ -6,7 +6,7 @@ import { assertUnreachable, isNotUndefined } from '../../../../src/util/assert' import { DefaultMap } from '../../../../src/util/defaultmap' import { EnvironmentBuilderPrinter } from './environment-builder-printer' -import { wrap, wrapControlDependency, wrapReference } from './printer' +import { wrap, wrapControlDependencies, wrapReference } from './printer' import { EdgeType, splitEdgeTypes } from '../../../../src/dataflow/graph/edge' import type { DataflowGraph, FunctionArgument } from '../../../../src/dataflow/graph/graph' import { isPositionalArgument } from '../../../../src/dataflow/graph/graph' @@ -248,7 +248,7 @@ class DataflowBuilderPrinter { private getControlDependencySuffix(arg: ControlDependency[] | undefined, prefix: string = '{ ', suffix: string = ' }'): string | undefined { if(arg !== undefined) { - return `${prefix}controlDependencies: ${wrapControlDependency(arg)}${suffix}` + return `${prefix}controlDependencies: ${wrapControlDependencies(arg)}${suffix}` } return undefined } diff --git a/test/functionality/_helper/dataflow/environment-builder-printer.ts b/test/functionality/_helper/dataflow/environment-builder-printer.ts index 82d57d5708..caff09dac5 100644 --- a/test/functionality/_helper/dataflow/environment-builder-printer.ts +++ b/test/functionality/_helper/dataflow/environment-builder-printer.ts @@ -1,5 +1,5 @@ import { assertUnreachable, isNotUndefined } from '../../../../src/util/assert' -import { wrap, wrapControlDependency } from './printer' +import { wrap, wrapControlDependencies } from './printer' import type { IEnvironment, REnvironmentInformation } from '../../../../src/dataflow/environments/environment' import { BuiltInEnvironment } from '../../../../src/dataflow/environments/environment' import type { IdentifierDefinition } from '../../../../src/dataflow/environments/identifier' @@ -77,7 +77,7 @@ export class EnvironmentBuilderPrinter { } private getControlDependencyArgument(def: IdentifierDefinition) { - return def.controlDependencies ? wrapControlDependency(def.controlDependencies) : undefined + return def.controlDependencies ? wrapControlDependencies(def.controlDependencies) : undefined } private push() { diff --git a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts index 04d6932da8..221a906b32 100644 --- a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts @@ -214,43 +214,43 @@ if(y) { } print(x)`, emptyGraph() .use('3', 'y') - .use('6', 'z', { controlDependencies: ['27'] }) + .use('6', 'z', { controlDependencies: [{ id: '27', when: true }] }) .use('29', 'x') .reads('29', ['9', '15', '23']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .argument('2', ['1', '0']) - .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('11', '<-', [argumentInCall('9'), argumentInCall('10')], { returns: ['9'], reads: [BuiltIn], controlDependencies: [{ id: '19', when: true }, { id: '27', when: true }], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('11', ['10', '9']) .argument('12', '11') - .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependencies: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('17', '<-', [argumentInCall('15'), argumentInCall('16')], { returns: ['15'], reads: [BuiltIn], controlDependencies: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('12', '{', [argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], controlDependencies: [{ id: '19', when: true }, { id: '27', when: true }], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('17', '<-', [argumentInCall('15'), argumentInCall('16')], { returns: ['15'], reads: [BuiltIn], controlDependencies: [{ id: '19', when: false }, { id: '27', when: true }], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('17', ['16', '15']) .argument('18', '17') - .call('18', '{', [argumentInCall('17')], { returns: ['17'], reads: [BuiltIn], controlDependencies: ['19', '27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('18', '{', [argumentInCall('17')], { returns: ['17'], reads: [BuiltIn], controlDependencies: [{ id: '19', when: false }, { id: '27', when: true }], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('19', '6') .argument('19', '12') .argument('19', '18') - .call('19', 'if', [argumentInCall('6'), argumentInCall('12'), argumentInCall('18')], { returns: ['12', '18'], reads: ['6', BuiltIn], onlyBuiltIn: true, controlDependencies: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('19', 'if', [argumentInCall('6'), argumentInCall('12'), argumentInCall('18')], { returns: ['12', '18'], reads: ['6', BuiltIn], onlyBuiltIn: true, controlDependencies: [{ id: '27', when: true }], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('20', '19') - .call('20', '{', [argumentInCall('19')], { returns: ['19'], reads: [BuiltIn], controlDependencies: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) - .call('25','<-', [argumentInCall('23'), argumentInCall('24')], { returns: ['23'], reads: [BuiltIn], controlDependencies: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('20', '{', [argumentInCall('19')], { returns: ['19'], reads: [BuiltIn], controlDependencies: [{ id: '27', when: true }], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('25','<-', [argumentInCall('23'), argumentInCall('24')], { returns: ['23'], reads: [BuiltIn], controlDependencies: [{ id: '27', when: false }], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('25', ['24', '23']) .argument('26', '25') - .call('26', '{', [argumentInCall('25')], { returns: ['25'], reads: [BuiltIn], controlDependencies: ['27'], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('26', '{', [argumentInCall('25')], { returns: ['25'], reads: [BuiltIn], controlDependencies: [{ id: '27', when: false }], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('27', '3') .argument('27', '20') .argument('27', '26') .call('27', 'if', [argumentInCall('3'), argumentInCall('20'), argumentInCall('26')], { returns: ['20', '26'], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('31', '29') - .call('31', 'print', [argumentInCall('29')], { returns: ['29'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '9', '11', ['27']).defineVariable('x', '15', '17', ['27']).defineVariable('x', '23', '25', ['27']) }) + .call('31', 'print', [argumentInCall('29')], { returns: ['29'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '9', '11', [{ id: '27', when: false }]).defineVariable('x', '15', '17', [{ id: '27', when: false }]).defineVariable('x', '23', '25', [{ id: '27', when: false }]) }) .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) .constant('10') - .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: ['27'] }) + .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [{ id: '27', when: true }] }) .constant('16') - .defineVariable('15', 'x', { definedBy: ['16', '17'], controlDependencies: ['27'] }) + .defineVariable('15', 'x', { definedBy: ['16', '17'], controlDependencies: [{ id: '27', when: true }] }) .constant('24') - .defineVariable('23', 'x', { definedBy: ['24', '25'], controlDependencies: ['27'] }) + .defineVariable('23', 'x', { definedBy: ['24', '25'], controlDependencies: [{ id: '27', when: false }] }) ) }) describe('Get and assign', () => { @@ -263,14 +263,13 @@ a()`, emptyGraph() .use('5', 'y') .call('4', '<-', [argumentInCall('0'), argumentInCall('3')], { returns: ['0'], reads: [BuiltIn] }) .argument('4', ['3', '0']) - .call('15', 'assign', [argumentInCall('9'), argumentInCall('13')], { returns: ['9'], reads: [BuiltIn], environment: defaultEnv().defineFunction('a', '0', '4'), onlyBuiltIn: true, controlDependencies: ['17'] }) + .call('15', 'assign', [argumentInCall('9'), argumentInCall('13')], { returns: ['9'], reads: [BuiltIn], environment: defaultEnv().defineFunction('a', '0', '4'), onlyBuiltIn: true, controlDependencies: [{ id: '17', when: true }] }) .argument('15', ['13', '9']) - .call('16', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], controlDependencies: ['17'], environment: defaultEnv().defineFunction('a', '0', '4') }) - .argument('16', '8') + .call('16', '{', [argumentInCall('15', { controlDependencies: [{ id: '17', when: true }] })], { returns: ['15'], reads: [BuiltIn], controlDependencies: [{ id: '17', when: true }], environment: defaultEnv().defineFunction('a', '0', '4') }) .argument('17', '5') .argument('17', '16') - .call('17', 'if', [argumentInCall('5'), argumentInCall('16'), EmptyArgument], { returns: ['16'], reads: ['5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineFunction('a', '0', '4', ['17']) }) - .call('19', 'a', [], { returns: ['1', '11'], reads: ['9', '0'], environment: defaultEnv().defineFunction('a', '9', '15', ['17']).defineFunction('a', '0', '4', ['17']) }) + .call('17', 'if', [argumentInCall('5'), argumentInCall('16'), EmptyArgument], { returns: ['16'], reads: ['5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineFunction('a', '0', '4', [{ id: '17', when: true }]) }) + .call('19', 'a', [], { returns: ['1', '11'], reads: ['9', '0'], environment: defaultEnv().defineFunction('a', '9', '15', [{ id: '17', when: true }]).defineFunction('a', '0', '4', [{ id: '17', when: true }]) }) .calls('19', ['3', '13']) .constant('1', undefined, false) .defineFunction('3', ['1'], { @@ -291,7 +290,7 @@ a()`, emptyGraph() graph: new Set(['11']), environment: defaultEnv().pushEnv() }) - .defineVariable('9', '"a"', { definedBy: ['13', '15'], controlDependencies: ['17'] }) + .defineVariable('9', '"a"', { definedBy: ['13', '15'], controlDependencies: [{ id: '17', when: true }] }) ) assertDataflow(label('assign from get', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'newlines', 'assignment-functions', 'strings', 'unnamed-arguments']), shell, 'b <- 5\nassign("a", get("b"))\nprint(a)', emptyGraph() diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts index 980ac3bdac..86f2779384 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts @@ -496,7 +496,6 @@ f(5)`, emptyGraph() .defineVariable('0', 'f', { definedBy: ['22', '23'] }) .constant('25') .definesOnCall('25', '1')) - // this is potentially incorrect, see https://github.com/Code-Inspect/flowr/issues/816 assertDataflow(label('return in if',['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-named', 'newlines', 'numbers', ...OperatorDatabase['*'].capabilities, 'return', 'unnamed-arguments', 'if']), shell, `f <- function(x) { x <- 3 * x @@ -508,14 +507,12 @@ f(5)`, emptyGraph() return(x) } -f(5)`, emptyGraph() +f(5)`, emptyGraph() .use('7', 'x', undefined, false) .reads('7', '1') .use('10', 'k', undefined, false) .use('12', 'x', undefined, false) .reads('12', '5') - .use('26', 'x', undefined, false) - .reads('26', ['5', '22']) .argument('8', '7') .call('8', '*', [argumentInCall('6'), argumentInCall('7')], { returns: [], reads: [BuiltIn, '6', '7'], onlyBuiltIn: true, environment: defaultEnv().pushEnv().defineParameter('x', '1', '2') }, false) .argument('8', '6') @@ -523,22 +520,16 @@ f(5)`, emptyGraph() .call('9', '<-', [argumentInCall('5'), argumentInCall('8')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('x', '1', '2') }, false) .argument('9', '5') .argument('14', '12') - .call('14', 'return', [argumentInCall('12')], { returns: ['12'], reads: [BuiltIn], controlDependencies: ['21'], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) - .call('19', 'return', [argumentInCall('17')], { returns: ['17'], reads: [BuiltIn], controlDependencies: ['21'], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) + .call('14', 'return', [argumentInCall('12')], { returns: ['12'], reads: [BuiltIn], controlDependencies: [{ id: '21', when: true }], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) + .call('19', 'return', [argumentInCall('17')], { returns: ['17'], reads: [BuiltIn], controlDependencies: [{ id: '21', when: false }], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) .argument('19', '17') .argument('21', '10') .argument('21', '14') .argument('21', '19') - .call('21', 'if', [argumentInCall('10'), argumentInCall('14', { controlDependencies: ['21'] }), argumentInCall('19', { controlDependencies: ['21'] })], { returns: ['14', '19'], reads: ['10', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) - .call('24', '<-', [argumentInCall('22', { controlDependencies: [] }), argumentInCall('23')], { returns: ['22'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) - .argument('24', ['23', '22']) - .argument('28', '26') - .call('28', 'return', [argumentInCall('26')], { returns: ['26'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9').defineVariable('x', '22', '24', []) }, false) + .call('21', 'if', [argumentInCall('10'), argumentInCall('14', { controlDependencies: [{ id: '21', when: true }] }), argumentInCall('19', { controlDependencies: [{ id: '21', when: false }] })], { returns: ['14', '19'], reads: ['10', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) .argument('29', '9') .argument('29', '21') - .argument('29', '24') - .argument('29', '28') - .call('29', '{', [argumentInCall('9'), argumentInCall('21'), argumentInCall('24', { controlDependencies: [] }), argumentInCall('28', { controlDependencies: [] })], { returns: ['28', '14', '19'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9').defineVariable('x', '22', '24', []) }, false) + .call('29', '{', [argumentInCall('9'), argumentInCall('21')], { returns: ['14', '19'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }, false) .call('31', '<-', [argumentInCall('0'), argumentInCall('30')], { returns: ['0'], reads: [BuiltIn] }) .argument('31', ['30', '0']) .call('35', 'f', [argumentInCall('33')], { returns: ['29'], reads: ['0'], environment: defaultEnv().defineFunction('f', '0', '31') }) @@ -548,15 +539,13 @@ f(5)`, emptyGraph() .constant('6', undefined, false) .defineVariable('5', 'x', { definedBy: ['8', '9'] }, false) .constant('17', undefined, false) - .constant('23', undefined, false) - .defineVariable('22', 'x', { definedBy: ['23', '24'], controlDependencies: [] }, false) .defineFunction('30', ['29'], { out: [], in: [{ nodeId: '10', name: 'k', controlDependencies: [] }], unknownReferences: [], entryPoint: '29', - graph: new Set(['1', '6', '7', '8', '5', '9', '10', '12', '14', '17', '19', '21', '23', '22', '24', '26', '28', '29']), - environment: defaultEnv().pushEnv().defineParameter('x', '1', '2').defineVariable('x', '5', '9').defineVariable('x', '22', '24', []) + graph: new Set(['1', '6', '7', '8', '5', '9', '10', '12', '14', '17', '19', '21', '29']), + environment: defaultEnv().pushEnv().defineVariable('x', '5', '9') }) .defineVariable('0', 'f', { definedBy: ['30', '31'] }) .constant('33') @@ -621,7 +610,7 @@ f(3)`, emptyGraph() unknownReferences: [], entryPoint: '17', graph: new Set(['10', '15', '14', '16', '17']), - environment: defaultEnv().pushEnv().defineVariable('f', '14', '16') + environment: defaultEnv().defineVariable('f', '14', '16').pushEnv().defineParameter('g', '10', '11') }, { environment: defaultEnv().defineVariable('f', '14', '16') }) .defineVariable('9', 'm', { definedBy: ['18', '19'] }) .defineVariable('21', 'x', { definedBy: [] }, false) diff --git a/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts b/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts index 9e68e18e2e..f09373ab6e 100644 --- a/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/loops/dataflow-for-loop-tests.ts @@ -193,10 +193,10 @@ print(x)`, emptyGraph() .argument('2', ['1', '0']) .call('7', '<-', [argumentInCall('5'), argumentInCall('6')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('7', ['6', '5']) - .call('9', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: ['11'], environment: defaultEnv().defineVariable('x', '5', '7') }) + .call('9', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [{ id: '11', when: true }], environment: defaultEnv().defineVariable('x', '5', '7') }) .argument('11', '8') .argument('11', '9') - .call('11', 'if', [argumentInCall('8'), argumentInCall('9', { controlDependencies: ['11'] }), EmptyArgument], { returns: ['9'], reads: [BuiltIn, '8'], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '5', '7') }) + .call('11', 'if', [argumentInCall('8'), argumentInCall('9', { controlDependencies: [{ id: '11', when: true }] }), EmptyArgument], { returns: ['9'], reads: [BuiltIn, '8'], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '5', '7') }) .argument('12', '7') .argument('12', '11') .call('12', '{', [argumentInCall('7'), argumentInCall('11')], { returns: ['11'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '5', '7') }) @@ -251,12 +251,12 @@ print(x)`, emptyGraph() .argument('2', ['1', '0']) .call('6', ':', [argumentInCall('4'), argumentInCall('5')], { returns: [], reads: ['4', '5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('6', ['4', '5']) - .call('11', '<-', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: ['14'] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) + .call('11', '<-', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: [{ id: '14', when: true }] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) .argument('11', ['10', '9']) - .call('12', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['14']) }) + .call('12', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', [{ id: '14', when: true }]) }) .argument('13', '11') .argument('13', '12') - .call('13', '{', [argumentInCall('11', { controlDependencies: [] }), argumentInCall('12', { controlDependencies: [] })], { returns: ['12'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['14']) }) + .call('13', '{', [argumentInCall('11', { controlDependencies: [] }), argumentInCall('12', { controlDependencies: [] })], { returns: ['12'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', [{ id: '14', when: true }]) }) .argument('14', '6') .argument('14', '13') .call('14', 'for', [argumentInCall('3'), argumentInCall('6'), argumentInCall('13', { controlDependencies: [] })], { returns: [], reads: ['3', '6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('i', '3', '14') }) @@ -269,7 +269,7 @@ print(x)`, emptyGraph() .defineVariable('3', 'i', { definedBy: ['6'] }) .constant('4') .constant('5') - .constant('10', { controlDependencies: ['14'] }) + .constant('10', { controlDependencies: [{ id: '14', when: true }] }) .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] })) assertDataflow(label('Break in condition', ['for-loop', 'name-normal', 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments', 'if']), shell, `x <- 1 @@ -286,15 +286,15 @@ print(x)`, emptyGraph() .argument('2', ['1', '0']) .call('6', ':', [argumentInCall('4'), argumentInCall('5')], { returns: [], reads: ['4', '5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('6', ['4', '5']) - .call('11', '<-', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: ['17', '15'] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) + .call('11', '<-', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: [{ id: '17', when: true }, { id: '15', when: true }] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) .argument('11', ['10', '9']) - .call('13', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['17']) }) + .call('13', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', [{ id: '17', when: true }]) }) .argument('15', '12') .argument('15', '13') - .call('15', 'if', [argumentInCall('12', { controlDependencies: [] }), argumentInCall('13', { controlDependencies: [] }), EmptyArgument], { returns: ['13'], reads: ['12', BuiltIn], onlyBuiltIn: true, controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['17', '15']) }) + .call('15', 'if', [argumentInCall('12', { controlDependencies: [] }), argumentInCall('13', { controlDependencies: [] }), EmptyArgument], { returns: ['13'], reads: ['12', BuiltIn], onlyBuiltIn: true, controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', [{ id: '17', when: true },{ id: '15', when: true }]) }) .argument('16', '11') .argument('16', '15') - .call('16', '{', [argumentInCall('11', { controlDependencies: [] }), argumentInCall('15', { controlDependencies: [] })], { returns: ['15'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['17', '15']) }) + .call('16', '{', [argumentInCall('11', { controlDependencies: [] }), argumentInCall('15', { controlDependencies: [] })], { returns: ['15'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', [{ id: '17', when: true }, { id: '15', when: true }]) }) .argument('17', '6') .argument('17', '16') .call('17', 'for', [argumentInCall('3'), argumentInCall('6'), argumentInCall('16', { controlDependencies: [] })], { returns: [], reads: ['3', '6', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2', []).defineVariable('x', '9', '11', []).defineVariable('i', '3', '17') }) @@ -307,7 +307,7 @@ print(x)`, emptyGraph() .defineVariable('3', 'i', { definedBy: ['6'] }) .constant('4') .constant('5') - .constant('10', { controlDependencies: ['17', '15'] }) + .constant('10', { controlDependencies: [{ id: '17', when: true }, { id: '15', when: true }] }) .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] })) assertDataflow(label('Next', ['for-loop', 'newlines', 'name-normal', 'numbers', 'next', 'semicolons', 'unnamed-arguments']), shell, `x <- 1 @@ -323,10 +323,10 @@ print(x)`, emptyGraph() .argument('2', ['1', '0']) .call('6', ':', [argumentInCall('4'), argumentInCall('5')], { returns: [], reads: ['4', '5', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('6', ['4', '5']) - .call('11', '<-', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: ['19'] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) + .call('11', '<-', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: [{ id: '19', when: true }] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [] }) .argument('11', ['10', '9']) - .call('12', 'next', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['19']) }) - .call('16', '<-', [argumentInCall('14', { controlDependencies: [] }), argumentInCall('15', { controlDependencies: ['19'] })], { returns: ['14'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', ['19']) }) + .call('12', 'next', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', [{ id: '19', when: true }]) }) + .call('16', '<-', [argumentInCall('14', { controlDependencies: [] }), argumentInCall('15', { controlDependencies: [{ id: '19', when: true }] })], { returns: ['14'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '9', '11', [{ id: '19', when: true }]) }) .argument('16', ['15', '14']) .argument('18', '11') .call('18', '{', [argumentInCall('11', { controlDependencies: [] })], { returns: ['11'], reads: [BuiltIn], controlDependencies: [] }) @@ -342,9 +342,9 @@ print(x)`, emptyGraph() .defineVariable('3', 'i', { definedBy: ['6'] }) .constant('4') .constant('5') - .constant('10', { controlDependencies: ['19'] }) + .constant('10', { controlDependencies: [{ id: '19', when: true }] }) .defineVariable('9', 'x', { definedBy: ['10', '11'], controlDependencies: [] }) - .constant('15', { controlDependencies: ['19'] }) + .constant('15', { controlDependencies: [{ id: '19', when: true }] }) .defineVariable('14', 'x', { definedBy: ['15', '16'], controlDependencies: [] })) }) @@ -360,14 +360,14 @@ print(x)`, emptyGraph() .reads('13', ['0', '6']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .argument('2', ['1', '0']) - .call('8', '<-', [argumentInCall('6', { controlDependencies: [] }), argumentInCall('7', { controlDependencies: ['11'] })], { returns: ['6'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('8', '<-', [argumentInCall('6', { controlDependencies: [] }), argumentInCall('7', { controlDependencies: [{ id: '11', when: true }] })], { returns: ['6'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('8', ['7', '6']) - .call('9', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['11']) }) + .call('9', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '11', when: true }]) }) .argument('10', '8') .argument('10', '9') - .call('10', '{', [argumentInCall('8', { controlDependencies: [] }), argumentInCall('9', { controlDependencies: [] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['11']) }) + .call('10', '{', [argumentInCall('8', { controlDependencies: [] }), argumentInCall('9', { controlDependencies: [] })], { returns: ['9'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '11', when: true }]) }) .argument('11', '10') - .call('11', 'while', [argumentInCall('3'), argumentInCall('10', { controlDependencies: [] })], { returns: [], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['11']) }) + .call('11', 'while', [argumentInCall('3'), argumentInCall('10', { controlDependencies: [] })], { returns: [], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '11', when: true }]) }) .argument('11', '3') .nse('11', '10') .argument('15', '13') @@ -375,7 +375,7 @@ print(x)`, emptyGraph() .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) .constant('3') - .constant('7', { controlDependencies: ['11'] }) + .constant('7', { controlDependencies: [{ id: '11', when: true }] }) .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependencies: [] })) assertDataflow(label('Break in condition', ['while-loop', 'name-normal', 'numbers', 'semicolons', 'newlines', 'break', 'unnamed-arguments', 'if']), shell, `x <- 1 @@ -390,17 +390,17 @@ print(x)`, emptyGraph() .reads('16', ['0', '6']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .argument('2', ['1', '0']) - .call('8', '<-', [argumentInCall('6', { controlDependencies: [] }), argumentInCall('7', { controlDependencies: ['14', '12'] })], { returns: ['6'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('8', '<-', [argumentInCall('6', { controlDependencies: [] }), argumentInCall('7', { controlDependencies: [{ id: '14', when: true }, { id: '12', when: true }] })], { returns: ['6'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('8', ['7', '6']) - .call('10', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['14']) }) + .call('10', 'break', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '14', when: true }]) }) .argument('12', '9') .argument('12', '10') - .call('12', 'if', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: [] }), EmptyArgument], { returns: ['10'], reads: [BuiltIn, '9'], onlyBuiltIn: true, controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['14', '12']) }) + .call('12', 'if', [argumentInCall('9', { controlDependencies: [] }), argumentInCall('10', { controlDependencies: [] }), EmptyArgument], { returns: ['10'], reads: [BuiltIn, '9'], onlyBuiltIn: true, controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '14', when: true }, { id: '12', when: true }]) }) .argument('13', '8') .argument('13', '12') - .call('13', '{', [argumentInCall('8', { controlDependencies: [] }), argumentInCall('12', { controlDependencies: [] })], { returns: ['12'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['14', '12']) }) + .call('13', '{', [argumentInCall('8', { controlDependencies: [] }), argumentInCall('12', { controlDependencies: [] })], { returns: ['12'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '14', when: true }, { id: '12', when: true }]) }) .argument('14', '13') - .call('14', 'while', [argumentInCall('3'), argumentInCall('13', { controlDependencies: [] })], { returns: [], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['14', '12']) }) + .call('14', 'while', [argumentInCall('3'), argumentInCall('13', { controlDependencies: [] })], { returns: [], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '14', when: true }, { id: '12', when: true }]) }) .argument('14', '3') .nse('14', '13') .argument('18', '16') @@ -408,7 +408,7 @@ print(x)`, emptyGraph() .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) .constant('3') - .constant('7', { controlDependencies: ['14', '12'] }) + .constant('7', { controlDependencies: [{ id: '14', when: true }, { id: '12', when: true }] }) .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependencies: [] })) assertDataflow(label('Next', ['while-loop', 'newlines', 'name-normal', 'numbers', 'next', 'semicolons', 'unnamed-arguments']), shell, `x <- 1 @@ -422,15 +422,15 @@ print(x)`, emptyGraph() .reads('18', ['0', '6', '11']) .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) .argument('2', ['1', '0']) - .call('8', '<-', [argumentInCall('6', { controlDependencies: [] }), argumentInCall('7', { controlDependencies: ['16'] })], { returns: ['6'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2') }) + .call('8', '<-', [argumentInCall('6', { controlDependencies: [] }), argumentInCall('7', { controlDependencies: [{ id: '16', when: true }] })], { returns: ['6'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2') }) .argument('8', ['7', '6']) - .call('9', 'next', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['16']) }) - .call('13', '<-', [argumentInCall('11', { controlDependencies: [] }), argumentInCall('12', { controlDependencies: ['16'] })], { returns: ['11'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['16']) }) + .call('9', 'next', [], { returns: [], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '16', when: true }]) }) + .call('13', '<-', [argumentInCall('11', { controlDependencies: [] }), argumentInCall('12', { controlDependencies: [{ id: '16', when: true }] })], { returns: ['11'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '16', when: true }]) }) .argument('13', ['12', '11']) .argument('15', '8') - .call('15', '{', [argumentInCall('8', { controlDependencies: [] })], { returns: ['8'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['16']).defineVariable('x', '11', '13', []) }) + .call('15', '{', [argumentInCall('8', { controlDependencies: [] })], { returns: ['8'], reads: [BuiltIn], controlDependencies: [], environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '16', when: true }]).defineVariable('x', '11', '13', []) }) .argument('16', '15') - .call('16', 'while', [argumentInCall('3'), argumentInCall('15', { controlDependencies: [] })], { returns: [], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', ['16']).defineVariable('x', '11', '13', []) }) + .call('16', 'while', [argumentInCall('3'), argumentInCall('15', { controlDependencies: [] })], { returns: [], reads: ['3', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().defineVariable('x', '0', '2').defineVariable('x', '6', '8', [{ id: '16', when: true }]).defineVariable('x', '11', '13', []) }) .argument('16', '3') .nse('16', '15') .argument('20', '18') @@ -438,9 +438,9 @@ print(x)`, emptyGraph() .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) .constant('3') - .constant('7', { controlDependencies: ['16'] }) + .constant('7', { controlDependencies: [{ id: '16', when: true }] }) .defineVariable('6', 'x', { definedBy: ['7', '8'], controlDependencies: [] }) - .constant('12', { controlDependencies: ['16'] }) + .constant('12', { controlDependencies: [{ id: '16', when: true }] }) .defineVariable('11', 'x', { definedBy: ['12', '13'], controlDependencies: [] })) }) }) diff --git a/test/functionality/slicing/static-program-slices/control-flow-tests.ts b/test/functionality/slicing/static-program-slices/control-flow-tests.ts index c1e01ac1af..6e87bcb86f 100644 --- a/test/functionality/slicing/static-program-slices/control-flow-tests.ts +++ b/test/functionality/slicing/static-program-slices/control-flow-tests.ts @@ -77,7 +77,6 @@ f(5)`, ['9@f'],`f <- function(x) { return(x) } f(5)`) - // this is incorrect, see https://github.com/Code-Inspect/flowr/issues/816 assertSliced(label('dead code (return in if)', ['name-normal', 'formals-named', 'newlines', ...OperatorDatabase['<-'].capabilities, ...OperatorDatabase['*'].capabilities, 'numbers', 'if', 'return', 'unnamed-arguments', 'comments']), shell, `f <- function(x) { x <- 3 * x @@ -94,8 +93,6 @@ f(5)`, ['12@f'], `f <- function(x) { x <- 3 * x if(k) return(x) else return(1) - x <- 2 - return(x) } f(5)`) }) From d51e26d7fe88a4c8c5c37d21671c64c588654fbf Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 May 2024 15:24:29 +0200 Subject: [PATCH 15/23] test: add additional labels to some tests --- .../atomic/dataflow-redefine-tests.ts | 4 ++-- .../functions/dataflow-function-call-tests.ts | 2 +- .../functions/dataflow-function-definition-tests.ts | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-redefine-tests.ts b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-redefine-tests.ts index 4009ce90f2..d38db1e73c 100644 --- a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-redefine-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-redefine-tests.ts @@ -67,7 +67,7 @@ print(x)`, emptyGraph() .definesOnCall('7', '1') .constant('9') .defineVariable('8', 'x', { definedBy: ['9', '10'] })) - assertDataflow(label('<-', []), + assertDataflow(label('<-', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'newlines', 'name-escaped', ...OperatorDatabase['*'].capabilities, 'named-arguments']), shell, `x <- 2 \`<-\` <- \`*\` x <- 3 @@ -94,7 +94,7 @@ print(y = x)`, emptyGraph() .defineVariable('0', 'x', { definedBy: ['1', '2'] }) .defineVariable('3', '`<-`', { definedBy: ['4', '5'] }) .constant('7')) - assertDataflow(label('<- in function', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'normal-definition', 'implicit-return','newlines', ...OperatorDatabase['*'].capabilities, 'call-normal', 'unnamed-arguments']), + assertDataflow(label('<- in function', ['name-normal', 'name-escaped', ...OperatorDatabase['<-'].capabilities, 'normal-definition', 'implicit-return','newlines', ...OperatorDatabase['*'].capabilities, 'call-normal', 'unnamed-arguments']), shell, `f <- function() { x <- 2 \`<-\` <- \`*\` diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-call-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-call-tests.ts index 1064313391..9834217266 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-call-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-call-tests.ts @@ -133,7 +133,7 @@ a(i)`, emptyGraph() outGraph ) - assertDataflow(label('Calling a function which returns another', ['name-normal', 'normal-definition', 'implicit-return', 'call-normal', 'numbers']), shell, `a <- function() { function() { 42 } } + assertDataflow(label('Calling a function which returns another', ['name-normal', 'normal-definition', 'implicit-return', 'call-normal', 'numbers', 'closures']), shell, `a <- function() { function() { 42 } } a()()`, emptyGraph() .call('6', '{', [argumentInCall('5')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().pushEnv().pushEnv() }, false) .call('8', '{', [argumentInCall('7')], { returns: ['7'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts index 86f2779384..8d9b3954a9 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts @@ -169,7 +169,7 @@ describe('Function Definition', withShell(shell => { environment: defaultEnv().pushEnv().defineVariable('x', '3', '4') }) ) - assertDataflow(label('global define with <<- in function, read after', ['normal-definition', 'name-normal', 'numbers', ...OperatorDatabase['<<-'].capabilities, 'semicolons']), shell, 'function() { x <<- 3; }; x', emptyGraph() + assertDataflow(label('global define with <<- in function, read after', ['normal-definition', 'name-normal', 'numbers', ...OperatorDatabase['<<-'].capabilities, 'semicolons', 'side-effects-in-function-call']), shell, 'function() { x <<- 3; }; x', emptyGraph() .use('7', 'x') .call('4', '<<-', [argumentInCall('2'), argumentInCall('3')], { returns: ['2'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) .call('5', '{', [argumentInCall('4')], { returns: ['4'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) @@ -184,7 +184,7 @@ describe('Function Definition', withShell(shell => { environment: defaultEnv().defineVariable('x', '2', '4').pushEnv() }, { environment: defaultEnv().defineVariable('x', '2', '4') }) ) - assertDataflow(label('global define with ->> in function, read after', ['normal-definition', 'numbers', ...OperatorDatabase['->>'].capabilities, 'semicolons', 'name-normal']), shell, 'function() { 3 ->> x; }; x', emptyGraph() + assertDataflow(label('global define with ->> in function, read after', ['normal-definition', 'numbers', ...OperatorDatabase['->>'].capabilities, 'semicolons', 'name-normal', 'side-effects-in-function-call']), shell, 'function() { 3 ->> x; }; x', emptyGraph() .use('7', 'x') .call('4', '->>', [argumentInCall('2'), argumentInCall('3')], { returns: ['3'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) .call('5', '{', [argumentInCall('4')], { returns: ['4'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) @@ -350,7 +350,7 @@ describe('Function Definition', withShell(shell => { ) }) describe('Bind environment to correct exit point', () => { - assertDataflow(label('Two possible exit points to bind y closure', ['normal-definition', 'name-normal', ...OperatorDatabase['<-'].capabilities, 'implicit-return', 'if', 'return']), shell, `function() { + assertDataflow(label('Two possible exit points to bind y closure', ['normal-definition', 'name-normal', ...OperatorDatabase['<-'].capabilities, 'implicit-return', 'if', 'return', 'closures']), shell, `function() { g <- function() { y } y <- 5 if(z) @@ -415,7 +415,7 @@ describe('Function Definition', withShell(shell => { }) describe('Nested Function Definitions', () => { - assertDataflow(label('double nested functions', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'normal-definition', 'unnamed-arguments', 'semicolons']), shell, 'a <- function() { x <- function(x) { x <- b }; x }; b <- 3; a', emptyGraph() + assertDataflow(label('double nested functions', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'normal-definition', 'unnamed-arguments', 'semicolons', 'closures']), shell, 'a <- function() { x <- function(x) { x <- b }; x }; b <- 3; a', emptyGraph() .use('9', 'b', undefined, false) .use('14', 'x', undefined, false) .reads('14', '3') From 391dec61f01622b19209942d2388a960dcc37200 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 May 2024 18:16:59 +0200 Subject: [PATCH 16/23] test: fix assignment of unsupported claims closes #820 --- src/r-bridge/data/data.ts | 2 +- src/r-bridge/lang-4.x/ast/model/operators.ts | 2 +- .../atomic/dataflow-atomic-tests.ts | 6 +++--- test/functionality/r-bridge/lang/ast/parse-constructs.ts | 4 ++-- test/functionality/r-bridge/lang/ast/parse-values.ts | 2 +- .../slicing/static-program-slices/simple-tests.ts | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/r-bridge/data/data.ts b/src/r-bridge/data/data.ts index effa9105d1..255b91ce5a 100644 --- a/src/r-bridge/data/data.ts +++ b/src/r-bridge/data/data.ts @@ -463,7 +463,7 @@ export const flowrCapabilities = { name: 'Sequencing', id: 'built-in-sequencing', supported: 'not', - description: '_Handle `:`, `seq`, ... as they are used often._' + description: '_Handle `:`, `seq`, ... by gathering value information using abstract interpretation._' }, { name: 'Internal and Primitive Functions', diff --git a/src/r-bridge/lang-4.x/ast/model/operators.ts b/src/r-bridge/lang-4.x/ast/model/operators.ts index 8ad71fe915..50664823c1 100644 --- a/src/r-bridge/lang-4.x/ast/model/operators.ts +++ b/src/r-bridge/lang-4.x/ast/model/operators.ts @@ -73,7 +73,7 @@ export const OperatorDatabase: Record if we change this we have to create custom tests! (with arithmetic, there is the automatic test set) */ - ':': { name: 'sequence operator', stringUsedInRAst: RawRType.Colon, stringUsedInternally: ':', writtenAs: 'infix', arity: OperatorArity.Binary, usedAs: 'operation', capabilities: ['binary-operator', 'infix-calls', 'function-calls', 'built-in-sequencing'] }, + ':': { name: 'sequence operator', stringUsedInRAst: RawRType.Colon, stringUsedInternally: ':', writtenAs: 'infix', arity: OperatorArity.Binary, usedAs: 'operation', capabilities: ['binary-operator', 'infix-calls', 'function-calls'] }, '?': { name: 'question', stringUsedInRAst: RawRType.Question, stringUsedInternally: '?', writtenAs: 'prefix', arity: OperatorArity.Unary, usedAs: 'operation', capabilities: ['unary-operator', 'built-in-help'] } } /* eslint-enable */ diff --git a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts index 0448c0d216..912ce153fc 100644 --- a/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/atomic/dataflow-atomic-tests.ts @@ -367,7 +367,7 @@ describe('Atomic (dataflow information)', withShell(shell => { .defineVariable('0', 'x', { definedBy: ['4', '5'] }) ) - assertDataflow(label('For', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'return-value-of-assignments', 'for-loop', 'numbers', 'built-in-sequencing']), + assertDataflow(label('For', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'return-value-of-assignments', 'for-loop', 'numbers']), shell, 'x <- for (i in 1:4) 3', emptyGraph() .call('4', ':', [argumentInCall('2'), argumentInCall('3')], { returns: [], reads: [BuiltIn, '2', '3'], onlyBuiltIn: true }) .call('7', 'for', [argumentInCall('1'), argumentInCall('4'), argumentInCall('5')], { returns: [], reads: [BuiltIn, '1', '4'], onlyBuiltIn: true, environment: defaultEnv().defineVariable('i', '1', '7') }) @@ -628,7 +628,7 @@ describe('Atomic (dataflow information)', withShell(shell => { describe('Loops', () => { describe('For', () => { - assertDataflow(label('simple constant for-loop', ['for-loop', 'numbers', 'name-normal', 'built-in-sequencing', 'grouping']), + assertDataflow(label('simple constant for-loop', ['for-loop', 'numbers', 'name-normal', 'grouping']), shell, 'for(i in 1:10) { 1 }', emptyGraph() .call('3', ':', [argumentInCall('1'), argumentInCall('2')], { returns: [], reads: ['1', '2', BuiltIn], onlyBuiltIn: true }) .call('7', '{', [argumentInCall('6')], { returns: ['6'], reads: [BuiltIn], controlDependencies: [] }) @@ -639,7 +639,7 @@ describe('Atomic (dataflow information)', withShell(shell => { .constant('2') .constant('6', { controlDependencies: [] }) ) - assertDataflow(label('using loop variable in body', ['for-loop', 'numbers', 'name-normal', 'built-in-sequencing', 'grouping']), + assertDataflow(label('using loop variable in body', ['for-loop', 'numbers', 'name-normal', 'grouping']), shell, 'for(i in 1:10) { i }', emptyGraph() .use('6', 'i', { controlDependencies: [] }) .reads('6', '0') diff --git a/test/functionality/r-bridge/lang/ast/parse-constructs.ts b/test/functionality/r-bridge/lang/ast/parse-constructs.ts index f6aed9eef5..a2576a8382 100644 --- a/test/functionality/r-bridge/lang/ast/parse-constructs.ts +++ b/test/functionality/r-bridge/lang/ast/parse-constructs.ts @@ -258,7 +258,7 @@ describe('Parse simple constructs', withShell(shell => { }) describe('loops', () => { describe('for', () => { - assertAst(label('for(i in 1:10) 2', ['for-loop', 'name-normal', 'numbers', 'built-in-sequencing']), shell, 'for(i in 1:42)2', + assertAst(label('for(i in 1:10) 2', ['for-loop', 'name-normal', 'numbers']), shell, 'for(i in 1:42)2', exprList({ type: RType.ForLoop, location: rangeFrom(1, 1, 1, 3), @@ -304,7 +304,7 @@ describe('Parse simple constructs', withShell(shell => { ignoreAdditionalTokens: true } ) - assertAst(label('for-loop with comment', ['for-loop', 'name-normal', 'numbers', 'built-in-sequencing', 'comments', 'newlines']), shell, `for(#a + assertAst(label('for-loop with comment', ['for-loop', 'name-normal', 'numbers', 'comments', 'newlines']), shell, `for(#a i#b in#c 1:42#d diff --git a/test/functionality/r-bridge/lang/ast/parse-values.ts b/test/functionality/r-bridge/lang/ast/parse-values.ts index 9973d91943..0108e006b3 100644 --- a/test/functionality/r-bridge/lang/ast/parse-values.ts +++ b/test/functionality/r-bridge/lang/ast/parse-values.ts @@ -100,7 +100,7 @@ describe('Constant Parsing', for(const symbol of RSymbolPool) { const range = rangeFrom(1, symbol.symbolStart, 1, symbol.symbolStart + symbol.val.length - 1) const exported = symbol.namespace !== undefined - const mapped = exported ? [symbol.internal ? 'accessing-internal-names' as const : 'accessing-exported-names' as const] : [] + const mapped = exported && !symbol.internal ? ['accessing-exported-names' as const] : [] assertAst(label(symbol.str, ['name-normal', ...mapped]), shell, symbol.str, exprList({ type: RType.Symbol, diff --git a/test/functionality/slicing/static-program-slices/simple-tests.ts b/test/functionality/slicing/static-program-slices/simple-tests.ts index 837ea02023..a62c8c2a08 100644 --- a/test/functionality/slicing/static-program-slices/simple-tests.ts +++ b/test/functionality/slicing/static-program-slices/simple-tests.ts @@ -19,7 +19,7 @@ describe('Simple', withShell(shell => { shell, 'if(FALSE) { x <- 3 } else { x <- 4 }\nx', ['2@x'], 'x <- 4\nx') }) describe('Independent Control-Flow', () => { - assertSliced(label('For-Loop', ['name-normal', 'for-loop', 'newlines', 'unnamed-arguments', 'numbers', 'built-in-sequencing', ...OperatorDatabase['<-'].capabilities, 'function-calls', ...OperatorDatabase['*'].capabilities, 'precedence']), + assertSliced(label('For-Loop', ['name-normal', 'for-loop', 'newlines', 'unnamed-arguments', 'numbers', ...OperatorDatabase['<-'].capabilities, 'function-calls', ...OperatorDatabase['*'].capabilities, 'precedence']), shell, ` x <- 1 for(i in 1:10) { @@ -69,9 +69,9 @@ x`, { shell, 'a <- 4\na <- list(1,2)\na[3]', ['3@a'], 'a <- list(1,2)\na') assertSliced(label('variable', ['name-normal', 'numbers', ...OperatorDatabase['<-'].capabilities, 'newlines', 'unnamed-arguments', 'single-bracket-access']), shell, 'i <- 4\na <- list(1,2)\nb <- a[i]', ['3@b'], 'i <- 4\na <- list(1,2)\nb <- a[i]') - assertSliced(label('subset sequence', ['name-normal', 'numbers', ...OperatorDatabase['<-'].capabilities, 'newlines', 'unnamed-arguments', 'built-in-sequencing', 'empty-arguments', 'single-bracket-access', 'subsetting']), + assertSliced(label('subset sequence', ['name-normal', 'numbers', ...OperatorDatabase['<-'].capabilities, 'newlines', 'unnamed-arguments', 'empty-arguments', 'single-bracket-access', 'subsetting']), shell, 'i <- 4\na <- list(1,2)\n b <- a[1:i,]', ['3@b'], 'i <- 4\na <- list(1,2)\nb <- a[1:i,]') - assertSliced(label('range assignment', ['name-normal', 'numbers', ...OperatorDatabase['<-'].capabilities, 'newlines', 'unnamed-arguments', 'built-in-sequencing', 'empty-arguments', 'single-bracket-access', 'subsetting', 'range-assignment']), + assertSliced(label('range assignment', ['name-normal', 'numbers', ...OperatorDatabase['<-'].capabilities, 'newlines', 'unnamed-arguments', 'empty-arguments', 'single-bracket-access', 'subsetting', 'range-assignment']), shell, 'a <- 1:10\na[1:5] <- 3\na', ['3@a'], 'a <- 1 : 10\na[1:5] <- 3\na') describe('Definitions', () => { describe('[[', () => { @@ -122,7 +122,7 @@ a <- 5 `, ['3@a'], 'a <- 5') }) describe('The classic', () => { - const capabilities: SupportedFlowrCapabilityId[] = ['name-normal', 'numbers', ...OperatorDatabase['<-'].capabilities, 'call-normal', 'newlines', 'unnamed-arguments', 'for-loop', ...OperatorDatabase['+'].capabilities, ...OperatorDatabase['*'].capabilities, 'built-in-sequencing', 'strings', 'precedence'] + const capabilities: SupportedFlowrCapabilityId[] = ['name-normal', 'numbers', ...OperatorDatabase['<-'].capabilities, 'call-normal', 'newlines', 'unnamed-arguments', 'for-loop', ...OperatorDatabase['+'].capabilities, ...OperatorDatabase['*'].capabilities, 'strings', 'precedence'] const code = ` sum <- 0 product <- 1 From 6e927f0eb8852fb21e27fc2d15aa408150988587 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 May 2024 19:00:54 +0200 Subject: [PATCH 17/23] test: additional dataflow tests in various categories --- .../expression-lists/dataflow-read-tests.ts | 46 +++++ .../dataflow-function-definition-tests.ts | 172 ++++++++++++++++++ .../functions/dataflow-source-tests.ts | 71 +++++++- 3 files changed, 288 insertions(+), 1 deletion(-) diff --git a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-read-tests.ts b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-read-tests.ts index e2fbd18ca7..b4553f487f 100644 --- a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-read-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-read-tests.ts @@ -91,4 +91,50 @@ describe('Lists with variable references', withShell(shell => { .defineVariable('3', 'x', { definedBy: ['4', '5'] }) ) }) + // potentially incorrect? redefinition appears correct in dataflow graph, but why is the {} still flagged up as an expression list? + describe('Redefining expression lists', () => { + assertDataflow(label('redefining {', ['name-escaped', ...OperatorDatabase['<-'].capabilities, 'formals-dot-dot-dot', 'implicit-return', 'numbers', 'newlines']), + shell, `\`{\` <- function(...) 3 +x <- 4 +{ + x <- 2 + print(x) +} +print(x)`, emptyGraph() + .use('16', 'x') + .reads('16', '12') + .use('21', 'x') + .reads('21', '12') + .call('6', '<-', [argumentInCall('0'), argumentInCall('5')], { returns: ['0'], reads: [BuiltIn] }) + .argument('6', ['5', '0']) + .call('9', '<-', [argumentInCall('7'), argumentInCall('8')], { returns: ['7'], reads: [BuiltIn], environment: defaultEnv().defineFunction('{', '0', '6') }) + .argument('9', ['8', '7']) + .call('14', '<-', [argumentInCall('12'), argumentInCall('13')], { returns: ['12'], reads: [BuiltIn], environment: defaultEnv().defineFunction('{', '0', '6').defineVariable('x', '7', '9') }) + .argument('14', ['13', '12']) + .definesOnCall('14', '1') + .argument('18', '16') + .call('18', 'print', [argumentInCall('16')], { returns: ['16'], reads: [BuiltIn], environment: defaultEnv().defineFunction('{', '0', '6').defineVariable('x', '12', '14') }) + .definesOnCall('18', '1') + .argument('19', '14') + .argument('19', '18') + .call('19', '{', [argumentInCall('14'), argumentInCall('18')], { returns: ['3'], reads: ['0'], environment: defaultEnv().defineFunction('{', '0', '6').defineVariable('x', '7', '9') }) + .calls('19', '5') + .argument('23', '21') + .call('23', 'print', [argumentInCall('21')], { returns: ['21'], reads: [BuiltIn], environment: defaultEnv().defineFunction('{', '0', '6').defineVariable('x', '12', '14') }) + .defineVariable('1', '...', { definedBy: [] }, false) + .constant('3', undefined, false) + .defineFunction('5', ['3'], { + out: [], + in: [{ nodeId: '3', name: undefined, controlDependencies: [] }], + unknownReferences: [], + entryPoint: '3', + graph: new Set(['1', '3']), + environment: defaultEnv().pushEnv().defineParameter('...', '1', '2') + }) + .defineVariable('0', '`{`', { definedBy: ['5', '6'] }) + .constant('8') + .defineVariable('7', 'x', { definedBy: ['8', '9'] }) + .constant('13') + .defineVariable('12', 'x', { definedBy: ['13', '14'] })) + }) })) diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts index 8d9b3954a9..d4d12518b3 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts @@ -5,6 +5,7 @@ import { label } from '../../../_helper/label' import { BuiltIn } from '../../../../../src/dataflow/environments/built-in' import { OperatorDatabase } from '../../../../../src/r-bridge/lang-4.x/ast/model/operators' import { EmptyArgument } from '../../../../../src/r-bridge/lang-4.x/ast/model/nodes/r-function-call' +import { UnnamedFunctionCallPrefix } from '../../../../../src/dataflow/internal/process/functions/call/unnamed-call-handling' describe('Function Definition', withShell(shell => { describe('Only functions', () => { @@ -450,6 +451,177 @@ describe('Function Definition', withShell(shell => { .constant('19') .defineVariable('18', 'b', { definedBy: ['19', '20'] }) ) + assertDataflow(label('closure w/ default arguments',['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-default', 'numbers', 'newlines', 'implicit-return', 'normal-definition', 'closures', 'unnamed-arguments']), + shell, `f <- function(x = 1) { + function() x +} +g <- f(2) +print(g())`, emptyGraph() + .use('6', 'x', undefined, false) + .reads('6', '1') + .call('9', '{', [argumentInCall('8')], { returns: ['8'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('x', '1', '3') }, false) + .argument('9', '8') + .call('11', '<-', [argumentInCall('0'), argumentInCall('10')], { returns: ['0'], reads: [BuiltIn] }) + .argument('11', ['10', '0']) + .call('16', 'f', [argumentInCall('14')], { returns: ['9'], reads: ['0'], environment: defaultEnv().defineFunction('f', '0', '11') }) + .argument('16', '14') + .calls('16', '10') + .argument('17', '16') + .call('17', '<-', [argumentInCall('12'), argumentInCall('16')], { returns: ['12'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '11') }) + .argument('17', '12') + .call('20', 'g', [], { returns: ['6'], reads: ['12'], environment: defaultEnv().defineFunction('f', '0', '11').defineVariable('g', '12', '17') }) + .calls('20', '8') + .argument('22', '20') + .call('22', 'print', [argumentInCall('20')], { returns: ['20'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '11').defineVariable('g', '12', '17') }) + .defineVariable('1', 'x', { definedBy: ['2'] }, false) + .constant('2', undefined, false) + .defineFunction('8', ['6'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '6', + graph: new Set(['6']), + environment: defaultEnv().pushEnv().pushEnv() + }, { environment: defaultEnv().pushEnv() }, false) + .defineFunction('10', ['9'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '9', + graph: new Set(['1', '2', '8', '9']), + environment: defaultEnv().pushEnv().defineParameter('x', '1', '3') + }) + .defineVariable('0', 'f', { definedBy: ['10', '11'] }) + .constant('14') + .definesOnCall('14', '1') + .defineVariable('12', 'g', { definedBy: ['16', '17'] })) + assertDataflow(label('nested closures w/ default arguments', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-default', 'numbers', 'newlines', 'lambda-syntax', 'implicit-return', ...OperatorDatabase['+'].capabilities, 'closures', 'grouping']), + shell, `f <- function(x = 1) { + (\\(y = 2) function(z = 3) x + y + z)() +} +g <- f(8) +print(g())`, emptyGraph() + .use('14', 'x', undefined, false) + .reads('14', '1') + .use('15', 'y', undefined, false) + .use('17', 'z', undefined, false) + .reads('17', '11') + .argument('16', '14') + .argument('16', '15') + .call('16', '+', [argumentInCall('14'), argumentInCall('15')], { returns: [], reads: [BuiltIn, '14', '15'], onlyBuiltIn: true, environment: defaultEnv().pushEnv().pushEnv().pushEnv().defineParameter('z', '11', '13') }, false) + .argument('18', '16') + .argument('18', '17') + .call('18', '+', [argumentInCall('16'), argumentInCall('17')], { returns: [], reads: ['16', '17', BuiltIn], onlyBuiltIn: true, environment: defaultEnv().pushEnv().pushEnv().pushEnv().defineParameter('z', '11', '13') }, false) + .call('23', '(', [argumentInCall('22')], { returns: ['22'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('x', '1', '3') }, false) + .argument('23', '22') + .call('24', `${UnnamedFunctionCallPrefix}24`, [], { returns: ['20'], reads: ['23'], environment: defaultEnv().pushEnv().defineParameter('x', '1', '3') }, false) + .calls('24', ['23', '22']) + .argument('25', '23') + .call('25', '{', [argumentInCall('23')], { returns: ['23'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('x', '1', '3') }, false) + .call('27', '<-', [argumentInCall('0'), argumentInCall('26')], { returns: ['0'], reads: [BuiltIn] }) + .argument('27', ['26', '0']) + .call('32', 'f', [argumentInCall('30')], { returns: ['25'], reads: ['0'], environment: defaultEnv().defineFunction('f', '0', '27') }) + .argument('32', '30') + .calls('32', '26') + .argument('33', '32') + .call('33', '<-', [argumentInCall('28'), argumentInCall('32')], { returns: ['28'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '27') }) + .argument('33', '28') + .call('36', 'g', [], { returns: ['20'], reads: ['28'], environment: defaultEnv().defineFunction('f', '0', '27').defineVariable('g', '28', '33') }) + .calls('36', '22') + .argument('38', '36') + .call('38', 'print', [argumentInCall('36')], { returns: ['36'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '27').defineVariable('g', '28', '33') }) + .defineVariable('1', 'x', { definedBy: ['2'] }, false) + .constant('2', undefined, false) + .defineVariable('8', 'y', { definedBy: ['9'] }, false) + .constant('9', undefined, false) + .defineVariable('11', 'z', { definedBy: ['12'] }, false) + .constant('12', undefined, false) + .defineFunction('20', ['18'], { + out: [], + in: [{ nodeId: '15', name: 'y', controlDependencies: [] }], + unknownReferences: [], + entryPoint: '18', + graph: new Set(['11', '12', '14', '15', '16', '17', '18']), + environment: defaultEnv().pushEnv().pushEnv().pushEnv().defineParameter('z', '11', '13') + }, { environment: defaultEnv().pushEnv().pushEnv() }, false) + .defineFunction('22', ['20'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '20', + graph: new Set(['8', '9', '20']), + environment: defaultEnv().pushEnv().pushEnv().defineParameter('y', '8', '10') + }, { environment: defaultEnv().pushEnv() }, false) + .defineFunction('26', ['25'], { + out: [], + in: [{ nodeId: '24', name: `${UnnamedFunctionCallPrefix}24`, controlDependencies: [] }], + unknownReferences: [], + entryPoint: '25', + graph: new Set(['1', '2', '22', '23', '24', '25']), + environment: defaultEnv().pushEnv().defineParameter('x', '1', '3') + }) + .defineVariable('0', 'f', { definedBy: ['26', '27'] }) + .constant('30') + .definesOnCall('30', '1') + .defineVariable('28', 'g', { definedBy: ['32', '33'] })) + assertDataflow(label('closure w/ side effects', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'normal-definition', 'newlines', 'closures', ...OperatorDatabase['<<-'].capabilities, 'side-effects-in-function-call', ...OperatorDatabase['+'].capabilities, 'numbers']), + shell, `f <- function() { + function() { + x <<- x + 1 + x + } +} +x <- 2 +f()() +print(x)`, emptyGraph() + .use('6', 'x', undefined, false) + .use('10', 'x', undefined, false) + .reads('10', '5') + .use('23', 'x') + .reads('23', '5') + .argument('8', '6') + .call('8', '+', [argumentInCall('6'), argumentInCall('7')], { returns: [], reads: [BuiltIn, '6', '7'], onlyBuiltIn: true, environment: defaultEnv().pushEnv().pushEnv() }, false) + .argument('8', '7') + .argument('9', '8') + .call('9', '<<-', [argumentInCall('5'), argumentInCall('8')], { returns: ['5'], reads: [BuiltIn], environment: defaultEnv().pushEnv().pushEnv() }, false) + .argument('9', '5') + .argument('11', '9') + .argument('11', '10') + .call('11', '{', [argumentInCall('9'), argumentInCall('10')], { returns: ['10'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '5', '9').pushEnv().pushEnv() }, false) + .call('13', '{', [argumentInCall('12')], { returns: ['12'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) + .argument('13', '12') + .call('15', '<-', [argumentInCall('0'), argumentInCall('14')], { returns: ['0'], reads: [BuiltIn] }) + .argument('15', ['14', '0']) + .call('18', '<-', [argumentInCall('16'), argumentInCall('17')], { returns: ['16'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '15') }) + .argument('18', ['17', '16']) + .call('20', 'f', [], { returns: ['13'], reads: ['0'], environment: defaultEnv().defineFunction('f', '0', '15').defineVariable('x', '16', '18') }) + .calls('20', '14') + .call('21', `${UnnamedFunctionCallPrefix}21`, [], { returns: ['11'], reads: ['20', '16'], environment: defaultEnv().defineFunction('f', '0', '15').defineVariable('x', '16', '18') }) + .calls('21', ['20', '12']) + .argument('25', '23') + .call('25', 'print', [argumentInCall('23')], { returns: ['23'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '15').defineVariable('x', '5', '9') }) + .constant('7', undefined, false) + .defineVariable('5', 'x', { definedBy: ['8', '9'] }, false) + .sideEffectOnCall('5', '21') + .defineFunction('12', ['11'], { + out: [], + in: [{ nodeId: '6', name: 'x', controlDependencies: [] }], + unknownReferences: [], + entryPoint: '11', + graph: new Set(['6', '7', '8', '5', '9', '10', '11']), + environment: defaultEnv().defineVariable('x', '5', '9').pushEnv().pushEnv() + }, { environment: defaultEnv().defineVariable('x', '5', '9').pushEnv() }, false) + .defineFunction('14', ['13'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: '13', + graph: new Set(['12', '13']), + environment: defaultEnv().pushEnv() + }) + .defineVariable('0', 'f', { definedBy: ['14', '15'] }) + .constant('17') + .defineVariable('16', 'x', { definedBy: ['17', '18'] })) }) describe('Dead Code', () => { diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts index 6e87e18d16..1ffddc14a7 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts @@ -15,7 +15,9 @@ describe('source', withShell(shell => { const sources = { simple: 'N <- 9', recursive1: 'x <- 1\nsource("recursive2")', - recursive2: 'cat(x)\nsource("recursive1")' + recursive2: 'cat(x)\nsource("recursive1")', + closure1: 'f <- function() { function() 3 }', + closure2: 'f <- function() { x <<- 3 }' } setSourceProvider(requestProviderFromText(sources)) @@ -91,4 +93,71 @@ describe('source', withShell(shell => { .constant('1') .defineVariable('0', 'x', { definedBy: ['1', '2'] }) ) + + assertDataflow(label('sourcing a closure', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'sourcing-external-files', 'newlines', 'normal-definition', 'implicit-return', 'closures', 'numbers']), + shell, 'source("closure1")\ng <- f()\nprint(g())', emptyGraph() + .call('3', 'source', [argumentInCall('1')], { returns: [], reads: [BuiltIn] }) + .argument('3', '1') + .call('closure1-1:1-1:6-8', '<-', [argumentInCall('closure1-1:1-1:6-0'), argumentInCall('closure1-1:1-1:6-7')], { returns: ['closure1-1:1-1:6-0'], reads: [BuiltIn] }) + .argument('closure1-1:1-1:6-8', ['closure1-1:1-1:6-7', 'closure1-1:1-1:6-0']) + .call('6', 'f', [], { returns: ['closure1-1:1-1:6-5'], reads: ['closure1-1:1-1:6-0'], environment: defaultEnv().defineFunction('f', 'closure1-1:1-1:6-0', 'closure1-1:1-1:6-8') }) + .calls('6', 'closure1-1:1-1:6-7') + .argument('7', '6') + .call('7', '<-', [argumentInCall('4'), argumentInCall('6')], { returns: ['4'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', 'closure1-1:1-1:6-0', 'closure1-1:1-1:6-8') }) + .argument('7', '4') + .call('10', 'g', [], { returns: ['closure1-1:1-1:6-3'], reads: ['4'], environment: defaultEnv().defineFunction('f', 'closure1-1:1-1:6-0', 'closure1-1:1-1:6-8').defineVariable('g', '4', '7') }) + .calls('10', 'closure1-1:1-1:6-5') + .argument('12', '10') + .call('12', 'print', [argumentInCall('10')], { returns: ['10'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', 'closure1-1:1-1:6-0', 'closure1-1:1-1:6-8').defineVariable('g', '4', '7') }) + .constant('1') + .constant('closure1-1:1-1:6-3', undefined, false) + .defineFunction('closure1-1:1-1:6-5', ['closure1-1:1-1:6-3'], { + out: [], + in: [{ nodeId: 'closure1-1:1-1:6-3', name: undefined, controlDependencies: [] }], + unknownReferences: [], + entryPoint: 'closure1-1:1-1:6-3', + graph: new Set(['closure1-1:1-1:6-3']), + environment: defaultEnv().pushEnv().pushEnv() + }, { environment: defaultEnv().pushEnv() }, false) + .defineFunction('closure1-1:1-1:6-7', ['closure1-1:1-1:6-5'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: 'closure1-1:1-1:6-5', + graph: new Set(['closure1-1:1-1:6-5']), + environment: defaultEnv().pushEnv() + }) + .defineVariable('closure1-1:1-1:6-0', 'f', { definedBy: ['closure1-1:1-1:6-7', 'closure1-1:1-1:6-8'] }) + .defineVariable('4', 'g', { definedBy: ['6', '7'] })) + assertDataflow(label('sourcing a closure w/ side effects', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'sourcing-external-files', 'newlines', 'normal-definition', 'implicit-return', 'closures', 'numbers', ...OperatorDatabase['<<-'].capabilities]), + shell, 'x <- 2\nsource("closure2")\nf()\nprint(x)', emptyGraph() + .use('10', 'x') + .reads('10', 'closure2-2:1-2:6-3') + .call('2', '<-', [argumentInCall('0'), argumentInCall('1')], { returns: ['0'], reads: [BuiltIn] }) + .argument('2', ['1', '0']) + .call('6', 'source', [argumentInCall('4')], { returns: [], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('6', '4') + .call('closure2-2:1-2:6-5', '<<-', [argumentInCall('closure2-2:1-2:6-3'), argumentInCall('closure2-2:1-2:6-4')], { returns: ['closure2-2:1-2:6-3'], reads: [BuiltIn], environment: defaultEnv().pushEnv() }, false) + .argument('closure2-2:1-2:6-5', ['closure2-2:1-2:6-4', 'closure2-2:1-2:6-3']) + .call('closure2-2:1-2:6-8', '<-', [argumentInCall('closure2-2:1-2:6-0'), argumentInCall('closure2-2:1-2:6-7')], { returns: ['closure2-2:1-2:6-0'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', '0', '2') }) + .argument('closure2-2:1-2:6-8', ['closure2-2:1-2:6-7', 'closure2-2:1-2:6-0']) + .call('8', 'f', [], { returns: ['closure2-2:1-2:6-5'], reads: ['closure2-2:1-2:6-0'], environment: defaultEnv().defineVariable('x', '0', '2').defineFunction('f', 'closure2-2:1-2:6-0', 'closure2-2:1-2:6-8') }) + .calls('8', 'closure2-2:1-2:6-7') + .argument('12', '10') + .call('12', 'print', [argumentInCall('10')], { returns: ['10'], reads: [BuiltIn], environment: defaultEnv().defineVariable('x', 'closure2-2:1-2:6-3', 'closure2-2:1-2:6-5').defineFunction('f', 'closure2-2:1-2:6-0', 'closure2-2:1-2:6-8') }) + .constant('1') + .defineVariable('0', 'x', { definedBy: ['1', '2'] }) + .constant('4') + .constant('closure2-2:1-2:6-4', undefined, false) + .defineVariable('closure2-2:1-2:6-3', 'x', { definedBy: ['closure2-2:1-2:6-4', 'closure2-2:1-2:6-5'] }, false) + .sideEffectOnCall('closure2-2:1-2:6-3', '8') + .defineFunction('closure2-2:1-2:6-7', ['closure2-2:1-2:6-5'], { + out: [], + in: [], + unknownReferences: [], + entryPoint: 'closure2-2:1-2:6-5', + graph: new Set(['closure2-2:1-2:6-4', 'closure2-2:1-2:6-3', 'closure2-2:1-2:6-5']), + environment: defaultEnv().defineVariable('x', 'closure2-2:1-2:6-3', 'closure2-2:1-2:6-5').pushEnv() + }, { environment: defaultEnv().defineVariable('x', 'closure2-2:1-2:6-3', 'closure2-2:1-2:6-5') }) + .defineVariable('closure2-2:1-2:6-0', 'f', { definedBy: ['closure2-2:1-2:6-7', 'closure2-2:1-2:6-8'] })) })) From 7ee954f6ddb7686e4fd6dd7cb57189e13ca5e772 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 May 2024 19:03:47 +0200 Subject: [PATCH 18/23] feat-fix: fixed errors when running new tests on 4.0.0 --- .../expression-lists/dataflow-if-then-tests.ts | 5 +++-- .../functions/dataflow-function-definition-tests.ts | 3 ++- .../slicing/static-program-slices/calls-tests.ts | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts index 221a906b32..3855db3fa0 100644 --- a/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/expression-lists/dataflow-if-then-tests.ts @@ -5,6 +5,7 @@ import { label } from '../../../_helper/label' import { BuiltIn } from '../../../../../src/dataflow/environments/built-in' import { OperatorDatabase } from '../../../../../src/r-bridge/lang-4.x/ast/model/operators' import { EmptyArgument } from '../../../../../src/r-bridge/lang-4.x/ast/model/nodes/r-function-call' +import { MIN_VERSION_LAMBDA } from '../../../../../src/r-bridge/lang-4.x/ast/model/versions' describe('Lists with if-then constructs', withShell(shell => { for(const assign of ['<-', '<<-', '=']) { @@ -290,8 +291,8 @@ a()`, emptyGraph() graph: new Set(['11']), environment: defaultEnv().pushEnv() }) - .defineVariable('9', '"a"', { definedBy: ['13', '15'], controlDependencies: [{ id: '17', when: true }] }) - ) + .defineVariable('9', '"a"', { definedBy: ['13', '15'], controlDependencies: [{ id: '17', when: true }] }), + { minRVersion: MIN_VERSION_LAMBDA }) assertDataflow(label('assign from get', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'newlines', 'assignment-functions', 'strings', 'unnamed-arguments']), shell, 'b <- 5\nassign("a", get("b"))\nprint(a)', emptyGraph() .use('7', '"b"') diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts index d4d12518b3..c8d7a07218 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts @@ -6,6 +6,7 @@ import { BuiltIn } from '../../../../../src/dataflow/environments/built-in' import { OperatorDatabase } from '../../../../../src/r-bridge/lang-4.x/ast/model/operators' import { EmptyArgument } from '../../../../../src/r-bridge/lang-4.x/ast/model/nodes/r-function-call' import { UnnamedFunctionCallPrefix } from '../../../../../src/dataflow/internal/process/functions/call/unnamed-call-handling' +import { MIN_VERSION_LAMBDA } from '../../../../../src/r-bridge/lang-4.x/ast/model/versions' describe('Function Definition', withShell(shell => { describe('Only functions', () => { @@ -797,6 +798,6 @@ f(3)`, emptyGraph() }) .definesOnCall('27', '10') .constant('31') - .definesOnCall('31', '21')) + .definesOnCall('31', '21'), { minRVersion: MIN_VERSION_LAMBDA }) }) })) diff --git a/test/functionality/slicing/static-program-slices/calls-tests.ts b/test/functionality/slicing/static-program-slices/calls-tests.ts index d2380ffc67..cd334f4f53 100644 --- a/test/functionality/slicing/static-program-slices/calls-tests.ts +++ b/test/functionality/slicing/static-program-slices/calls-tests.ts @@ -2,6 +2,7 @@ import { assertSliced, withShell } from '../../_helper/shell' import { label } from '../../_helper/label' import { OperatorDatabase } from '../../../../src/r-bridge/lang-4.x/ast/model/operators' import type { SupportedFlowrCapabilityId } from '../../../../src/r-bridge/data/get' +import { MIN_VERSION_LAMBDA } from '../../../../src/r-bridge/lang-4.x/ast/model/versions' describe('Calls', withShell(shell => { describe('Simple Calls', () => { @@ -447,7 +448,7 @@ if(y) { } a()`, ['5@a'], `a <- function() 2 if(y) { assign("a", function() 1) } -a()`) +a()`, { minRVersion: MIN_VERSION_LAMBDA }) }) describe('DelayedAssign', () => { assertSliced(label('using delayed-assign as assignment', ['name-normal', 'numbers', 'assignment-functions', 'strings', 'newlines', 'global-scope']), From e4b8731ae2f4e4b5085aa16c65fdd08b9a06418c Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 May 2024 19:33:06 +0200 Subject: [PATCH 19/23] test: added slice versions of new dataflow tests --- .../dataflow-function-definition-tests.ts | 2 +- .../static-program-slices/calls-tests.ts | 31 +++++++++++++++++++ .../control-flow-tests.ts | 10 ++++++ .../static-program-slices/source-tests.ts | 25 +++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 test/functionality/slicing/static-program-slices/source-tests.ts diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts index c8d7a07218..76bffa7fef 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts @@ -564,7 +564,7 @@ print(g())`, emptyGraph() .defineVariable('0', 'f', { definedBy: ['26', '27'] }) .constant('30') .definesOnCall('30', '1') - .defineVariable('28', 'g', { definedBy: ['32', '33'] })) + .defineVariable('28', 'g', { definedBy: ['32', '33'] }), { minRVersion: MIN_VERSION_LAMBDA }) assertDataflow(label('closure w/ side effects', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'normal-definition', 'newlines', 'closures', ...OperatorDatabase['<<-'].capabilities, 'side-effects-in-function-call', ...OperatorDatabase['+'].capabilities, 'numbers']), shell, `f <- function() { function() { diff --git a/test/functionality/slicing/static-program-slices/calls-tests.ts b/test/functionality/slicing/static-program-slices/calls-tests.ts index cd334f4f53..a94334bac3 100644 --- a/test/functionality/slicing/static-program-slices/calls-tests.ts +++ b/test/functionality/slicing/static-program-slices/calls-tests.ts @@ -573,4 +573,35 @@ if(x == 3) { x`) }) }) + describe('Closures', () => { + assertSliced(label('closure w/ default arguments',['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-default', 'numbers', 'newlines', 'implicit-return', 'normal-definition', 'closures', 'unnamed-arguments']), + shell, `f <- function(x = 1) { + function() x +} +g <- f(2) +print(g())`, ['5@g'], `f <- function(x=1) { function() x } +g <- f(2) +g()`) + assertSliced(label('nested closures w/ default arguments', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-default', 'numbers', 'newlines', 'lambda-syntax', 'implicit-return', ...OperatorDatabase['+'].capabilities, 'closures', 'grouping']), + shell, `f <- function(x = 1) { + (\\(y = 2) function(z = 3) x + y + z)() +} +g <- f(8) +print(g())`, ['5@g'], `f <- function(x=1) {} +g <- f(8) +g()`, { minRVersion: MIN_VERSION_LAMBDA }) + assertSliced(label('closure w/ side effects', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'normal-definition', 'newlines', 'closures', ...OperatorDatabase['<<-'].capabilities, 'side-effects-in-function-call', ...OperatorDatabase['+'].capabilities, 'numbers']), + shell, `f <- function() { + function() { + x <<- x + 1 + x + } +} +x <- 2 +f()() +print(x)`, ['9@x'], `f <- function() { function() x <<- x + 1 } +x <- 2 +f() +x`) + }) })) diff --git a/test/functionality/slicing/static-program-slices/control-flow-tests.ts b/test/functionality/slicing/static-program-slices/control-flow-tests.ts index 6e87bcb86f..41c8d6ad9f 100644 --- a/test/functionality/slicing/static-program-slices/control-flow-tests.ts +++ b/test/functionality/slicing/static-program-slices/control-flow-tests.ts @@ -96,4 +96,14 @@ f(5)`, ['12@f'], `f <- function(x) { } f(5)`) }) + describe('Redefinitions', () => { + assertSliced(label('redefining {', ['name-escaped', ...OperatorDatabase['<-'].capabilities, 'formals-dot-dot-dot', 'implicit-return', 'numbers', 'newlines']), + shell, `\`{\` <- function(...) 3 +x <- 4 +{ + x <- 2 + print(x) +} +print(x)`, ['7@x'], 'x <- 2\nx') + }) })) diff --git a/test/functionality/slicing/static-program-slices/source-tests.ts b/test/functionality/slicing/static-program-slices/source-tests.ts new file mode 100644 index 0000000000..162cd46a7c --- /dev/null +++ b/test/functionality/slicing/static-program-slices/source-tests.ts @@ -0,0 +1,25 @@ +import { assertSliced, withShell } from '../../_helper/shell' +import { setSourceProvider } from '../../../../src/dataflow/internal/process/functions/call/built-in/built-in-source' +import { requestProviderFromFile, requestProviderFromText } from '../../../../src/r-bridge/retriever' +import { label } from '../../_helper/label' +import { OperatorDatabase } from '../../../../src/r-bridge/lang-4.x/ast/model/operators' + +describe('source', withShell(shell => { + // reset the source provider back to the default value after our tests + after(() => setSourceProvider(requestProviderFromFile())) + + const sources = { + simple: 'N <- 9', + closure1: 'f <- function() { function() 3 }', + closure2: 'f <- function() { x <<- 3 }' + } + setSourceProvider(requestProviderFromText(sources)) + + // these are incorrect - where is the content from the sourced file? + assertSliced(label('simple source', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'unnamed-arguments', 'strings', 'sourcing-external-files','newlines']), + shell, 'source("simple")\ncat(N)', ['2@N'], 'N') + assertSliced(label('sourcing a closure', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'sourcing-external-files', 'newlines', 'normal-definition', 'implicit-return', 'closures', 'numbers']), + shell, 'source("closure1")\ng <- f()\nprint(g())', ['3@g'], 'g <- f()\ng()') + assertSliced(label('sourcing a closure w/ side effects', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'sourcing-external-files', 'newlines', 'normal-definition', 'implicit-return', 'closures', 'numbers', ...OperatorDatabase['<<-'].capabilities]), + shell, 'x <- 2\nsource("closure2")\nf()\nprint(x)', ['4@x'], 'f()\nx') +})) From 56b803b9d108b5e6d59d1be66b0ca2331a8755fe Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 May 2024 19:47:35 +0200 Subject: [PATCH 20/23] feat-fix: fixed source provider settings in tests --- .../functions/dataflow-source-tests.ts | 6 ++---- .../slicing/static-program-slices/source-tests.ts | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts index 1ffddc14a7..889d6466ec 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-source-tests.ts @@ -9,9 +9,6 @@ import { BuiltIn } from '../../../../../src/dataflow/environments/built-in' import { EmptyArgument } from '../../../../../src/r-bridge/lang-4.x/ast/model/nodes/r-function-call' describe('source', withShell(shell => { - // reset the source provider back to the default value after our tests - after(() => setSourceProvider(requestProviderFromFile())) - const sources = { simple: 'N <- 9', recursive1: 'x <- 1\nsource("recursive2")', @@ -19,7 +16,8 @@ describe('source', withShell(shell => { closure1: 'f <- function() { function() 3 }', closure2: 'f <- function() { x <<- 3 }' } - setSourceProvider(requestProviderFromText(sources)) + before(() => setSourceProvider(requestProviderFromText(sources))) + after(() => setSourceProvider(requestProviderFromFile())) assertDataflow(label('simple source', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'unnamed-arguments', 'strings', 'sourcing-external-files','newlines']), shell, 'source("simple")\ncat(N)', emptyGraph() .use('5', 'N') diff --git a/test/functionality/slicing/static-program-slices/source-tests.ts b/test/functionality/slicing/static-program-slices/source-tests.ts index 162cd46a7c..6568e9f48c 100644 --- a/test/functionality/slicing/static-program-slices/source-tests.ts +++ b/test/functionality/slicing/static-program-slices/source-tests.ts @@ -5,15 +5,13 @@ import { label } from '../../_helper/label' import { OperatorDatabase } from '../../../../src/r-bridge/lang-4.x/ast/model/operators' describe('source', withShell(shell => { - // reset the source provider back to the default value after our tests - after(() => setSourceProvider(requestProviderFromFile())) - const sources = { simple: 'N <- 9', closure1: 'f <- function() { function() 3 }', closure2: 'f <- function() { x <<- 3 }' } - setSourceProvider(requestProviderFromText(sources)) + before(() => setSourceProvider(requestProviderFromText(sources))) + after(() => setSourceProvider(requestProviderFromFile())) // these are incorrect - where is the content from the sourced file? assertSliced(label('simple source', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'unnamed-arguments', 'strings', 'sourcing-external-files','newlines']), From d13605d3f28a8e0a8409701a48ec63de9736a954 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 May 2024 19:49:02 +0200 Subject: [PATCH 21/23] doc: annotate incorrect tests with their corresponding issues --- test/functionality/slicing/static-program-slices/calls-tests.ts | 1 + .../functionality/slicing/static-program-slices/source-tests.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functionality/slicing/static-program-slices/calls-tests.ts b/test/functionality/slicing/static-program-slices/calls-tests.ts index a94334bac3..079b475554 100644 --- a/test/functionality/slicing/static-program-slices/calls-tests.ts +++ b/test/functionality/slicing/static-program-slices/calls-tests.ts @@ -573,6 +573,7 @@ if(x == 3) { x`) }) }) + // these have some inconsistencies, see https://github.com/Code-Inspect/flowr/issues/821 describe('Closures', () => { assertSliced(label('closure w/ default arguments',['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-default', 'numbers', 'newlines', 'implicit-return', 'normal-definition', 'closures', 'unnamed-arguments']), shell, `f <- function(x = 1) { diff --git a/test/functionality/slicing/static-program-slices/source-tests.ts b/test/functionality/slicing/static-program-slices/source-tests.ts index 6568e9f48c..eedc5aafb2 100644 --- a/test/functionality/slicing/static-program-slices/source-tests.ts +++ b/test/functionality/slicing/static-program-slices/source-tests.ts @@ -13,7 +13,7 @@ describe('source', withShell(shell => { before(() => setSourceProvider(requestProviderFromText(sources))) after(() => setSourceProvider(requestProviderFromFile())) - // these are incorrect - where is the content from the sourced file? + // these are incorrect - where is the content from the sourced file? (see https://github.com/Code-Inspect/flowr/issues/822) assertSliced(label('simple source', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'numbers', 'unnamed-arguments', 'strings', 'sourcing-external-files','newlines']), shell, 'source("simple")\ncat(N)', ['2@N'], 'N') assertSliced(label('sourcing a closure', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'sourcing-external-files', 'newlines', 'normal-definition', 'implicit-return', 'closures', 'numbers']), From 3028a139b8e3f23a2a0bc11aa42accb245546191 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 24 May 2024 19:53:10 +0200 Subject: [PATCH 22/23] feat-fix: fixed slice tests not ensuring the user config matches --- test/functionality/_helper/shell.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/functionality/_helper/shell.ts b/test/functionality/_helper/shell.ts index 10fe3281c1..8c7783dd55 100644 --- a/test/functionality/_helper/shell.ts +++ b/test/functionality/_helper/shell.ts @@ -293,6 +293,8 @@ export function assertSliced(name: string | TestLabel, shell: RShell, input: str const fullname = decorateLabelContext(name, ['slice']) const t = it(`${JSON.stringify(criteria)} ${fullname}`, async function() { + await ensureConfig(shell, this, userConfig) + const result = await new PipelineExecutor(DEFAULT_RECONSTRUCT_PIPELINE,{ getId, request: requestFromInput(input), From 80f20316669b05821ab8ec3a0b86394507dbc33f Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 27 May 2024 12:34:08 +0200 Subject: [PATCH 23/23] test: updated tests to new fixes --- .../functions/dataflow-function-definition-tests.ts | 11 ++++++----- .../slicing/static-program-slices/calls-tests.ts | 7 +++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts index 76bffa7fef..1c7bd2dcef 100644 --- a/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts +++ b/test/functionality/dataflow/processing-of-elements/functions/dataflow-function-definition-tests.ts @@ -505,6 +505,7 @@ print(g())`, emptyGraph() .use('14', 'x', undefined, false) .reads('14', '1') .use('15', 'y', undefined, false) + .reads('15', '8') .use('17', 'z', undefined, false) .reads('17', '11') .argument('16', '14') @@ -517,8 +518,8 @@ print(g())`, emptyGraph() .argument('23', '22') .call('24', `${UnnamedFunctionCallPrefix}24`, [], { returns: ['20'], reads: ['23'], environment: defaultEnv().pushEnv().defineParameter('x', '1', '3') }, false) .calls('24', ['23', '22']) - .argument('25', '23') - .call('25', '{', [argumentInCall('23')], { returns: ['23'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('x', '1', '3') }, false) + .argument('25', '24') + .call('25', '{', [argumentInCall('24')], { returns: ['24'], reads: [BuiltIn], environment: defaultEnv().pushEnv().defineParameter('x', '1', '3') }, false) .call('27', '<-', [argumentInCall('0'), argumentInCall('26')], { returns: ['0'], reads: [BuiltIn] }) .argument('27', ['26', '0']) .call('32', 'f', [argumentInCall('30')], { returns: ['25'], reads: ['0'], environment: defaultEnv().defineFunction('f', '0', '27') }) @@ -527,8 +528,8 @@ print(g())`, emptyGraph() .argument('33', '32') .call('33', '<-', [argumentInCall('28'), argumentInCall('32')], { returns: ['28'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '27') }) .argument('33', '28') - .call('36', 'g', [], { returns: ['20'], reads: ['28'], environment: defaultEnv().defineFunction('f', '0', '27').defineVariable('g', '28', '33') }) - .calls('36', '22') + .call('36', 'g', [], { returns: ['18'], reads: ['28'], environment: defaultEnv().defineFunction('f', '0', '27').defineVariable('g', '28', '33') }) + .calls('36', '20') .argument('38', '36') .call('38', 'print', [argumentInCall('36')], { returns: ['36'], reads: [BuiltIn], environment: defaultEnv().defineFunction('f', '0', '27').defineVariable('g', '28', '33') }) .defineVariable('1', 'x', { definedBy: ['2'] }, false) @@ -539,7 +540,7 @@ print(g())`, emptyGraph() .constant('12', undefined, false) .defineFunction('20', ['18'], { out: [], - in: [{ nodeId: '15', name: 'y', controlDependencies: [] }], + in: [], unknownReferences: [], entryPoint: '18', graph: new Set(['11', '12', '14', '15', '16', '17', '18']), diff --git a/test/functionality/slicing/static-program-slices/calls-tests.ts b/test/functionality/slicing/static-program-slices/calls-tests.ts index 079b475554..ad0464c519 100644 --- a/test/functionality/slicing/static-program-slices/calls-tests.ts +++ b/test/functionality/slicing/static-program-slices/calls-tests.ts @@ -446,7 +446,7 @@ cat(4 %a% 5)`) if(y) { assign("a", function() 1) } -a()`, ['5@a'], `a <- function() 2 +a()`, ['5@a'], `a <- \\() 2 if(y) { assign("a", function() 1) } a()`, { minRVersion: MIN_VERSION_LAMBDA }) }) @@ -573,7 +573,6 @@ if(x == 3) { x`) }) }) - // these have some inconsistencies, see https://github.com/Code-Inspect/flowr/issues/821 describe('Closures', () => { assertSliced(label('closure w/ default arguments',['name-normal', ...OperatorDatabase['<-'].capabilities, 'formals-default', 'numbers', 'newlines', 'implicit-return', 'normal-definition', 'closures', 'unnamed-arguments']), shell, `f <- function(x = 1) { @@ -588,7 +587,7 @@ g()`) (\\(y = 2) function(z = 3) x + y + z)() } g <- f(8) -print(g())`, ['5@g'], `f <- function(x=1) {} +print(g())`, ['5@g'], `f <- function(x=1) { (\\(y=2) function(z=3) x + y + z)() } g <- f(8) g()`, { minRVersion: MIN_VERSION_LAMBDA }) assertSliced(label('closure w/ side effects', ['name-normal', ...OperatorDatabase['<-'].capabilities, 'normal-definition', 'newlines', 'closures', ...OperatorDatabase['<<-'].capabilities, 'side-effects-in-function-call', ...OperatorDatabase['+'].capabilities, 'numbers']), @@ -602,7 +601,7 @@ x <- 2 f()() print(x)`, ['9@x'], `f <- function() { function() x <<- x + 1 } x <- 2 -f() +f()() x`) }) }))