Thread Rating:
• 0 Vote(s) - 0 Average
• 1
• 2
• 3
• 4
• 5
 A For-Next bug in 1.2.8-s682 Darkstar Member Posts: 92 Threads: 8 Joined: Mar 2011 Reputation: 0 03-29-2011, 06:24 PM This works: Code:```For i = AttrAddress to AttrAddress + NumberOfCells - 1   Poke i, AttrColor Next i``` This does not: Code:```For AttrAddress = AttrAddress to AttrAddress + NumberOfCells - 1   Poke AttrAddress, AttrColor Next AttrAddress``` This would work in other dialects. Thanks, Darkstar boriel Administrator Posts: 1,757 Threads: 55 Joined: Aug 2019 Reputation: 24 03-30-2011, 08:35 AM Darkstar Wrote:This works: Code:```For i = AttrAddress to AttrAddress + NumberOfCells - 1   Poke i, AttrColor Next i``` This does not: Code:```For AttrAddress = AttrAddress to AttrAddress + NumberOfCells - 1   Poke AttrAddress, AttrColor Next AttrAddress``` This would work in other dialects. Thanks, DarkstarThis is related to the ZX Basic to have "Dynamic" evaluation on each pass. In your loop: Code:```For i = i to i + N - 1   Poke i, AttrColor Next i```the expression i + N - 1 is evaluated *on each pass* (like in C). On most BASIC dialects (including Sinclair BASIC), that expression is only evaluated the 1st time (on entering the loop). On each pass, i + N - 1 is recalculated, and since it's always increasing, the loop will eventually overflow (or run forever). At the moment, the only way to fix this is: Code:```LET z = i + N - 1 For i = i to z   Poke i, AttrColor Next i```Can you check this? Which produces the expected behavior. I'm thinking in fixing this in an more efficient manner, so the user can choose dynamic or static FOR loops with a #pragma directive, and let FOR to be static by default for compatibility's sake. What do you think? britlion Posting Freak Posts: 805 Threads: 135 Joined: Apr 2009 Reputation: 5 03-30-2011, 10:12 AM Boriel, I think that's probably the right choice, since most basic dialects use it. You can always do a dynamic expression with a do...until (x) style loop, where it feels more natural to have an expression evaluated each loop, I think. Will static evaluation speed up for loops? boriel Administrator Posts: 1,757 Threads: 55 Joined: Aug 2019 Reputation: 24 03-30-2011, 10:26 AM britlion Wrote:Boriel, I think that's probably the right choice, since most basic dialects use it. You can always do a dynamic expression with a do...until (x) style loop, where it feels more natural to have an expression evaluated each loop, I think. Will static evaluation speed up for loops?Certainly, if they're complex expressions. Static ones are just like using a temporary variable to store them. The problem is... how to compile them? :roll: Using the stack is a problem if the user jumps out the loop using GOTO. Using a static place is also problematic (and a waste of memory). The most straightforward solution is to use a hidden variable and implement it as shown above. This would imply FOR-NEXT variables will take twice the space of a normal variable, anyway (Sinclair BASIC also makes a distinction between normal variables and FOR-NEXT ones, not only in their length name, but also in their internal implementation). Darkstar Member Posts: 92 Threads: 8 Joined: Mar 2011 Reputation: 0 03-30-2011, 03:56 PM boriel Wrote:At the moment, the only way to fix this is: Code:```LET z = i + N - 1 For i = i to z   Poke i, AttrColor Next i```Can you check this? Which produces the expected behavior. I'm thinking in fixing this in an more efficient manner, so the user can choose dynamic or static FOR loops with a #pragma directive, and let FOR to be static by default for compatibility's sake. What do you think? This would work, no need to check it and it would speed up the current code. I did think that this was it, that is how the loops were evaluated at the beginning. This did produce some "undefined" behaviour that did not make any sense. Is a directive needed? Looks to me that the C style is the poor mans way of doing For-Next loops. What are the benefits? There are already some cons as noted above both in terms of workarounds and speed. If you are thinking about attracting C coders then I think the sacrifice in consistency, even with a pragma directive, is not worth it. A man is nothing if not consistent. Thanks for your(s) reply(s), Darkstar. boriel Administrator Posts: 1,757 Threads: 55 Joined: Aug 2019 Reputation: 24 03-30-2011, 05:00 PM I also agree with both Britlion and you. I'm going to implement this behaviour by default. If the programmer wants the dynamic behaviour s/he will be able to enable it using something like: Code:`#pragma for dynamic`or Code:`#pragma for static`which will be enabled by default (needs not to be used unless you want to switch from/to dynamic for). What do you think? Darkstar Member Posts: 92 Threads: 8 Joined: Mar 2011 Reputation: 0 03-30-2011, 05:45 PM boriel Wrote:I also agree with both Britlion and you. I'm going to implement this behaviour by default. If the programmer wants the dynamic behaviour s/he will be able to enable it using something like: Code:`#pragma for dynamic`or Code:`#pragma for static`which will be enabled by default (needs not to be used unless you want to switch from/to dynamic for). What do you think? Well, static should be a default behaviour yes for consistency but is there any benfits to be derived from dynamic that outweigs the costs? If the answer is no then why go through the work of implementing a directive and it would only add to the confusion amoung coders that expect a language to behave in a certain way in my oppinion. Darkstar. boriel Administrator Posts: 1,757 Threads: 55 Joined: Aug 2019 Reputation: 24 03-30-2011, 05:53 PM Implementing dynamic is much easier (it's already done) and saves memory comparing to static. Static might be faster sometimes (eg. when using expressions), and take twice the memory for each iterator variable. I think leaving it alone should be ok (since almost no one will be using it). FOR is currently "dynamic" and has not caused much trouble when porting original Sinclair BASIC programs. In fact FOR loops are expensive in much ways (code, speed, etc). While and DO...LOOP are much faster and simpler. Darkstar Member Posts: 92 Threads: 8 Joined: Mar 2011 Reputation: 0 03-30-2011, 06:12 PM boriel Wrote:Implementing dynamic is much easier (it's already done) and saves memory comparing to static. Static might be faster sometimes (eg. when using expressions), and take twice the memory for each iterator variable. I think leaving it alone should be ok (since almost no one will be using it). FOR is currently "dynamic" and has not caused much trouble when porting original Sinclair BASIC programs. In fact FOR loops are expensive in much ways (code, speed, etc). While and DO...LOOP are much faster and simpler. If you use expressions then you already have to use an extra variable (double the amount) if speed is the concern and it always is with computers not to mention the ZX at 3.5 MHz. It is the classical speed vs size when it comes to opptimization and you can lay the burden on the programmer or the compiler. This is a compiler's job and it makes for a cleaner code for a programers perspective in the end instead of having an extra variable hanging around that you have to DIM in future versions of this compiler. Dynamic is not in lieu with the BASIC tradition or desing philosophy and For-Next loops are a fact of life. This could lead to pontential trouble in porting, sometimes people have to revise and rewrite instead of preserving the work they have done. Compiler writing is about the whole and not the individual in my humble oppinion. Darkstar. boriel Administrator Posts: 1,757 Threads: 55 Joined: Aug 2019 Reputation: 24 03-30-2011, 06:31 PM Darkstar Wrote:boriel Wrote:Implementing dynamic is much easier (it's already done) and saves memory comparing to static. Static might be faster sometimes (eg. when using expressions), and take twice the memory for each iterator variable. I think leaving it alone should be ok (since almost no one will be using it). FOR is currently "dynamic" and has not caused much trouble when porting original Sinclair BASIC programs. In fact FOR loops are expensive in much ways (code, speed, etc). While and DO...LOOP are much faster and simpler.If you use expressions then you already have to use an extra variable (double the amount)Not exactly: the code that computes the FOR upper limit expression is the same (regardless its static or dynamic calculated on each iteration). The difference is that once it's used it's discarded (dynamic) or must be stored to be reused later (static). Other than that, there's no difference. I was to implement that anyway (there's another thread in this forum asking for that), but leaving the possibility to use a dynamic for if one wants. I meant: can't see why we must enforce dynamic removal once static is the default behaviour. Darkstar Member Posts: 92 Threads: 8 Joined: Mar 2011 Reputation: 0 03-30-2011, 06:55 PM boriel Wrote:Darkstar Wrote:boriel Wrote:Implementing dynamic is much easier (it's already done) and saves memory comparing to static. Static might be faster sometimes (eg. when using expressions), and take twice the memory for each iterator variable. I think leaving it alone should be ok (since almost no one will be using it). FOR is currently "dynamic" and has not caused much trouble when porting original Sinclair BASIC programs. In fact FOR loops are expensive in much ways (code, speed, etc). While and DO...LOOP are much faster and simpler.If you use expressions then you already have to use an extra variable (double the amount)Not exactly: the code that computes the FOR upper limit expression is the same (regardless its static or dynamic calculated on each iteration). The difference is that once it's used it's discarded (dynamic) or must be stored to be reused later (static). Other than that, there's no difference. I was to implement that anyway (there's another thread in this forum asking for that), but leaving the possibility to use a dynamic for if one wants. I meant: can't see why we must enforce dynamic removal once static is the default behaviour. Yes, it throws it away and if you want to retain it then you have to set up an extra variable in your code and by logic I assume that if you use the upper limit as an iterator it overwrites the upper limit instead of the case with static where it is kept as a single background variable. No need to enforce a removal but I do not see much sense in keeping a dynamic structure unless you want to shave off a one extra internal variable and the code to manage it meaning certain limitations. If you want to be really smart then the compiler could decide which loops would benefit from a dynamic structure vs a static one, and instead of having two sets of For-Next code in the compiler just do a branch based on a flag but that could eat up the savings made so... If you were going to implement it anyway then that's good, as a default. Thanks, Darkstar. boriel Administrator Posts: 1,757 Threads: 55 Joined: Aug 2019 Reputation: 24 03-30-2011, 07:13 PM Darkstar Wrote:No need to enforce a removal but I do not see much sense in keeping a dynamic structure unless you want to shave off a one extra internal variable and the code to manage it meaning certain limitations. If you want to be really smart then the compiler could decide which loops would benefit from a dynamic structure vs a static one, and instead of having two sets of For-Next code in the compiler just do a branch based on a flag but that could eat up the savings made so...Hey, that's a much nicer idea instead:!: But could be difficult. At the moment, only constant expressions are detected as invariant code. There's still much work to do in this area. Please, be patient. Darkstar Member Posts: 92 Threads: 8 Joined: Mar 2011 Reputation: 0 03-30-2011, 09:49 PM boriel Wrote:Not exactly: the code that computes the FOR upper limit expression is the same (regardless its static or dynamic calculated on each iteration). The difference is that once it's used it's discarded (dynamic) or must be stored to be reused later (static). Other than that, there's no difference. I was to implement that anyway (there's another thread in this forum asking for that), but leaving the possibility to use a dynamic for if one wants. I meant: can't see why we must enforce dynamic removal once static is the default behaviour. Found it: help-support/topic434.html#p1124 boriel Wrote:Notice also that FOR upper limit is evaluated ON EACH iteration (like C). So if len(a\$) changes, the loop will shorten. So better use a temporary var l to store initial LEN(a\$). Arrays subscripts starts from 0 to N-1 (like in C). But this behavior can be changed using --sinclair or --array-base switch. NOTE: I'm planning (for compatibility) an --string-base (so LEN and string-slicing will work exactly as in Sinclair BASIC, by specifying --string-base=1). Also with FOR, stating --constant-for etc... Then how about evaluating the expression once and have internal variables for Lower, Higher and Step limits that do not chance as I assume that that is the traditional way in BASIC, or only the upper limit as the loop is already running. It could make for a speed gain. britlion Posting Freak Posts: 805 Threads: 135 Joined: Apr 2009 Reputation: 5 03-31-2011, 09:57 AM You know it occurs to me that it might spot cases where it could keep it on register. Simple loops that don't do much, and live below 256 for B or 65536 for BC.. Remember that code I showed you that made djnz-like speed from a 16 bit counter? Perhaps implementing a push-pop to bc if it calls something that would need that register. But quite a lot of for-next loops are to a static number, or in the next best case from something like 1 to uInteger. Both of which could be stored in registers, assuming that doesn't get too complicated. And of course, it would be blinding fast « Next Oldest | Next Newest »

Forum Jump:

Users browsing this thread: 1 Guest(s)