AndreVanDelft / scala

The SubScript extension to the Scala programming language
http://www.subscript-lang.org/
12 stars 1 forks source link

/ .. doesn't work #21

Closed anatoliykmetyuk closed 9 years ago

anatoliykmetyuk commented 10 years ago

As for now, "/ .." seems not to break activation. Observe the following script in the debugger:

  def script..
    live = process(1) / ..

    process(x: Int) = {println(x)}
anatoliykmetyuk commented 10 years ago

so as for now I'm using "; ..." as a replacement for "/ .." to test the actor example, since "/ .." will just trigger infinite activation

AndreVanDelft commented 10 years ago

I added test cases such as [ a / .. ] to OperatorsSuite; these made the program hang. There was no output showing where the hanging was. Therefore I added a "-v" command line option for verbose output. Running the suite with " | more" we see that the "a" is activated a second time (and more, if we let "more" proceed":

>> 22 Continuation 4 / ... {2 Activation 4 / ..., 26 Deactivation 4 / ..., 25 Break 4 / ..., 4 / ...}  4 / S=false nActivated=2 (=0S+2N)
++ 27 Activation 12 a

So this points to CommonScriptExecutor.handleContinuation()

AndreVanDelft commented 10 years ago

Fixed the issue (and about 5 more failing tests) For this purpose I added var aaActivated = false to N_n_ary_op. This is a bit messy, but a clean up has low priority FTTB.

AndreVanDelft commented 10 years ago

OperatorsSuite was not strict enough. After I improved it, the process a b / .. appeared to be spawning one a too much after an a had been processed from the input stream: the expected tokens were then a,a,b instead of a,b. For the time being this should not be a showstopper IMO; x / .. will in many cases work fine.

anatoliykmetyuk commented 10 years ago
live = {println("x")} {println("y")} / ..

at certain point of time, leftmost node of the graph under "/" has Success and this success is also assigned to the rightmost node that is a "clone" of this node. This may happen due to non-referential comparison of case classes.

case class Foo(x: Int)
val x = Foo(3)
val y = Foo(3)
x == y // true
x eq y // false

Also:

live = {println("x")} / ..

here, after first node has success, "/" by itself has success without any continuation

AndreVanDelft commented 9 years ago

I intend to really solve this issue now; I'll log my actions here so that others may learn how to tackle such problems (or how not to tackle). OperatorsSuite now reports by default all failed tests, except when in silent mode (-s). So:

build/pack/bin/scala subscript.test.OperatorsSuiteApp 
test 330:   a b/..                  after input: a     should expect:   ab - Fails; expects:  aab; already marked as FAIL
test 360:   ./a b                                      should expect:   1a - Fails; expects:    a; already marked as FAIL
test 366:   .|a b                                      should expect:   1a - Fails; expects:    a; already marked as FAIL
test 369:   ./a b/./c d                                should expect:   1a - Fails; expects:   ac; already marked as FAIL
test 564:   (a;{**};b) ...||c ...   after input: a     should expect:   bc - Fails; expects:    c; already marked as FAIL
test 565:   (a;{**};b) ...||c ...   after input: ab    should expect:   ac - Fails; expects:    c; already marked as FAIL

The interesting failed test has index 330. So we can run the test program with this index as a parameter. This gives all call graph messages, and when code fragments are about to be executed, the call graph is shown:

build/pack/bin/scala subscript.test.OperatorsSuiteApp 330
test 330:   a b/..                  after input: a     should expect:   ab
++ 1 Activation  3 <lambda>
-- 1 Activation  3 <lambda>
>> 1 Activation  3 <lambda>
++ 2 Activation  4 /
-- 2 Activation  4 /
>> 2 Activation  4 /
++ 3 Activation  5 ;
++ 4 Continuation  4 / {2 Activation  4 /,  5 ;}  4 / S=false nActivated=1 (=0S+1N)
-- 3 Activation  5 ;
>> 3 Activation  5 ;
++ 5 Activation  6 a
++ 6 Continuation  5 ; {3 Activation  5 ;,  6 a}  5 ; S=false nActivated=1 (=0S+1N)
-- 5 Activation  6 a
>> 5 Activation  6 a
...
>> 13 AAToBeExecuted 11 {??}
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
  *                            4 / S=false nActivated=2 (=0S+2N)
   *                           5 ; S=false nActivated=1 (=0S+1N)
----*------------------------- 6 a
     *                         7 a
      *                        8 atom
       *                       9 atom
        *                     10 @:
---------*--------------------11 {??}
=== Messages ===
=== End ===
++ 30 AAExecutionFinished 11 {??}
...

Such tracing may often be helpful, but the current bug requires that we inspect the call graph at any message handling. For this we supply also the -V flag, for "very verbose":

build/pack/bin/scala subscript.test.OperatorsSuiteApp -V 330
test 330:   a b/..                  after input: a     should expect:   ab
++ 1 Activation  3 <lambda>
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
=== Messages ===
  1     Activation  3 <lambda>
=== End ===
-- 1 Activation  3 <lambda>
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
=== Messages ===
=== End ===
...

This yields a long list. Browse through it to see where the two subtrees with the a scripts have been grown:

++ 112 Activation 33 {??}
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
  *                            4 / S=false nActivated=5 (=0S+5N)
  |*                           5 ; S=false nActivated=2 (=1S+1N)
--|-*-------------------------13 b
  |  *                        14 b
  |   *                       15 atom
  |    *                      16 atom
  |     *                     17 @:
--|------*--------------------18 {??}
  |*                          19 ; S=false nActivated=1 (=0S+1N)
  | *                         20 a
  |  *                        21 a
  |   *                       22 atom
--|----*----------------------23 atom
  |     *                     24 @:
  |      *                    25 {??}
  |*                          27 ; S=false nActivated=1 (=0S+1N)
  | *                         28 a
--|--*------------------------29 a
  |   *                       30 atom
  |    *                      31 atom
  |     *                     32 @:
  |      *                    33 {??}

So this is where things must have already gone wrong. Now we go to the three places where the continuation messages for /... were handled; the first of which that did not lead to a new a branch, whereas the other two did. The handling of continuation messages stand out in the log because of relatively long listings of attribute values. The handling of /... stand out even more since these listings have double size. There is a "finally" part, and an A+...+G part; these listings are created in trait ContinuationHandler. At the end of these loggings there may be a line such as ++ 77 Activation 19 ;, indicating that another node is activated as a result of handling the Continuation message.

>> 25 Continuation  4 / ... {2 Activation  4 / ..., 29 Deactivation  4 / ..., 28 Break  4 / ...,  4 / ...}  4 / S=false nActivated=2 (=0S+2N)
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
  *                            4 / S=false nActivated=2 (=0S+2N)
   *                           5 ; S=false nActivated=1 (=0S+1N)
----*------------------------- 6 a
     *                         7 a
      *                        8 atom
       *                       9 atom
        *                     10 @:
---------*--------------------11 {??}
=== Messages ===
 13 AAToBeExecuted 11 {??}
=== End ===
F:
                           activationMode: Optional
                             hadFullBreak: false
              nActivatedMandatoryChildren: 2
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 2
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: -1
                    indexChild_marksPause: -1
                              aaActivated: true
                     aaActivated_optional: false
Finally:
                           activationMode: Optional
                             hadFullBreak: false
              nActivatedMandatoryChildren: 2
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 2
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: -1
                    indexChild_marksPause: 12
                              aaActivated: true
                     aaActivated_optional: false
                             activateNext: false
                          activationEnded: false
                activationEndedOptionally: false
                            shouldSucceed: false

and

>> 42 Continuation  4 / ... {73 AAActivated  4 / ..., 41 AAHappened  4 / ...,  4 / ...}  4 / S=false nActivated=2 (=0S+2N)
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
  *                            4 / S=false nActivated=2 (=0S+2N)
   *                           5 ; S=false nActivated=2 (=1S+1N)
----*-------------------------13 b
     *                        14 b
      *                       15 atom
       *                      16 atom
        *                     17 @:
---------*--------------------18 {??}
=== Messages ===
 66 AAToBeExecuted 18 {??}
=== End ===
Finally:
                           activationMode: Active
                             hadFullBreak: false
              nActivatedMandatoryChildren: 2
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 2
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: 12
                    indexChild_marksPause: -1
                              aaActivated: true
                     aaActivated_optional: false
                             activateNext: true
                          activationEnded: false
                activationEndedOptionally: false
                            shouldSucceed: false
++ 77 Activation 19 ;

and

>> 78 Continuation  4 / ... {-1 Activation  4 / ..., 94 AAActivated  4 / ...,  4 / ...}  4 / S=false nActivated=3 (=0S+3N)
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
  *                            4 / S=false nActivated=3 (=0S+3N)
  |*                           5 ; S=false nActivated=2 (=1S+1N)
--|-*-------------------------13 b
  |  *                        14 b
  |   *                       15 atom
  |    *                      16 atom
  |     *                     17 @:
--|------*--------------------18 {??}
  |*                          19 ; S=false nActivated=1 (=0S+1N)
  | *                         20 a
  |  *                        21 a
  |   *                       22 atom
--|----*----------------------23 atom
  |     *                     24 @:
  |      *                    25 {??}
=== Messages ===
 66 AAToBeExecuted 18 {??}
 87 AAToBeExecuted 25 {??}
=== End ===
C:
                           activationMode: Active
                             hadFullBreak: false
              nActivatedMandatoryChildren: 3
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 3
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: 12
                    indexChild_marksPause: -1
                              aaActivated: true
                     aaActivated_optional: true
Finally:
                           activationMode: Active
                             hadFullBreak: false
              nActivatedMandatoryChildren: 3
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 3
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: 12
                    indexChild_marksPause: -1
                              aaActivated: true
                     aaActivated_optional: true
                             activateNext: true
                          activationEnded: false
                activationEndedOptionally: false
                            shouldSucceed: false
++ 98 Activation 26 ..

and

>> 99 Continuation  4 / ... {-1 Activation  4 / ..., 103 Deactivation  4 / ..., 102 Break  4 / ...,  4 / ...}  4 / S=false nActivated=4 (=0S+4N)
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
  *                            4 / S=false nActivated=4 (=0S+4N)
  |*                           5 ; S=false nActivated=2 (=1S+1N)
--|-*-------------------------13 b
  |  *                        14 b
  |   *                       15 atom
  |    *                      16 atom
  |     *                     17 @:
--|------*--------------------18 {??}
  |*                          19 ; S=false nActivated=1 (=0S+1N)
  | *                         20 a
  |  *                        21 a
  |   *                       22 atom
--|----*----------------------23 atom
  |     *                     24 @:
  |      *                    25 {??}
=== Messages ===
 66 AAToBeExecuted 18 {??}
 87 AAToBeExecuted 25 {??}
=== End ===
E:
                           activationMode: Optional
                             hadFullBreak: false
              nActivatedMandatoryChildren: 4
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 4
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: 12
                    indexChild_marksPause: -1
                              aaActivated: true
                     aaActivated_optional: true
Finally:
                           activationMode: Active
                             hadFullBreak: false
              nActivatedMandatoryChildren: 4
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 4
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: -1
                    indexChild_marksPause: -1
                              aaActivated: true
                     aaActivated_optional: false
                             activateNext: true
                          activationEnded: false
                activationEndedOptionally: false
                            shouldSucceed: false
++ 104 Activation 27 ;

and

>> 105 Continuation  4 / ... {-1 Activation  4 / ..., 121 AAActivated  4 / ...,  4 / ...}  4 / S=false nActivated=5 (=0S+5N)
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
  *                            4 / S=false nActivated=5 (=0S+5N)
  |*                           5 ; S=false nActivated=2 (=1S+1N)
--|-*-------------------------13 b
  |  *                        14 b
  |   *                       15 atom
  |    *                      16 atom
  |     *                     17 @:
--|------*--------------------18 {??}
  |*                          19 ; S=false nActivated=1 (=0S+1N)
  | *                         20 a
  |  *                        21 a
  |   *                       22 atom
--|----*----------------------23 atom
  |     *                     24 @:
  |      *                    25 {??}
  |*                          27 ; S=false nActivated=1 (=0S+1N)
  | *                         28 a
--|--*------------------------29 a
  |   *                       30 atom
  |    *                      31 atom
  |     *                     32 @:
  |      *                    33 {??}
=== Messages ===
 66 AAToBeExecuted 18 {??}
 87 AAToBeExecuted 25 {??}
114 AAToBeExecuted 33 {??}
=== End ===
C:
                           activationMode: Active
                             hadFullBreak: false
              nActivatedMandatoryChildren: 5
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 5
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: -1
                    indexChild_marksPause: -1
                              aaActivated: true
                     aaActivated_optional: false
Finally:
                           activationMode: Active
                             hadFullBreak: false
              nActivatedMandatoryChildren: 5
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 5
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: -1
                    indexChild_marksPause: -1
                              aaActivated: true
                     aaActivated_optional: false
                             activateNext: true
                          activationEnded: false
                activationEndedOptionally: false
                            shouldSucceed: false
++ 125 Activation 34 ..

and

>> 126 Continuation  4 / ... {-1 Activation  4 / ..., 130 Deactivation  4 / ..., 129 Break  4 / ...,  4 / ...}  4 / S=false nActivated=6 (=0S+6N)
------------------------------ 1 ** S=false nActivated=1 (=0S+1N)
*                              2 <root>
 *                             3 <lambda>
  *                            4 / S=false nActivated=6 (=0S+6N)
  |*                           5 ; S=false nActivated=2 (=1S+1N)
--|-*-------------------------13 b
  |  *                        14 b
  |   *                       15 atom
  |    *                      16 atom
  |     *                     17 @:
--|------*--------------------18 {??}
  |*                          19 ; S=false nActivated=1 (=0S+1N)
  | *                         20 a
  |  *                        21 a
  |   *                       22 atom
--|----*----------------------23 atom
  |     *                     24 @:
  |      *                    25 {??}
  |*                          27 ; S=false nActivated=1 (=0S+1N)
  | *                         28 a
--|--*------------------------29 a
  |   *                       30 atom
  |    *                      31 atom
  |     *                     32 @:
  |      *                    33 {??}
=== Messages ===
 66 AAToBeExecuted 18 {??}
 87 AAToBeExecuted 25 {??}
114 AAToBeExecuted 33 {??}
=== End ===
F:
                           activationMode: Optional
                             hadFullBreak: false
              nActivatedMandatoryChildren: 6
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 6
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: -1
                    indexChild_marksPause: -1
                              aaActivated: true
                     aaActivated_optional: false
Finally:
                           activationMode: Optional
                             hadFullBreak: false
              nActivatedMandatoryChildren: 6
   nActivatedMandatoryChildrenWithSuccess: 0
nActivatedMandatoryChildrenWithoutSuccess: 6
               nActivatedOptionalChildren: 0
    nActivatedOptionalChildrenWithSuccess: 0
 nActivatedOptionalChildrenWithoutSuccess: 0
             indexChild_marksOptionalPart: -1
                    indexChild_marksPause: 34
                              aaActivated: true
                     aaActivated_optional: false
                             activateNext: false
                          activationEnded: false
                activationEndedOptionally: false
                            shouldSucceed: false

The latter one does not activate a new node in the call graph; hence the cycle ends here.

This comment has grown very large; time to leave it like this. In the next comment I will analyse the /... Continuation message handlings.

AndreVanDelft commented 9 years ago

To summarize: the following are indexes of continuation messages, together with the branches these take.

25 - branch F, no further activation 42 - no explicit branch (will be H), activate ; 78 - branch C, activate .. 99 - branch E, activate ; << this should not have happened 105 - branch C, activate .. 126 - branch F, no further activation

AndreVanDelft commented 9 years ago

It looks like it has been really fixed now: https://github.com/AndreVanDelft/scala/commit/06257608764c14c3ca12883df754c3e69697b1fe