robhagemans / pcbasic

PC-BASIC - A free, cross-platform emulator for the GW-BASIC family of interpreters
http://www.pc-basic.org
Other
396 stars 48 forks source link

Operator precedence not compatible with GW-Basic #132

Closed axelkern closed 2 years ago

axelkern commented 3 years ago

Bug report

Problem

The unary sign ("+" or "-") has a different precedence in expressions than in GW-BASIC. In GW-BASIC the unary operator has the second highest precedence after "^" while PC-BASIC treats the unary operator with the same precedence as the binary "+"/"-". As a consequence PC-BASIC does calculate differently in some (rare) cases. The approach of PC-BASIC is however in line with the current documentation.

The different precedence behavior can be checked with the below calculation: 12/+3*4 alternatively 12/-3*4 PC-BASIC calculates: 12/+(3*4) = 1 GW-BASIC calculates 12/(+3)*4 = 16

The higher precedence of the unary negation is documented in the GW-BASIC User's Guide in chapter 6.4.1 Arithmetic Operators. It can also be validated in the GW-BASIC source code (File GWEVAL.ASM, lines 640-644 and 763-766) https://github.com/microsoft/GW-BASIC/blob/edf82c2ebf6bfe099c2054e0ae125c3efe5769c4/GWEVAL.ASM#L640 https://github.com/microsoft/GW-BASIC/blob/edf82c2ebf6bfe099c2054e0ae125c3efe5769c4/GWEVAL.ASM#L763

Steps

  1. ?12/+3*4
  2. Output should be 16, but PC-BASIC displays 1

Program

10 IF 12/+3*4=1 THEN PRINT "PC-BASIC" ELSE PRINT "GW-BASIC" Crash log

Notes PC-BASIC version: 2.0.3 Operating system version: Win GW-BASIC version: 3.2.3 (under DOSBox)

robhagemans commented 3 years ago

Thanks! Confirmed your test case on my side. That's surprising, I thought I had the operator precedence worked out by now. I'll look into this - the documentation suggests this was done on purpose but I can't remember why.

robhagemans commented 3 years ago

So the unary operator (in PC-BASIC) causes the whole of (34) to be taken as the denominator, because it is more loosely bound than the . Which is different form GW-BASIC and also counterintuitive. Occurs on both 2.0 and 1.2 branch so this bug has been around for a while.

axelkern commented 3 years ago

I'm working on a small retro Basic Compiler project. While trying to gather more info on the operator's precedence I came across the PC-BASIC documentation and found the info on the unary operator contradicting. At first I thought it doesn't make any difference in practice. All the test cases that came to my mind came to the same result. Finally I found this rather simple case where it deviates. I guess there are not many Basic programs around which would be affected by this...

robhagemans commented 2 years ago

Fixed on develop by commit 209a5d56b, thanks @rbergen !