On Thu, May 31, 2018 at 1:22 PM, Eliot Miranda <eliot.miranda@gmail.com> wrote:
Hi Marcel, Hi All,

On Thu, May 31, 2018 at 3:26 AM, Marcel Taeumel <marcel.taeumel@hpi.de> wrote:
Hi, there.

I cannot browse the senders of #@-.

I thought I'd try and look for examples of binary selectors followed by plus or minus signs.  It turned out to be harder than I thought. It did find an issue with Shout.  Shout incorrectly flags a keyword followed by a negative constant with no intervening whitespace as a syntax error.  e.g. this from IntervalTest>>testExtent
self assert: (1 to: 10) extent = 9.
self assert: (1 to: 10 by: 2) extent = 9.
self assert: (1 to:-1) extent = -2

Shout flags a syntax error from ":-1) extent", but this is legal.

Anyway, for the browse code I'm able to see just four false positives using the following looking for negative integers:

CurrentReadOnlySourceFiles cacheDuring:
[self systemNavigation browseAllSelect:
[:m|
(m scanForInstructionSequence:
[:a :b|
a selector = #pushConstant:
and: [a argument isInteger
and: [a argument negative
and: [b selector = #send:super:numArgs:
and: [b arguments first isBinary]]]]])
and: [| sansComments |
sansComments := String streamContents:
[:o| | inComment s |
inComment := false.
s := m getSource asString readStream.
[s atEnd] whileFalse:
[inComment
ifTrue: [s next = $" ifTrue: [inComment := false]]
ifFalse:
[s peek = $"
ifTrue: [inComment := true. s next]
ifFalse: [o nextPut: s next]]].
o contents].
(sansComments piecesCutWhere: [:a :b| b = $-]) allButLast
anySatisfy:
[:s| s last isSeparator not and: [s last isDigit not and: [('''${[()' includes: s last) not and: [s last asSymbol isBinary]]]]]]].

The scanForInstructionSequence: code looks for binary selectors with negative arguments (e.g. 1@-1).
sansComments strips the method source of its comments so we're not confused by characters in comments.
To look for binary selectors followed by '-' I use piecesCutWhere: to cut at the '-', and look at the last character of the preceding piece.
Alas a separator or a digit as symbol (e.g. #' ' and #'9') answer true to isBinary, so they need filtering out.
And there are plenty of occurrences of '-1' {-1. (-1 etc that are not examples of binary selectors.

The above found four false positives and no examples.  The following looks for positive numbers too. It's much slower, but also detects far more false positives.  Can anyone suggest better code?

Doh!  Here's a much better way.  We can use the scanner to tokenize the method and find offending binary tokens in the stream:

CurrentReadOnlySourceFiles cacheDuring:
[self systemNavigation browseAllSelect:
[:m|
(m scanForInstructionSequence:
[:a :b|
a selector = #pushConstant:
and: [a argument isInteger
and: [b selector = #send:super:numArgs:
and: [b arguments first isBinary]]]])
and: [(Scanner new typedScanTokens: m getSource) anySatisfy:
[:t| t isSymbol and: [t isBinary and: [t size > 1 and: ['+-' includes: t last]]]]]]]
 
With this I find only one method, a false positive, Utilities class>>#fixUpProblemsWithAllCategory, which contains the symbol #'-- all --'


CurrentReadOnlySourceFiles cacheDuring:
[self systemNavigation browseAllSelect:
[:m|
(m scanForInstructionSequence:
[:a :b|
a selector = #pushConstant:
and: [a argument isInteger
and: [b selector = #send:super:numArgs:
and: [b arguments first isBinary]]]])
and: [| sansComments |
sansComments := String streamContents:
[:o| | inComment s |
inComment := false.
s := m getSource asString readStream.
[s atEnd] whileFalse:
[inComment
ifTrue: [s next = $" ifTrue: [inComment := false]]
ifFalse:
[s peek = $"
ifTrue: [inComment := true. s next]
ifFalse: [o nextPut: s next]]].
o contents].
(sansComments piecesCutWhere: [:a :b| '+-' includes: b]) allButLast
anySatisfy:
[:s| s last isSeparator not and: [s last isDigit not and: [('''${[()' includes: s last) not and: [s last asSymbol isBinary]]]]]]].



Best,
Marcel

_,,,^..^,,,_
best, Eliot



--
_,,,^..^,,,_
best, Eliot