• pMARS associativity bug

    From John Metcalf@21:1/5 to All on Sun May 1 06:59:36 2022
    Hi,

    Has anyone got a patch for the associativity bug in pMARS? E.g. the
    following two DATs should be identical, but are evaluated right-to-left
    when assembled:

    dat 0 - 2*1000 - 3*100
    dat 0 - 3*100 - 2*1000

    Assembles to:

    START DAT.F # 0, $ -1700
    DAT.F # 0, $ 1700

    Thanks,

    John

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Gunnell@21:1/5 to John Metcalf on Sun May 1 06:46:03 2022
    On Sunday, 1 May 2022 at 2:59:37 pm UTC+8, John Metcalf wrote:
    Hi,

    Has anyone got a patch for the associativity bug in pMARS? E.g. the
    following two DATs should be identical, but are evaluated right-to-left
    when assembled:

    dat 0 - 2*1000 - 3*100
    dat 0 - 3*100 - 2*1000

    Assembles to:

    START DAT.F # 0, $ -1700
    DAT.F # 0, $ 1700

    Thanks,

    John

    No but I did manage to build the standalone test version of eval.c. It is late at night here now, I'll have a look at it tomorrow.

    Steveg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Gunnell@21:1/5 to Stephen Gunnell on Sun May 1 17:04:34 2022
    On Monday, 2 May 2022 at 7:40:48 am UTC+8, Stephen Gunnell wrote:
    On Sunday, 1 May 2022 at 9:46:04 pm UTC+8, Stephen Gunnell wrote:
    On Sunday, 1 May 2022 at 2:59:37 pm UTC+8, John Metcalf wrote:
    Hi,

    Has anyone got a patch for the associativity bug in pMARS? E.g. the following two DATs should be identical, but are evaluated right-to-left when assembled:

    dat 0 - 2*1000 - 3*100
    dat 0 - 3*100 - 2*1000

    Assembles to:

    START DAT.F # 0, $ -1700
    DAT.F # 0, $ 1700

    Thanks,

    John
    No but I did manage to build the standalone test version of eval.c. It is late at night here now, I'll have a look at it tomorrow.

    Steveg
    Okay, I can confirm that as a bug in eval.c:
    steve@steve-Latitude-5320:~/pmars-0.9.2/src$ ./evaltest
    Enter infix expression: 0-2*1000-3*100
    1700 = (2000 - (3 * ..))
    1700 = ((2 * 1000) - ..)
    -1700 = (0 - (2 * ..))
    -1700 = (0 # (0 - ..))
    Evaluation result: -1700

    I'll spelunk around in there and see if I can see what is going on. But it is at least 30 years since I last wrote an expression parsed so I may be some time relearning.

    Steveg

    It is implementing precedence correctly but it is evaluating equal precedence right to left rather than left to right:

    steve@steve-Latitude-5320:~/pmars-0.9.2/src$ ./evaltest
    Enter infix expression: 0-2*1000-3*100
    CALC x 2 y 1000 op *
    CALC x 3 y 100 op *
    CALC x 2000 y 300 op -
    D 1700 = (2000 - (3 * ..))
    A 1700 = ((2 * 1000) - ..)
    CALC x 0 y 1700 op -
    D -1700 = (0 - (2 * ..))
    CALC x 0 y -1700 op #
    D -1700 = (0 # (0 - ..))
    Evaluation result: -1700

    Steveg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Gunnell@21:1/5 to Stephen Gunnell on Sun May 1 16:40:47 2022
    On Sunday, 1 May 2022 at 9:46:04 pm UTC+8, Stephen Gunnell wrote:
    On Sunday, 1 May 2022 at 2:59:37 pm UTC+8, John Metcalf wrote:
    Hi,

    Has anyone got a patch for the associativity bug in pMARS? E.g. the following two DATs should be identical, but are evaluated right-to-left when assembled:

    dat 0 - 2*1000 - 3*100
    dat 0 - 3*100 - 2*1000

    Assembles to:

    START DAT.F # 0, $ -1700
    DAT.F # 0, $ 1700

    Thanks,

    John
    No but I did manage to build the standalone test version of eval.c. It is late at night here now, I'll have a look at it tomorrow.

    Steveg

    Okay, I can confirm that as a bug in eval.c:
    steve@steve-Latitude-5320:~/pmars-0.9.2/src$ ./evaltest
    Enter infix expression: 0-2*1000-3*100
    1700 = (2000 - (3 * ..))
    1700 = ((2 * 1000) - ..)
    -1700 = (0 - (2 * ..))
    -1700 = (0 # (0 - ..))
    Evaluation result: -1700

    I'll spelunk around in there and see if I can see what is going on. But it is at least 30 years since I last wrote an expression parsed so I may be some time relearning.

    Steveg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Gunnell@21:1/5 to Stephen Gunnell on Sun May 1 17:14:04 2022
    On Monday, 2 May 2022 at 8:04:35 am UTC+8, Stephen Gunnell wrote:
    On Monday, 2 May 2022 at 7:40:48 am UTC+8, Stephen Gunnell wrote:
    On Sunday, 1 May 2022 at 9:46:04 pm UTC+8, Stephen Gunnell wrote:
    On Sunday, 1 May 2022 at 2:59:37 pm UTC+8, John Metcalf wrote:
    Hi,

    Has anyone got a patch for the associativity bug in pMARS? E.g. the following two DATs should be identical, but are evaluated right-to-left when assembled:

    dat 0 - 2*1000 - 3*100
    dat 0 - 3*100 - 2*1000

    Assembles to:

    START DAT.F # 0, $ -1700
    DAT.F # 0, $ 1700

    Thanks,

    John
    No but I did manage to build the standalone test version of eval.c. It is late at night here now, I'll have a look at it tomorrow.

    Steveg
    Okay, I can confirm that as a bug in eval.c:
    steve@steve-Latitude-5320:~/pmars-0.9.2/src$ ./evaltest
    Enter infix expression: 0-2*1000-3*100
    1700 = (2000 - (3 * ..))
    1700 = ((2 * 1000) - ..)
    -1700 = (0 - (2 * ..))
    -1700 = (0 # (0 - ..))
    Evaluation result: -1700

    I'll spelunk around in there and see if I can see what is going on. But it is at least 30 years since I last wrote an expression parsed so I may be some time relearning.

    Steveg
    It is implementing precedence correctly but it is evaluating equal precedence right to left rather than left to right:
    steve@steve-Latitude-5320:~/pmars-0.9.2/src$ ./evaltest
    Enter infix expression: 0-2*1000-3*100
    CALC x 2 y 1000 op *
    CALC x 3 y 100 op *
    CALC x 2000 y 300 op -
    D 1700 = (2000 - (3 * ..))
    A 1700 = ((2 * 1000) - ..)
    CALC x 0 y 1700 op -
    D -1700 = (0 - (2 * ..))
    CALC x 0 y -1700 op #
    D -1700 = (0 # (0 - ..))
    Evaluation result: -1700

    Steveg

    In eval.c find:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 >= prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result);
    change to:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 > prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result);

    ie: change "prec2 >= prevPrec" to "prec2 > prevPrec"

    steve@steve-Latitude-5320:~/pmars-0.9.2/src$ ./evaltest
    Enter infix expression: 0-2*1000-3*100
    CALC x 2 y 1000 op *
    B 2000 = (2 * 1000)
    CALC x 0 y 2000 op -
    CALC x 3 y 100 op *
    CALC x -2000 y 300 op -
    D -2300 = (-2000 - (3 * ..))
    C -2300 = .. ? (0 - (2 * ..))
    CALC x 0 y -2300 op #
    D -2300 = (0 # (0 - ..))
    Evaluation result: -2300

    I've been meaning to chase this for a while but my trivial examples didn't fail, thanks for the bump John.

    Steveg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John Metcalf@21:1/5 to Stephen Gunnell on Wed May 4 18:31:27 2022
    On Sun, 01 May 2022 17:14:04 -0700, Stephen Gunnell wrote:

    In eval.c find:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 >= prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result); change to:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 > prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result);

    ie: change "prec2 >= prevPrec" to "prec2 > prevPrec"

    steve@steve-Latitude-5320:~/pmars-0.9.2/src$ ./evaltest Enter infix expression: 0-2*1000-3*100
    CALC x 2 y 1000 op *
    B 2000 = (2 * 1000)
    CALC x 0 y 2000 op -
    CALC x 3 y 100 op *
    CALC x -2000 y 300 op -
    D -2300 = (-2000 - (3 * ..))
    C -2300 = .. ? (0 - (2 * ..))
    CALC x 0 y -2300 op #
    D -2300 = (0 # (0 - ..))
    Evaluation result: -2300

    I've been meaning to chase this for a while but my trivial examples
    didn't fail, thanks for the bump John.

    Steveg

    Fantastic, thanks. I'm on holiday at the moment, but will run a few test
    cases when I return and check which published warriors are affected. I
    tested Corewin, which assembles the examples correctly.

    I use code similar to the following when optimizing and wondered why the results have been off :-)

    x equ y-25*step+(!E 0 50!)*step

    John

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John Metcalf@21:1/5 to John Metcalf on Sun May 22 10:02:51 2022
    On Wed, 04 May 2022 18:31:27 +0000, John Metcalf wrote:

    On Sun, 01 May 2022 17:14:04 -0700, Stephen Gunnell wrote:

    In eval.c find:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 >= prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result);
    change to:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 > prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result);

    ie: change "prec2 >= prevPrec" to "prec2 > prevPrec"

    Sorry for the delay. I've made the change above and there's a new
    problem :-( There's an error with the following DAT:

    dat 0-2*3-2*3+12

    Using the new eval.c:

    Error in line 1: 'dat 0-2*3-2*3+12'
    Bad expression
    Number of errors: 1

    I've been searching and I think there might be a patch on Sourceforge (I haven't tested this yet):

    https://sourceforge.net/p/corewar/bugs/3/

    John

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Gunnell@21:1/5 to John Metcalf on Sun May 22 03:53:37 2022
    On Sunday, 22 May 2022 at 6:02:53 pm UTC+8, John Metcalf wrote:
    On Wed, 04 May 2022 18:31:27 +0000, John Metcalf wrote:

    On Sun, 01 May 2022 17:14:04 -0700, Stephen Gunnell wrote:

    In eval.c find:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 >= prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result);
    change to:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 > prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result);

    ie: change "prec2 >= prevPrec" to "prec2 > prevPrec"
    Sorry for the delay. I've made the change above and there's a new
    problem :-( There's an error with the following DAT:

    dat 0-2*3-2*3+12

    Using the new eval.c:

    Error in line 1: 'dat 0-2*3-2*3+12'
    Bad expression
    Number of errors: 1

    I've been searching and I think there might be a patch on Sourceforge (I haven't tested this yet):

    https://sourceforge.net/p/corewar/bugs/3/

    John
    I see the same error in the testeval executable ... I've looked at the patch and I don't see why it would work. So I'm doing some further checking.
    Steveg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Gunnell@21:1/5 to Stephen Gunnell on Sun May 22 04:44:06 2022
    On Sunday, 22 May 2022 at 6:53:38 pm UTC+8, Stephen Gunnell wrote:
    On Sunday, 22 May 2022 at 6:02:53 pm UTC+8, John Metcalf wrote:
    On Wed, 04 May 2022 18:31:27 +0000, John Metcalf wrote:

    On Sun, 01 May 2022 17:14:04 -0700, Stephen Gunnell wrote:

    In eval.c find:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 >= prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result);
    change to:
    if ((prec1 = PRECEDENCE(oper1)) >= (prec2 = PRECEDENCE(oper2))) {
    if (prec2 > prevPrec || prec1 <= prevPrec) {
    expr = eval(prec1, calc(val1, val2, oper1), oper2, expr, result);

    ie: change "prec2 >= prevPrec" to "prec2 > prevPrec"
    Sorry for the delay. I've made the change above and there's a new
    problem :-( There's an error with the following DAT:

    dat 0-2*3-2*3+12

    Using the new eval.c:

    Error in line 1: 'dat 0-2*3-2*3+12'
    Bad expression
    Number of errors: 1

    I've been searching and I think there might be a patch on Sourceforge (I haven't tested this yet):

    https://sourceforge.net/p/corewar/bugs/3/

    John
    I see the same error in the testeval executable ... I've looked at the patch and I don't see why it would work. So I'm doing some further checking.
    Steveg

    Somehow I was missing most of the patch ... it looks reasonable now that I can see all of it. I'll have to get a clean version of eval.c to apply it.
    Steveg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John Metcalf@21:1/5 to Stephen Gunnell on Wed May 25 14:53:46 2022
    On Sun, 22 May 2022 04:44:06 -0700, Stephen Gunnell wrote:

    Somehow I was missing most of the patch ... it looks reasonable now that
    I can see all of it. I'll have to get a clean version of eval.c to apply
    it.
    Steveg

    Testing your change to eval.c and Bjoern's patch, I found 17 published
    warriors which assemble differently:

    babyswing.red, baselinep.red, bipolar.red, blackbox.red, borkked.red,
    damageinf.red, dawn.red, demented40.red, fixed.red, fragility.red,
    headortail.red, jedimp.red, lex2.red, mymoorekiller.red, retroq.red,
    twister.red, whatever.red

    I also found 3 warriors which refused to assemble using your change:

    aeka.red, ethanol.red, jedimp.red

    I need to take a closer look at the affected warriors.

    John

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John Metcalf@21:1/5 to John Metcalf on Wed May 25 19:47:16 2022
    On Wed, 25 May 2022 14:53:46 +0000, John Metcalf wrote:

    On Sun, 22 May 2022 04:44:06 -0700, Stephen Gunnell wrote:

    Somehow I was missing most of the patch ... it looks reasonable now
    that I can see all of it. I'll have to get a clean version of eval.c to
    apply it.
    Steveg

    Testing your change to eval.c and Bjoern's patch, I found 17 published warriors which assemble differently:

    babyswing.red, baselinep.red, bipolar.red, blackbox.red, borkked.red,
    damageinf.red, dawn.red, demented40.red, fixed.red, fragility.red,
    headortail.red, jedimp.red, lex2.red, mymoorekiller.red, retroq.red,
    twister.red, whatever.red

    I also found 3 warriors which refused to assemble using your change:

    aeka.red, ethanol.red, jedimp.red

    I need to take a closer look at the affected warriors.

    John

    Sorry, I should've been clearer. Your change gave the same results as the patch, apart from the 3 warriors which didn't assemble.

    I've benchmarked the above with and without the fix, and the scores are
    very similar. Most of the differences seem to be in boot distances /
    qscans.

    John

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Gunnell@21:1/5 to John Metcalf on Thu May 26 23:05:36 2022
    On Thursday, 26 May 2022 at 3:47:18 am UTC+8, John Metcalf wrote:
    On Wed, 25 May 2022 14:53:46 +0000, John Metcalf wrote:

    On Sun, 22 May 2022 04:44:06 -0700, Stephen Gunnell wrote:

    Somehow I was missing most of the patch ... it looks reasonable now line >> that I can see all of it. I'll have to get a clean version of eval.c to
    apply it.
    Steveg

    Testing your change to eval.c and Bjoern's patch, I found 17 published warriors which assemble differently:

    babyswing.red, baselinep.red, bipolar.red, blackbox.red, borkked.red, damageinf.red, dawn.red, demented40.red, fixed.red, fragility.red, headortail.red, jedimp.red, lex2.red, mymoorekiller.red, retroq.red, twister.red, whatever.red

    I also found 3 warriors which refused to assemble using your change:

    aeka.red, ethanol.red, jedimp.red

    I need to take a closer look at the affected warriors.

    John
    Sorry, I should've been clearer. Your change gave the same results as the patch, apart from the 3 warriors which didn't assemble.

    I've benchmarked the above with and without the fix, and the scores are
    very similar. Most of the differences seem to be in boot distances /
    qscans.

    John

    I've looked at Aeka and I think it has exposed one of the other bugs that Bjorn has addressed.
    The failing line in Aeka is overly complex.

    btw, in case it is useful I added this to the makefile to build the standalone evaltest exe:
    evaltest: Makefile config.h global.h eval.c
    @echo Compiling eval.o
    @$(CC) $(CFLAGS) -DDEBUG -DSTANDALONE -c eval.c
    @$(CC) -o evaltest eval.o $(LIB)
    @strip evaltest
    @echo done

    Steve.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Skybuck Flying@21:1/5 to John Metcalf on Fri May 27 03:49:15 2022
    On Sunday, May 1, 2022 at 8:59:37 AM UTC+2, John Metcalf wrote:
    Hi,

    Has anyone got a patch for the associativity bug in pMARS? E.g. the
    following two DATs should be identical, but are evaluated right-to-left
    when assembled:

    dat 0 - 2*1000 - 3*100
    dat 0 - 3*100 - 2*1000

    Assembles to:

    START DAT.F # 0, $ -1700
    DAT.F # 0, $ 1700

    What should be the correct output according to you ?

    dat 0 - 2*1000 - 3*100
    dat 0 - 3*100 - 2*1000

    The way I read this is:

    a dat instruction followed by one parameter only, is that legal syntax ? let's assume it is and continue, then a formula happens:

    0 minus 2 multiplied by 1000 minus 3 multiplied by 100.

    Let's follow math rules.

    Multiply has to be done first:

    0 - 2000 - 300

    https://www.skillsyouneed.com/num/subtraction.html

    Must go from left tor right

    0 - 2000 = -2000
    -2000 - 300 = -2300

    So to me the correct answer should be -2300

    Then mars tries to apply a start label leading to the following result:
    start dat value
    dat value

    According to you there are strange things going on, the value is strange and the sign of the value is strange and different per line.

    In corewin it produces the correct result:
    0000*DAT.F #0 $-2300
    0001 DAT.F #0 $-2300

    One more reason to ditch pmars, it's code base is sloppy at best ! ;)

    Bye,
    Skybuck.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)