correct form for Problem With Blocks

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

correct form for Problem With Blocks

Squeak - Dev mailing list
Hi Folks,

I am importing my grammar/xtreams parsing work into its own image so that I can change my system fonts without making my other projects look funky with the chages.

The base image is:


Image
-----
/home/wm/usr/src/smalltalk/squeak6.0alpha/shared/Squeak6.0alpha-19802-64bit.image
Squeak6.0alpha
latest update: #20147

to the latest:

/home/wm/Squeak/images/WikitextParser/WikitextParser.image
Squeak6.0alpha
latest update: #20188

During the import of my work, I ran into this issue regarding Store Into in a block:




The parser is looking for patterns of  (10e2)e2....i.e.  exponential notation of unknown length, i.e. per the comment on Collection inject: into:  accumulate a running value...



Per the email chain referenced, the "Allow block argument assignment" is allowed in the former, and not allowed in the latest, which is cool with me, but...

My question is "what is the generic form" that I can use to duplicate the behaviour I want?
Here is the original method with the bad store into:
Float: first exponent: pairs
  <action: 'Float' arguments:#(1 2)>

"Float <- ( Number / Group / Function ) (''e'' ( Number / Group / Function ))+"

|result|
  result := pairs inject: first
                        into: [ :base  :pair |
                                    (pair first = 'e')
                                               ifTrue: [
                                                            (pair last abs > 1)
                                                                  ifTrue:[ base := Float readFrom: ((base asString) , 'e', (pair last asString))]
                                                                  ifFalse:[ base := (base * (10 raisedTo:(pair last) ))]]].

transcripton ifTrue:[Transcript show:'Float ' , (result asFloat); cr. ].


^ result asFloat



Here is my "hack" to fix it , (I create a tmp variable outside the block to use in place of the "base"):


Float: first exponent: pairs
  <action: 'Float' arguments:#(1 2)>

"Float <- ( Number / Group / Function ) (''e'' ( Number / Group / Function ))+"

|result tmp|
        result := pairs inject: first
                              into: [ :base  :pair |
                                          (pair first = 'e')
                                                ifTrue: [
                                                      (pair last abs > 1)
                                                            ifTrue:[tmp := base.
                                                                        tmp := Float readFrom: ((tmp asString) , 'e', (pair last asString))]
                                                                        tmp := Float readFrom: ((tmp asString) , 'e', (pair last asString)).
                                                                        tmp]
                                                            ifFalse:[tmp := base.
                                                                        tmp := (tmp * (10 raisedTo:(pair last) ))]]].
                                                                        tmp := (tmp * (10 raisedTo:(pair last) )).
                                                                        tmp]]].

transcripton ifTrue:[Transcript show:'Float ' , (result asFloat); cr. ].


^ result asFloat

I got a bad feeling about this one.


Is there a general form for this ?


My brain is a bit foggy from working the graveyard shift so what would be obvious while in normal conditions , is not obvious today.


Thanks for you time.





Reply | Threaded
Open this post in threaded view
|

Re: correct form for Problem With Blocks

Levente Uzonyi
Hi Tim,

On Thu, 11 Feb 2021, gettimothy via Squeak-dev wrote:

> Hi Folks,
>
> I am importing my grammar/xtreams parsing work into its own image so that I can change my system fonts without making my other projects look funky with the chages.
>
> The base image is:
>
>
> Image
> -----
> /home/wm/usr/src/smalltalk/squeak6.0alpha/shared/Squeak6.0alpha-19802-64bit.image
> Squeak6.0alpha
> latest update: #20147
>
> to the latest:
>
> /home/wm/Squeak/images/WikitextParser/WikitextParser.image
> Squeak6.0alpha
> latest update: #20188
>
> During the import of my work, I ran into this issue regarding Store Into in a block:
>
>
> http://forum.world.st/Cuis-problem-with-blocks-td1047783.html#a1049556
>
>
> The parser is looking for patterns of  (10e2)e2....i.e.  exponential notation of unknown length, i.e. per the comment on Collection inject: into:  accumulate a running value...
>
>
>
> Per the email chain referenced, the "Allow block argument assignment" is allowed in the former, and not allowed in the latest, which is cool with me, but...
>
> My question is "what is the generic form" that I can use to duplicate the behaviour I want?
> Here is the original method with the bad store into:
>       Float: first exponent: pairs
>   <action: 'Float' arguments:#(1 2)>
>
> "Float <- ( Number / Group / Function ) (''e'' ( Number / Group / Function ))+"
>
> |result|
>   result := pairs inject: first
>                         into: [ :base  :pair |
>                                     (pair first = 'e')
>                                                ifTrue: [
>                                                             (pair last abs > 1)
>                                                                   ifTrue:[ base := Float readFrom: ((base asString) , 'e', (pair last asString))]
>                                                                   ifFalse:[ base := (base * (10 raisedTo:(pair last) ))]]].
That makes no sense. I can't even fathom how it works.
#inject:into:'s second argument, the block, must return the computed
value.
Currently that block returns the value assigned to base when pair first =
'e' and nil otherwise.
So, if it works correctly now, which is doubtful, then just remove the
assignments to base from the block and it should just work.

>
> transcripton ifTrue:[Transcript show:'Float ' , (result asFloat); cr. ].
>
>
> ^ result asFloat
>
>
>
>
> Here is my "hack" to fix it , (I create a tmp variable outside the block to use in place of the "base"):
>
>
>       Float: first exponent: pairs
>   <action: 'Float' arguments:#(1 2)>
>
> "Float <- ( Number / Group / Function ) (''e'' ( Number / Group / Function ))+"
>
> |result tmp|
>         result := pairs inject: first
>                               into: [ :base  :pair |
>                                           (pair first = 'e')
>                                                 ifTrue: [
>                                                       (pair last abs > 1)
>                                                             ifTrue:[tmp := base.
>                                                                         tmp := Float readFrom: ((tmp asString) , 'e', (pair last asString))]
>                                                                         tmp := Float readFrom: ((tmp asString) , 'e', (pair last asString)).
>                                                                         tmp]
>                                                             ifFalse:[tmp := base.
>                                                                         tmp := (tmp * (10 raisedTo:(pair last) ))]]].
>                                                                         tmp := (tmp * (10 raisedTo:(pair last) )).
>                                                                         tmp]]].
Those parentheses don't look well balanced, but anyway, there's no need
to use tmp, especially not one at the outer scope.


Levente

>
> transcripton ifTrue:[Transcript show:'Float ' , (result asFloat); cr. ].
>
>
> ^ result asFloat
>
>
> I got a bad feeling about this one.
>
>
> Is there a general form for this ?
>
>
> My brain is a bit foggy from working the graveyard shift so what would be obvious while in normal conditions , is not obvious today.
>
>
> Thanks for you time.
>
>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: correct form for Problem With Blocks

Squeak - Dev mailing list
In reply to this post by Squeak - Dev mailing list
Hi Levente,

Thank you for your reply.

That makes no sense. I can't even fathom how it works.
#inject:into:'s second argument, the block, must return the computed
value.
Currently that block returns the value assigned to base when pair first =
'e' and nil otherwise.
So, if it works correctly now, which is doubtful, then just remove the
assignments to base from the block and it should just work.
I did, it does. thx.

Fwiw, here are the tests I have for this rule ...It might make things clearer on what it is meant to accomplish.  The pattern is borrowed from some Algebraic PEG grammar I found on the net.
The purpose is to support some PHP-isms in the wikitext grammar...basically PHP version of callbacks given a pattern.

testFloat

<timeout: 5 "seconds">

"Float <-  Multiplicand  (''e'' Multiplicand)+"
| n output actor |

actor := PEGWikiMediaGeneratorTables new.
actor transcripton: false.  "disable tracing to Transcript"

n := '-2.3e-4'.
output := parser parse: 'Negation' stream: n reading actor: actor.
self assert: (output = -0.00023 ).

n := '6e2e3'.
output := parser parse: 'Float' stream: n reading actor: actor.
self assert: (output = 600000.0) .


n := '2e3'.
output := parser parse: 'Float' stream: n reading actor: actor.
self assert: (output = 2000) .


n := '-2.3e-4'.
output := parser parse: 'Negation' stream: n reading actor: actor.
self assert: (output = -0.00023 ).




n := '(trunc2)e(trunc-3)'.
output := parser parse: 'Float' stream: n reading actor: actor.
self assert: (output = 0.002) .


n := '(trunc2)e(trunc0)'.
output := parser parse: 'Float' stream: n reading actor: actor.
self assert: (output = 2) .

n := '(trunc2)e(trunc18)'.
output := parser parse: 'Float' stream: n reading actor: actor. 
self assert: (output = 2.0e18) .

n := '(trunc2)e(trunc19)'.
output := parser parse: 'Float' stream: n reading actor: actor.
self assert: (output = 2.0e19) .

n := '6e(5-2)'.
output := parser parse: 'Float' stream: n reading actor: actor.
self assert: (output = 6000.0) .

n := '(5-2)e-2'.
output := parser parse: 'Float' stream: n reading actor: actor.
self assert: (output = 0.03) .


n := '6e(5-2)e-2'.
output := parser parse: 'Float' stream: n reading actor: actor.
self assert: (output = 60) .


n := '5.0e-324'.  "(Float fmin) * (Float fmax)"
output := parser parse: 'Operation' stream: n reading actor: actor.
self assert: (output = (Float fmin) ) .