fastbasic icon indicating copy to clipboard operation
fastbasic copied to clipboard

Signed Integers with loops & memory

Open ukcroupier opened this issue 6 years ago • 9 comments

I know this probably isn't a bug and is working within the parameters of signed integers, but it is a problem that shows the need for an option to use unsigned integers.

I was testing some scrolling and hit a problem, I've condensed it down to the code in the attached file.

This drops memtop to reserve memory for the scroll, it then sets up the DL and then loops through memory and displays a character moving diagonally.

As long as PAGE<=64 everything works fine but if I wanted a larger area for my scrolled screen then it hits an issue with signed integers. If I set PAGE=68 the loop will have the following value:

FOR A=32014 TO -16640

This causes program flow to drop through the loop without executing it.

In order to work with memory (and therefore my scrolling screen) am I forced to use floating point to avoid issues with the sign flipping?

An option to use unsigned integers would solve this. Being able to select signed or unsigned as your default would be great. TEST.TXT

ukcroupier avatar Sep 17 '19 10:09 ukcroupier

I guess I could code stuff like this with offsets (as in attached file) but it's a bit of a pain.

TEST1.TXT

ukcroupier avatar Sep 18 '19 07:09 ukcroupier

Hi!

You are right, FOR loops with small signed integers is a mess - you run into problems easily.

I don't want to add unsigned integers to the language as the parser would be a lot bigger and slower, as you would need to parse expressions as signed and unsigned and select which works better, see:

This expression should be parsed as unsigned:

FOR A=1 TO 40000 : NEXT

But this expression should be parsed as signed:

X = -1
FOR A=1 TO 10000*X : NEXT

And both should include different code for the "FOR" and the "NEXT" statements!

The root cause is that FOR ends the iteration by doing a signed comparison, and that comparison can fail on unexpected ways.

My recommendation, don't ever use FOR loops. They tend to be slower and more complicated that WHILE and REPEAT loops, for example:

A=HI*256+270
E=(HI+PAGE-1)*256
REPEAT
	PAUSE 10
	POKE A-257,0
        POKE A,17
        A = A + 257
UNTIL A - E > 0

The above would work whenever the total range (END - START) is < 32768.

Another possibility, instead of an arbitrary "OFFSET" as you programmed, simply loop from 0 always, also would work whenever the range is < 32768:

O=HI*256+270
FOR A=0 TO (HI+PAGE-1)*256-O STEP 257
	PAUSE 10
	POKE O+A-257,0
	POKE O+A,17
NEXT A

Hope the above helps.

dmsc avatar Sep 18 '19 16:09 dmsc

Thanks for the advice, very useful.

But wouldn't it be fairly simple to make a compiler that only uses integers 0-65535 instead of signed? For games programming working without negatives would be easier than worrying about bugs involving signed integers.

The only time I've every needed a negative in games is for -1 and I can easily code around that.

ukcroupier avatar Sep 18 '19 18:09 ukcroupier

Hi!

But wouldn't it be fairly simple to make a compiler that only uses integers 0-65535 instead of signed? For games programming working without negatives would be easier than worrying about bugs involving signed integers.

The only time I've every needed a negative in games is for -1 and I can easily code around that.

I haven't tough of that, an unsigned only version could be easy to do. I modeled the signed-integer support on other integer BASIC of the time, like Microsoft BASIC, so I tough it would be less confusing.

You could ask other people opinions in the atariage (programming) forum :)

Have Fun!

dmsc avatar Sep 18 '19 19:09 dmsc

Another tough, how do you express negative STEP's in a FOR statement with unsigned only arithmetic?

Or if you have a "speed" variable, how do you express negative numbers there?

Have Fun!

dmsc avatar Sep 18 '19 19:09 dmsc

I'm sure some games would find negatives useful, but if it's easy to do then why not give us the option to compile with signed or unsigned.

I know I'm being a pain, but for me accessing memory without unusual things happening is the main issue, I can code around issues with negative numbers.

BTW: I'm only bugging you because I love BASIC (and FastBasic is awesome). I can code in C, Pascal, Assembler to varying degrees of competence (also PHP, COBOL, Pearl), but BASIC is what I love.

ukcroupier avatar Sep 18 '19 20:09 ukcroupier

Hi!

I'm sure some games would find negatives useful, but if it's easy to do then why not give us the option to compile with signed or unsigned.

I know I'm being a pain, but for me accessing memory without unusual things happening is the main issue, I can code around issues with negative numbers.

You are not being a pain :), your input is appreciated.

Problem is, maintaining another build (or two more, unsigned only and unsigned + FP) will be more work and a maintenance burden, so I won't jump to it immediately.

So, I will prefer to find another solution that would be simpler.

For example, I could add a "unsigned FOR loop" that would treat numbers as unsigned for the loop end... I don't like this syntax, but:

  FOR A=1 UP 40000 : .... do something ... : NEXT

  FOR A=40000 UP 1 : .... do something... : NEXT

BTW: I'm only bugging you because I love BASIC (and FastBasic is awesome). I can code in C, Pascal, Assembler to varying degrees of competence (also PHP, COBOL, Pearl), but BASIC is what I love.

Thanks!

Have Fun!

dmsc avatar Sep 19 '19 02:09 dmsc

I never considered having to maintain all those builds, yeah it's a lot of work.

The unsigned loop is a nice workaround, it's the kind of thing I'd do so it's probably a bad idea lol

Given the multiple ways of working around the problem you've shown, and the fact that it's only really an issue when crossing the 'signed bondry' I think you should probably invest your time doing something more important :)

ukcroupier avatar Sep 19 '19 05:09 ukcroupier

Hi!

I never considered having to maintain all those builds, yeah it's a lot of work.

The unsigned loop is a nice workaround, it's the kind of thing I'd do so it's probably a bad idea lol

Given the multiple ways of working around the problem you've shown, and the fact that it's only really an issue when crossing the 'signed bondry' I think you should probably invest your time doing something more important :)

Well, I really want to rewrite the FOR loop handling, as I don't like how it is currently implemented - the address of the loop variable, the step and the end value are all pushed to the stack and the value is updated on the NEXT statement.

This allows the FOR variable to be any expression - for example "FOR S(2*X+1)=0 TO 10", as the address is stored it does not needs reevaluation on each iteration. But, I think that this flexibility is not really needed, I could limit the parser to allow only a single variable, and optimize for that case.

That time, I will revisit all options to make the loops over "addresses" (unsigned) better.

Have Fun!

dmsc avatar Sep 20 '19 02:09 dmsc