Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add handle recursive expressions #25

Closed
wants to merge 10 commits into from
Closed

Add handle recursive expressions #25

wants to merge 10 commits into from

Conversation

borodichAlex
Copy link

@borodichAlex borodichAlex commented Jul 27, 2022

  • tests and linter show no problems (npm t)
  • tests are added/updated for bug fixes and new features
  • code is properly formatted (npm run fmt)
  • description of changes is added in CHANGELOG.md

Сloses #5

test/unit.js Outdated Show resolved Hide resolved
test/unit.js Outdated Show resolved Hide resolved
test/unit.js Outdated Show resolved Hide resolved
@tshemsedinov
Copy link
Member

We can't throw on a first recursion iteration, because expressions can contain conditions and we can exit recursion. Here is another test case to show exit from recursion. But this implementation throws.

Instead of call chain we can just use try/catch to intercept RangeError: Maximum call stack size exceeded or can use array to hold call stack and count cell name in this array to add limitation for throwing an error after 1000 recursion steps or so. @borodichAlex

@borodichAlex
Copy link
Author

We can't throw on a first recursion iteration, because expressions can contain conditions and we can exit recursion. Here is another test case to show exit from recursion. But this implementation throws.

Instead of call chain we can just use try/catch to intercept RangeError: Maximum call stack size exceeded or can use array to hold call stack and count cell name in this array to add limitation for throwing an error after 1000 recursion steps or so. @borodichAlex

I implemented the second option. Only I used Map instead of Array.
Limit in 1000 steps is very much. 'RangeError: Maximum call stack size exceeded' is throw before than it. Can we will set limit in 100 steps?

test/unit.js Outdated Show resolved Hide resolved
test/unit.js Outdated
const sheet = new Sheet();
sheet.cells['A1'] = 100;
sheet.cells['B1'] = 2;
sheet.cells['C1'] = '= A1 === 100 ? A1 * (A1 = 1, E1) : 5';
Copy link
Author

@borodichAlex borodichAlex Jul 28, 2022

Choose a reason for hiding this comment

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

How does assignment work in this case? A1 = 1
When I run this code, I don't see to change value in A1.

When I run this code, I don't see to change value in A1. But I see new A1 property in end of object.

<ref *1> Sheet {
  data: Map(2) { 'A1' => 100, 'B1' => 2 },
  expressions: Map(3) {
    'C1' => [Function (anonymous)],
    'D1' => [Function (anonymous)],
    'E1' => [Function (anonymous)]
  },
  values: [Circular *1],
  context: [Circular *1],
  cells: [Circular *1],
  callChain: Map(3) { 'E1' => 1, 'D1' => 1, 'C1' => 1 },
  A1: 1
}

@tshemsedinov

Copy link
Author

@borodichAlex borodichAlex Jul 29, 2022

Choose a reason for hiding this comment

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

I'm not sure. But case above is don't work correctly.
So, I added test case which exit from recursive expression but I use Math.random instead of Assigment (A1 = 1) 51f9230

@tshemsedinov

const sheet = new Sheet();
sheet.cells['A1'] = 100;
sheet.cells['B1'] = 2;
sheet.cells['C1'] = '=Math.round(Math.random()) ? A1 * E1 : 5';
Copy link

@blackakula blackakula Jul 30, 2022

Choose a reason for hiding this comment

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

Math.random is not stable for use in unit tests. Of course, it is a low probability, that you will get 100 "one"s results in a row, but still, one of 2^100 test runs may fail with message:

Exit from recursive expression use Math.random ........ 0/1
  not ok fail
    --- wanted                                                                                     
    +++ found                                                                                      
    -[null]                                                                                        
    +{                                                                                             
    +  "message": "Recursive expression error"                                                     
    +  "name": "Error"                                                                             
    +  "stack": "Error: Recursive expression error                                                 

Copy link
Author

Choose a reason for hiding this comment

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

Oh, ok, thanks
I used this test to show 'exit from recursive expression' (only math.random came to mind)
when somebody will say how assignment in expression is work to I fix previous test

Copy link
Member

Choose a reason for hiding this comment

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

We can use F1 as a counter, increment it each C1 cell calculation triggered and exit recursion after certain limit

Copy link
Author

Choose a reason for hiding this comment

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

We can use F1 as a counter, increment it each C1 cell calculation triggered and exit recursion after certain limit

How we can change cell's value? @tshemsedinov
I written about it above

Comment on lines +35 to +37
sheet.cells['C1'] = '= A1 *E1';
sheet.cells['D1'] = '=C1+8';
sheet.cells['E1'] = '=D1/2';
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sheet.cells['C1'] = '= A1 *E1';
sheet.cells['D1'] = '=C1+8';
sheet.cells['E1'] = '=D1/2';
sheet.cells['C1'] = '= A1 * E1';
sheet.cells['D1'] = '= C1 + 8';
sheet.cells['E1'] = '= D1 / 2';

@borodichAlex borodichAlex closed this by deleting the head repository Oct 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants