Re: Euphoria's strengths
- Posted by petelomax Jan 11, 2015
- 1532 views
like access to the var table
I certainly wouldn't complain if someone came up with a patch to implement this in Euphoria.
It's just plain hard to do.
Really? Of course I'm looking at this from a purely Phix perspective, and apart from nested block scopes, I'd say this was reasonably trivial.
Unless you were expecting it to magic previously-undeclared variables out of thin air or suchlike.
If one of those pesky fatal errors can print "i = 5" to an ex.err then the runtime can clearly map values/storage addresses and variables/names.
A good first step might be sharing ideas and maybe even code on how we can modify eu.ex and execute.e to do things like implement access to the variable table. Thoughts?
This is how it might go in Phix, not that I'm convinced it would necessarily prove to be particularly useful:
A var_id(), like routine_id(), is a simple integer index to the symbol table.
Only two fairly simple routines can actually use a variable id, set_var(id, x) and x = get_var(id).
NB The following two restrictions may cause arguments, but I'd rather limit things, even drastically, than have mildly incorrect code potentially cause any and all manner of weirdness...
Since it is not permitted to access a block scoped variable outside that scope, but the scope of a variable and a corresponding variable id may differ, variable ids may not be obtained for variables with a limited (block level) scope. In the example below var_id("i") and var_id("j") are fine but var_id("k") and var_id("l") are not, because of where i, j, k, and l are defined. Obviously, you are free to store a variable_id, when you can get one, in a block scoped variable.
While global and file-level variables have precisely one location, and variable ids for them can be used anywhere, parameters and locals can have zero or more locations, and variable ids for them can only be used in the same routine where they are declared. Oh, and obviously because of standard scope rules, that is also the only place you can obtain a variable id for a local in the first place. Both set_var and get_var check the currently active frame is correct, and hence a viable storage location exists, before proceeding (when dealing with a local variable). In the example code below there is absolutely no possible valid storage location to store the 7, as there is no active frame for f, which is where j lives.
The following code illustrates some permitted and invalid uses:
procedure p(integer id) set_var(id,4) end procedure integer i function f() integer j integer idi = var_id("i") integer idj = var_id("j") set_var(idi,5) -- fine p(idi) -- fine set_var(idj,6) -- fine p(idj) -- runtime error if c then integer k integer idk = var_id("k") -- error (k not top-level) end if return idj -- dubious end function set_var(f(),7) -- runtime error if c then integer l integer idl = var_id("l") -- error (l not top-level) end if
Technically it would be quite possible to make p(idj) find and trash the callee's j, but potentially risky, would have to would have to fail if g() called it anyway, unless f() called g(), and even then it could be an unrelated call we're clobbering...
Lastly, set_var() must also invoke the appropriate typecheck, if any.
I would be quite happy to make set_var() yield true/false rather than crash on invalid var_id. I'd want valid_id() over get_var() returning {SUCCESS,x} but I won't argue.
Did I miss anything?
Pete
PS Of course that was the theory, practice may be a different matter altogether.