1. Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Mario Steele <eumario at trilake.net> Feb 13, 2005
- 542 views
Hello All, I just wanted report this bug before 2.5 went Final, cause this is indeed a major bug. I've tested this under 2.5 and 2.4, and 2.4 works correctly, but 2.5 does not. You can see it happening when you invoke the trace like I have it written.
with trace sequence stack constant NewValue = {0,0,1,0} stack = {} trace(1) function recursive_call(integer i) integer ib stack &= 0 ib = length(stack) stack[ib] = NewValue for x = 1 to 4 do if stack[ib][i] = 0 then stack[ib][i] = recursive_call(i+1) end if end for return ib end function integer i i = recursive_call(1) ? stack machine_proc(26,0)
It should be pretty self explainitory, but incase your wondering, stack is a top-level variable, not a temporary variable. when running through recursion calls, the last sequence to be added to the list, get's free'd, voided, or whatever, then it drops off the sequence list after the recursion call is completed. This shouldn't be happening, cause... again, stack is a top-level variable. I have confirmed that 2.5 Beta is the one I'm using when this happens, if anyone else wants to test, feel free to. The way the sequence SHOULD look after the exit of all recursion calls: stack = { {2,0,1,0}, {0,3,1,0}, {0,0,1,0} } The way the sequence DOES look with 2.5 Beta: stack = { {2,0,1,0} }
2. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Robert Craig <rds at RapidEuphoria.com> Feb 13, 2005
- 471 views
Mario Steele wrote: > I just wanted report this bug before 2.5 went Final, cause this is indeed > a major bug. I've tested this under 2.5 and 2.4, and 2.4 works correctly, > but 2.5 does not. You can see it happening when you invoke the trace > like I have it written. > > }}} <eucode> > with trace > sequence stack > > constant NewValue = {0,0,1,0} > stack = {} > > trace(1) > function recursive_call(integer i) > integer ib > stack &= 0 > ib = length(stack) > stack[ib] = NewValue > for x = 1 to 4 do > if stack[ib][i] = 0 then > stack[ib][i] = recursive_call(i+1) > end if > end for > return ib > end function > > integer i > i = recursive_call(1) > ? stack > machine_proc(26,0) > </eucode> {{{ It's not a bug. It's a change in the way things work in a rare, ambiguous, and undocumented area. I should mention this in the 2.5 alpha release notes or somewhere. In order to efficiently support the new $ feature, I had to change the order of operations when subscripts are performed on the left-hand-side of an assignment. e.g. stack[ib][i] = recursive_call(i+1) In 2.4, all expressions are evaluated first, then the lhs subscripting is performed and the rhs value is assigned. In 2.5, I (generally) need to perform each lhs subscript as I go along, from left to right, before evaluating the subscript expression that comes after it, since I may need to know the proper value of $ in the subsequent subscript expression. In 2.4, you obviously counted on recursive_call() being completed before the subscripted assignment was done, and you counted on stack being changed by the side-effects of that call, before the assignment to stack was done. None of this was documented in the Reference Manual. You just tried it, and it worked. In 2.5, the lhs var being subscripted will keep its original value (I just increment its ref count), and will then be modified by the assignment. The effect of any side-effects on that var (i.e. stack) will be lost as the assignment is completed. If I don't preserve the original value, I can easily have crashes due to your having "pulled the rug out from under me" while I'm in the middle of trying to subscript a now non-existent value. And, no, I don't want to insert checks all over the place for this bizarre situation. You only have to worry about this change if you are doing a subscripted assignment with multiple subscripts on the lhs, and in the same statement you are calling a function that has the side-effect of modifying the lhs var (even as it is being assigned-to). You can make things work the way you want, and also make your code more readable, by performing the function call in a separate statement before trying to modify the lhs variable. Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com
3. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Mario Steele <eumario at trilake.net> Feb 13, 2005
- 459 views
- Last edited Feb 14, 2005
Robert Craig wrote: > It's not a bug. > It's a change in the way things work in a rare, > ambiguous, and undocumented area. > > I should mention this in the 2.5 alpha release notes > or somewhere. > > In order to efficiently support the new $ feature, > I had to change the order of operations when subscripts > are performed on the left-hand-side of an assignment. e.g. > > stack[ib][i] = recursive_call(i+1) > > In 2.4, all expressions are evaluated first, then > the lhs subscripting is performed and the rhs value is assigned. > > In 2.5, I (generally) need to perform each lhs subscript as I go along, > from left to right, before evaluating the subscript expression > that comes after it, since I may need to know the proper value of $ > in the subsequent subscript expression. > > In 2.4, you obviously counted on recursive_call() being completed > before the subscripted assignment was done, and you counted > on stack being changed by the side-effects of that call, before > the assignment to stack was done. > None of this was documented in the Reference Manual. > You just tried it, and it worked. > > In 2.5, the lhs var being subscripted will keep its original > value (I just increment its ref count), and will then be > modified by the assignment. The effect of any side-effects > on that var (i.e. stack) will be lost > as the assignment is completed. If I don't preserve the original > value, I can easily have crashes due to your having > "pulled the rug out from under me" while I'm in the middle of > trying to subscript a now non-existent value. And, no, I don't > want to insert checks all over the place for this bizarre situation. > > You only have to worry about this change if you are doing > a subscripted assignment with multiple subscripts on the lhs, > and in the same statement you are calling a function > that has the side-effect of modifying the lhs var (even as it > is being assigned-to). > > You can make things work the way you want, and also > make your code more readable, by performing the function call > in a separate statement before trying to modify the lhs variable. Okay, all of this I can understand. However, this now just added a new level of complexity to my code for a OOP library I'm currently developing. The reason why I brought this up, is cause I'm using a similar routine to create Nested Objects based apon a decloration of a class. EG:
Class("MyClassB") Member("MyVar1",INTEGER) EndClass() Class("MyClassA") Member("MyVar2",ATOM) Member("ClassB","MyClassB") EndClass() constant NewClass = new("MyClassA",{})
Since the new design of Euphoria, makes it impossible for me to correctly do recursive creation of Sub-Classes, I now have to find a way to create the sub-class effectivly, cause it seems to me, that anyway I go, according to the new rules, as soon as I exit a call, the sequence I just added to the variable, Now dis-appears on me. About the only way I can make this work, is if I have some kind of construct routine to create all the nested sequences, and when they are all created, return it to the caller, and have the caller store the entire sequence into the variable, in order for the changes to remain constant. This equals more instructions for the interpreter to execute, and parse, which will equal slower speeds. Not that I was developing this library for speed. Oh well, Back to the drawing board. Maybe I'll come up with something to make the changes STAY in the variable. Mario Steele
4. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Mario Steele <eumario at trilake.net> Feb 13, 2005
- 472 views
- Last edited Feb 14, 2005
Okay, after doing some experimenting, I found what you mean. You should word the Documentation, and explination more vividly, then what was originally stated: In order to recursivly assign something to a sequence, you need to in-directly assign the value after the recursive call is made. Example:
function recursive_call(integer i) integer ib, id stack &= 0 ib = length(stack) for x = 1 to 4 do if stack[ib][i] = 0 then id = recursive_call(i+1) stack[ib][i] = id end if end for return ib end function
Which to me, that's a waste of a variable space, that Euphoria is now forced to have to allocate, and deallocate everytime the function is ran through. But anyways, I got it figured out now. It lends nothing to readability, just confusion, and making recursive calls to modify sequences utterly useless. Mario Steele
5. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Pete Lomax <petelomax at blueyonder.co.uk> Feb 13, 2005
- 460 views
- Last edited Feb 14, 2005
On Sun, 13 Feb 2005 11:49:30 -0800, Mario Steele <guest at RapidEuphoria.com> wrote: >Oh well, Back to the drawing board. Maybe I'll come up with something to >make the changes STAY in the variable. What Rob actually said was you have to do this: tmp = recursive_call(i+1) stack[ib][i] = tmp Regards, Pete
6. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Derek Parnell <ddparnell at bigpond.com> Feb 13, 2005
- 499 views
- Last edited Feb 14, 2005
Mario Steele wrote: > > Hello All, > > I just wanted report this bug before 2.5 went Final, cause this is indeed > a major bug. I've tested this under 2.5 and 2.4, and 2.4 works correctly, > but 2.5 does not. You can see it happening when you invoke the trace > like I have it written. > > }}} <eucode> > with trace > sequence stack > > constant NewValue = {0,0,1,0} > stack = {} > > trace(1) > function recursive_call(integer i) > integer ib > stack &= 0 > ib = length(stack) > stack[ib] = NewValue > for x = 1 to 4 do > if stack[ib][i] = 0 then > stack[ib][i] = recursive_call(i+1) > end if > end for > return ib > end function > > integer i > i = recursive_call(1) > ? stack > machine_proc(26,0) > </eucode> {{{ > > It should be pretty self explainitory, but incase your wondering, stack > is a top-level variable, not a temporary variable. when running through > recursion calls, the last sequence to be added to the list, get's free'd, > voided, or whatever, then it drops off the sequence list after the recursion > call is completed. This shouldn't be happening, cause... again, stack is > a top-level variable. > > I have confirmed that 2.5 Beta is the one I'm using when this happens, if > anyone else wants to test, feel free to. > > The way the sequence SHOULD look after the exit of all recursion calls: > stack = { {2,0,1,0}, {0,3,1,0}, {0,0,1,0} } > > The way the sequence DOES look with 2.5 Beta: > stack = { {2,0,1,0} } Technically speaking its not a bug, in the sense that it is not failing to meet specifications. I will defend Robert's right to implement Euphoria with this behaviour, namely that from v2.5, Euphoria evaluates the left hand side (LHS) of an assignment before it evaluates the RHS. Even though no major language does this (they evaluate the RHS first then the LHS), Robert has the right to have Euphoria do what he likes. The reasons for him doing this aren't even relevant, because regardless of why he has choosen to change the behaviour of Euphoria, he has every right to do it. If any mistakes have been made, it could be that RDS has not documented this behaviour (i.e. specified it), and that RDS has not explicitly brought to our attention this change in behaviour. These are oversights that I'm positive will be rectified before the final release. It is not unreasonable for people to assume that RHS-before-LHS evaluation would be done, as this is the normal or common approach used in major languages such as C, C++, C#, Java, VB, COBOL, Pascal, Fortran, etc... It just needs to be clearly documented, with examples of how to make it work like we all expect, for us to move forward. I think we all agree that Euphoria is not a conventional language, in that it does do a few things that other languages do not do. For example the notable "if seq = seq then ..." syntax. Other languages regard this as a comparision operation, but Euphoria treats it as a sequence creation operation. So the precedent has been set for Euphoria to do things in a different manner from what we are accustomed to in other languages. The "work around" is to ensure that the LHS has no evaluations to be done that could be influenced by the RHS. So in your example code above, you could write ... if stack[ib][i] = 0 then lLocalTemp = recursive_call(i+1) stack[ib][i] = lLocalTemp end if However, now that this new behaviour has been brought to light, I will need to inspect Win32lib to make sure I'm not doing the undocumented thing. -- Derek Parnell Melbourne, Australia irc://irc.sorcery.net:9000/euphoria
7. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Mario Steele <eumario at trilake.net> Feb 13, 2005
- 479 views
- Last edited Feb 14, 2005
After reading the post you made, and doing several runs of my own, I've come to my own conclusion of how things are working now. You said, that you would have to make all kinds of checks throughout the code to make sure you wasn't screwing something up. To me, after looking at the program logic, both from execution, trial and error, and my own thoughts on program flow with Euphoria, I can only ask, Why this behavior was choosen over the default behavior? And yes, this is Documented in the Reference Manual. Section: 2.2.4 -> 2.2.9 If you notice, that's the majority of the Sequence refrence, but the more specific points are this: Section 2.2.5 Subscripting of Sequences " A single element of a sequence may be selected by giving the element number in square brackets. Element numbers start at 1. Non-integer subscripts are rounded down to an integer. For example, if x contains {5, 7.2, 9, 0.5, 13} then x[2] is 7.2. Suppose we assign something different to x[2]: x[2] = {11,22,33} Then x becomes: {5, {11,22,33}, 9, 0.5, 13}. Now if we ask for x[2] we get {11,22,33} and if we ask for x[2][3] we get the atom 33. If you try to subscript with a number that is outside of the range 1 to the number of elements, you will get a subscript error. For example x[0], x[-99] or x[6] will cause errors. So will x[1][3] since x[1] is not a sequence." Now why wouldn't this be valid as well, for your addition of the $? $ should be the last entry into the sequence, at the time of the evaluation of the lhs, just as with length() shows the length of the sequence at the time of evaluation. So, if you do this:
sequence stack stack = {1,2,3,4} procedure removeOne() stack = stac[1..length(stack)-1] end procedure integer i i = length(stack) removeOne() stack[i] = 1
It should error out. The same should be true for the '$' operator. I mean, it would only make sense. Oviously, the lhs evaluation length() is what we are wanting, not what we add to it, or remove from it. If we wanted that, then we would do that after the assignment, as it has allways been done before. I'm just trying to make sense of my own ideals of how Euphoria's rules are. And Derek Parnell is right, this is your interpreter. I'm just trying to see the point of trying to account for every possibility, with a single operator, when it isn't nesscarly needed. Mario Steele
8. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by "Kat" <gertie at visionsix.com> Feb 15, 2005
- 474 views
On 13 Feb 2005, at 12:14, Mario Steele wrote: > > > posted by: Mario Steele <eumario at trilake.net> > > Okay, after doing some experimenting, I found what you mean. > > You should word the Documentation, and explination more vividly, then what > was originally stated: > > In order to recursivly assign something to a sequence, you need to > in-directly assign the value after the recursive call is made. > > Example: > }}} <eucode> > function recursive_call(integer i) > integer ib, id > stack &= 0 > ib = length(stack) > for x = 1 to 4 do > if stack[ib][i] = 0 then > id = recursive_call(i+1) > stack[ib][i] = id > end if > end for > return ib > end function > </eucode> {{{ > > Which to me, that's a waste of a variable space, that Euphoria is now forced > to > have to allocate, and deallocate everytime the function is ran through. > > But anyways, I got it figured out now. It lends nothing to readability, > just confusion, and making recursive calls to modify sequences utterly > useless. Deja vu all over again. I stopped using Turbo Pascal because of variable- recursion problems like this. Kat
9. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Robert Craig <rds at RapidEuphoria.com> Feb 15, 2005
- 474 views
Kat wrote: > On 13 Feb 2005, at 12:14, Mario Steele wrote: > > But anyways, I got it figured out now. It lends nothing to readability, > > just confusion, and making recursive calls to modify sequences utterly > > useless. > > Deja vu all over again. I stopped using Turbo Pascal because of variable- > recursion problems like this. There are no known problems with recursion in Euphoria. The fact that his example uses recursion is a "red herring". The incompatibility that we discussed has *nothing* to do with recursion. It has to do with modifying a variable in two different ways in the same statement, and expecting it to work a certain way, even though the manual is silent on the issue. In 2.5 this rare and weird case now works differently when multiple subscripts are used on the lhs. The change was needed to efficiently support the new $ feature. Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com
10. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Alexander Toresson <alexander.toresson at gmail.com> Feb 15, 2005
- 484 views
Robert Craig wrote: > > Kat wrote: > > On 13 Feb 2005, at 12:14, Mario Steele wrote: > > > But anyways, I got it figured out now. It lends nothing to readability, > > > just confusion, and making recursive calls to modify sequences utterly > > > useless. > > > > Deja vu all over again. I stopped using Turbo Pascal because of variable- > > recursion problems like this. > > There are no known problems with recursion in Euphoria. Only disagreements of how it should work, and the current way is a problem in the eyes of many. > The fact that his example uses recursion is a "red herring". > The incompatibility that we discussed has *nothing* to do with recursion. Though it *does* affect recursion. > It has to do with modifying a variable in two different ways > in the same statement, and expecting it to work a certain way, > even though the manual is silent on the issue. In 2.5 this rare > and weird case now works differently when multiple subscripts > are used on the lhs. The change was needed to efficiently support > the new $ feature. Maybe it's rare, but not weird. I myself think it's obvious that the rhs is evaluated before the lhs is evaluated and assigned the value of the rhs. Because that's what the code says. Evaluate the rhs, then assign it to the lhs. I don't understand the reason changing that. Regards, Alexander Toresson Assembly. Push 'till you pop.
11. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Robert Craig <rds at RapidEuphoria.com> Feb 15, 2005
- 490 views
Alexander Toresson wrote: > > Robert Craig wrote: > > There are no known problems with recursion in Euphoria. > > Only disagreements of how it should work, and the current way is a problem > in the eyes of many. I'm not aware of *any* complaints about how recursion is handled in Euphoria. Please elaborate. Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com
12. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Georg Wrede <georg at iki.fi> Feb 15, 2005
- 479 views
> > > > Example: > > }}} <eucode> > > function recursive_call(integer i) > > integer ib, id > > stack &= 0 > > ib = length(stack) > > for x = 1 to 4 do > > if stack[ib][i] = 0 then > > id = recursive_call(i+1) > > stack[ib][i] = id > > end if > > end for > > return ib > > end function > > </eucode> {{{ > > > > Which to me, that's a waste of a variable space, that Euphoria is now forced > > to > > have to allocate, and deallocate everytime the function is ran through. Is it actually true that such a temporary, local, variable gets into the executable? One would think that it'd be optimised away? -- Another Euphoric, since Nov. 18, 2004 --
13. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Robert Craig <rds at RapidEuphoria.com> Feb 15, 2005
- 490 views
Georg Wrede wrote: > Is it actually true that such a temporary, local, variable gets into > the executable? One would think that it'd be optimised away? The time and space used by the extra variable are both absolutely trivial, if not zero. Without the extra variable, Euphoria would anyway have to create an internal temp variable to hold the result. Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com
14. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by "Kat" <gertie at visionsix.com> Feb 15, 2005
- 465 views
- Last edited Feb 16, 2005
On 15 Feb 2005, at 11:03, Robert Craig wrote: > > > posted by: Robert Craig <rds at RapidEuphoria.com> > > Georg Wrede wrote: > > Is it actually true that such a temporary, local, variable gets into > > the executable? One would think that it'd be optimised away? > > The time and space used by the extra variable are both > absolutely trivial, if not zero. Without the extra variable, > Euphoria would anyway have to create an internal temp variable > to hold the result. Ok, lets do that, and save the programmer time and effort remembering it. Kat
15. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Georg Wrede <georg at iki.fi> Feb 15, 2005
- 482 views
- Last edited Feb 16, 2005
Kat wrote: > > On 15 Feb 2005, at 11:03, Robert Craig wrote: > > posted by: Robert Craig <rds at RapidEuphoria.com> > > Georg Wrede wrote: > > > Is it actually true that such a temporary, local, variable gets into > > > the executable? One would think that it'd be optimised away? > > > > The time and space used by the extra variable are both > > absolutely trivial, if not zero. Without the extra variable, > > Euphoria would anyway have to create an internal temp variable > > to hold the result. So, splitting
stack[ib][i] = function_call_with_side_effects(i+1)
on two lines, like
tmp = function_call_with_side_effects(i+1) stack[ib][i] = tmp
is actually "for free"!! Very nice. There's also the issue of writing non-ambiguous code. Just like putting a few extra parentheses in complicated logical expressions, splitting lines like the above just serve the reader of the code. They make a huge service to all by making it explicit what order of evaluation we want. Besides, the next guy who has to take over your code doesn't have to know esoteria and arcana about Euphoria enough to guess himself what the order of evaluation would be on a single line. (I could cite Stroustrup, Kernighan, Pike, Hunt, Meyers, Wilson, and others on this, but if this point doesn't get through to all, it probably wouldn't, even if I looked up the pages and quoted.) -- Another Euphoric, since Nov. 18, 2004 --
16. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Patrick Barnes <mrtrick at gmail.com> Feb 15, 2005
- 469 views
- Last edited Feb 16, 2005
On Tue, 15 Feb 2005 13:58:41 -0800, Georg Wrede <guest at rapideuphoria.com> wrote: > }}} <eucode> > tmp = function_call_with_side_effects(i+1) > stack[ib][i] = tmp > </eucode> {{{ > > is actually "for free"!! Very nice. > > There's also the issue of writing non-ambiguous code. Just like > putting a few extra parentheses in complicated logical expressions, > splitting lines like the above just serve the reader of the code. > > They make a huge service to all by making it explicit what order > of evaluation we want. Besides, the next guy who has to take over > your code doesn't have to know esoteria and arcana about Euphoria > enough to guess himself what the order of evaluation would be on > a single line. I agree, code should be written unambiguously. Rob, it's not possible to stop someone from creating unreadable code, but it would help the Euphoria community if a warning was given for ambiguous things like this - if a variable is modified in the same line as it is referenced. -- MrTrick
17. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by CChris <christian.cuvier at agriculture.gouv.fr> Feb 15, 2005
- 478 views
- Last edited Feb 16, 2005
Alexander Toresson wrote: > > Robert Craig wrote: > > > > Kat wrote: > > > On 13 Feb 2005, at 12:14, Mario Steele wrote: > > > > But anyways, I got it figured out now. It lends nothing to readability, > > > > just confusion, and making recursive calls to modify sequences utterly > > > > useless. > > > > > > Deja vu all over again. I stopped using Turbo Pascal because of variable- > > > recursion problems like this. > > > > There are no known problems with recursion in Euphoria. > > Only disagreements of how it should work, and the current way is a problem > in the eyes of many. > > > The fact that his example uses recursion is a "red herring". > > The incompatibility that we discussed has *nothing* to do with recursion. > > Though it *does* affect recursion. > > > It has to do with modifying a variable in two different ways > > in the same statement, and expecting it to work a certain way, > > even though the manual is silent on the issue. In 2.5 this rare > > and weird case now works differently when multiple subscripts > > are used on the lhs. The change was needed to efficiently support > > the new $ feature. > > Maybe it's rare, but not weird. I myself think it's obvious that the rhs is > evaluated before the lhs is evaluated and assigned the value of the rhs. > Because that's what the code says. Evaluate the rhs, then assign it to the > lhs. > > I don't understand the reason changing that. > >From the disassembly Matt posted, it appears that Eu does no constant folding usually. What RC is telling us is that $ uses some constant folding. When computing s[1][length(s[1])], the interpreter doesn't remember that there's a temporary var holding s[1] at the time it parses the second index; even worse, the temp was possibly destroyed, so that remembering it wouldn't help. Thus, s[1] is fetched once again, which is a waste of CPU cycles. s[1][$] does remember that s[1] is being subscripted, so that no extra time is spent looking twice for s[1] or its length. I remembered an old post 2-3 years ago about about Eu 2.3 not using constant folding as an optimisation tool, and found that would explain the story neatly. CChris > Regards, Alexander Toresson > > Assembly. Push 'till you pop. >
18. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Pete Lomax <petelomax at blueyonder.co.uk> Feb 16, 2005
- 458 views
On Tue, 15 Feb 2005 08:51:18 -0800, Robert Craig <guest at RapidEuphoria.com> wrote: >It has to do with modifying a variable in two different ways >in the same statement, Trying not to be toady, but that is an excellent point, not just for Eu but coding in any language. Regards, Pete
19. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by John E <jwfe at talk21.com> Feb 16, 2005
- 469 views
A look at the MISRA rules for using the C language is enough to put anyone off relying on side-effects. Not to mention many of the most useful standard libraries. Georg mentioned a Kernighan and Pike (amongst others) a few posts back. Here, from K&P's 'The Practice of Programming': str[i++] = str[i++] = ' '; is likely to give the wrong answer. Also: array[i++] = i; can give varying results. So the order of evaluation in perhaps the most pervasive language is not to be relied on. Fortunately Eu doesn't isn't C; no assigments-as-expressions here. Why use C habits dating from the time when compilers needed help to produce efficient code, in Eu? Personally, as only a recent and light user, I wouldn't miss $ if it was removed. John
20. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by "Juergen Luethje" <j.lue at gmx.de> Feb 16, 2005
- 492 views
Patrick Barnes wrote: <snip> > I agree, code should be written unambiguously. Rob, it's not possible > to stop someone from creating unreadable code, but it would help the > Euphoria community if a warning was given for ambiguous things like > this - if a variable is modified in the same line as it is referenced. I agree, too. Is it actually possible for Euphoria to detect such ambiguous code? If so, a warning IMHO would be very helpful. Are other languages capable of displaying a warning in such a situation? If not, that would give Euphoria another advantage over "normal" languages. Regards, Juergen
21. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Robert Craig <rds at RapidEuphoria.com> Feb 16, 2005
- 484 views
Juergen Luethje wrote: > > Patrick Barnes wrote: > > <snip> > > > I agree, code should be written unambiguously. Rob, it's not possible > > to stop someone from creating unreadable code, but it would help the > > Euphoria community if a warning was given for ambiguous things like > > this - if a variable is modified in the same line as it is referenced. > > I agree, too. Is it actually possible for Euphoria to detect such > ambiguous code? If so, a warning IMHO would be very helpful. Are other > languages capable of displaying a warning in such a situation? If not, > that would give Euphoria another advantage over "normal" languages. I could give a warning, but I think the false-alarm ratio would be too high for it to be useful. There would often be dozens or maybe hundreds of variables that might potentially be overwritten as a result of a function call. It's theoretically impossible to always know at compile-time whether a given variable will actually be overwritten at run-time. In many cases the potential will seem to be there, but in reality it will not happen. Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com
22. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Patrick Barnes <mrtrick at gmail.com> Feb 16, 2005
- 490 views
- Last edited Feb 17, 2005
On Wed, 16 Feb 2005 07:59:27 -0800, Robert Craig <guest at rapideuphoria.com> wrote: > I could give a warning, but I think the false-alarm ratio would > be too high for it to be useful. There would often be > dozens or maybe hundreds of variables that might potentially > be overwritten as a result of a function call. It's theoretically > impossible to always know at compile-time whether a given variable > will actually be overwritten at run-time. In many cases the > potential will seem to be there, but in reality it will not happen. Maybe hundreds? I don't mean a warning when a global variable might be modified in a function, I mean a warning where in LHS = RHS(), the LHS contains global variables that might be modified inside the RHS() function. I think you can agree that this is the case being discussed, and it's a problem that cannot be simply resolved by the programmer. Some examples:
integer i function do_i() i = 20 return i + 1 end function i = 10 i = do_i() }}} <eucode> In this case, it's no big deal, i will be rewritten by the function return anyway - no warning: i = 21 }}} <eucode> sequence arr arr = {1,2,3,4,5} function rem(integer i) arr = arr[1..i-1]&arr[i+1..$] return arr end function arr = rem(3)
Again, not a problem, as arr is rewritten by the function return - no warning: arr = {1,2,4,5}
sequence arr arr = {1,2,3,4,5} function rem(integer i) arr = arr[1..i-1]&arr[i+1..$] return i*i end function arr[3] = rem(3)
This is a problem, as the LHS has to be resolved... does it refer to arr before rem() is called, or after? WARNING. If after, arr = {1,2,9,5}. If before, who knows? Maybe i*i is assigned to an element that is deleted immediately after...
sequence arr integer ind arr = {1,2,3,4,5} ind = 3 function stuff() ind = 2 return 100 end function arr[ind] = stuff()
This is a problem, as the subscripting variable is changed by the function... WARNING If it's resolved before, arr = {1,2,100,4,5}. If after, arr = {1,100,3,4,5}
sequence arr integer ind arr = {1,2,3,4,5} ind = 3 function stuff() arr = {5,4,3,2,1} ind = 2 return 100 end function arr = arr[1..2] & stuff() & arr[ind]
Hmm, can the RHS ever be ambiguous? Maybe a problem, Rob? WARNING? Assuming that all the elements are resolved before the function: arr = {1,2, 100, 3} Assuming that elements are resolved after the function: arr = {5,4, 100, 4} Assuming that elements are resolved in their order: arr = {1,2, 100, 4} Very strange stuff, but it could quite easily happen. A similar example could occur where the LHS is an atom, with mathematical ops on the RHS rather than concats. Another example may occur where in a slice operation: arr[var..func()] , var is modified by func(). Seems to me, that warnings should occur if: * The left-hand-side is a sequence AND * The left-hand-side is subscripted by a variable AND * That variable is modified by the RHS function Or * The left-hand-side is a sequence AND * The left-hand-side is subscripted by a variable or a literal AND * The array is modified by the RHS function Or * An expression consists of both a variable and a function call (connected together with concat or mathop, etc) AND * That function call modifies the variable I don't think there would be many false positives here... Rob, what 'hundreds' are you talking about? -- MrTrick
23. Re: Major Bug in Interpreter [Attn: Robert Craig]
- Posted by Robert Craig <rds at RapidEuphoria.com> Feb 17, 2005
- 478 views
Patrick Barnes wrote: > I don't think there would be many false positives here... Rob, what > 'hundreds' are you talking about? When I was implementing this stuff several months ago, I did some tests, and found that while some examples were fairly trivial, it quite often turned out, especially in large Windows prgrams, that a very large number of variables could potentially be overwritten by a particular function call used on the RHS of a multiply subscripted assignment. The reasons for this are: 1. The function contains calls to other functions and procedures, which contain calls to other functions and procedures etc. ... 2. A call-back can happen whenever Euphoria calls a .dll routine. The Euphoria call-back function might modify variables, directly or through calls to other routines. 3. A program might have a forward call via routine id that opens up almost all the (non-private) variables in the whole program to possible modification A human might be able to analyze the source code and rule out the possibility of a routine calling another routine in a given situation, or a call-back happening, but it's not practical for the Euphoria parser to do this. If you want to experiment with warnings, modify source\parser.e to issue a warning anytime the variable "dangerous" is set to true. I think that's essentially what you are after. Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com