diff --git a/src/dataflow/environments/default-builtin-config.ts b/src/dataflow/environments/default-builtin-config.ts index 98198086ca1..b90fa8dfa0e 100644 --- a/src/dataflow/environments/default-builtin-config.ts +++ b/src/dataflow/environments/default-builtin-config.ts @@ -217,6 +217,14 @@ export const DefaultBuiltinConfig: BuiltInDefinitions = [ { type: 'function', names: ['('], processor: 'builtin:default', config: { returnsNthArgument: 0 }, assumePrimitive: true }, { type: 'function', names: ['load', 'load_all', 'setwd', 'set.seed'], processor: 'builtin:default', config: { hasUnknownSideEffects: true, forceArgs: [true] }, assumePrimitive: false }, { type: 'function', names: ['body', 'formals', 'environment'], processor: 'builtin:default', config: { hasUnknownSideEffects: true, forceArgs: [true] }, assumePrimitive: true }, + { type: 'function', names: ['.Call', '.External', '.C', '.Fortran'], processor: 'builtin:default', config: { hasUnknownSideEffects: true, forceArgs: [true], + treatAsFnCall: { + '.Call': ['.NAME'], + '.External': ['.NAME'], + '.C': ['.NAME'], + '.Fortran': ['.NAME'] + } + }, assumePrimitive: true }, { type: 'function', names: ['eval'], processor: 'builtin:eval', config: { includeFunctionCall: true }, assumePrimitive: true }, { type: 'function', names: ['cat'], processor: 'builtin:default', config: { forceArgs: 'all', hasUnknownSideEffects: { type: 'link-to-last-call', callName: /^sink$/ } }, assumePrimitive: false }, { type: 'function', names: ['switch'], processor: 'builtin:default', config: { forceArgs: [true] }, assumePrimitive: false }, diff --git a/src/dataflow/eval/resolve/alias-tracking.ts b/src/dataflow/eval/resolve/alias-tracking.ts index dc5bcf9210a..f2b8fed6461 100644 --- a/src/dataflow/eval/resolve/alias-tracking.ts +++ b/src/dataflow/eval/resolve/alias-tracking.ts @@ -168,6 +168,8 @@ export function resolveIdToValue(id: NodeId | RNodeWithParent | undefined, { env } else { return Top; } + case RType.FunctionDefinition: + return setFrom({ type: 'function-definition' }); case RType.FunctionCall: case RType.BinaryOp: case RType.UnaryOp: diff --git a/src/dataflow/eval/resolve/resolve.ts b/src/dataflow/eval/resolve/resolve.ts index 121d9e917ba..46061d8e13f 100644 --- a/src/dataflow/eval/resolve/resolve.ts +++ b/src/dataflow/eval/resolve/resolve.ts @@ -38,6 +38,8 @@ export function resolveNode(resolve: VariableResolve, a: RNodeWithParent, env?: return intervalFrom(a.content.num, a.content.num); } else if(a.type === RType.Logical) { return a.content.valueOf() ? ValueLogicalTrue : ValueLogicalFalse; + } else if(a.type === RType.FunctionDefinition) { + return { type: 'function-definition' }; } else if((a.type === RType.FunctionCall || a.type === RType.BinaryOp || a.type === RType.UnaryOp) && graph) { const origin = getOriginInDfg(graph, a.info.id)?.[0]; if(origin === undefined || origin.type !== OriginType.BuiltInFunctionOrigin) { diff --git a/src/dataflow/eval/values/r-value.ts b/src/dataflow/eval/values/r-value.ts index add60036660..a7e0c2a3d73 100644 --- a/src/dataflow/eval/values/r-value.ts +++ b/src/dataflow/eval/values/r-value.ts @@ -38,6 +38,9 @@ export interface ValueString = Lift type: 'string' value: Str } +export interface ValueFunctionDefinition { + type: 'function-definition' +} export interface ValueMissing { type: 'missing' } @@ -55,6 +58,7 @@ export type Value = Lift< | ValueString | ValueLogical | ValueMissing + | ValueFunctionDefinition > export type ValueType = V extends { type: infer T } ? T : never export type ValueTypes = ValueType @@ -143,6 +147,8 @@ export function stringifyValue(value: Lift): string { return tryStringifyBoTop(v.value, l => l === 'maybe' ? 'maybe' : l ? 'TRUE' : 'FALSE', () => '⊤ (logical)', () => '⊥ (logical)'); case 'missing': return '(missing)'; + case 'function-definition': + return 'fn-def'; default: assertUnreachable(t); } diff --git a/src/dataflow/fn/higher-order-function.ts b/src/dataflow/fn/higher-order-function.ts new file mode 100644 index 00000000000..7c60f06a1cc --- /dev/null +++ b/src/dataflow/fn/higher-order-function.ts @@ -0,0 +1,80 @@ +import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id'; +import type { DataflowGraph } from '../graph/graph'; +import type { DataflowGraphVertexArgument, DataflowGraphVertexFunctionDefinition } from '../graph/vertex'; +import { isFunctionCallVertex, isFunctionDefinitionVertex } from '../graph/vertex'; +import { isNotUndefined } from '../../util/assert'; +import { edgeIncludesType, EdgeType } from '../graph/edge'; +import { resolveIdToValue } from '../eval/resolve/alias-tracking'; +import { VariableResolve } from '../../config'; +import { EmptyArgument } from '../../r-bridge/lang-4.x/ast/model/nodes/r-function-call'; +import { valueSetGuard } from '../eval/values/general'; + +function isAnyReturnAFunction(def: DataflowGraphVertexFunctionDefinition, graph: DataflowGraph): boolean { + const workingQueue: DataflowGraphVertexArgument[] = def.exitPoints.map(d => graph.getVertex(d, true)).filter(isNotUndefined); + const seen = new Set(); + while(workingQueue.length > 0) { + const current = workingQueue.pop() as DataflowGraphVertexArgument; + if(seen.has(current.id)) { + continue; + } + seen.add(current.id); + if(isFunctionDefinitionVertex(current)) { + return true; + } + const next = graph.outgoingEdges(current.id) ?? []; + for(const [t, { types }] of next) { + if(edgeIncludesType(types, EdgeType.Returns)) { + const v = graph.getVertex(t, true); + if(v) { + workingQueue.push(v); + } + } + } + } + return false; +} + +function inspectCallSitesArgumentsFns(def: DataflowGraphVertexFunctionDefinition, graph: DataflowGraph): boolean { + const callSites = graph.ingoingEdges(def.id); + + for(const [callerId, { types }] of callSites ?? []) { + if(!edgeIncludesType(types, EdgeType.Calls)) { + continue; + } + const caller = graph.getVertex(callerId, true); + if(!caller || !isFunctionCallVertex(caller)) { + continue; + } + for(const arg of caller.args) { + if(arg === EmptyArgument) { + continue; + } + const value = valueSetGuard(resolveIdToValue(arg.nodeId, { graph, idMap: graph.idMap, resolve: VariableResolve.Alias, full: true })); + if(value?.elements.some(e => e.type === 'function-definition')) { + return true; + } + } + } + return false; +} + +/** + * Determines whether the function with the given id is a higher-order function, i.e., + * either takes a function as an argument or (may) returns a function. + * If the return is an identity, e.g., `function(x) x`, this is not considered higher-order, + * if no function is passed as an argument. + */ +export function isHigherOrder(id: NodeId, graph: DataflowGraph): boolean { + const vert = graph.getVertex(id); + if(!vert || !isFunctionDefinitionVertex(vert)) { + return false; + } + + // 1. check whether any of the exit types is a function + if(isAnyReturnAFunction(vert, graph)) { + return true; + } + + // 2. check whether any of the callsites passes a function + return inspectCallSitesArgumentsFns(vert, graph); +} \ No newline at end of file diff --git a/src/documentation/print-query-wiki.ts b/src/documentation/print-query-wiki.ts index e6b5fd27bdf..34f15477ef9 100644 --- a/src/documentation/print-query-wiki.ts +++ b/src/documentation/print-query-wiki.ts @@ -41,6 +41,9 @@ import { printCfgCode } from './doc-util/doc-cfg'; import { executeDfShapeQuery } from '../queries/catalog/df-shape-query/df-shape-query-executor'; import { SliceDirection } from '../core/steps/all/static-slicing/00-slice'; import { documentReplSession } from './doc-util/doc-repl'; +import { + executeHigherOrderQuery +} from '../queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor'; registerQueryDocumentation('call-context', { @@ -274,6 +277,29 @@ ${ } }); + +registerQueryDocumentation('inspect-higher-order', { + name: 'Inspect Higher-Order Functions Query', + type: 'active', + shortDescription: 'Determine whether functions are higher-order functions', + functionName: executeHigherOrderQuery.name, + functionFile: '../queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.ts', + buildExplanation: async(shell: RShell) => { + const exampleCode = 'f <- function() function(x) x; f()'; + return ` +With this query you can identify which functions in the code are higher-order functions, i.e., either take a function as an argument or return a function. +Please note, that functions that are just identities (e.g., \`function(x) x\`) are not considered higher-order if they do not take a function as an argument. + +Using the example code \`${exampleCode}\` the following query returns the information for all identified function definitions whether they are higher-order functions: +${ + await showQuery(shell, exampleCode, [{ + type: 'inspect-higher-order', + }], { showCode: true }) +} + `; + } +}); + registerQueryDocumentation('origin', { name: 'Origin Query', type: 'active', diff --git a/src/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.ts b/src/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.ts new file mode 100644 index 00000000000..1b3ce9cc256 --- /dev/null +++ b/src/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.ts @@ -0,0 +1,48 @@ +import type { + InspectHigherOrderQuery, InspectHigherOrderQueryResult +} from './inspect-higher-order-query-format'; +import type { BasicQueryData } from '../../base-query-format'; +import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse'; +import { tryResolveSliceCriterionToId } from '../../../slicing/criterion/parse'; +import { isFunctionDefinitionVertex } from '../../../dataflow/graph/vertex'; +import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id'; +import { isHigherOrder } from '../../../dataflow/fn/higher-order-function'; + + +export function executeHigherOrderQuery({ dataflow: { graph }, ast }: BasicQueryData, queries: readonly InspectHigherOrderQuery[]): InspectHigherOrderQueryResult { + const start = Date.now(); + let filters: SingleSlicingCriterion[] | undefined = undefined; + // filter will remain undefined if at least one of the queries wants all functions + for(const q of queries) { + if(q.filter === undefined) { + filters = undefined; + break; + } else { + filters ??= []; + filters = filters.concat(filters); + } + } + + const filterFor = new Set(); + if(filters) { + for(const f of filters) { + const i = tryResolveSliceCriterionToId(f, ast.idMap); + if(i !== undefined) { + filterFor.add(i); + } + } + } + const fns = graph.vertices(true) + .filter(([,v]) => isFunctionDefinitionVertex(v) && (filterFor.size === 0 || filterFor.has(v.id))); + const result: Record = {}; + for(const [id,] of fns) { + result[id] = isHigherOrder(id, graph); + } + + return { + '.meta': { + timing: Date.now() - start + }, + higherOrder: result + }; +} diff --git a/src/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.ts b/src/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.ts new file mode 100644 index 00000000000..5726056a55d --- /dev/null +++ b/src/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.ts @@ -0,0 +1,43 @@ +import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format'; +import { bold } from '../../../util/text/ansi'; +import Joi from 'joi'; +import type { QueryResults, SupportedQuery } from '../../query'; +import { executeHigherOrderQuery } from './inspect-higher-order-query-executor'; +import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id'; +import { normalizeIdToNumberIfPossible } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id'; +import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse'; +import { formatRange } from '../../../util/mermaid/dfg'; + +/** + * Either returns all function definitions alongside whether they are higher-order functions, + * or just those matching the filters. + */ +export interface InspectHigherOrderQuery extends BaseQueryFormat { + readonly type: 'inspect-higher-order'; + readonly filter?: SingleSlicingCriterion[] +} + +export interface InspectHigherOrderQueryResult extends BaseQueryResult { + readonly higherOrder: Record; +} + +export const InspectHigherOrderQueryDefinition = { + executor: executeHigherOrderQuery, + asciiSummarizer: (formatter, processed, queryResults, result) => { + const out = queryResults as QueryResults<'inspect-higher-order'>['inspect-higher-order']; + result.push(`Query: ${bold('inspect-higher-order', formatter)} (${out['.meta'].timing.toFixed(0)}ms)`); + for(const [r, v] of Object.entries(out.higherOrder)) { + const loc = processed.normalize.idMap.get(normalizeIdToNumberIfPossible(r))?.location ?? undefined; + result.push(` - Function ${bold(r, formatter)} (${formatRange(loc)}) is ${v ? '' : 'not '}a higher-order function`); + } + return true; + }, + schema: Joi.object({ + type: Joi.string().valid('inspect-higher-order').required().description('The type of the query.'), + filter: Joi.array().items(Joi.string().required()).optional().description('If given, only function definitions that match one of the given slicing criteria are considered. Each criterion can be either `line:column`, `line@variable-name`, or `$id`, where the latter directly specifies the node id of the function definition to be considered.') + }).description('Either returns all function definitions alongside whether they are higher-order functions, or just those matching the filters.'), + flattenInvolvedNodes: (queryResults: BaseQueryResult): NodeId[] => { + const out = queryResults as QueryResults<'inspect-higher-order'>['inspect-higher-order']; + return Object.keys(out.higherOrder).filter(id => out.higherOrder[id]); + } +} as const satisfies SupportedQuery<'inspect-higher-order'>; diff --git a/src/queries/query.ts b/src/queries/query.ts index 96aa8fead78..cc5bed05528 100644 --- a/src/queries/query.ts +++ b/src/queries/query.ts @@ -48,6 +48,11 @@ import type { DfShapeQuery } from './catalog/df-shape-query/df-shape-query-forma import { DfShapeQueryDefinition } from './catalog/df-shape-query/df-shape-query-format'; import type { AsyncOrSync, AsyncOrSyncType, Writable } from 'ts-essentials'; import type { FlowrConfigOptions } from '../config'; +import type { + InspectHigherOrderQuery } from './catalog/inspect-higher-order-query/inspect-higher-order-query-format'; +import { + InspectHigherOrderQueryDefinition +} from './catalog/inspect-higher-order-query/inspect-higher-order-query-format'; /** * These are all queries that can be executed from within flowR @@ -68,6 +73,7 @@ export type Query = CallContextQuery | DependenciesQuery | LocationMapQuery | HappensBeforeQuery + | InspectHigherOrderQuery | ResolveValueQuery | ProjectQuery | OriginQuery @@ -103,25 +109,26 @@ export interface SupportedQuery { + function testHigherOrder( + label: string, + code: string, + expect: { + pos?: SingleSlicingCriterion[] + neg?: SingleSlicingCriterion[] + } + ) { + for(const [exp, crit] of [[true, expect.pos], [false, expect.neg]] as const) { + for(const c of crit ?? []) { + test(`${label} (expect ${c} to be ${exp ? 'ho' : 'not ho'})`, async() => { + const df = await createDataflowPipeline(ts, { + request: requestFromInput(code) + }, defaultConfigOptions).allRemainingSteps(); + + const id = tryResolveSliceCriterionToId(c, df.normalize.idMap); + // move up the error message :sparkles: + assert.isDefined(id, `could not resolve criterion ${c}`); + + assert.strictEqual(isHigherOrder(id, df.dataflow.graph), exp); + }); + } + } + } + + describe('function definitions', () => { + testHigherOrder('identity, no calls','f <- function(x) x', { neg: ['1@function'] }); + testHigherOrder('returning fn', 'f <- function()\n function(x) x', { pos: ['1@function'], neg: ['2@function'] }); + testHigherOrder('maybe returning fn','f <- function() {\nif(u) 42 else { function(x) x }}', { + pos: ['1@function'], + neg: ['2@function'] + }); // function maybe returning another function + }); + + describe('function calls', () => { + testHigherOrder('constant call', 'f <- function(x) x\nf(42)', { neg: ['1@function', '2@f'] }); + testHigherOrder('pass fn argument', 'f <- function(x) x\nf(function(y) y)', { pos: ['1@function'], neg: ['2@function'] }); + }); +})); diff --git a/test/functionality/slicing/backward/static-backward-program-slices/calls.test.ts b/test/functionality/slicing/backward/static-backward-program-slices/calls.test.ts index b2208b77d89..69d47b28c84 100644 --- a/test/functionality/slicing/backward/static-backward-program-slices/calls.test.ts +++ b/test/functionality/slicing/backward/static-backward-program-slices/calls.test.ts @@ -669,9 +669,6 @@ foo(.x = f(3))`); assertSliced(label('Without using primitive', [ 'built-in-internal-and-primitive-functions' ]), shell, 'print <- function(...) 42\nprint(3)', ['2@print'], 'print <- function(...) 42\nprint(3)'); - assertSliced(label('Without using primitive', [ - 'built-in-internal-and-primitive-functions' - ]), shell, 'print <- function(...) 42\nfoo <- .Primitive("print")(3)', ['2@foo'], 'foo <- .Primitive("print")(3)'); }); describe('Data Table Assignments', () => { const caps: SupportedFlowrCapabilityId[] = [ diff --git a/wiki/Overview.md b/wiki/Overview.md index 252d3c85943..3c229701e9d 100644 --- a/wiki/Overview.md +++ b/wiki/Overview.md @@ -87,7 +87,7 @@ Set WindowBar Colorful Set CursorBlink false Set PlaybackSpeed 3.0 Set TypingSpeed 0.15 -` + Type "docker run -it --rm eagleoutice/flowr" Sleep 200ms Enter diff --git a/wiki/Query API.md b/wiki/Query API.md index d8eb43c7298..499aaebd9d9 100644 --- a/wiki/Query API.md +++ b/wiki/Query API.md @@ -1,4 +1,4 @@ -_This document was generated from '[src/documentation/print-query-wiki.ts](https://github.com/flowr-analysis/flowr/tree/main//src/documentation/print-query-wiki.ts)' on 2025-09-04, 22:56:47 UTC presenting an overview of flowR's query API (v2.4.8, using R v4.5.0). Please do not edit this file/wiki page directly._ +_This document was generated from '[src/documentation/print-query-wiki.ts](https://github.com/flowr-analysis/flowr/tree/main//src/documentation/print-query-wiki.ts)' on 2025-09-24, 19:58:25 UTC presenting an overview of flowR's query API (v2.5.0, using R v4.5.1). Please do not edit this file/wiki page directly._ This page briefly summarizes flowR's query API, represented by the executeQueries function in [`./src/queries/query.ts`](https://github.com/flowr-analysis/flowr/tree/main/./src/queries/query.ts). Please see the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to access this API. @@ -39,6 +39,8 @@ For now, we support the following **active** queries (which we will refer to sim Check whether one normalized AST node happens before another in the CFG. 1. [Id-Map Query](#id-map-query) (`id-map`):\ Returns the id-map of the normalized AST of the given code. +1. [Inspect Higher-Order Functions Query](#inspect-higher-order-functions-query) (`inspect-higher-order`):\ + Determine whether functions are higher-order functions 1. [Lineage Query](#lineage-query) (`lineage`):\ Returns lineage of a criteria. 1. [Linter Query](#linter-query) (`linter`):\ @@ -313,6 +315,15 @@ Valid item types: _The first slicing criterion._ - **b** string [required] _The second slicing criterion._ + - **.** object + _Either returns all function definitions alongside whether they are higher-order functions, or just those matching the filters._ + - **type** string [required] + _The type of the query._ + Allows only the values: 'inspect-higher-order' + - **filter** array [optional] + _If given, only function definitions that match one of the given slicing criteria are considered. Each criterion can be either `line:column`, `line@variable-name`, or `$id`, where the latter directly specifies the node id of the function definition to be considered._ + Valid item types: + - **.** string [required] - **.** object _The resolve value query used to get definitions of an identifier_ - **type** string [required] @@ -727,7 +738,7 @@ points`"] ``` -(The analysis required _28.9 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.) +(The analysis required _15.6 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.) @@ -770,14 +781,14 @@ Just as an example, the following [Call-Context Query](#call-context-query) find _Results (prettified and summarized):_ -Query: **call-context** (0 ms)\ +Query: **call-context** (1 ms)\    ╰ **input**\      ╰ **csv-file**: _`read_csv`_ (L.6), _`read_csv`_ (L.7)\ -_All queries together required ≈2 ms (1ms accuracy, total 12 ms)_ +_All queries together required ≈1 ms (1ms accuracy, total 5 ms)_
Show Detailed Results as Json -The analysis required _11.6 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _5.4 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -789,7 +800,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "call-context": { ".meta": { - "timing": 0 + "timing": 1 }, "kinds": { "input": { @@ -811,7 +822,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte } }, ".meta": { - "timing": 2 + "timing": 1 } } ``` @@ -901,11 +912,11 @@ Query: **call-context** (1 ms)\    ╰ **visualize**\      ╰ **text**: _`mean`_ (L.9), _`mean`_ (L.19)\      ╰ **plot**: _`points`_ (L.17) with 1 link (_`plot`_ (L.16))\ -_All queries together required ≈1 ms (1ms accuracy, total 13 ms)_ +_All queries together required ≈1 ms (1ms accuracy, total 8 ms)_
Show Detailed Results as Json -The analysis required _13.1 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _8.4 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -1018,11 +1029,11 @@ _Results (prettified and summarized):_ Query: **call-context** (0 ms)\    ╰ **.**\      ╰ **.**: _`foo`_ (L.2) with 1 alias root (_`my_test_function`_ (L.1)), _`bar`_ (L.4) with 1 alias root (_`my_test_function`_ (L.1))\ -_All queries together required ≈0 ms (1ms accuracy, total 6 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 3 ms)_
Show Detailed Results as Json -The analysis required _5.8 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _3.3 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -1152,11 +1163,11 @@ Query: **config** (0 ms)\         }\     }\ }\ -_All queries together required ≈0 ms (1ms accuracy, total 1 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 0 ms)_
Show Detailed Results as Json -The analysis required _0.5 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _0.3 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -1233,7 +1244,7 @@ Please note that, in the repl, a special syntax starting with `+` (which should ```shell $ docker run -it --rm eagleoutice/flowr # or npm run flowr -flowR repl using flowR v2.4.8, R v4.5.0 (r-shell engine) +flowR repl using flowR v2.5.0, R v4.5.1 (r-shell engine) R> :query @config +solver.slicer.threshold=10000 ``` @@ -1282,7 +1293,7 @@ Query: config (0 ms) } } } -All queries together required ≈1 ms (1ms accuracy, total 4 ms) +All queries together required ≈0 ms (1ms accuracy, total 2 ms) ``` @@ -1325,13 +1336,13 @@ In other words, if you have a script simply reading: `if(TRUE) 1 else 2`, the fo _Results (prettified and summarized):_ -Query: **control-flow** (1ms)\ +Query: **control-flow** (0ms)\    ╰ CFG: https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgbjYoW1wiYFJFeHByZXNzaW9uTGlzdCAoNilgXCJdKVxuICAgIG41W1wiYFJJZlRoZW5FbHNlICg1KVxuIzM0O2lmKFRSVUUpIDEgZWxzZSAyIzM0O2BcIl1cbiAgICBuNS1leGl0KCg1LWV4aXQpKVxuICAgIG4wKFtcImBSTG9naWNhbCAoMClcbiMzNDtUUlVFIzM0O2BcIl0pXG4gICAgbjIoW1wiYFJFeHByZXNzaW9uTGlzdCAoMilcbiMzNDsxIzM0O2BcIl0pXG4gICAgbjEoW1wiYFJOdW1iZXIgKDEpXG4jMzQ7MSMzNDtgXCJdKVxuICAgIG4yLWV4aXQoKDItZXhpdCkpXG4gICAgbjQoW1wiYFJFeHByZXNzaW9uTGlzdCAoNClcbiMzNDsyIzM0O2BcIl0pXG4gICAgbjMoW1wiYFJOdW1iZXIgKDMpXG4jMzQ7MiMzNDtgXCJdKVxuICAgIG40LWV4aXQoKDQtZXhpdCkpXG4gICAgbjYtZXhpdCgoNi1leGl0KSlcbiAgICBuNSAtLi0+fFwiRkRcInwgbjZcbiAgICBuMSAtLi0+fFwiRkRcInwgbjJcbiAgICBuMi1leGl0IC0uLT58XCJGRFwifCBuMVxuICAgIG4zIC0uLT58XCJGRFwifCBuNFxuICAgIG40LWV4aXQgLS4tPnxcIkZEXCJ8IG4zXG4gICAgbjIgLS0+fFwiQ0QgKFRSVUUpXCJ8IG4wXG4gICAgbjQgLS0+fFwiQ0QgKEZBTFNFKVwifCBuMFxuICAgIG4wIC0uLT58XCJGRFwifCBuNVxuICAgIG41LWV4aXQgLS4tPnxcIkZEXCJ8IG4yLWV4aXRcbiAgICBuNS1leGl0IC0uLT58XCJGRFwifCBuNC1leGl0XG4gICAgbjYtZXhpdCAtLi0+fFwiRkRcInwgbjUtZXhpdFxuICAgIHN0eWxlIG42IHN0cm9rZTpjeWFuLHN0cm9rZS13aWR0aDo2LjVweDsgICAgc3R5bGUgbjYtZXhpdCBzdHJva2U6Z3JlZW4sc3Ryb2tlLXdpZHRoOjYuNXB4OyIsIm1lcm1haWQiOnsiYXV0b1N5bmMiOnRydWV9fQ==\ -_All queries together required ≈1 ms (1ms accuracy, total 3 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _2.7 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.4 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -1343,7 +1354,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "control-flow": { ".meta": { - "timing": 1 + "timing": 0 }, "controlFlow": { "returns": [], @@ -1595,7 +1606,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte } }, ".meta": { - "timing": 1 + "timing": 0 } } ``` @@ -1643,7 +1654,7 @@ _All queries together required ≈1 ms (1ms accuracy, total 2 ms)_
Show Detailed Results as Json -The analysis required _2.5 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.5 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -1940,7 +1951,7 @@ flowchart RL ``` -_(The analysis required _2.1 ms_ (including the dataflow analysis, normalization, and parsing with the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +_(The analysis required _1.2 ms_ (including the dataflow analysis, normalization, and parsing with the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We used the following simplifications: `unique-cf-sets`, `to-basic-blocks` . )_ @@ -1974,11 +1985,11 @@ _Results (prettified and summarized):_ Query: **control-flow** (1ms)\    ╰ CFG: https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgbjYoW1wiYFJFeHByZXNzaW9uTGlzdCAoNilgXCJdKVxuICAgIG41W1wiYFJJZlRoZW5FbHNlICg1KVxuIzM0O2lmKFRSVUUpIDEgZWxzZSAyIzM0O2BcIl1cbiAgICBuNS1leGl0KCg1LWV4aXQpKVxuICAgIG4wKFtcImBSTG9naWNhbCAoMClcbiMzNDtUUlVFIzM0O2BcIl0pXG4gICAgbjIoW1wiYFJFeHByZXNzaW9uTGlzdCAoMilcbiMzNDsxIzM0O2BcIl0pXG4gICAgbjEoW1wiYFJOdW1iZXIgKDEpXG4jMzQ7MSMzNDtgXCJdKVxuICAgIG4yLWV4aXQoKDItZXhpdCkpXG4gICAgbjQoW1wiYFJFeHByZXNzaW9uTGlzdCAoNClcbiMzNDsyIzM0O2BcIl0pXG4gICAgbjMoW1wiYFJOdW1iZXIgKDMpXG4jMzQ7MiMzNDtgXCJdKVxuICAgIG40LWV4aXQoKDQtZXhpdCkpXG4gICAgbjYtZXhpdCgoNi1leGl0KSlcbiAgICBuNSAtLi0+fFwiRkRcInwgbjZcbiAgICBuMSAtLi0+fFwiRkRcInwgbjJcbiAgICBuMi1leGl0IC0uLT58XCJGRFwifCBuMVxuICAgIG4zIC0uLT58XCJGRFwifCBuNFxuICAgIG40LWV4aXQgLS4tPnxcIkZEXCJ8IG4zXG4gICAgbjIgLS0+fFwiQ0QgKFRSVUUpXCJ8IG4wXG4gICAgbjAgLS4tPnxcIkZEXCJ8IG41XG4gICAgbjUtZXhpdCAtLi0+fFwiRkRcInwgbjItZXhpdFxuICAgIG41LWV4aXQgLS4tPnxcIkZEXCJ8IG40LWV4aXRcbiAgICBuNi1leGl0IC0uLT58XCJGRFwifCBuNS1leGl0XG4gICAgc3R5bGUgbjYgc3Ryb2tlOmN5YW4sc3Ryb2tlLXdpZHRoOjYuNXB4OyAgICBzdHlsZSBuNi1leGl0IHN0cm9rZTpncmVlbixzdHJva2Utd2lkdGg6Ni41cHg7IiwibWVybWFpZCI6eyJhdXRvU3luYyI6dHJ1ZX19\ -_All queries together required ≈1 ms (1ms accuracy, total 3 ms)_ +_All queries together required ≈1 ms (1ms accuracy, total 2 ms)_
Show Detailed Results as Json -The analysis required _2.6 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.5 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -2285,7 +2296,7 @@ flowchart RL ``` -_(The analysis required _2.0 ms_ (including the dataflow analysis, normalization, and parsing with the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +_(The analysis required _1.5 ms_ (including the dataflow analysis, normalization, and parsing with the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We used the following simplifications: `unique-cf-sets`, `analyze-dead-code` . )_ @@ -2318,13 +2329,13 @@ Or, completely remove dead code: _Results (prettified and summarized):_ -Query: **control-flow** (1ms)\ +Query: **control-flow** (0ms)\    ╰ CFG: https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgbjYoW1wiYFJFeHByZXNzaW9uTGlzdCAoNilgXCJdKVxuICAgIG41W1wiYFJJZlRoZW5FbHNlICg1KVxuIzM0O2lmKFRSVUUpIDEgZWxzZSAyIzM0O2BcIl1cbiAgICBuNS1leGl0KCg1LWV4aXQpKVxuICAgIG4wKFtcImBSTG9naWNhbCAoMClcbiMzNDtUUlVFIzM0O2BcIl0pXG4gICAgbjIoW1wiYFJFeHByZXNzaW9uTGlzdCAoMilcbiMzNDsxIzM0O2BcIl0pXG4gICAgbjEoW1wiYFJOdW1iZXIgKDEpXG4jMzQ7MSMzNDtgXCJdKVxuICAgIG4yLWV4aXQoKDItZXhpdCkpXG4gICAgbjYtZXhpdCgoNi1leGl0KSlcbiAgICBuNSAtLi0+fFwiRkRcInwgbjZcbiAgICBuMSAtLi0+fFwiRkRcInwgbjJcbiAgICBuMi1leGl0IC0uLT58XCJGRFwifCBuMVxuICAgIG4yIC0tPnxcIkNEIChUUlVFKVwifCBuMFxuICAgIG4wIC0uLT58XCJGRFwifCBuNVxuICAgIG41LWV4aXQgLS4tPnxcIkZEXCJ8IG4yLWV4aXRcbiAgICBuNi1leGl0IC0uLT58XCJGRFwifCBuNS1leGl0XG4gICAgc3R5bGUgbjYgc3Ryb2tlOmN5YW4sc3Ryb2tlLXdpZHRoOjYuNXB4OyAgICBzdHlsZSBuNi1leGl0IHN0cm9rZTpncmVlbixzdHJva2Utd2lkdGg6Ni41cHg7IiwibWVybWFpZCI6eyJhdXRvU3luYyI6dHJ1ZX19\ -_All queries together required ≈1 ms (1ms accuracy, total 2 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _1.9 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.4 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -2336,7 +2347,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "control-flow": { ".meta": { - "timing": 1 + "timing": 0 }, "controlFlow": { "returns": [], @@ -2519,7 +2530,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte } }, ".meta": { - "timing": 1 + "timing": 0 } } ``` @@ -2567,7 +2578,7 @@ flowchart RL ``` -_(The analysis required _1.7 ms_ (including the dataflow analysis, normalization, and parsing with the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +_(The analysis required _1.2 ms_ (including the dataflow analysis, normalization, and parsing with the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We used the following simplifications: `unique-cf-sets`, `analyze-dead-code`, `remove-dead-code` . )_ @@ -2621,11 +2632,11 @@ _Results (prettified and summarized):_ Query: **dataflow-cluster** (0ms)\    ╰ Found 1 cluster\       ╰ {3, 0, 1, 2} ([marked](https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgMXt7XCJgIzkxO1JOdW1iZXIjOTM7IDFcbiAgICAgICgxKVxuICAgICAgKjEuNipgXCJ9fVxuICAgIDBbXCJgIzkxO1JTeW1ib2wjOTM7IHhcbiAgICAgICgwKVxuICAgICAgKjEuMSpgXCJdXG4gICAgMltbXCJgIzkxO1JCaW5hcnlPcCM5MzsgIzYwOyM0NTtcbiAgICAgICgyKVxuICAgICAgKjEuMS02KlxuICAgICgwLCAxKWBcIl1dXG4gICAgYnVpbHQtaW46Xy1bXCJgQnVpbHQtSW46XG4jNjA7IzQ1O2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpfLSBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgMyhbXCJgIzkxO1JTeW1ib2wjOTM7IHhcbiAgICAgICgzKVxuICAgICAgKjEuOSpgXCJdKVxuICAgIDAgLS0+fFwiZGVmaW5lZC1ieVwifCAxXG4gICAgMCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDJcbiAgICAyIC0tPnxcImFyZ3VtZW50XCJ8IDFcbiAgICAyIC0tPnxcInJldHVybnMsIGFyZ3VtZW50XCJ8IDBcbiAgICAyIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Xy1cbiAgICBsaW5rU3R5bGUgNCBzdHJva2U6Z3JheTtcbiAgICAzIC0tPnxcInJlYWRzXCJ8IDAiLCJtZXJtYWlkIjp7ImF1dG9TeW5jIjp0cnVlfX0=))\ -_All queries together required ≈0 ms (1ms accuracy, total 2 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _1.7 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.3 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -2701,7 +2712,7 @@ _All queries together required ≈0 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _1.4 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _0.8 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -2770,18 +2781,18 @@ Using the example code from above, the following query returns all clusters: _Results (prettified and summarized):_ -Query: **dataflow-cluster** (1ms)\ +Query: **dataflow-cluster** (0ms)\    ╰ Found 5 clusters\       ╰ {89, 87, 85, 82, 18, 22, ... (see JSON)} ([marked](https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgMXt7XCJgIzkxO1JTeW1ib2wjOTM7IGdncGxvdFxuICAgICAgKDEpXG4gICAgICAqMS45LTE0KmBcIn19XG4gICAgM1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgzKVxuICAgICAgKjEuMS0xNSpcbiAgICAoMSlgXCJdXVxuICAgIHN0eWxlIDMgc3Ryb2tlOnJlZCxzdHJva2Utd2lkdGg6NXB4OyBcbiAgICBidWlsdC1pbjpsaWJyYXJ5W1wiYEJ1aWx0LUluOlxubGlicmFyeWBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpsaWJyYXJ5IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1e3tcImAjOTE7UlN5bWJvbCM5MzsgZHBseXJcbiAgICAgICg1KVxuICAgICAgKjIuOS0xMypgXCJ9fVxuICAgIDdbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBsaWJyYXJ5XG4gICAgICAoNylcbiAgICAgICoyLjEtMTQqXG4gICAgKDUpYFwiXV1cbiAgICBzdHlsZSA3IHN0cm9rZTpyZWQsc3Ryb2tlLXdpZHRoOjVweDsgXG4gICAgOXt7XCJgIzkxO1JTeW1ib2wjOTM7IHJlYWRyXG4gICAgICAoOSlcbiAgICAgICozLjktMTMqYFwifX1cbiAgICAxMVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgxMSlcbiAgICAgICozLjEtMTQqXG4gICAgKDkpYFwiXV1cbiAgICBzdHlsZSAxMSBzdHJva2U6cmVkLHN0cm9rZS13aWR0aDo1cHg7IFxuICAgIDE0e3tcImAjOTE7UlN0cmluZyM5MzsgIzM5O2RhdGEuY3N2IzM5O1xuICAgICAgKDE0KVxuICAgICAgKjYuMTgtMjcqYFwifX1cbiAgICAxNltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMTYpXG4gICAgICAqNi45LTI4KlxuICAgICgxNClgXCJdXVxuICAgIDEyW1wiYCM5MTtSU3ltYm9sIzkzOyBkYXRhXG4gICAgICAoMTIpXG4gICAgICAqNi4xLTQqYFwiXVxuICAgIDE3W1tcImAjOTE7UkJpbmFyeU9wIzkzOyAjNjA7IzQ1O1xuICAgICAgKDE3KVxuICAgICAgKjYuMS0yOCpcbiAgICAoMTIsIDE2KWBcIl1dXG4gICAgYnVpbHQtaW46Xy1bXCJgQnVpbHQtSW46XG4jNjA7IzQ1O2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpfLSBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgMjB7e1wiYCM5MTtSU3RyaW5nIzkzOyAjMzk7ZGF0YTIuY3N2IzM5O1xuICAgICAgKDIwKVxuICAgICAgKjcuMTktMjkqYFwifX1cbiAgICAyMltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMjIpXG4gICAgICAqNy4xMC0zMCpcbiAgICAoMjApYFwiXV1cbiAgICAxOFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICgxOClcbiAgICAgICo3LjEtNSpgXCJdXG4gICAgMjNbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMjMpXG4gICAgICAqNy4xLTMwKlxuICAgICgxOCwgMjIpYFwiXV1cbiAgICAyNihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgyNilcbiAgICAgICo5LjExLTE0KmBcIl0pXG4gICAgMjd7e1wiYCM5MTtSU3ltYm9sIzkzOyB4XG4gICAgICAoMjcpXG4gICAgICAqOS4xMS0xNipgXCJ9fVxuICAgIDI5W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDI5KVxuICAgICAgKjkuMTEtMTYqXG4gICAgKDI2LCAyNylgXCJdXVxuICAgIGJ1aWx0LWluOl9bXCJgQnVpbHQtSW46XG4kYFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOl8gc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDMxW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDMxKVxuICAgICAgKjkuNi0xNypcbiAgICAoMjkpYFwiXV1cbiAgICBidWlsdC1pbjptZWFuW1wiYEJ1aWx0LUluOlxubWVhbmBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjptZWFuIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAyNFtcImAjOTE7UlN5bWJvbCM5MzsgbVxuICAgICAgKDI0KVxuICAgICAgKjkuMSpgXCJdXG4gICAgMzJbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMzIpXG4gICAgICAqOS4xLTE3KlxuICAgICgyNCwgMzEpYFwiXV1cbiAgICAzNChbXCJgIzkxO1JTeW1ib2wjOTM7IG1cbiAgICAgICgzNClcbiAgICAgICoxMC43KmBcIl0pXG4gICAgMzZbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDM2KVxuICAgICAgKjEwLjEtOCpcbiAgICAoMzQpYFwiXV1cbiAgICBidWlsdC1pbjpwcmludFtcImBCdWlsdC1JbjpcbnByaW50YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOnByaW50IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAzOChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgzOClcbiAgICAgICoxMi4xLTQqYFwiXSlcbiAgICA0MyhbXCJgIzkxO1JTeW1ib2wjOTM7IHhcbiAgICAgICg0MylcbiAgICAgICoxMy4yNCpgXCJdKVxuICAgIDQ0KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB4XG4gICAgICAoNDQpXG4gICAgICAqMTMuMjAqYFwiXSlcbiAgICA0NihbXCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg0NilcbiAgICAgICoxMy4zMSpgXCJdKVxuICAgIDQ3KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB5XG4gICAgICAoNDcpXG4gICAgICAqMTMuMjcqYFwiXSlcbiAgICA0OFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGFlc1xuICAgICAgKDQ4KVxuICAgICAgKjEzLjE2LTMyKlxuICAgICh4ICg0NCksIHkgKDQ3KSlgXCJdXVxuICAgIDUwW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgZ2dwbG90XG4gICAgICAoNTApXG4gICAgICAqMTMuOS0zMypcbiAgICAoMzgsIDQ4KWBcIl1dXG4gICAgYnVpbHQtaW46Z2dwbG90W1wiYEJ1aWx0LUluOlxuZ2dwbG90YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOmdncGxvdCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTJbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBkYXRhICUjNjI7JVxuXHRnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpXG4gICAgICAoNTIpXG4gICAgICAqMTIuNi04KlxuICAgICgzOCwgNTApYFwiXV1cbiAgICBidWlsdC1pbjpfX19bXCJgQnVpbHQtSW46XG4lIzYyOyVgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46X19fIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1NFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGdlb20jOTU7cG9pbnRcbiAgICAgICg1NClcbiAgICAgICoxNC45LTIwKmBcIl1dXG4gICAgYnVpbHQtaW46Z2VvbV9wb2ludFtcImBCdWlsdC1Jbjpcbmdlb20jOTU7cG9pbnRgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46Z2VvbV9wb2ludCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTVbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM0MztcbiAgICAgICg1NSlcbiAgICAgICoxMi4xLTE0LjIwKlxuICAgICg1MiwgNTQpYFwiXV1cbiAgICA1NyhbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNTcpXG4gICAgICAqMTYuNi0xMCpgXCJdKVxuICAgIDU4e3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDU4KVxuICAgICAgKjE2LjYtMTIqYFwifX1cbiAgICA2MFtbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg2MClcbiAgICAgICoxNi42LTEyKlxuICAgICg1NywgNTgpYFwiXV1cbiAgICA2MihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjIpXG4gICAgICAqMTYuMTUtMTkqYFwiXSlcbiAgICA2M3t7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg2MylcbiAgICAgICoxNi4xNS0yMSpgXCJ9fVxuICAgIDY1W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDY1KVxuICAgICAgKjE2LjE1LTIxKlxuICAgICg2MiwgNjMpYFwiXV1cbiAgICA2N1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBsb3RcbiAgICAgICg2NylcbiAgICAgICoxNi4xLTIyKlxuICAgICg2MCwgNjUpYFwiXV1cbiAgICBidWlsdC1pbjpwbG90W1wiYEJ1aWx0LUluOlxucGxvdGBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwbG90IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA2OShbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjkpXG4gICAgICAqMTcuOC0xMipgXCJdKVxuICAgIDcwe3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDcwKVxuICAgICAgKjE3LjgtMTQqYFwifX1cbiAgICA3MltbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg3MilcbiAgICAgICoxNy44LTE0KlxuICAgICg2OSwgNzApYFwiXV1cbiAgICA3NChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNzQpXG4gICAgICAqMTcuMTctMjEqYFwiXSlcbiAgICA3NXt7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg3NSlcbiAgICAgICoxNy4xNy0yMypgXCJ9fVxuICAgIDc3W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDc3KVxuICAgICAgKjE3LjE3LTIzKlxuICAgICg3NCwgNzUpYFwiXV1cbiAgICA3OVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBvaW50c1xuICAgICAgKDc5KVxuICAgICAgKjE3LjEtMjQqXG4gICAgKDcyLCA3NylgXCJdXVxuICAgIGJ1aWx0LWluOnBvaW50c1tcImBCdWlsdC1JbjpcbnBvaW50c2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwb2ludHMgc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDgyKFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICg4MilcbiAgICAgICoxOS4xMi0xNipgXCJdKVxuICAgIDgze3tcImAjOTE7UlN5bWJvbCM5Mzsga1xuICAgICAgKDgzKVxuICAgICAgKjE5LjEyLTE4KmBcIn19XG4gICAgODVbW1wiYCM5MTtSQWNjZXNzIzkzOyAkXG4gICAgICAoODUpXG4gICAgICAqMTkuMTItMTgqXG4gICAgKDgyLCA4MylgXCJdXVxuICAgIDg3W1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDg3KVxuICAgICAgKjE5LjctMTkqXG4gICAgKDg1KWBcIl1dXG4gICAgODlbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDg5KVxuICAgICAgKjE5LjEtMjAqXG4gICAgKDg3KWBcIl1dXG4gICAgMyAtLT58XCJhcmd1bWVudFwifCAxXG4gICAgMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgMSBzdHJva2U6Z3JheTtcbiAgICA3IC0tPnxcImFyZ3VtZW50XCJ8IDVcbiAgICA3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bGlicmFyeVxuICAgIGxpbmtTdHlsZSAzIHN0cm9rZTpncmF5O1xuICAgIDExIC0tPnxcImFyZ3VtZW50XCJ8IDlcbiAgICAxMSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgNSBzdHJva2U6Z3JheTtcbiAgICAxNiAtLT58XCJhcmd1bWVudFwifCAxNFxuICAgIDEyIC0tPnxcImRlZmluZWQtYnlcInwgMTZcbiAgICAxMiAtLT58XCJkZWZpbmVkLWJ5XCJ8IDE3XG4gICAgMTcgLS0+fFwiYXJndW1lbnRcInwgMTZcbiAgICAxNyAtLT58XCJyZXR1cm5zLCBhcmd1bWVudFwifCAxMlxuICAgIDE3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Xy1cbiAgICBsaW5rU3R5bGUgMTEgc3Ryb2tlOmdyYXk7XG4gICAgMjIgLS0+fFwiYXJndW1lbnRcInwgMjBcbiAgICAxOCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDIyXG4gICAgMTggLS0+fFwiZGVmaW5lZC1ieVwifCAyM1xuICAgIDIzIC0tPnxcImFyZ3VtZW50XCJ8IDIyXG4gICAgMjMgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMThcbiAgICAyMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDE3IHN0cm9rZTpncmF5O1xuICAgIDI2IC0tPnxcInJlYWRzXCJ8IDEyXG4gICAgMjkgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDI2XG4gICAgMjkgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDI3XG4gICAgMjkgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDIxIHN0cm9rZTpncmF5O1xuICAgIDMxIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAyOVxuICAgIDMxIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bWVhblxuICAgIGxpbmtTdHlsZSAyMyBzdHJva2U6Z3JheTtcbiAgICAyNCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDMxXG4gICAgMjQgLS0+fFwiZGVmaW5lZC1ieVwifCAzMlxuICAgIDMyIC0tPnxcImFyZ3VtZW50XCJ8IDMxXG4gICAgMzIgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMjRcbiAgICAzMiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDI4IHN0cm9rZTpncmF5O1xuICAgIDM0IC0tPnxcInJlYWRzXCJ8IDI0XG4gICAgMzYgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDM0XG4gICAgMzYgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwcmludFxuICAgIGxpbmtTdHlsZSAzMSBzdHJva2U6Z3JheTtcbiAgICAzOCAtLT58XCJyZWFkc1wifCAxMlxuICAgIDQ0IC0tPnxcInJlYWRzXCJ8IDQzXG4gICAgNDcgLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJyZWFkc1wifCA0M1xuICAgIDQ4IC0tPnxcImFyZ3VtZW50XCJ8IDQ0XG4gICAgNDggLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJhcmd1bWVudFwifCA0N1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA0OFxuICAgIDUwIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Z2dwbG90XG4gICAgbGlua1N0eWxlIDQwIHN0cm9rZTpncmF5O1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAzOFxuICAgIDUyIC0tPnxcImFyZ3VtZW50XCJ8IDM4XG4gICAgNTIgLS0+fFwiYXJndW1lbnRcInwgNTBcbiAgICA1MiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9fX1xuICAgIGxpbmtTdHlsZSA0NCBzdHJva2U6Z3JheTtcbiAgICA1NCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmdlb21fcG9pbnRcbiAgICBsaW5rU3R5bGUgNDUgc3Ryb2tlOmdyYXk7XG4gICAgNTQgLS0+fFwicmVhZHNcInwgNTBcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTJcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTRcbiAgICA1NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNDkgc3Ryb2tlOmdyYXk7XG4gICAgNTcgLS0+fFwicmVhZHNcInwgMThcbiAgICA2MCAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNTdcbiAgICA2MCAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNThcbiAgICA2MCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTMgc3Ryb2tlOmdyYXk7XG4gICAgNjIgLS0+fFwicmVhZHNcInwgMThcbiAgICA2NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNjJcbiAgICA2NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNjNcbiAgICA2NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTcgc3Ryb2tlOmdyYXk7XG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDYwXG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDY1XG4gICAgNjcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwbG90XG4gICAgbGlua1N0eWxlIDYwIHN0cm9rZTpncmF5O1xuICAgIDY5IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzIgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDY5XG4gICAgNzIgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDcwXG4gICAgNzIgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY0IHN0cm9rZTpncmF5O1xuICAgIDc0IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzcgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDc0XG4gICAgNzcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDc1XG4gICAgNzcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY4IHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3MlxuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3N1xuICAgIDc5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cG9pbnRzXG4gICAgbGlua1N0eWxlIDcxIHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzXCJ8IDY3XG4gICAgODIgLS0+fFwicmVhZHNcInwgMThcbiAgICA4NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgODJcbiAgICA4NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgODNcbiAgICA4NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNzYgc3Ryb2tlOmdyYXk7XG4gICAgODcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDg1XG4gICAgODcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjptZWFuXG4gICAgbGlua1N0eWxlIDc4IHN0cm9rZTpncmF5O1xuICAgIDg5IC0tPnxcInJlYWRzLCByZXR1cm5zLCBhcmd1bWVudFwifCA4N1xuICAgIDg5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cHJpbnRcbiAgICBsaW5rU3R5bGUgODAgc3Ryb2tlOmdyYXk7IiwibWVybWFpZCI6eyJhdXRvU3luYyI6dHJ1ZX19))\       ╰ {55, 52, 38, 12, 16, 14, ... (see JSON)} ([marked](https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgMXt7XCJgIzkxO1JTeW1ib2wjOTM7IGdncGxvdFxuICAgICAgKDEpXG4gICAgICAqMS45LTE0KmBcIn19XG4gICAgM1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgzKVxuICAgICAgKjEuMS0xNSpcbiAgICAoMSlgXCJdXVxuICAgIHN0eWxlIDMgc3Ryb2tlOnJlZCxzdHJva2Utd2lkdGg6NXB4OyBcbiAgICBidWlsdC1pbjpsaWJyYXJ5W1wiYEJ1aWx0LUluOlxubGlicmFyeWBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpsaWJyYXJ5IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1e3tcImAjOTE7UlN5bWJvbCM5MzsgZHBseXJcbiAgICAgICg1KVxuICAgICAgKjIuOS0xMypgXCJ9fVxuICAgIDdbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBsaWJyYXJ5XG4gICAgICAoNylcbiAgICAgICoyLjEtMTQqXG4gICAgKDUpYFwiXV1cbiAgICBzdHlsZSA3IHN0cm9rZTpyZWQsc3Ryb2tlLXdpZHRoOjVweDsgXG4gICAgOXt7XCJgIzkxO1JTeW1ib2wjOTM7IHJlYWRyXG4gICAgICAoOSlcbiAgICAgICozLjktMTMqYFwifX1cbiAgICAxMVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgxMSlcbiAgICAgICozLjEtMTQqXG4gICAgKDkpYFwiXV1cbiAgICBzdHlsZSAxMSBzdHJva2U6cmVkLHN0cm9rZS13aWR0aDo1cHg7IFxuICAgIDE0e3tcImAjOTE7UlN0cmluZyM5MzsgIzM5O2RhdGEuY3N2IzM5O1xuICAgICAgKDE0KVxuICAgICAgKjYuMTgtMjcqYFwifX1cbiAgICAxNltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMTYpXG4gICAgICAqNi45LTI4KlxuICAgICgxNClgXCJdXVxuICAgIDEyW1wiYCM5MTtSU3ltYm9sIzkzOyBkYXRhXG4gICAgICAoMTIpXG4gICAgICAqNi4xLTQqYFwiXVxuICAgIDE3W1tcImAjOTE7UkJpbmFyeU9wIzkzOyAjNjA7IzQ1O1xuICAgICAgKDE3KVxuICAgICAgKjYuMS0yOCpcbiAgICAoMTIsIDE2KWBcIl1dXG4gICAgYnVpbHQtaW46Xy1bXCJgQnVpbHQtSW46XG4jNjA7IzQ1O2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpfLSBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgMjB7e1wiYCM5MTtSU3RyaW5nIzkzOyAjMzk7ZGF0YTIuY3N2IzM5O1xuICAgICAgKDIwKVxuICAgICAgKjcuMTktMjkqYFwifX1cbiAgICAyMltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMjIpXG4gICAgICAqNy4xMC0zMCpcbiAgICAoMjApYFwiXV1cbiAgICAxOFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICgxOClcbiAgICAgICo3LjEtNSpgXCJdXG4gICAgMjNbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMjMpXG4gICAgICAqNy4xLTMwKlxuICAgICgxOCwgMjIpYFwiXV1cbiAgICAyNihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgyNilcbiAgICAgICo5LjExLTE0KmBcIl0pXG4gICAgMjd7e1wiYCM5MTtSU3ltYm9sIzkzOyB4XG4gICAgICAoMjcpXG4gICAgICAqOS4xMS0xNipgXCJ9fVxuICAgIDI5W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDI5KVxuICAgICAgKjkuMTEtMTYqXG4gICAgKDI2LCAyNylgXCJdXVxuICAgIGJ1aWx0LWluOl9bXCJgQnVpbHQtSW46XG4kYFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOl8gc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDMxW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDMxKVxuICAgICAgKjkuNi0xNypcbiAgICAoMjkpYFwiXV1cbiAgICBidWlsdC1pbjptZWFuW1wiYEJ1aWx0LUluOlxubWVhbmBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjptZWFuIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAyNFtcImAjOTE7UlN5bWJvbCM5MzsgbVxuICAgICAgKDI0KVxuICAgICAgKjkuMSpgXCJdXG4gICAgMzJbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMzIpXG4gICAgICAqOS4xLTE3KlxuICAgICgyNCwgMzEpYFwiXV1cbiAgICAzNChbXCJgIzkxO1JTeW1ib2wjOTM7IG1cbiAgICAgICgzNClcbiAgICAgICoxMC43KmBcIl0pXG4gICAgMzZbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDM2KVxuICAgICAgKjEwLjEtOCpcbiAgICAoMzQpYFwiXV1cbiAgICBidWlsdC1pbjpwcmludFtcImBCdWlsdC1JbjpcbnByaW50YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOnByaW50IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAzOChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgzOClcbiAgICAgICoxMi4xLTQqYFwiXSlcbiAgICA0MyhbXCJgIzkxO1JTeW1ib2wjOTM7IHhcbiAgICAgICg0MylcbiAgICAgICoxMy4yNCpgXCJdKVxuICAgIDQ0KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB4XG4gICAgICAoNDQpXG4gICAgICAqMTMuMjAqYFwiXSlcbiAgICA0NihbXCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg0NilcbiAgICAgICoxMy4zMSpgXCJdKVxuICAgIDQ3KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB5XG4gICAgICAoNDcpXG4gICAgICAqMTMuMjcqYFwiXSlcbiAgICA0OFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGFlc1xuICAgICAgKDQ4KVxuICAgICAgKjEzLjE2LTMyKlxuICAgICh4ICg0NCksIHkgKDQ3KSlgXCJdXVxuICAgIDUwW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgZ2dwbG90XG4gICAgICAoNTApXG4gICAgICAqMTMuOS0zMypcbiAgICAoMzgsIDQ4KWBcIl1dXG4gICAgYnVpbHQtaW46Z2dwbG90W1wiYEJ1aWx0LUluOlxuZ2dwbG90YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOmdncGxvdCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTJbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBkYXRhICUjNjI7JVxuXHRnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpXG4gICAgICAoNTIpXG4gICAgICAqMTIuNi04KlxuICAgICgzOCwgNTApYFwiXV1cbiAgICBidWlsdC1pbjpfX19bXCJgQnVpbHQtSW46XG4lIzYyOyVgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46X19fIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1NFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGdlb20jOTU7cG9pbnRcbiAgICAgICg1NClcbiAgICAgICoxNC45LTIwKmBcIl1dXG4gICAgYnVpbHQtaW46Z2VvbV9wb2ludFtcImBCdWlsdC1Jbjpcbmdlb20jOTU7cG9pbnRgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46Z2VvbV9wb2ludCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTVbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM0MztcbiAgICAgICg1NSlcbiAgICAgICoxMi4xLTE0LjIwKlxuICAgICg1MiwgNTQpYFwiXV1cbiAgICA1NyhbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNTcpXG4gICAgICAqMTYuNi0xMCpgXCJdKVxuICAgIDU4e3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDU4KVxuICAgICAgKjE2LjYtMTIqYFwifX1cbiAgICA2MFtbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg2MClcbiAgICAgICoxNi42LTEyKlxuICAgICg1NywgNTgpYFwiXV1cbiAgICA2MihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjIpXG4gICAgICAqMTYuMTUtMTkqYFwiXSlcbiAgICA2M3t7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg2MylcbiAgICAgICoxNi4xNS0yMSpgXCJ9fVxuICAgIDY1W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDY1KVxuICAgICAgKjE2LjE1LTIxKlxuICAgICg2MiwgNjMpYFwiXV1cbiAgICA2N1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBsb3RcbiAgICAgICg2NylcbiAgICAgICoxNi4xLTIyKlxuICAgICg2MCwgNjUpYFwiXV1cbiAgICBidWlsdC1pbjpwbG90W1wiYEJ1aWx0LUluOlxucGxvdGBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwbG90IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA2OShbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjkpXG4gICAgICAqMTcuOC0xMipgXCJdKVxuICAgIDcwe3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDcwKVxuICAgICAgKjE3LjgtMTQqYFwifX1cbiAgICA3MltbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg3MilcbiAgICAgICoxNy44LTE0KlxuICAgICg2OSwgNzApYFwiXV1cbiAgICA3NChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNzQpXG4gICAgICAqMTcuMTctMjEqYFwiXSlcbiAgICA3NXt7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg3NSlcbiAgICAgICoxNy4xNy0yMypgXCJ9fVxuICAgIDc3W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDc3KVxuICAgICAgKjE3LjE3LTIzKlxuICAgICg3NCwgNzUpYFwiXV1cbiAgICA3OVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBvaW50c1xuICAgICAgKDc5KVxuICAgICAgKjE3LjEtMjQqXG4gICAgKDcyLCA3NylgXCJdXVxuICAgIGJ1aWx0LWluOnBvaW50c1tcImBCdWlsdC1JbjpcbnBvaW50c2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwb2ludHMgc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDgyKFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICg4MilcbiAgICAgICoxOS4xMi0xNipgXCJdKVxuICAgIDgze3tcImAjOTE7UlN5bWJvbCM5Mzsga1xuICAgICAgKDgzKVxuICAgICAgKjE5LjEyLTE4KmBcIn19XG4gICAgODVbW1wiYCM5MTtSQWNjZXNzIzkzOyAkXG4gICAgICAoODUpXG4gICAgICAqMTkuMTItMTgqXG4gICAgKDgyLCA4MylgXCJdXVxuICAgIDg3W1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDg3KVxuICAgICAgKjE5LjctMTkqXG4gICAgKDg1KWBcIl1dXG4gICAgODlbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDg5KVxuICAgICAgKjE5LjEtMjAqXG4gICAgKDg3KWBcIl1dXG4gICAgMyAtLT58XCJhcmd1bWVudFwifCAxXG4gICAgMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgMSBzdHJva2U6Z3JheTtcbiAgICA3IC0tPnxcImFyZ3VtZW50XCJ8IDVcbiAgICA3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bGlicmFyeVxuICAgIGxpbmtTdHlsZSAzIHN0cm9rZTpncmF5O1xuICAgIDExIC0tPnxcImFyZ3VtZW50XCJ8IDlcbiAgICAxMSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgNSBzdHJva2U6Z3JheTtcbiAgICAxNiAtLT58XCJhcmd1bWVudFwifCAxNFxuICAgIDEyIC0tPnxcImRlZmluZWQtYnlcInwgMTZcbiAgICAxMiAtLT58XCJkZWZpbmVkLWJ5XCJ8IDE3XG4gICAgMTcgLS0+fFwiYXJndW1lbnRcInwgMTZcbiAgICAxNyAtLT58XCJyZXR1cm5zLCBhcmd1bWVudFwifCAxMlxuICAgIDE3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Xy1cbiAgICBsaW5rU3R5bGUgMTEgc3Ryb2tlOmdyYXk7XG4gICAgMjIgLS0+fFwiYXJndW1lbnRcInwgMjBcbiAgICAxOCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDIyXG4gICAgMTggLS0+fFwiZGVmaW5lZC1ieVwifCAyM1xuICAgIDIzIC0tPnxcImFyZ3VtZW50XCJ8IDIyXG4gICAgMjMgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMThcbiAgICAyMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDE3IHN0cm9rZTpncmF5O1xuICAgIDI2IC0tPnxcInJlYWRzXCJ8IDEyXG4gICAgMjkgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDI2XG4gICAgMjkgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDI3XG4gICAgMjkgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDIxIHN0cm9rZTpncmF5O1xuICAgIDMxIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAyOVxuICAgIDMxIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bWVhblxuICAgIGxpbmtTdHlsZSAyMyBzdHJva2U6Z3JheTtcbiAgICAyNCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDMxXG4gICAgMjQgLS0+fFwiZGVmaW5lZC1ieVwifCAzMlxuICAgIDMyIC0tPnxcImFyZ3VtZW50XCJ8IDMxXG4gICAgMzIgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMjRcbiAgICAzMiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDI4IHN0cm9rZTpncmF5O1xuICAgIDM0IC0tPnxcInJlYWRzXCJ8IDI0XG4gICAgMzYgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDM0XG4gICAgMzYgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwcmludFxuICAgIGxpbmtTdHlsZSAzMSBzdHJva2U6Z3JheTtcbiAgICAzOCAtLT58XCJyZWFkc1wifCAxMlxuICAgIDQ0IC0tPnxcInJlYWRzXCJ8IDQzXG4gICAgNDcgLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJyZWFkc1wifCA0M1xuICAgIDQ4IC0tPnxcImFyZ3VtZW50XCJ8IDQ0XG4gICAgNDggLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJhcmd1bWVudFwifCA0N1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA0OFxuICAgIDUwIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Z2dwbG90XG4gICAgbGlua1N0eWxlIDQwIHN0cm9rZTpncmF5O1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAzOFxuICAgIDUyIC0tPnxcImFyZ3VtZW50XCJ8IDM4XG4gICAgNTIgLS0+fFwiYXJndW1lbnRcInwgNTBcbiAgICA1MiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9fX1xuICAgIGxpbmtTdHlsZSA0NCBzdHJva2U6Z3JheTtcbiAgICA1NCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmdlb21fcG9pbnRcbiAgICBsaW5rU3R5bGUgNDUgc3Ryb2tlOmdyYXk7XG4gICAgNTQgLS0+fFwicmVhZHNcInwgNTBcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTJcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTRcbiAgICA1NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNDkgc3Ryb2tlOmdyYXk7XG4gICAgNTcgLS0+fFwicmVhZHNcInwgMThcbiAgICA2MCAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNTdcbiAgICA2MCAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNThcbiAgICA2MCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTMgc3Ryb2tlOmdyYXk7XG4gICAgNjIgLS0+fFwicmVhZHNcInwgMThcbiAgICA2NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNjJcbiAgICA2NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNjNcbiAgICA2NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTcgc3Ryb2tlOmdyYXk7XG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDYwXG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDY1XG4gICAgNjcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwbG90XG4gICAgbGlua1N0eWxlIDYwIHN0cm9rZTpncmF5O1xuICAgIDY5IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzIgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDY5XG4gICAgNzIgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDcwXG4gICAgNzIgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY0IHN0cm9rZTpncmF5O1xuICAgIDc0IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzcgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDc0XG4gICAgNzcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDc1XG4gICAgNzcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY4IHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3MlxuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3N1xuICAgIDc5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cG9pbnRzXG4gICAgbGlua1N0eWxlIDcxIHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzXCJ8IDY3XG4gICAgODIgLS0+fFwicmVhZHNcInwgMThcbiAgICA4NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgODJcbiAgICA4NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgODNcbiAgICA4NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNzYgc3Ryb2tlOmdyYXk7XG4gICAgODcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDg1XG4gICAgODcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjptZWFuXG4gICAgbGlua1N0eWxlIDc4IHN0cm9rZTpncmF5O1xuICAgIDg5IC0tPnxcInJlYWRzLCByZXR1cm5zLCBhcmd1bWVudFwifCA4N1xuICAgIDg5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cHJpbnRcbiAgICBsaW5rU3R5bGUgODAgc3Ryb2tlOmdyYXk7IiwibWVybWFpZCI6eyJhdXRvU3luYyI6dHJ1ZX19))\       ╰ (has unknown side effect) {11, 9} ([marked](https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgMXt7XCJgIzkxO1JTeW1ib2wjOTM7IGdncGxvdFxuICAgICAgKDEpXG4gICAgICAqMS45LTE0KmBcIn19XG4gICAgM1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgzKVxuICAgICAgKjEuMS0xNSpcbiAgICAoMSlgXCJdXVxuICAgIHN0eWxlIDMgc3Ryb2tlOnJlZCxzdHJva2Utd2lkdGg6NXB4OyBcbiAgICBidWlsdC1pbjpsaWJyYXJ5W1wiYEJ1aWx0LUluOlxubGlicmFyeWBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpsaWJyYXJ5IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1e3tcImAjOTE7UlN5bWJvbCM5MzsgZHBseXJcbiAgICAgICg1KVxuICAgICAgKjIuOS0xMypgXCJ9fVxuICAgIDdbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBsaWJyYXJ5XG4gICAgICAoNylcbiAgICAgICoyLjEtMTQqXG4gICAgKDUpYFwiXV1cbiAgICBzdHlsZSA3IHN0cm9rZTpyZWQsc3Ryb2tlLXdpZHRoOjVweDsgXG4gICAgOXt7XCJgIzkxO1JTeW1ib2wjOTM7IHJlYWRyXG4gICAgICAoOSlcbiAgICAgICozLjktMTMqYFwifX1cbiAgICAxMVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgxMSlcbiAgICAgICozLjEtMTQqXG4gICAgKDkpYFwiXV1cbiAgICBzdHlsZSAxMSBzdHJva2U6cmVkLHN0cm9rZS13aWR0aDo1cHg7IFxuICAgIDE0e3tcImAjOTE7UlN0cmluZyM5MzsgIzM5O2RhdGEuY3N2IzM5O1xuICAgICAgKDE0KVxuICAgICAgKjYuMTgtMjcqYFwifX1cbiAgICAxNltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMTYpXG4gICAgICAqNi45LTI4KlxuICAgICgxNClgXCJdXVxuICAgIDEyW1wiYCM5MTtSU3ltYm9sIzkzOyBkYXRhXG4gICAgICAoMTIpXG4gICAgICAqNi4xLTQqYFwiXVxuICAgIDE3W1tcImAjOTE7UkJpbmFyeU9wIzkzOyAjNjA7IzQ1O1xuICAgICAgKDE3KVxuICAgICAgKjYuMS0yOCpcbiAgICAoMTIsIDE2KWBcIl1dXG4gICAgYnVpbHQtaW46Xy1bXCJgQnVpbHQtSW46XG4jNjA7IzQ1O2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpfLSBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgMjB7e1wiYCM5MTtSU3RyaW5nIzkzOyAjMzk7ZGF0YTIuY3N2IzM5O1xuICAgICAgKDIwKVxuICAgICAgKjcuMTktMjkqYFwifX1cbiAgICAyMltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMjIpXG4gICAgICAqNy4xMC0zMCpcbiAgICAoMjApYFwiXV1cbiAgICAxOFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICgxOClcbiAgICAgICo3LjEtNSpgXCJdXG4gICAgMjNbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMjMpXG4gICAgICAqNy4xLTMwKlxuICAgICgxOCwgMjIpYFwiXV1cbiAgICAyNihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgyNilcbiAgICAgICo5LjExLTE0KmBcIl0pXG4gICAgMjd7e1wiYCM5MTtSU3ltYm9sIzkzOyB4XG4gICAgICAoMjcpXG4gICAgICAqOS4xMS0xNipgXCJ9fVxuICAgIDI5W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDI5KVxuICAgICAgKjkuMTEtMTYqXG4gICAgKDI2LCAyNylgXCJdXVxuICAgIGJ1aWx0LWluOl9bXCJgQnVpbHQtSW46XG4kYFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOl8gc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDMxW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDMxKVxuICAgICAgKjkuNi0xNypcbiAgICAoMjkpYFwiXV1cbiAgICBidWlsdC1pbjptZWFuW1wiYEJ1aWx0LUluOlxubWVhbmBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjptZWFuIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAyNFtcImAjOTE7UlN5bWJvbCM5MzsgbVxuICAgICAgKDI0KVxuICAgICAgKjkuMSpgXCJdXG4gICAgMzJbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMzIpXG4gICAgICAqOS4xLTE3KlxuICAgICgyNCwgMzEpYFwiXV1cbiAgICAzNChbXCJgIzkxO1JTeW1ib2wjOTM7IG1cbiAgICAgICgzNClcbiAgICAgICoxMC43KmBcIl0pXG4gICAgMzZbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDM2KVxuICAgICAgKjEwLjEtOCpcbiAgICAoMzQpYFwiXV1cbiAgICBidWlsdC1pbjpwcmludFtcImBCdWlsdC1JbjpcbnByaW50YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOnByaW50IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAzOChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgzOClcbiAgICAgICoxMi4xLTQqYFwiXSlcbiAgICA0MyhbXCJgIzkxO1JTeW1ib2wjOTM7IHhcbiAgICAgICg0MylcbiAgICAgICoxMy4yNCpgXCJdKVxuICAgIDQ0KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB4XG4gICAgICAoNDQpXG4gICAgICAqMTMuMjAqYFwiXSlcbiAgICA0NihbXCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg0NilcbiAgICAgICoxMy4zMSpgXCJdKVxuICAgIDQ3KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB5XG4gICAgICAoNDcpXG4gICAgICAqMTMuMjcqYFwiXSlcbiAgICA0OFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGFlc1xuICAgICAgKDQ4KVxuICAgICAgKjEzLjE2LTMyKlxuICAgICh4ICg0NCksIHkgKDQ3KSlgXCJdXVxuICAgIDUwW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgZ2dwbG90XG4gICAgICAoNTApXG4gICAgICAqMTMuOS0zMypcbiAgICAoMzgsIDQ4KWBcIl1dXG4gICAgYnVpbHQtaW46Z2dwbG90W1wiYEJ1aWx0LUluOlxuZ2dwbG90YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOmdncGxvdCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTJbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBkYXRhICUjNjI7JVxuXHRnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpXG4gICAgICAoNTIpXG4gICAgICAqMTIuNi04KlxuICAgICgzOCwgNTApYFwiXV1cbiAgICBidWlsdC1pbjpfX19bXCJgQnVpbHQtSW46XG4lIzYyOyVgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46X19fIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1NFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGdlb20jOTU7cG9pbnRcbiAgICAgICg1NClcbiAgICAgICoxNC45LTIwKmBcIl1dXG4gICAgYnVpbHQtaW46Z2VvbV9wb2ludFtcImBCdWlsdC1Jbjpcbmdlb20jOTU7cG9pbnRgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46Z2VvbV9wb2ludCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTVbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM0MztcbiAgICAgICg1NSlcbiAgICAgICoxMi4xLTE0LjIwKlxuICAgICg1MiwgNTQpYFwiXV1cbiAgICA1NyhbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNTcpXG4gICAgICAqMTYuNi0xMCpgXCJdKVxuICAgIDU4e3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDU4KVxuICAgICAgKjE2LjYtMTIqYFwifX1cbiAgICA2MFtbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg2MClcbiAgICAgICoxNi42LTEyKlxuICAgICg1NywgNTgpYFwiXV1cbiAgICA2MihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjIpXG4gICAgICAqMTYuMTUtMTkqYFwiXSlcbiAgICA2M3t7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg2MylcbiAgICAgICoxNi4xNS0yMSpgXCJ9fVxuICAgIDY1W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDY1KVxuICAgICAgKjE2LjE1LTIxKlxuICAgICg2MiwgNjMpYFwiXV1cbiAgICA2N1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBsb3RcbiAgICAgICg2NylcbiAgICAgICoxNi4xLTIyKlxuICAgICg2MCwgNjUpYFwiXV1cbiAgICBidWlsdC1pbjpwbG90W1wiYEJ1aWx0LUluOlxucGxvdGBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwbG90IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA2OShbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjkpXG4gICAgICAqMTcuOC0xMipgXCJdKVxuICAgIDcwe3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDcwKVxuICAgICAgKjE3LjgtMTQqYFwifX1cbiAgICA3MltbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg3MilcbiAgICAgICoxNy44LTE0KlxuICAgICg2OSwgNzApYFwiXV1cbiAgICA3NChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNzQpXG4gICAgICAqMTcuMTctMjEqYFwiXSlcbiAgICA3NXt7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg3NSlcbiAgICAgICoxNy4xNy0yMypgXCJ9fVxuICAgIDc3W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDc3KVxuICAgICAgKjE3LjE3LTIzKlxuICAgICg3NCwgNzUpYFwiXV1cbiAgICA3OVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBvaW50c1xuICAgICAgKDc5KVxuICAgICAgKjE3LjEtMjQqXG4gICAgKDcyLCA3NylgXCJdXVxuICAgIGJ1aWx0LWluOnBvaW50c1tcImBCdWlsdC1JbjpcbnBvaW50c2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwb2ludHMgc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDgyKFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICg4MilcbiAgICAgICoxOS4xMi0xNipgXCJdKVxuICAgIDgze3tcImAjOTE7UlN5bWJvbCM5Mzsga1xuICAgICAgKDgzKVxuICAgICAgKjE5LjEyLTE4KmBcIn19XG4gICAgODVbW1wiYCM5MTtSQWNjZXNzIzkzOyAkXG4gICAgICAoODUpXG4gICAgICAqMTkuMTItMTgqXG4gICAgKDgyLCA4MylgXCJdXVxuICAgIDg3W1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDg3KVxuICAgICAgKjE5LjctMTkqXG4gICAgKDg1KWBcIl1dXG4gICAgODlbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDg5KVxuICAgICAgKjE5LjEtMjAqXG4gICAgKDg3KWBcIl1dXG4gICAgMyAtLT58XCJhcmd1bWVudFwifCAxXG4gICAgMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgMSBzdHJva2U6Z3JheTtcbiAgICA3IC0tPnxcImFyZ3VtZW50XCJ8IDVcbiAgICA3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bGlicmFyeVxuICAgIGxpbmtTdHlsZSAzIHN0cm9rZTpncmF5O1xuICAgIDExIC0tPnxcImFyZ3VtZW50XCJ8IDlcbiAgICAxMSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgNSBzdHJva2U6Z3JheTtcbiAgICAxNiAtLT58XCJhcmd1bWVudFwifCAxNFxuICAgIDEyIC0tPnxcImRlZmluZWQtYnlcInwgMTZcbiAgICAxMiAtLT58XCJkZWZpbmVkLWJ5XCJ8IDE3XG4gICAgMTcgLS0+fFwiYXJndW1lbnRcInwgMTZcbiAgICAxNyAtLT58XCJyZXR1cm5zLCBhcmd1bWVudFwifCAxMlxuICAgIDE3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Xy1cbiAgICBsaW5rU3R5bGUgMTEgc3Ryb2tlOmdyYXk7XG4gICAgMjIgLS0+fFwiYXJndW1lbnRcInwgMjBcbiAgICAxOCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDIyXG4gICAgMTggLS0+fFwiZGVmaW5lZC1ieVwifCAyM1xuICAgIDIzIC0tPnxcImFyZ3VtZW50XCJ8IDIyXG4gICAgMjMgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMThcbiAgICAyMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDE3IHN0cm9rZTpncmF5O1xuICAgIDI2IC0tPnxcInJlYWRzXCJ8IDEyXG4gICAgMjkgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDI2XG4gICAgMjkgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDI3XG4gICAgMjkgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDIxIHN0cm9rZTpncmF5O1xuICAgIDMxIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAyOVxuICAgIDMxIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bWVhblxuICAgIGxpbmtTdHlsZSAyMyBzdHJva2U6Z3JheTtcbiAgICAyNCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDMxXG4gICAgMjQgLS0+fFwiZGVmaW5lZC1ieVwifCAzMlxuICAgIDMyIC0tPnxcImFyZ3VtZW50XCJ8IDMxXG4gICAgMzIgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMjRcbiAgICAzMiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDI4IHN0cm9rZTpncmF5O1xuICAgIDM0IC0tPnxcInJlYWRzXCJ8IDI0XG4gICAgMzYgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDM0XG4gICAgMzYgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwcmludFxuICAgIGxpbmtTdHlsZSAzMSBzdHJva2U6Z3JheTtcbiAgICAzOCAtLT58XCJyZWFkc1wifCAxMlxuICAgIDQ0IC0tPnxcInJlYWRzXCJ8IDQzXG4gICAgNDcgLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJyZWFkc1wifCA0M1xuICAgIDQ4IC0tPnxcImFyZ3VtZW50XCJ8IDQ0XG4gICAgNDggLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJhcmd1bWVudFwifCA0N1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA0OFxuICAgIDUwIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Z2dwbG90XG4gICAgbGlua1N0eWxlIDQwIHN0cm9rZTpncmF5O1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAzOFxuICAgIDUyIC0tPnxcImFyZ3VtZW50XCJ8IDM4XG4gICAgNTIgLS0+fFwiYXJndW1lbnRcInwgNTBcbiAgICA1MiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9fX1xuICAgIGxpbmtTdHlsZSA0NCBzdHJva2U6Z3JheTtcbiAgICA1NCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmdlb21fcG9pbnRcbiAgICBsaW5rU3R5bGUgNDUgc3Ryb2tlOmdyYXk7XG4gICAgNTQgLS0+fFwicmVhZHNcInwgNTBcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTJcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTRcbiAgICA1NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNDkgc3Ryb2tlOmdyYXk7XG4gICAgNTcgLS0+fFwicmVhZHNcInwgMThcbiAgICA2MCAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNTdcbiAgICA2MCAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNThcbiAgICA2MCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTMgc3Ryb2tlOmdyYXk7XG4gICAgNjIgLS0+fFwicmVhZHNcInwgMThcbiAgICA2NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNjJcbiAgICA2NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNjNcbiAgICA2NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTcgc3Ryb2tlOmdyYXk7XG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDYwXG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDY1XG4gICAgNjcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwbG90XG4gICAgbGlua1N0eWxlIDYwIHN0cm9rZTpncmF5O1xuICAgIDY5IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzIgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDY5XG4gICAgNzIgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDcwXG4gICAgNzIgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY0IHN0cm9rZTpncmF5O1xuICAgIDc0IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzcgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDc0XG4gICAgNzcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDc1XG4gICAgNzcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY4IHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3MlxuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3N1xuICAgIDc5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cG9pbnRzXG4gICAgbGlua1N0eWxlIDcxIHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzXCJ8IDY3XG4gICAgODIgLS0+fFwicmVhZHNcInwgMThcbiAgICA4NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgODJcbiAgICA4NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgODNcbiAgICA4NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNzYgc3Ryb2tlOmdyYXk7XG4gICAgODcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDg1XG4gICAgODcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjptZWFuXG4gICAgbGlua1N0eWxlIDc4IHN0cm9rZTpncmF5O1xuICAgIDg5IC0tPnxcInJlYWRzLCByZXR1cm5zLCBhcmd1bWVudFwifCA4N1xuICAgIDg5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cHJpbnRcbiAgICBsaW5rU3R5bGUgODAgc3Ryb2tlOmdyYXk7IiwibWVybWFpZCI6eyJhdXRvU3luYyI6dHJ1ZX19))\       ╰ (has unknown side effect) {7, 5} ([marked](https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgMXt7XCJgIzkxO1JTeW1ib2wjOTM7IGdncGxvdFxuICAgICAgKDEpXG4gICAgICAqMS45LTE0KmBcIn19XG4gICAgM1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgzKVxuICAgICAgKjEuMS0xNSpcbiAgICAoMSlgXCJdXVxuICAgIHN0eWxlIDMgc3Ryb2tlOnJlZCxzdHJva2Utd2lkdGg6NXB4OyBcbiAgICBidWlsdC1pbjpsaWJyYXJ5W1wiYEJ1aWx0LUluOlxubGlicmFyeWBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpsaWJyYXJ5IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1e3tcImAjOTE7UlN5bWJvbCM5MzsgZHBseXJcbiAgICAgICg1KVxuICAgICAgKjIuOS0xMypgXCJ9fVxuICAgIDdbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBsaWJyYXJ5XG4gICAgICAoNylcbiAgICAgICoyLjEtMTQqXG4gICAgKDUpYFwiXV1cbiAgICBzdHlsZSA3IHN0cm9rZTpyZWQsc3Ryb2tlLXdpZHRoOjVweDsgXG4gICAgOXt7XCJgIzkxO1JTeW1ib2wjOTM7IHJlYWRyXG4gICAgICAoOSlcbiAgICAgICozLjktMTMqYFwifX1cbiAgICAxMVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgxMSlcbiAgICAgICozLjEtMTQqXG4gICAgKDkpYFwiXV1cbiAgICBzdHlsZSAxMSBzdHJva2U6cmVkLHN0cm9rZS13aWR0aDo1cHg7IFxuICAgIDE0e3tcImAjOTE7UlN0cmluZyM5MzsgIzM5O2RhdGEuY3N2IzM5O1xuICAgICAgKDE0KVxuICAgICAgKjYuMTgtMjcqYFwifX1cbiAgICAxNltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMTYpXG4gICAgICAqNi45LTI4KlxuICAgICgxNClgXCJdXVxuICAgIDEyW1wiYCM5MTtSU3ltYm9sIzkzOyBkYXRhXG4gICAgICAoMTIpXG4gICAgICAqNi4xLTQqYFwiXVxuICAgIDE3W1tcImAjOTE7UkJpbmFyeU9wIzkzOyAjNjA7IzQ1O1xuICAgICAgKDE3KVxuICAgICAgKjYuMS0yOCpcbiAgICAoMTIsIDE2KWBcIl1dXG4gICAgYnVpbHQtaW46Xy1bXCJgQnVpbHQtSW46XG4jNjA7IzQ1O2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpfLSBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgMjB7e1wiYCM5MTtSU3RyaW5nIzkzOyAjMzk7ZGF0YTIuY3N2IzM5O1xuICAgICAgKDIwKVxuICAgICAgKjcuMTktMjkqYFwifX1cbiAgICAyMltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMjIpXG4gICAgICAqNy4xMC0zMCpcbiAgICAoMjApYFwiXV1cbiAgICAxOFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICgxOClcbiAgICAgICo3LjEtNSpgXCJdXG4gICAgMjNbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMjMpXG4gICAgICAqNy4xLTMwKlxuICAgICgxOCwgMjIpYFwiXV1cbiAgICAyNihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgyNilcbiAgICAgICo5LjExLTE0KmBcIl0pXG4gICAgMjd7e1wiYCM5MTtSU3ltYm9sIzkzOyB4XG4gICAgICAoMjcpXG4gICAgICAqOS4xMS0xNipgXCJ9fVxuICAgIDI5W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDI5KVxuICAgICAgKjkuMTEtMTYqXG4gICAgKDI2LCAyNylgXCJdXVxuICAgIGJ1aWx0LWluOl9bXCJgQnVpbHQtSW46XG4kYFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOl8gc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDMxW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDMxKVxuICAgICAgKjkuNi0xNypcbiAgICAoMjkpYFwiXV1cbiAgICBidWlsdC1pbjptZWFuW1wiYEJ1aWx0LUluOlxubWVhbmBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjptZWFuIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAyNFtcImAjOTE7UlN5bWJvbCM5MzsgbVxuICAgICAgKDI0KVxuICAgICAgKjkuMSpgXCJdXG4gICAgMzJbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMzIpXG4gICAgICAqOS4xLTE3KlxuICAgICgyNCwgMzEpYFwiXV1cbiAgICAzNChbXCJgIzkxO1JTeW1ib2wjOTM7IG1cbiAgICAgICgzNClcbiAgICAgICoxMC43KmBcIl0pXG4gICAgMzZbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDM2KVxuICAgICAgKjEwLjEtOCpcbiAgICAoMzQpYFwiXV1cbiAgICBidWlsdC1pbjpwcmludFtcImBCdWlsdC1JbjpcbnByaW50YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOnByaW50IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAzOChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgzOClcbiAgICAgICoxMi4xLTQqYFwiXSlcbiAgICA0MyhbXCJgIzkxO1JTeW1ib2wjOTM7IHhcbiAgICAgICg0MylcbiAgICAgICoxMy4yNCpgXCJdKVxuICAgIDQ0KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB4XG4gICAgICAoNDQpXG4gICAgICAqMTMuMjAqYFwiXSlcbiAgICA0NihbXCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg0NilcbiAgICAgICoxMy4zMSpgXCJdKVxuICAgIDQ3KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB5XG4gICAgICAoNDcpXG4gICAgICAqMTMuMjcqYFwiXSlcbiAgICA0OFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGFlc1xuICAgICAgKDQ4KVxuICAgICAgKjEzLjE2LTMyKlxuICAgICh4ICg0NCksIHkgKDQ3KSlgXCJdXVxuICAgIDUwW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgZ2dwbG90XG4gICAgICAoNTApXG4gICAgICAqMTMuOS0zMypcbiAgICAoMzgsIDQ4KWBcIl1dXG4gICAgYnVpbHQtaW46Z2dwbG90W1wiYEJ1aWx0LUluOlxuZ2dwbG90YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOmdncGxvdCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTJbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBkYXRhICUjNjI7JVxuXHRnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpXG4gICAgICAoNTIpXG4gICAgICAqMTIuNi04KlxuICAgICgzOCwgNTApYFwiXV1cbiAgICBidWlsdC1pbjpfX19bXCJgQnVpbHQtSW46XG4lIzYyOyVgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46X19fIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1NFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGdlb20jOTU7cG9pbnRcbiAgICAgICg1NClcbiAgICAgICoxNC45LTIwKmBcIl1dXG4gICAgYnVpbHQtaW46Z2VvbV9wb2ludFtcImBCdWlsdC1Jbjpcbmdlb20jOTU7cG9pbnRgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46Z2VvbV9wb2ludCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTVbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM0MztcbiAgICAgICg1NSlcbiAgICAgICoxMi4xLTE0LjIwKlxuICAgICg1MiwgNTQpYFwiXV1cbiAgICA1NyhbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNTcpXG4gICAgICAqMTYuNi0xMCpgXCJdKVxuICAgIDU4e3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDU4KVxuICAgICAgKjE2LjYtMTIqYFwifX1cbiAgICA2MFtbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg2MClcbiAgICAgICoxNi42LTEyKlxuICAgICg1NywgNTgpYFwiXV1cbiAgICA2MihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjIpXG4gICAgICAqMTYuMTUtMTkqYFwiXSlcbiAgICA2M3t7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg2MylcbiAgICAgICoxNi4xNS0yMSpgXCJ9fVxuICAgIDY1W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDY1KVxuICAgICAgKjE2LjE1LTIxKlxuICAgICg2MiwgNjMpYFwiXV1cbiAgICA2N1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBsb3RcbiAgICAgICg2NylcbiAgICAgICoxNi4xLTIyKlxuICAgICg2MCwgNjUpYFwiXV1cbiAgICBidWlsdC1pbjpwbG90W1wiYEJ1aWx0LUluOlxucGxvdGBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwbG90IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA2OShbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjkpXG4gICAgICAqMTcuOC0xMipgXCJdKVxuICAgIDcwe3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDcwKVxuICAgICAgKjE3LjgtMTQqYFwifX1cbiAgICA3MltbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg3MilcbiAgICAgICoxNy44LTE0KlxuICAgICg2OSwgNzApYFwiXV1cbiAgICA3NChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNzQpXG4gICAgICAqMTcuMTctMjEqYFwiXSlcbiAgICA3NXt7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg3NSlcbiAgICAgICoxNy4xNy0yMypgXCJ9fVxuICAgIDc3W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDc3KVxuICAgICAgKjE3LjE3LTIzKlxuICAgICg3NCwgNzUpYFwiXV1cbiAgICA3OVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBvaW50c1xuICAgICAgKDc5KVxuICAgICAgKjE3LjEtMjQqXG4gICAgKDcyLCA3NylgXCJdXVxuICAgIGJ1aWx0LWluOnBvaW50c1tcImBCdWlsdC1JbjpcbnBvaW50c2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwb2ludHMgc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDgyKFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICg4MilcbiAgICAgICoxOS4xMi0xNipgXCJdKVxuICAgIDgze3tcImAjOTE7UlN5bWJvbCM5Mzsga1xuICAgICAgKDgzKVxuICAgICAgKjE5LjEyLTE4KmBcIn19XG4gICAgODVbW1wiYCM5MTtSQWNjZXNzIzkzOyAkXG4gICAgICAoODUpXG4gICAgICAqMTkuMTItMTgqXG4gICAgKDgyLCA4MylgXCJdXVxuICAgIDg3W1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDg3KVxuICAgICAgKjE5LjctMTkqXG4gICAgKDg1KWBcIl1dXG4gICAgODlbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDg5KVxuICAgICAgKjE5LjEtMjAqXG4gICAgKDg3KWBcIl1dXG4gICAgMyAtLT58XCJhcmd1bWVudFwifCAxXG4gICAgMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgMSBzdHJva2U6Z3JheTtcbiAgICA3IC0tPnxcImFyZ3VtZW50XCJ8IDVcbiAgICA3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bGlicmFyeVxuICAgIGxpbmtTdHlsZSAzIHN0cm9rZTpncmF5O1xuICAgIDExIC0tPnxcImFyZ3VtZW50XCJ8IDlcbiAgICAxMSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgNSBzdHJva2U6Z3JheTtcbiAgICAxNiAtLT58XCJhcmd1bWVudFwifCAxNFxuICAgIDEyIC0tPnxcImRlZmluZWQtYnlcInwgMTZcbiAgICAxMiAtLT58XCJkZWZpbmVkLWJ5XCJ8IDE3XG4gICAgMTcgLS0+fFwiYXJndW1lbnRcInwgMTZcbiAgICAxNyAtLT58XCJyZXR1cm5zLCBhcmd1bWVudFwifCAxMlxuICAgIDE3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Xy1cbiAgICBsaW5rU3R5bGUgMTEgc3Ryb2tlOmdyYXk7XG4gICAgMjIgLS0+fFwiYXJndW1lbnRcInwgMjBcbiAgICAxOCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDIyXG4gICAgMTggLS0+fFwiZGVmaW5lZC1ieVwifCAyM1xuICAgIDIzIC0tPnxcImFyZ3VtZW50XCJ8IDIyXG4gICAgMjMgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMThcbiAgICAyMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDE3IHN0cm9rZTpncmF5O1xuICAgIDI2IC0tPnxcInJlYWRzXCJ8IDEyXG4gICAgMjkgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDI2XG4gICAgMjkgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDI3XG4gICAgMjkgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDIxIHN0cm9rZTpncmF5O1xuICAgIDMxIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAyOVxuICAgIDMxIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bWVhblxuICAgIGxpbmtTdHlsZSAyMyBzdHJva2U6Z3JheTtcbiAgICAyNCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDMxXG4gICAgMjQgLS0+fFwiZGVmaW5lZC1ieVwifCAzMlxuICAgIDMyIC0tPnxcImFyZ3VtZW50XCJ8IDMxXG4gICAgMzIgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMjRcbiAgICAzMiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDI4IHN0cm9rZTpncmF5O1xuICAgIDM0IC0tPnxcInJlYWRzXCJ8IDI0XG4gICAgMzYgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDM0XG4gICAgMzYgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwcmludFxuICAgIGxpbmtTdHlsZSAzMSBzdHJva2U6Z3JheTtcbiAgICAzOCAtLT58XCJyZWFkc1wifCAxMlxuICAgIDQ0IC0tPnxcInJlYWRzXCJ8IDQzXG4gICAgNDcgLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJyZWFkc1wifCA0M1xuICAgIDQ4IC0tPnxcImFyZ3VtZW50XCJ8IDQ0XG4gICAgNDggLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJhcmd1bWVudFwifCA0N1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA0OFxuICAgIDUwIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Z2dwbG90XG4gICAgbGlua1N0eWxlIDQwIHN0cm9rZTpncmF5O1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAzOFxuICAgIDUyIC0tPnxcImFyZ3VtZW50XCJ8IDM4XG4gICAgNTIgLS0+fFwiYXJndW1lbnRcInwgNTBcbiAgICA1MiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9fX1xuICAgIGxpbmtTdHlsZSA0NCBzdHJva2U6Z3JheTtcbiAgICA1NCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmdlb21fcG9pbnRcbiAgICBsaW5rU3R5bGUgNDUgc3Ryb2tlOmdyYXk7XG4gICAgNTQgLS0+fFwicmVhZHNcInwgNTBcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTJcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTRcbiAgICA1NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNDkgc3Ryb2tlOmdyYXk7XG4gICAgNTcgLS0+fFwicmVhZHNcInwgMThcbiAgICA2MCAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNTdcbiAgICA2MCAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNThcbiAgICA2MCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTMgc3Ryb2tlOmdyYXk7XG4gICAgNjIgLS0+fFwicmVhZHNcInwgMThcbiAgICA2NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNjJcbiAgICA2NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNjNcbiAgICA2NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTcgc3Ryb2tlOmdyYXk7XG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDYwXG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDY1XG4gICAgNjcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwbG90XG4gICAgbGlua1N0eWxlIDYwIHN0cm9rZTpncmF5O1xuICAgIDY5IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzIgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDY5XG4gICAgNzIgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDcwXG4gICAgNzIgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY0IHN0cm9rZTpncmF5O1xuICAgIDc0IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzcgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDc0XG4gICAgNzcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDc1XG4gICAgNzcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY4IHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3MlxuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3N1xuICAgIDc5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cG9pbnRzXG4gICAgbGlua1N0eWxlIDcxIHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzXCJ8IDY3XG4gICAgODIgLS0+fFwicmVhZHNcInwgMThcbiAgICA4NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgODJcbiAgICA4NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgODNcbiAgICA4NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNzYgc3Ryb2tlOmdyYXk7XG4gICAgODcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDg1XG4gICAgODcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjptZWFuXG4gICAgbGlua1N0eWxlIDc4IHN0cm9rZTpncmF5O1xuICAgIDg5IC0tPnxcInJlYWRzLCByZXR1cm5zLCBhcmd1bWVudFwifCA4N1xuICAgIDg5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cHJpbnRcbiAgICBsaW5rU3R5bGUgODAgc3Ryb2tlOmdyYXk7IiwibWVybWFpZCI6eyJhdXRvU3luYyI6dHJ1ZX19))\       ╰ (has unknown side effect) {3, 1} ([marked](https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgMXt7XCJgIzkxO1JTeW1ib2wjOTM7IGdncGxvdFxuICAgICAgKDEpXG4gICAgICAqMS45LTE0KmBcIn19XG4gICAgM1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgzKVxuICAgICAgKjEuMS0xNSpcbiAgICAoMSlgXCJdXVxuICAgIHN0eWxlIDMgc3Ryb2tlOnJlZCxzdHJva2Utd2lkdGg6NXB4OyBcbiAgICBidWlsdC1pbjpsaWJyYXJ5W1wiYEJ1aWx0LUluOlxubGlicmFyeWBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpsaWJyYXJ5IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1e3tcImAjOTE7UlN5bWJvbCM5MzsgZHBseXJcbiAgICAgICg1KVxuICAgICAgKjIuOS0xMypgXCJ9fVxuICAgIDdbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBsaWJyYXJ5XG4gICAgICAoNylcbiAgICAgICoyLjEtMTQqXG4gICAgKDUpYFwiXV1cbiAgICBzdHlsZSA3IHN0cm9rZTpyZWQsc3Ryb2tlLXdpZHRoOjVweDsgXG4gICAgOXt7XCJgIzkxO1JTeW1ib2wjOTM7IHJlYWRyXG4gICAgICAoOSlcbiAgICAgICozLjktMTMqYFwifX1cbiAgICAxMVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGxpYnJhcnlcbiAgICAgICgxMSlcbiAgICAgICozLjEtMTQqXG4gICAgKDkpYFwiXV1cbiAgICBzdHlsZSAxMSBzdHJva2U6cmVkLHN0cm9rZS13aWR0aDo1cHg7IFxuICAgIDE0e3tcImAjOTE7UlN0cmluZyM5MzsgIzM5O2RhdGEuY3N2IzM5O1xuICAgICAgKDE0KVxuICAgICAgKjYuMTgtMjcqYFwifX1cbiAgICAxNltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMTYpXG4gICAgICAqNi45LTI4KlxuICAgICgxNClgXCJdXVxuICAgIDEyW1wiYCM5MTtSU3ltYm9sIzkzOyBkYXRhXG4gICAgICAoMTIpXG4gICAgICAqNi4xLTQqYFwiXVxuICAgIDE3W1tcImAjOTE7UkJpbmFyeU9wIzkzOyAjNjA7IzQ1O1xuICAgICAgKDE3KVxuICAgICAgKjYuMS0yOCpcbiAgICAoMTIsIDE2KWBcIl1dXG4gICAgYnVpbHQtaW46Xy1bXCJgQnVpbHQtSW46XG4jNjA7IzQ1O2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpfLSBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgMjB7e1wiYCM5MTtSU3RyaW5nIzkzOyAjMzk7ZGF0YTIuY3N2IzM5O1xuICAgICAgKDIwKVxuICAgICAgKjcuMTktMjkqYFwifX1cbiAgICAyMltbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHJlYWQjOTU7Y3N2XG4gICAgICAoMjIpXG4gICAgICAqNy4xMC0zMCpcbiAgICAoMjApYFwiXV1cbiAgICAxOFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICgxOClcbiAgICAgICo3LjEtNSpgXCJdXG4gICAgMjNbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMjMpXG4gICAgICAqNy4xLTMwKlxuICAgICgxOCwgMjIpYFwiXV1cbiAgICAyNihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgyNilcbiAgICAgICo5LjExLTE0KmBcIl0pXG4gICAgMjd7e1wiYCM5MTtSU3ltYm9sIzkzOyB4XG4gICAgICAoMjcpXG4gICAgICAqOS4xMS0xNipgXCJ9fVxuICAgIDI5W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDI5KVxuICAgICAgKjkuMTEtMTYqXG4gICAgKDI2LCAyNylgXCJdXVxuICAgIGJ1aWx0LWluOl9bXCJgQnVpbHQtSW46XG4kYFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOl8gc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDMxW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDMxKVxuICAgICAgKjkuNi0xNypcbiAgICAoMjkpYFwiXV1cbiAgICBidWlsdC1pbjptZWFuW1wiYEJ1aWx0LUluOlxubWVhbmBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjptZWFuIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAyNFtcImAjOTE7UlN5bWJvbCM5MzsgbVxuICAgICAgKDI0KVxuICAgICAgKjkuMSpgXCJdXG4gICAgMzJbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM2MDsjNDU7XG4gICAgICAoMzIpXG4gICAgICAqOS4xLTE3KlxuICAgICgyNCwgMzEpYFwiXV1cbiAgICAzNChbXCJgIzkxO1JTeW1ib2wjOTM7IG1cbiAgICAgICgzNClcbiAgICAgICoxMC43KmBcIl0pXG4gICAgMzZbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDM2KVxuICAgICAgKjEwLjEtOCpcbiAgICAoMzQpYFwiXV1cbiAgICBidWlsdC1pbjpwcmludFtcImBCdWlsdC1JbjpcbnByaW50YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOnByaW50IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICAzOChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGFcbiAgICAgICgzOClcbiAgICAgICoxMi4xLTQqYFwiXSlcbiAgICA0MyhbXCJgIzkxO1JTeW1ib2wjOTM7IHhcbiAgICAgICg0MylcbiAgICAgICoxMy4yNCpgXCJdKVxuICAgIDQ0KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB4XG4gICAgICAoNDQpXG4gICAgICAqMTMuMjAqYFwiXSlcbiAgICA0NihbXCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg0NilcbiAgICAgICoxMy4zMSpgXCJdKVxuICAgIDQ3KFtcImAjOTE7UkFyZ3VtZW50IzkzOyB5XG4gICAgICAoNDcpXG4gICAgICAqMTMuMjcqYFwiXSlcbiAgICA0OFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGFlc1xuICAgICAgKDQ4KVxuICAgICAgKjEzLjE2LTMyKlxuICAgICh4ICg0NCksIHkgKDQ3KSlgXCJdXVxuICAgIDUwW1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgZ2dwbG90XG4gICAgICAoNTApXG4gICAgICAqMTMuOS0zMypcbiAgICAoMzgsIDQ4KWBcIl1dXG4gICAgYnVpbHQtaW46Z2dwbG90W1wiYEJ1aWx0LUluOlxuZ2dwbG90YFwiXVxuICAgIHN0eWxlIGJ1aWx0LWluOmdncGxvdCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTJbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBkYXRhICUjNjI7JVxuXHRnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpXG4gICAgICAoNTIpXG4gICAgICAqMTIuNi04KlxuICAgICgzOCwgNTApYFwiXV1cbiAgICBidWlsdC1pbjpfX19bXCJgQnVpbHQtSW46XG4lIzYyOyVgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46X19fIHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA1NFtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IGdlb20jOTU7cG9pbnRcbiAgICAgICg1NClcbiAgICAgICoxNC45LTIwKmBcIl1dXG4gICAgYnVpbHQtaW46Z2VvbV9wb2ludFtcImBCdWlsdC1Jbjpcbmdlb20jOTU7cG9pbnRgXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46Z2VvbV9wb2ludCBzdHJva2U6Z3JheSxmaWxsOmxpZ2h0Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgNTVbW1wiYCM5MTtSQmluYXJ5T3AjOTM7ICM0MztcbiAgICAgICg1NSlcbiAgICAgICoxMi4xLTE0LjIwKlxuICAgICg1MiwgNTQpYFwiXV1cbiAgICA1NyhbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNTcpXG4gICAgICAqMTYuNi0xMCpgXCJdKVxuICAgIDU4e3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDU4KVxuICAgICAgKjE2LjYtMTIqYFwifX1cbiAgICA2MFtbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg2MClcbiAgICAgICoxNi42LTEyKlxuICAgICg1NywgNTgpYFwiXV1cbiAgICA2MihbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjIpXG4gICAgICAqMTYuMTUtMTkqYFwiXSlcbiAgICA2M3t7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg2MylcbiAgICAgICoxNi4xNS0yMSpgXCJ9fVxuICAgIDY1W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDY1KVxuICAgICAgKjE2LjE1LTIxKlxuICAgICg2MiwgNjMpYFwiXV1cbiAgICA2N1tbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBsb3RcbiAgICAgICg2NylcbiAgICAgICoxNi4xLTIyKlxuICAgICg2MCwgNjUpYFwiXV1cbiAgICBidWlsdC1pbjpwbG90W1wiYEJ1aWx0LUluOlxucGxvdGBcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwbG90IHN0cm9rZTpncmF5LGZpbGw6bGlnaHRncmF5LHN0cm9rZS13aWR0aDoycHgsb3BhY2l0eTouODtcbiAgICA2OShbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNjkpXG4gICAgICAqMTcuOC0xMipgXCJdKVxuICAgIDcwe3tcImAjOTE7UlN5bWJvbCM5MzsgeFxuICAgICAgKDcwKVxuICAgICAgKjE3LjgtMTQqYFwifX1cbiAgICA3MltbXCJgIzkxO1JBY2Nlc3MjOTM7ICRcbiAgICAgICg3MilcbiAgICAgICoxNy44LTE0KlxuICAgICg2OSwgNzApYFwiXV1cbiAgICA3NChbXCJgIzkxO1JTeW1ib2wjOTM7IGRhdGEyXG4gICAgICAoNzQpXG4gICAgICAqMTcuMTctMjEqYFwiXSlcbiAgICA3NXt7XCJgIzkxO1JTeW1ib2wjOTM7IHlcbiAgICAgICg3NSlcbiAgICAgICoxNy4xNy0yMypgXCJ9fVxuICAgIDc3W1tcImAjOTE7UkFjY2VzcyM5MzsgJFxuICAgICAgKDc3KVxuICAgICAgKjE3LjE3LTIzKlxuICAgICg3NCwgNzUpYFwiXV1cbiAgICA3OVtbXCJgIzkxO1JGdW5jdGlvbkNhbGwjOTM7IHBvaW50c1xuICAgICAgKDc5KVxuICAgICAgKjE3LjEtMjQqXG4gICAgKDcyLCA3NylgXCJdXVxuICAgIGJ1aWx0LWluOnBvaW50c1tcImBCdWlsdC1JbjpcbnBvaW50c2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpwb2ludHMgc3Ryb2tlOmdyYXksZmlsbDpsaWdodGdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDgyKFtcImAjOTE7UlN5bWJvbCM5MzsgZGF0YTJcbiAgICAgICg4MilcbiAgICAgICoxOS4xMi0xNipgXCJdKVxuICAgIDgze3tcImAjOTE7UlN5bWJvbCM5Mzsga1xuICAgICAgKDgzKVxuICAgICAgKjE5LjEyLTE4KmBcIn19XG4gICAgODVbW1wiYCM5MTtSQWNjZXNzIzkzOyAkXG4gICAgICAoODUpXG4gICAgICAqMTkuMTItMTgqXG4gICAgKDgyLCA4MylgXCJdXVxuICAgIDg3W1tcImAjOTE7UkZ1bmN0aW9uQ2FsbCM5MzsgbWVhblxuICAgICAgKDg3KVxuICAgICAgKjE5LjctMTkqXG4gICAgKDg1KWBcIl1dXG4gICAgODlbW1wiYCM5MTtSRnVuY3Rpb25DYWxsIzkzOyBwcmludFxuICAgICAgKDg5KVxuICAgICAgKjE5LjEtMjAqXG4gICAgKDg3KWBcIl1dXG4gICAgMyAtLT58XCJhcmd1bWVudFwifCAxXG4gICAgMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgMSBzdHJva2U6Z3JheTtcbiAgICA3IC0tPnxcImFyZ3VtZW50XCJ8IDVcbiAgICA3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bGlicmFyeVxuICAgIGxpbmtTdHlsZSAzIHN0cm9rZTpncmF5O1xuICAgIDExIC0tPnxcImFyZ3VtZW50XCJ8IDlcbiAgICAxMSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmxpYnJhcnlcbiAgICBsaW5rU3R5bGUgNSBzdHJva2U6Z3JheTtcbiAgICAxNiAtLT58XCJhcmd1bWVudFwifCAxNFxuICAgIDEyIC0tPnxcImRlZmluZWQtYnlcInwgMTZcbiAgICAxMiAtLT58XCJkZWZpbmVkLWJ5XCJ8IDE3XG4gICAgMTcgLS0+fFwiYXJndW1lbnRcInwgMTZcbiAgICAxNyAtLT58XCJyZXR1cm5zLCBhcmd1bWVudFwifCAxMlxuICAgIDE3IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Xy1cbiAgICBsaW5rU3R5bGUgMTEgc3Ryb2tlOmdyYXk7XG4gICAgMjIgLS0+fFwiYXJndW1lbnRcInwgMjBcbiAgICAxOCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDIyXG4gICAgMTggLS0+fFwiZGVmaW5lZC1ieVwifCAyM1xuICAgIDIzIC0tPnxcImFyZ3VtZW50XCJ8IDIyXG4gICAgMjMgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMThcbiAgICAyMyAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDE3IHN0cm9rZTpncmF5O1xuICAgIDI2IC0tPnxcInJlYWRzXCJ8IDEyXG4gICAgMjkgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDI2XG4gICAgMjkgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDI3XG4gICAgMjkgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDIxIHN0cm9rZTpncmF5O1xuICAgIDMxIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAyOVxuICAgIDMxIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46bWVhblxuICAgIGxpbmtTdHlsZSAyMyBzdHJva2U6Z3JheTtcbiAgICAyNCAtLT58XCJkZWZpbmVkLWJ5XCJ8IDMxXG4gICAgMjQgLS0+fFwiZGVmaW5lZC1ieVwifCAzMlxuICAgIDMyIC0tPnxcImFyZ3VtZW50XCJ8IDMxXG4gICAgMzIgLS0+fFwicmV0dXJucywgYXJndW1lbnRcInwgMjRcbiAgICAzMiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl8tXG4gICAgbGlua1N0eWxlIDI4IHN0cm9rZTpncmF5O1xuICAgIDM0IC0tPnxcInJlYWRzXCJ8IDI0XG4gICAgMzYgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDM0XG4gICAgMzYgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwcmludFxuICAgIGxpbmtTdHlsZSAzMSBzdHJva2U6Z3JheTtcbiAgICAzOCAtLT58XCJyZWFkc1wifCAxMlxuICAgIDQ0IC0tPnxcInJlYWRzXCJ8IDQzXG4gICAgNDcgLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJyZWFkc1wifCA0M1xuICAgIDQ4IC0tPnxcImFyZ3VtZW50XCJ8IDQ0XG4gICAgNDggLS0+fFwicmVhZHNcInwgNDZcbiAgICA0OCAtLT58XCJhcmd1bWVudFwifCA0N1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA0OFxuICAgIDUwIC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46Z2dwbG90XG4gICAgbGlua1N0eWxlIDQwIHN0cm9rZTpncmF5O1xuICAgIDUwIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAzOFxuICAgIDUyIC0tPnxcImFyZ3VtZW50XCJ8IDM4XG4gICAgNTIgLS0+fFwiYXJndW1lbnRcInwgNTBcbiAgICA1MiAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9fX1xuICAgIGxpbmtTdHlsZSA0NCBzdHJva2U6Z3JheTtcbiAgICA1NCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOmdlb21fcG9pbnRcbiAgICBsaW5rU3R5bGUgNDUgc3Ryb2tlOmdyYXk7XG4gICAgNTQgLS0+fFwicmVhZHNcInwgNTBcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTJcbiAgICA1NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNTRcbiAgICA1NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNDkgc3Ryb2tlOmdyYXk7XG4gICAgNTcgLS0+fFwicmVhZHNcInwgMThcbiAgICA2MCAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNTdcbiAgICA2MCAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNThcbiAgICA2MCAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTMgc3Ryb2tlOmdyYXk7XG4gICAgNjIgLS0+fFwicmVhZHNcInwgMThcbiAgICA2NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgNjJcbiAgICA2NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgNjNcbiAgICA2NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNTcgc3Ryb2tlOmdyYXk7XG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDYwXG4gICAgNjcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDY1XG4gICAgNjcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpwbG90XG4gICAgbGlua1N0eWxlIDYwIHN0cm9rZTpncmF5O1xuICAgIDY5IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzIgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDY5XG4gICAgNzIgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDcwXG4gICAgNzIgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY0IHN0cm9rZTpncmF5O1xuICAgIDc0IC0tPnxcInJlYWRzXCJ8IDE4XG4gICAgNzcgLS0+fFwicmVhZHMsIHJldHVybnMsIGFyZ3VtZW50XCJ8IDc0XG4gICAgNzcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDc1XG4gICAgNzcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDY4IHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3MlxuICAgIDc5IC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCA3N1xuICAgIDc5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cG9pbnRzXG4gICAgbGlua1N0eWxlIDcxIHN0cm9rZTpncmF5O1xuICAgIDc5IC0tPnxcInJlYWRzXCJ8IDY3XG4gICAgODIgLS0+fFwicmVhZHNcInwgMThcbiAgICA4NSAtLT58XCJyZWFkcywgcmV0dXJucywgYXJndW1lbnRcInwgODJcbiAgICA4NSAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgODNcbiAgICA4NSAtLi0+fFwicmVhZHMsIGNhbGxzXCJ8IGJ1aWx0LWluOl9cbiAgICBsaW5rU3R5bGUgNzYgc3Ryb2tlOmdyYXk7XG4gICAgODcgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDg1XG4gICAgODcgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjptZWFuXG4gICAgbGlua1N0eWxlIDc4IHN0cm9rZTpncmF5O1xuICAgIDg5IC0tPnxcInJlYWRzLCByZXR1cm5zLCBhcmd1bWVudFwifCA4N1xuICAgIDg5IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46cHJpbnRcbiAgICBsaW5rU3R5bGUgODAgc3Ryb2tlOmdyYXk7IiwibWVybWFpZCI6eyJhdXRvU3luYyI6dHJ1ZX19))\ -_All queries together required ≈1 ms (1ms accuracy, total 6 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 4 ms)_
Show Detailed Results as Json -The analysis required _6.3 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _3.7 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -2793,7 +2804,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "dataflow-cluster": { ".meta": { - "timing": 1 + "timing": 0 }, "clusters": [ { @@ -2880,7 +2891,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte ] }, ".meta": { - "timing": 1 + "timing": 0 } } ``` @@ -2937,7 +2948,7 @@ _All queries together required ≈0 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _1.3 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _0.9 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -2967,7 +2978,7 @@ x + 1 Dataflow Graph of the R Code -The analysis required _1.2 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +The analysis required _0.7 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We encountered no unknown side effects during the analysis. @@ -3040,15 +3051,15 @@ This query infers all shapes of dataframes within the code. For example, you can _Results (prettified and summarized):_ -Query: **df-shape** (3 ms)\ +Query: **df-shape** (2 ms)\    ╰ 7: {"colnames":["a"],"cols":[1,1],"rows":[3,3]}\    ╰ 0: {"colnames":["a"],"cols":[1,1],"rows":[3,3]}\    ╰ 14: {"colnames":["a"],"cols":[1,1],"rows":[0,0]}\ -_All queries together required ≈4 ms (1ms accuracy, total 5 ms)_ +_All queries together required ≈2 ms (1ms accuracy, total 3 ms)_
Show Detailed Results as Json -The analysis required _5.3 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _3.2 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -3060,7 +3071,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "df-shape": { ".meta": { - "timing": 3 + "timing": 2 }, "domains": [ [ @@ -3114,7 +3125,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte ] }, ".meta": { - "timing": 4 + "timing": 2 } } ``` @@ -3138,7 +3149,7 @@ filter(x, FALSE) Dataflow Graph of the R Code -The analysis required _1.9 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +The analysis required _1.2 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We encountered no unknown side effects during the analysis. @@ -3261,15 +3272,15 @@ In other words, if you have a script simply reading: `library(x)`, the following _Results (prettified and summarized):_ -Query: **dependencies** (6 ms)\ +Query: **dependencies** (4 ms)\    ╰ Libraries\        ╰ `library`\            ╰ Node Id: 3, `x`\ -_All queries together required ≈7 ms (1ms accuracy, total 7 ms)_ +_All queries together required ≈4 ms (1ms accuracy, total 5 ms)_
Show Detailed Results as Json -The analysis required _7.5 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _4.8 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -3281,7 +3292,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "dependencies": { ".meta": { - "timing": 6 + "timing": 4 }, "library": [ { @@ -3296,7 +3307,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte "visualize": [] }, ".meta": { - "timing": 7 + "timing": 4 } } ``` @@ -3344,7 +3355,7 @@ The following query returns the dependencies of the script. _Results (prettified and summarized):_ -Query: **dependencies** (8 ms)\ +Query: **dependencies** (4 ms)\    ╰ Libraries\        ╰ `loadNamespace`\            ╰ Node Id: 8, `bar`\ @@ -3366,11 +3377,11 @@ Query: **dependencies** (8 ms)\            ╰ Node Id: 28\        ╰ `geom_point`\            ╰ Node Id: 30\ -_All queries together required ≈8 ms (1ms accuracy, total 13 ms)_ +_All queries together required ≈4 ms (1ms accuracy, total 7 ms)_
Show Detailed Results as Json -The analysis required _12.6 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _7.3 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -3382,7 +3393,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "dependencies": { ".meta": { - "timing": 8 + "timing": 4 }, "library": [ { @@ -3437,7 +3448,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte ] }, ".meta": { - "timing": 8 + "timing": 4 } } ``` @@ -3494,11 +3505,11 @@ Query: **dependencies** (0 ms)\    ╰ Libraries\        ╰ `print`\            ╰ Node Id: 41, `hello world!`\ -_All queries together required ≈0 ms (1ms accuracy, total 4 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 3 ms)_
Show Detailed Results as Json -The analysis required _4.1 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _2.6 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -3592,13 +3603,13 @@ the following query returns that the first assignment happens always before the _Results (prettified and summarized):_ -Query: **happens-before** (1 ms)\ +Query: **happens-before** (0 ms)\    ╰ 1@x<2@y: always\ -_All queries together required ≈1 ms (1ms accuracy, total 2 ms)_ +_All queries together required ≈1 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _2.2 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.4 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -3610,7 +3621,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "happens-before": { ".meta": { - "timing": 1 + "timing": 0 }, "results": { "1@x<2@y": "always" @@ -3641,7 +3652,7 @@ y <- 2 Dataflow Graph of the R Code -The analysis required _1.5 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +The analysis required _1.0 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We encountered no unknown side effects during the analysis. @@ -3740,7 +3751,7 @@ _All queries together required ≈0 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _1.2 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _0.8 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -3770,7 +3781,7 @@ x + 1 Dataflow Graph of the R Code -The analysis required _1.2 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +The analysis required _0.8 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We encountered no unknown side effects during the analysis. @@ -3825,6 +3836,172 @@ Responsible for the execution of the Id-Map Query query is `executeIdMapQuery` i ----- +### Inspect Higher-Order Functions Query + + +With this query you can identify which functions in the code are higher-order functions, i.e., either take a function as an argument or return a function. +Please note, that functions that are just identities (e.g., `function(x) x`) are not considered higher-order if they do not take a function as an argument. + +Using the example code `f <- function() function(x) x; f()` the following query returns the information for all identified function definitions whether they are higher-order functions: + + + +```json +[ + { + "type": "inspect-higher-order" + } +] +``` + + +(This query can be shortened to `@inspect-higher-order` when used within the REPL command `:query`). + + + +_Results (prettified and summarized):_ + +Query: **inspect-higher-order** (0ms)\ +  - Function **5** (1.17-24) is not a higher-order function\ +  - Function **7** (1.6-13) is a higher-order function\ +_All queries together required ≈0 ms (1ms accuracy, total 2 ms)_ + +
Show Detailed Results as Json + +The analysis required _2.3 ms_ (including parsing and normalization and the query) within the generation environment. + +In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. +Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. + + + + +```json +{ + "inspect-higher-order": { + ".meta": { + "timing": 0 + }, + "higherOrder": { + "5": false, + "7": true + } + }, + ".meta": { + "timing": 0 + } +} +``` + + + +
+ + +
Original Code + + + + +```r +f <- function() function(x) x; f() +``` + +
+ +Dataflow Graph of the R Code + +The analysis required _1.3 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +We encountered no unknown side effects during the analysis. + + + +```mermaid +flowchart LR + 7["`#91;RFunctionDefinition#93; function + (7) + *1.6-29*`"] + +subgraph "flow-7" [function 7] + %% Environment of 5 [level: 1]: + %% Built-in + %% 751---------------------------------------- + %% 752---------------------------------------- + 5["`#91;RFunctionDefinition#93; function + (5) + *1.17-29*`"] + +subgraph "flow-5" [function 5] + 1["`#91;RSymbol#93; x + (1) + *1.26*`"] + 3(["`#91;RSymbol#93; x + (3) + *1.29*`"]) +end +end + 0["`#91;RSymbol#93; f + (0) + *1.1*`"] + 8[["`#91;RBinaryOp#93; #60;#45; + (8) + *1.1-29* + (0, 7)`"]] + built-in:_-["`Built-In: +#60;#45;`"] + style built-in:_- stroke:gray,fill:lightgray,stroke-width:2px,opacity:.8; + %% Environment of 10 [level: 0]: + %% Built-in + %% 763---------------------------------------- + %% f: {**f** (id: 0, type: Function, def. @8)} + 10[["`#91;RFunctionCall#93; f + (10) + *1.32-34*`"]] + 3 -->|"reads"| 1 +5 -.-|function| flow-5 + +7 -.-|function| flow-7 + + 0 -->|"defined-by"| 7 + 0 -->|"defined-by"| 8 + 8 -->|"argument"| 7 + 8 -->|"returns, argument"| 0 + 8 -.->|"reads, calls"| built-in:_- + linkStyle 7 stroke:gray; + 10 -->|"reads"| 0 + 10 -->|"returns"| 5 + 10 -->|"calls"| 7 +``` + + + + +
+ + + +
+ + + + + + + + + +
+ +Implementation Details + +Responsible for the execution of the Inspect Higher-Order Functions Query query is `executeHigherOrderQuery` in [`./src/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.ts`](https://github.com/flowr-analysis/flowr/tree/main/./src/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.ts). + +
+ + +----- + + ### Lineage Query @@ -3862,11 +4039,11 @@ _Results (prettified and summarized):_ Query: **lineage** (0 ms)\    ╰ 2@x: {3, 0, 1, 2, built-in:<-, }\ -_All queries together required ≈0 ms (1ms accuracy, total 2 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _1.6 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.2 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -3948,32 +4125,32 @@ In other words, if you have a script simply reading: `read.csv("i_do_not_exist.c _Results (prettified and summarized):_ -Query: **linter** (7 ms)\ +Query: **linter** (4 ms)\    ╰ **Deprecated Functions** (deprecated-functions):\        ╰ _Metadata_: {"totalDeprecatedCalls":0,"totalDeprecatedFunctionDefinitions":0,"searchTimeMs":1,"processTimeMs":0}\    ╰ **File Path Validity** (file-path-validity):\        ╰ certain:\            ╰ Path `i_do_not_exist.csv` at 1.1-30\ -       ╰ _Metadata_: {"totalReads":1,"totalUnknown":0,"totalWritesBeforeAlways":0,"totalValid":0,"searchTimeMs":1,"processTimeMs":0}\ +       ╰ _Metadata_: {"totalReads":1,"totalUnknown":0,"totalWritesBeforeAlways":0,"totalValid":0,"searchTimeMs":0,"processTimeMs":0}\    ╰ **Seeded Randomness** (seeded-randomness):\        ╰ _Metadata_: {"consumerCalls":0,"callsWithFunctionProducers":0,"callsWithAssignmentProducers":0,"callsWithNonConstantProducers":0,"searchTimeMs":1,"processTimeMs":0}\    ╰ **Absolute Paths** (absolute-file-paths):\ -       ╰ _Metadata_: {"totalConsidered":1,"totalUnknown":0,"searchTimeMs":1,"processTimeMs":0}\ +       ╰ _Metadata_: {"totalConsidered":1,"totalUnknown":0,"searchTimeMs":0,"processTimeMs":0}\    ╰ **Unused Definitions** (unused-definitions):\ -       ╰ _Metadata_: {"totalConsidered":0,"searchTimeMs":0,"processTimeMs":0}\ +       ╰ _Metadata_: {"totalConsidered":0,"searchTimeMs":0,"processTimeMs":1}\    ╰ **Naming Convention** (naming-convention):\        ╰ _Metadata_: {"numMatches":0,"numBreak":0,"searchTimeMs":0,"processTimeMs":0}\    ╰ **Dataframe Access Validation** (dataframe-access-validation):\ -       ╰ _Metadata_: {"numOperations":0,"numAccesses":0,"totalAccessed":0,"searchTimeMs":0,"processTimeMs":1}\ +       ╰ _Metadata_: {"numOperations":0,"numAccesses":0,"totalAccessed":0,"searchTimeMs":0,"processTimeMs":0}\    ╰ **Dead Code** (dead-code):\ -       ╰ _Metadata_: {"consideredNodes":5,"searchTimeMs":0,"processTimeMs":1}\ +       ╰ _Metadata_: {"consideredNodes":5,"searchTimeMs":0,"processTimeMs":0}\    ╰ **Useless Loops** (useless-loop):\        ╰ _Metadata_: {"numOfUselessLoops":0,"searchTimeMs":0,"processTimeMs":0}\ -_All queries together required ≈7 ms (1ms accuracy, total 8 ms)_ +_All queries together required ≈5 ms (1ms accuracy, total 5 ms)_
Show Detailed Results as Json -The analysis required _7.7 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _5.1 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -4012,7 +4189,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte "totalUnknown": 0, "totalWritesBeforeAlways": 0, "totalValid": 0, - "searchTimeMs": 1, + "searchTimeMs": 0, "processTimeMs": 0 } }, @@ -4032,7 +4209,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte ".meta": { "totalConsidered": 1, "totalUnknown": 0, - "searchTimeMs": 1, + "searchTimeMs": 0, "processTimeMs": 0 } }, @@ -4041,7 +4218,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte ".meta": { "totalConsidered": 0, "searchTimeMs": 0, - "processTimeMs": 0 + "processTimeMs": 1 } }, "naming-convention": { @@ -4060,7 +4237,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte "numAccesses": 0, "totalAccessed": 0, "searchTimeMs": 0, - "processTimeMs": 1 + "processTimeMs": 0 } }, "dead-code": { @@ -4068,7 +4245,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte ".meta": { "consideredNodes": 5, "searchTimeMs": 0, - "processTimeMs": 1 + "processTimeMs": 0 } }, "useless-loop": { @@ -4081,11 +4258,11 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte } }, ".meta": { - "timing": 7 + "timing": 4 } }, ".meta": { - "timing": 7 + "timing": 5 } } ``` @@ -4153,11 +4330,11 @@ Query: **location-map** (0 ms)\    ╰ File List:\       ╰ 0: ``\    ╰ Id List: {0, 1, 2, 3, 4, 5, 2-arg, ... (see JSON)}\ -_All queries together required ≈0 ms (1ms accuracy, total 3 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 4 ms)_
Show Detailed Results as Json -The analysis required _2.5 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _4.2 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -4378,7 +4555,7 @@ x + 1 Dataflow Graph of the R Code -The analysis required _1.4 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +The analysis required _1.2 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We encountered no unknown side effects during the analysis. @@ -4460,14 +4637,14 @@ print(x)` (with the `print(x)` in the second line), the following query returns _Results (prettified and summarized):_ -Query: **origin** (0 ms)\ +Query: **origin** (1 ms)\    ╰ Origins for {2@x}\     ╰ {"type":0,"id":0}\ -_All queries together required ≈0 ms (1ms accuracy, total 5 ms)_ +_All queries together required ≈1 ms (1ms accuracy, total 2 ms)_
Show Detailed Results as Json -The analysis required _4.7 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.7 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -4479,7 +4656,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "origin": { ".meta": { - "timing": 0 + "timing": 1 }, "results": { "2@x": [ @@ -4491,7 +4668,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte } }, ".meta": { - "timing": 0 + "timing": 1 } } ``` @@ -4515,7 +4692,7 @@ print(x) Dataflow Graph of the R Code -The analysis required _1.7 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +The analysis required _1.4 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We encountered unknown side effects (with ids: 6 (linked)) during the analysis. @@ -4613,7 +4790,7 @@ _All queries together required ≈0 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _1.4 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.2 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -4655,7 +4832,7 @@ x + 1 Dataflow Graph of the R Code -The analysis required _1.2 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +The analysis required _2.8 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We encountered no unknown side effects during the analysis. @@ -4746,7 +4923,7 @@ _All queries together required ≈1 ms (1ms accuracy, total 3 ms)_
Show Detailed Results as Json -The analysis required _3.3 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _2.9 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -4818,7 +4995,7 @@ print(x) Dataflow Graph of the R Code -The analysis required _3.4 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +The analysis required _1.3 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We encountered unknown side effects (with ids: 6 (linked)) during the analysis. @@ -4933,13 +5110,13 @@ Using the example code `x + 1`, the following query returns all uses of 'x' in t _Results (prettified and summarized):_ -Query: **search** (0 ms)\ +Query: **search** (1 ms)\    ╰ [query](https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4wKFwiPGI+Z2V0PC9iPihmaWx0ZXI6ICMxMjM7IzM0O25hbWUjMzQ7IzU4OyMzNDt4IzM0OyMxMjU7KTxici8+X2dlbmVyYXRvcl9cIikgLS0+IDFbXCI8Yj5maWx0ZXI8L2I+KGZpbHRlcjogIzM0O3VzZSMzNDspPGJyLz5fdHJhbnNmb3JtZXJfXCJdIiwibWVybWFpZCI6eyJhdXRvU3luYyI6dHJ1ZX19): {0}\ -_All queries together required ≈0 ms (1ms accuracy, total 2 ms)_ +_All queries together required ≈1 ms (1ms accuracy, total 1 ms)_
Show Detailed Results as Json -The analysis required _1.5 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.2 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -4951,7 +5128,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte { "search": { ".meta": { - "timing": 0 + "timing": 1 }, "results": [ { @@ -4982,7 +5159,7 @@ Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Inte ] }, ".meta": { - "timing": 0 + "timing": 1 } } ``` @@ -5005,7 +5182,7 @@ x + 1 Dataflow Graph of the R Code -The analysis required _1.2 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. +The analysis required _1.4 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment. We encountered no unknown side effects during the analysis. @@ -5106,7 +5283,7 @@ _All queries together required ≈1 ms (1ms accuracy, total 3 ms)_
Show Detailed Results as Json -The analysis required _3.3 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _2.6 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -5204,7 +5381,7 @@ _All queries together required ≈1 ms (1ms accuracy, total 2 ms)_
Show Detailed Results as Json -The analysis required _2.2 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.7 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -5294,7 +5471,7 @@ _All queries together required ≈1 ms (1ms accuracy, total 2 ms)_
Show Detailed Results as Json -The analysis required _2.1 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _1.8 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -5417,11 +5594,11 @@ _Results (prettified and summarized):_ Query: **call-context** (0 ms)\    ╰ **visualize**\      ╰ **text**: _`mean`_ (L.9), _`print`_ (L.10), _`mean`_ (L.19), _`print`_ (L.19)\ -_All queries together required ≈0 ms (1ms accuracy, total 6 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 5 ms)_
Show Detailed Results as Json -The analysis required _6.1 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _4.7 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -5504,11 +5681,11 @@ _Results (prettified and summarized):_ Query: **call-context** (0 ms)\    ╰ **visualize**\      ╰ **text**: _`mean`_ (L.9), _`print`_ (L.10), _`mean`_ (L.19), _`print`_ (L.19)\ -_All queries together required ≈0 ms (1ms accuracy, total 6 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 5 ms)_
Show Detailed Results as Json -The analysis required _6.0 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _4.6 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those. @@ -5606,11 +5783,11 @@ _Results (prettified and summarized):_ Query: **call-context** (0 ms)\    ╰ **visualize**\      ╰ **text**: _`mean`_ (L.9) with 1 call (UNKNOWN: built-in (info: undefined)), _`mean`_ (L.19) with 1 call (UNKNOWN: built-in (info: undefined))\ -_All queries together required ≈0 ms (1ms accuracy, total 7 ms)_ +_All queries together required ≈0 ms (1ms accuracy, total 4 ms)_
Show Detailed Results as Json -The analysis required _6.6 ms_ (including parsing and normalization and the query) within the generation environment. +The analysis required _4.2 ms_ (including parsing and normalization and the query) within the generation environment. In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those.