1. Switch question - yet again!
- Posted by jessedavis Sep 28, 2016
- 11606 views
Windows 7 pro sp1 euphoria: 4.0.5 (362497032f33, 2012-10-11)
It's been nearly a week and again I am lost. I'm missing something but I don't see what it is.
include std/stack.e as st include jd/jd.e constant op = st:new(FILO) --create a new stack item push(op,23) --add integer 23 to stack pf(op,"op in main") --pf() prints anything inside the parenthesi pf(peek_top(op),"Top of the stack op") --just to show there is really something on the stack show_stack(op) ak() --forces the command window to stay open procedure show_stack(integer stk) pf(stk,"stk in procedure") pf(op,"op in procedure") switch stk do --this is line 15 case op then puts(1,"in first case...\n") case 3 then --just another case! end switch end procedure
Produces the following output:
op in main => 2
Top of the stack op => 23
stk in procedure => 2
op in procedure => 2
C:\Users\Jesse\Software\Euphoria\lexer\z.exw:15 in procedure show_stack()
A machine-level exception occurred during execution of this statement (signal 5)
... called from C:\Users\Jesse\Software\Euphoria\lexer\z.exw:8
--> See ex.err
Press Enter...
Any help would be appreciated...
thanks & Regards,
jd
2. Re: Switch question - yet again!
- Posted by Spock Sep 28, 2016
- 11569 views
Try replacing the switch/case block with a normal if block.
If it works perhaps you could do the same replacement _everywhere_ in your code.. and discover, strangely, that your programs all seem to be working better..
Spock
3. Re: Switch question - yet again!
- Posted by _tom (admin) Sep 28, 2016
- 11582 views
There is a mystery here which I can't explain.
Example 1 // works
include std/stack.e constant op = 1 ? op --> 1 integer stk = op ? stk --> 1 switch stk do case op then puts(1, "\n result is first stack \n" ) case else puts(1, "\n result is something else \n") end switch --> result is first stack
Example 2 // fails
include std/stack.e constant op = stack:new(FIFO) ? op --> 1 // "stacks" start numbering at one integer stk = op ? stk --> 1 switch stk do case op then puts(1, "\n result is first stack \n" ) case else puts(1, "\n result is something else \n") end switch --> machine level exeception
Since "op" is a constant, in theory it should work in a switch statement--but it fails.
Example 3 // works
include std/stack.e constant op = stack:new(FILO) ? op --> 1 // "stacks" start numbering at one stack:push(op, 23 ) ? stack:peek_top(op) --> 23 // value at top of "op" stack show_stack( op ) procedure show_stack( integer stk ) puts(1, "\n executing show_stack \n" ) ? stk ? op -- this does work if equal(stk,op) then puts(1, "\n result is first stack \n" ) else puts(1, "\n result is something else \n" ) end if end procedure --> result is first stack
_tom
4. Re: Switch question - yet again!
- Posted by petelomax Sep 28, 2016
- 11545 views
From April (may or may not be the same bug):
This is a known issue in Euphoria 4.1. This is not an issue in Euphoria 4.0. I invite you to use Euphoria 4.0 instead. I also think your post shows a much smaller and compact version of an example. I would like you to post it to ticket 944. Remove the Syntatic sugar provided by 4.1 and compile the latest sources of 4.0 so you don't get bit by the bugs in 4.0.5.
The ticket number is 944. It is available at http://openeuphoria.org/ticket/944.wc
SD Pringle
The changeset date is Mon May 02 21:36:47 2016 -0300 (4 months ago), it may be worth trying this on something built after that date.
Pete
5. Re: Switch question - yet again!
- Posted by jessedavis Sep 28, 2016
- 11512 views
Try replacing the switch/case block with a normal if block.
If it works perhaps you could do the same replacement _everywhere_ in your code.. and discover, strangely, that your programs all seem to be working better..
Spock
Yes, I can do this. I have done it before and sworn on a stack of Bibles I wouldn't use switch again. I am weak. It was such a simple piece of code. How could I go wrong?
All this aside, switch does have some useful features that makes coding easier and, if implemented suitably, should be more efficient than other methods.
Thanks for your prompt reply.
Regards,
jd
6. Re: Switch question - yet again!
- Posted by jessedavis Sep 28, 2016
- 11549 views
From April (may or may not be the same bug):
This is a known issue in Euphoria 4.1. This is not an issue in Euphoria 4.0. I invite you to use Euphoria 4.0 instead. I also think your post shows a much smaller and compact version of an example. I would like you to post it to ticket 944. Remove the Syntatic sugar provided by 4.1 and compile the latest sources of 4.0 so you don't get bit by the bugs in 4.0.5.
The ticket number is 944. It is available at http://openeuphoria.org/ticket/944.wc
SD Pringle
The changeset date is Mon May 02 21:36:47 2016 -0300 (4 months ago), it may be worth trying this on something built after that date.
Pete
I am not sure if this is the same problem. At the time the problem I was having was the value of a constant was somehow being changed while inside the switch statement. The effect was that it would choose the incorrect case, not crash the program.
In response to Mr. Pringle's suggestion I went back to:
Windows 7 pro sp1 euphoria: 4.0.5 (362497032f33, 2012-10-11)
I will try a later build if I can find one.
Thanks for the quick reply.
regards,
jd
7. Re: Switch question - yet again!
- Posted by PeteE Sep 28, 2016
- 11488 views
I tried reducing the test case. I think it comes down to using an integer with a delete routine attached as a case value. (stack.e uses eumem.e which uses delete routine) I filed a ticket.
procedure delete_proc(object x) puts(1, "deleting ") ? x end procedure constant op = delete_routine(1, routine_id("delete_proc")) switch op do case op then puts(1, "in first case...\n") end switch
deleting 1 /home/pete/Downloads/euphoria-4.1.0-Linux-x64/switchdelete.ex:8 A machine-level exception occurred during execution of this statement (signal 11) --> See ex.err
8. Re: Switch question - yet again!
- Posted by jessedavis Sep 28, 2016
- 11522 views
There is a mystery here which I can't explain.
_tom
This started out because I tried to use the stack feature spelled out in section 8.33.
Using the stack type definition causes a different error in the switch statement:
C:\Users\Jesse\Software\Euphoria\lexer\z.exw:16 <0091>:: found variable but expected 'else', an atom, string, constant or enum case op then ^
This in response to using:
stack op = st:new(FILO) --create a new stack item
So, I tried declaring it to be a constant type instead, producing the even worse program crash.
Anyway, thanks for you help.
regards,
jd
9. Re: Switch question - yet again!
- Posted by jessedavis Sep 28, 2016
- 11500 views
I tried reducing the test case. I think it comes down to using an integer with a delete routine attached as a case value. (stack.e uses eumem.e which uses delete routine) I filed a ticket.
Thanks guys. I'll leave you to it! The alligators have surfaced in another part of the plantation. I'll be gone until next week. Who would have thought that draining a swamp could be so difficult?
Regards,
jd
10. Re: Switch question - yet again!
- Posted by Spock Sep 28, 2016
- 11530 views
Try replacing the switch/case block with a normal if block.
If it works perhaps you could do the same replacement _everywhere_ in your code.. and discover, strangely, that your programs all seem to be working better..
Spock
Yes, I can do this. I have done it before and sworn on a stack of Bibles I wouldn't use switch again. I am weak. It was such a simple piece of code. How could I go wrong?
All this aside, switch does have some useful features that makes coding easier and, if implemented suitably, should be more efficient than other methods.
Wikipedia has some propaganda on the use of switch. In the very rare cases when I might need anything like it I do this:
while 1 do if x = a then .. end if -- fallthough here if x = b then .. exit end if -- break from block if x = c then .. end if exit end while
Slightly verbose but much safer and flexible ..
Spock
11. Re: Switch question - yet again!
- Posted by jessedavis Sep 29, 2016
- 11476 views
Wikipedia has some propaganda on the use of switch. In the very rare cases when I might need anything like it I do this:
Spock
Hand on Bible, I will NOT use switch statements.
Thanks for the Wikipedia article. Very interesting reading.
Thanks & Regards,
jd
12. Re: Switch question - yet again!
- Posted by irv Nov 12, 2022
- 9674 views
I tried reducing the test case. I think it comes down to using an integer with a delete routine attached as a case value. (stack.e uses eumem.e which uses delete routine) I filed a ticket.
procedure delete_proc(object x) puts(1, "deleting ") ? x end procedure constant op = delete_routine(1, routine_id("delete_proc")) switch op do case op then puts(1, "in first case...\n") end switch
deleting 1 /home/pete/Downloads/euphoria-4.1.0-Linux-x64/switchdelete.ex:8 A machine-level exception occurred during execution of this statement (signal 11) --> See ex.err
And... six years later, 4.2 gives the same error.
13. Re: Switch question - yet again!
- Posted by ghaberek (admin) Nov 14, 2022
- 9420 views
And... six years later, 4.2 gives the same error.
Well like I said, I haven't been working much on tickets. I poked at that one and suggested a patch to try. We should discuss further in the ticket comments: https://openeuphoria.org/ticket/963.wc
-Greg
14. Re: Switch question - yet again!
- Posted by SDPringle Nov 15, 2022
- 9234 views
I can make for you available a Euphoria 4.2 build. Do you have GNU C (MINGW) installed for compiling Euphoria?
15. Re: Switch question - yet again!
- Posted by jessedavis Nov 15, 2022
- 9213 views
This is amazing! I gave up on switch ages ago. It is good to see someone is thinking about it as it is a useful shorthand way to deal with selections. Now Euphoria is the only language I use as it is the fastest way to generate code.
Thanks for all you do.
Regards, jd
16. Re: Switch question - yet again!
- Posted by irv Nov 15, 2022
- 9130 views
I can make for you available a Euphoria 4.2 build. Do you have GNU C (MINGW) installed for compiling Euphoria?
Yes, I do, and I compiled 4.2 just 2 days ago, from github:
Euphoria Interpreter v4.2.0 development 64-bit Linux, Using System Memory Revision Date: 2022-07-03 04:24:05 Id: 29ec7a3b83a082a0b62ddb15f2dabeb4c1c52bafDo you have a modified version to test?
17. Re: Switch question - yet again!
- Posted by SDPringle Nov 16, 2022
- 8950 views
It is clear none of us has the time/ability combination to fix the innumerable problems with attaching destructors to atoms. Euphoria 4.0 went fast for adding new features and whenever you do so defects get introduced along with features. Some might have the ability to track down this bug but apparently not the time (inclination). Others may have lots of time and want to but not the ability.
I have come to avoid doing certain things:
Features I avoid using include:
- attaching destructors to atoms
- Using object() as a function to determine whether you set your variable or not
- std/http.e routines
- ifdef style syntax
- things that would be impossible or illegal in C/node/Java.
The first two are avoided because there are all kinds of corner cases that bite you. Putting an uninitialized object into object() is totally unneeded when you can have dummy values. It sometimes takes years before someone notices a bug that gets introduced. So, I tend to use the features that have been around longer rather than the newer stuff. I have never had a problem with the flow control statements. These seem rock solid. Library routines are different because they run on top of the front end and generally keep with my avoid list above. However, I don't use std/http.e because it is and has always been obsolete. We were already with HTTPS everywhere when someone added it. If you need to transfer over the internet, use curl.
With ifdef you can perfectly check for platforms that don't exist or are misspelled or of the wrong case. This results in hours lost because of a typo in debugging. It's like the macro processor for C except far more primitive.
Lastly, because I mostly write in Node/C plus plus/Java, a lot of the habits I learned in these languages become part of my coding style. Therefore, I think the same is true for most people. So using a non-literal as a case value is something probably none of the development team ever tried. So that's another reasons this bug would exist.
18. Re: Switch question - yet again!
- Posted by ghaberek (admin) Nov 16, 2022
- 8983 views
It is clear none of us has the time/ability combination to fix the innumerable problems with attaching destructors to atoms. Euphoria 4.0 went fast for adding new features and whenever you do so defects get introduced along with features. Some might have the ability to track down this bug but apparently not the time (inclination). Others may have lots of time and want to but not the ability.
This has definitely been the case with me. It's taken literally years to get up to speed on the internals of Euphoria and start adding or fixing things.
The first two are avoided because there are all kinds of corner cases that bite you. Putting an uninitialized object into object() is totally unneeded when you can have dummy values. It sometimes takes years before someone notices a bug that gets introduced. So, I tend to use the features that have been around longer rather than the newer stuff. I have never had a problem with the flow control statements. These seem rock solid.
Euphoria MVC makes heavy use of maps which it turns out didn't release from std/eumem.e correctly depending on how I passed them around. I ended up writing mvc/mapdbg.e to track this down so an app running in the development web server wouldn't run out of memory so quickly. I also use switch a lot and have never run into the issue but I can't say I've ever assigned a destructor to a constant. It seems irrelevant to do so but it still shouldn't cause an issue.
Library routines are different because they run on top of the front end and generally keep with my avoid list above. However, I don't use std/http.e because it is and has always been obsolete. We were already with HTTPS everywhere when someone added it. If you need to transfer over the internet, use curl.
I'm planning bundle a libcurl wrapper with Euphoria 4.2 (including DLLs on on Windows and rely on system libcurl on *nix). I originally planned to then rebuild std/net/http.e as a wrapper for CURL but after working on FFI I'm thinking I'll just mark std/net/http.e routines as deprecate and leave it at that.
With ifdef you can perfectly check for platforms that don't exist or are misspelled or of the wrong case. This results in hours lost because of a typo in debugging. It's like the macro processor for C except far more primitive.
I wonder if we should adapt this feature to contain table of all potential standard ifdef conditions that start at "off" and get flipped to "on" accordingly. Then we could add a warning for unrecognized conditions. Even add a similarity matching for unknown conditions. Something like "skipping unknown ifdef condition BITS34. did you mean BITS32?" And for truly optional conditions, you could also add without warning += ifdef CONDITION to avoid unnecessary "unknown ifdef CONDITION."
Lastly, because I mostly write in Node/C plus plus/Java, a lot of the habits I learned in these languages become part of my coding style. Therefore, I think the same is true for most people. So using a non-literal as a case value is something probably none of the development team ever tried. So that's another reasons this bug would exist.
We should ensure Euphoria isn't a language that causes too much friction for folks coming from other languages or using several languages at once. So far I think we've done a good job of that but it's important to keep in mind as we make changes. In this case, constants should be constant and releasing a constant before the end of the program should cause a big red flag. But the backend doesn't check the symbol table for an object's scope during a cleanup. Maybe it should if it's not too much work and won't a performance hit? It would only need to be for user-defined cleanups not all dereferencing in general.
-Greg
19. Re: Switch question - yet again!
- Posted by SDPringle Nov 21, 2022
- 8192 views
I'm planning bundle a libcurl wrapper with Euphoria 4.2 (including DLLs on on Windows and rely on system libcurl on *nix). I originally planned to then rebuild std/net/http.e as a wrapper for CURL but after working on FFI I'm thinking I'll just mark std/net/http.e routines as deprecate and leave it at that.
I agree. Because our user base is small, let's leave it in there so we don't infuriate the n users that use it. I wonder whether n is 0.
I wonder if we should adapt this feature to contain table of all potential standard ifdef conditions that start at "off" and get flipped to "on" accordingly. Then we could add a warning for unrecognized conditions. Even add a similarity matching for unknown conditions. Something like "skipping unknown ifdef condition BITS34. did you mean BITS32?" And for truly optional conditions, you could also add without warning += ifdef CONDITION to avoid unnecessary "unknown ifdef CONDITION."
That sounds great, if you have time for that. You could also need a statement to declare for user defined symbols for ifdef. Suppose one wants to create a symbol like NDEBUG for ifdef statements. Today you would simply use
ifdef NDEBUG then print(1, "here\n") end ifdef
But you mostly wouldn't need to remove the warning if there was another statement available like 'declare NDEBUG' that you could use as this:
-- this, in my imaginary Euphoria 4.2, tells the interpreter that NDEBUG might be used in a ifdef export declare NDEBUG
We should ensure Euphoria isn't a language that causes too much friction for folks coming from other languages or using several languages at once. So far I think we've done a good job of that but it's important to keep in mind as we make changes. In this case, constants should be constant and releasing a constant before the end of the program should cause a big red flag. But the backend doesn't check the symbol table for an object's scope during a cleanup. Maybe it should if it's not too much work and won't a performance hit? It would only need to be for user-defined cleanups not all dereferencing in general.
-Greg
As you know, internally when a destructor is added to an integer the representation of integer objects use a structure, which contains the reference count and store the integer as a double or long double, and a pointer to the destructor. This gets returned. If this new object triggers a INT_CHECK operation through trying to optimize a switch then the destructor gets called prematurely. That happens and in this case it seems like it is a use after free or double free error in the backend.
- idea: get rid of destructors on integers. Save yourself a lot of headaches and probably fix other bug scenarios also. The cost is type safety now because all of the io routines would have to accept general atoms for the file handle rather than only integers.
- idea: make switches generate the same code as if x = case1 then ... elsif x = case2 then ... ... end if
- idea: remove all C-int style optimization. Change the front-end system so that objects are never assumed at compile time to be integers. I don't have the skill set for this and would probably introduce more bugs.
- idea: get rid of delete_routine all together. Nobody likes this idea but for completeness I include it here.
20. Re: Switch question - yet again!
- Posted by ghaberek (admin) Nov 21, 2022
- 8204 views
I agree. Because our user base is small, let's leave it in there so we don't infuriate the n users that use it. I wonder whether n is 0.
I was going to put together a feature survey but it looks like Google killed Surveys, so I have to find another service and I've apparently lost whatever surveys I had created in the past.
So give me a bit to review survey options and I'll put something together to see who uses what. (I will not include any personal identity questions this time; I learned my lesson last time.)
That sounds great, if you have time for that. You could also need a statement to declare for user defined symbols for ifdef. Suppose one wants to create a symbol like NDEBUG for ifdef statements. Today you would simply use
ifdef NDEBUG then print(1, "here\n") end ifdef
But you mostly wouldn't need to remove the warning if there was another statement available like 'declare NDEBUG' that you could use as this:
-- this, in my imaginary Euphoria 4.2, tells the interpreter that NDEBUG might be used in a ifdef export declare NDEBUG
I was going to combine define your own words and with / without warning like this:
without warning define NDEBUG -- ignore warning when NDEBUG is not defined ifdef NDEBUG then print(1, "here\n") end ifdef
As you know, internally when a destructor is added to an integer the representation of integer objects use a structure, which contains the reference count and store the integer as a double or long double, and a pointer to the destructor. This gets returned.
I thought it was simply promoting the integer to an atom. Is it using some other structure to carry an integer value with a destructor? Where is this defined?
-Greg
21. Re: Switch question - yet again!
- Posted by SDPringle Nov 22, 2022
- 8022 views
As you know, internally when a destructor is added to an integer the representation of integer objects use a structure, which contains the reference count and store the integer as a double or long double, and a pointer to the destructor. This gets returned.
I thought it was simply promoting the integer to an atom. Is it using some other structure to carry an integer value with a destructor? Where is this defined?
-Greg
In my own way, I was describing promotion of an integer to an atom. Sometimes code counts on passed values being integers and the bug here would seem to be a failure to check whether it is a native integer or promoted integer to atom in the generated C code (and thus the translator part) or the C language back-end part.
22. Re: Switch question - yet again!
- Posted by petelomax Nov 22, 2022
- 8020 views
- Last edited Nov 23, 2022
Features I avoid using include:
- Using object() as a function to determine whether you set your variable or not
Just so you know, that is kinda the way Phix implements optional parameters, if you have:
-- file e06a.e object dflt = "default\n" global procedure pd(object x=dflt) puts(1,x) end procedure
Then Phix effectively implements that as
global procedure pd(object x=<undefined>) if not object(x) then x=dflt end if
I don't know too much about how Euphoria works, except to say that if you also have:
include e06a.e procedure p() object dflt = "p's default\n" pd() end procedure procedure q() pd() end procedure p() q() -- output: Phix/4.1.0 4.0.0 -- default p's default -- default default
Which lightly surprised me, I didn't know there had been a change between 4.0 and 4.1 but the former looks in both [local] scopes. Anyway, no matter.
It's taken literally years to get up to speed on the internals of Euphoria and start adding or fixing things.
I often wonder how long it would take someone to get to grips with the innards of Phix.
- idea: get rid of destructors on integers. The cost is type safety now because all of the io routines would have to accept general atoms for the file handle rather than only integers.
I am considering that too, see below.
Alternatively, you could force (only whenever delete_routine() is involved) say:
--integer fn = delete_routine(open(...)); puts(fn,"hello") ==> sequence fn = delete_routine({open(...)}); puts(fn[1],"hello")
- idea: make switches generate the same code as if x = case1 then ... elsif x = case2 then ... ... end if
Phix generates the same ir for both "switch" and "if" constructs, then (since there is a potential significant speed gain) decides whether to emit a cmp/jmp daisy-chain or a jump table (better for >8, I found).
[Of course it applies all the extra required "is switchable" checks such as all tests on same lhs var, no and/or/</<=/>/>=/!=, etc.]
- idea: get rid of destructors on integers.
- idea: get rid of delete_routine all together. Nobody likes this idea but for completeness I include it here.
Slightly off to one side, I was [yet again] contemplating adding an array type (fixed length, homogenous/all-integers or all-floats).
Part of the reason for doing that was to get rid of reference counts [and shifted memory addresses] on floats [that is, within said, now if I could do it for all floats...]
Three things popped out of that:
- first: of course there wouldn't be any ref counts, delete_routines, etc on any of the individual elements.
- second: I already had the perfect type for that, a (binary) string, just the compiler needs to understand it has a different [local] use.
- third: there really should be a way to add arbitrary attributes to a sequence (and strings, but certainly not atoms).
A delete_routine would actually be better held in such an attribute system, and in fact I could use the existing space for a delete_routine as some kind of [potentially indirected, and
maybe even multiple times] "attribute index", and that way allow the programmer total (or at least a or b style) flexibility over "per sequence" or "per class of sequence" attributes.
The ex.err could end up something like:
main.exw: filepath[attrdx:2] = {"name","path"} builtins/attributes.e: attributes[1] = {...} attributes[2] = {...} -- (this one applies/belongs to filepath)
Anyway, I didn't really finish that design thought, it would certainly need something akin to delete routines to manage it's own cleanup, and I certainly didn't get round to writing any actual code.
23. Re: Switch question - yet again!
- Posted by katsmeow Nov 25, 2022
- 7505 views
I'm planning bundle a libcurl wrapper with Euphoria 4.2 (including DLLs on on Windows and rely on system libcurl on *nix). I originally planned to then rebuild std/net/http.e as a wrapper for CURL but after working on FFI I'm thinking I'll just mark std/net/http.e routines as deprecate and leave it at that.
I agree. Because our user base is small, let's leave it in there so we don't infuriate the n users that use it. I wonder whether n is 0.
Three opinions:
If i ever get a website again, i won't spring for https support. It's like, i put the site up for people to read, why secure it so people can read it in private? As a consumer, wget.
On a lan that's airgapped from the net, plain ole http is a handy way for those computers to talk amongst themselves.
PS: i do use wget-1.20.3-win64 , called from OE sometimes, to access https sites online. I've used wget since the Eu v3 days.
Kat
24. Re: Switch question - yet again!
- Posted by ghaberek (admin) Nov 28, 2022
- 7101 views
If i ever get a website again, i won't spring for https support. It's like, i put the site up for people to read, why secure it so people can read it in private? As a consumer, wget.
HTTPS is less about privacy and more about security: providing a validated certificate ensures identity about the web server that regular HTTP is incapable of providing. This prevents man-in-the-middle attacks from compromising the integrity of the request between server and client. Is it perfect? No. But in the modern age cybersecurity it's a huge step in the right direction.
On a lan that's airgapped from the net, plain ole http is a handy way for those computers to talk amongst themselves.
Of course, certainly. I think it's very helpful to be able to stand up a simple HTTP-only service for private use and for local testing and development. Adding HTTPS would only complicate matters. I've started work on a development web server on the Euphoria MVC project that I may move back to Euphoria itself. It's basically the httpd.ex demo with a lot more bells and whistles. But it has no concept of HTTPS nor would I expect it to.
PS: i do use wget-1.20.3-win64 , called from OE sometimes, to access https sites online. I've used wget since the Eu v3 days.
Would there be much difference between making an external call to wget versus using a wrapper to call functions in libcurl.dll? I guess it's all about perspective and intent. I want to make applications that can call a URL and get back a string in real time (API calls, mostly). But if your intent is having something that determines which content it needs and then does something to download that content, calling out to wget works all the same. Leaving one application for another and then waiting for it to complete has its costs, but then again so does having to build a "call" in parts and the process the result. Tomayto/tomahto, I suppose.
-Greg