1. Introspection?
- Posted by axtens_bruce Mar 15, 2023
- 1059 views
procedure Hello(sequence place) puts(1, "Hello, " & place & "!\n") end procedure Hello("World")
Is there any way for Hello to be able to see its own name so that one might code
procedure Hello(sequence place) puts(1, me() & ", " & place & "!\n") end procedure Hello("World")
I can't think of a good reason right now for that ability. Just curious.
-Bruce
2. Re: Introspection?
- Posted by ChrisB (moderator) Mar 16, 2023
- 999 views
procedure Hello(sequence place) puts(1, "Hello, " & place & "!\n") end procedure Hello("World")
Is there any way for Hello to be able to see its own name so that one might code
procedure Hello(sequence place) puts(1, me() & ", " & place & "!\n") end procedure Hello("World")
I can't think of a good reason right now for that ability. Just curious.
-Bruce
Hi
Are you asking for recursion, where a procedure calls itself?
procedure Hello(sequence place) --puts(1, me() & ", " & place & "!\n") Hello("Continent on ") puts(1, place) end procedure Hello("World")
This does wok but watch for the infinite loops. Set a break flag
integer break_flag = 0 procedure Hello(sequence place) if break_flag > 1 then return end if break_flag += 1 Hello("Continent on ") puts(1, place) end procedure Hello("World")
3. Re: Introspection?
- Posted by axtens_bruce Mar 16, 2023
- 1014 views
Are you asking for recursion, where a procedure calls itself?
No. Instead I'm asking for a routine to "know" what it is, itself, called.
By way of background, consider 3 short items I wrote over on dev.to regarding similar abilities in C# and JavaScript.
-Bruce
4. Re: Introspection?
- Posted by ghaberek (admin) Mar 16, 2023
- 993 views
Is there any way for Hello to be able to see its own name so that one might code
This is somewhat supported by using call_stack() from euphoria/debug/debug.e, the same way I demonstrated for variable_id. (These routines need more documentation for the 4.2 release.)
But it's only available in the interpreter and things can get weird if the interpreter inlines a call, which will be left out of the stack (you can disable this using without inline for a small performance loss).
Here's an example that sort-of recreates the C preprocessor macros like __LINE__ and __FILE__ (although they're functions here since we don't have macros per se).
include euphoria/debug/debug.e -- cs[1] is call_stack() itself -- cs[2] is the calling routine function __FUNC() sequence cs = call_stack() return cs[2][CS_ROUTINE_NAME] end function function __FILE() sequence cs = call_stack() return cs[2][CS_FILE_NAME] end function function __LINE() sequence cs = call_stack() return cs[2][CS_LINE_NO] end function -- heck, let's throw date and time in there too! constant MONTH = {"Jan","Feb","Mar","Apr","May", "Jun","Jul","Aug","Sep","Oct","Nov","Dec"} function __DATE() sequence d = date() d[1] = d[1] + 1900 d[2] = MONTH[d[2]] return sprintf( "%s %02d %d", {d[2],d[3],d[1]} ) end function function __TIME() sequence d = date() return sprintf( "%02d:%02d:%02d", d[4..6] ) end function procedure Hello(sequence place) printf(1, "%s %s ", {__DATE(),__TIME()}) printf(1, "%s:%d ", {__FILE(),__LINE()}) printf(1, "%s, %s!\n", {__FUNC(),place}) end procedure Hello("World")
Output:
$ eui /tmp/demo.ex Mar 16 2023 11:32:05 /tmp/demo.ex:21 Hello, World!
I can't think of a good reason right now for that ability. Just curious.
I can: logging! I make heavy use of this feature in mvc/logger.e which will be ported to the standard library for Euphoria 4.2.
Right now you'd use it like this:
function max( atom x, atom y ) log_trace( "x=%g, y=%g", {x,y} ) return 0 end function ? max( 2, 3 )
Then call the interpreter with -D LOG_TRACE and get some fancy output complete with colored text (if writing to STDOUT or STDERR).
$ eui -D LOG_TRACE /tmp/demo.ex 2023-03-16 11:20:00 TRACE max@/tmp/demo.ex:2 x=2, y=3
In fact I should be able to combine that with what I demonstrated for variable_id() to provide cleaner and simpler per-call logging. Stay tuned for that.
-Greg
5. Re: Introspection?
- Posted by petelomax Mar 17, 2023
- 810 views
In Phix:
function me(integer rid) return get_routine_info(rid)[4] end function procedure Hello(sequence place) puts(1, me(Hello) & ", " & place & "!\n") end procedure Hello("World")
or
function me() integer rid #ilASM{ [32] mov eax,[ebp+20] -- prev_ebp mov eax,[eax+8] -- rtn_id mov [rid],eax [64] mov rax,[rbp+40] -- prev_rbp mov rax,[rax+16] -- rtn_id mov [rid],rax } return get_routine_info(rid)[4] end function procedure Hello(sequence place) puts(1, me() & ", " & place & "!\n") end procedure Hello("World")
If there is a real use for it, I could easily make get_routine_info(0) yield {...,"me"}, and get_routine_info(-1) yield {...,"Hello"}, ie get a rid<=0 from the call stack.
Heck, why not just do that anyway:
requires("1.0.3") function me() return get_routine_info(-1)[4] end function procedure Hello(sequence place) puts(1, me() & ", " & place & "!\n") end procedure Hello("World")
PS: My JavaScript implementation of get_routine_info() was this:
function get_routine_info(fn) { return ["sequence",fn.length,0,"",fn.name]; }
Which means:
"sequence": ignore this / 1-based indexes,
fn.length: the max number of arguments,
0: there is no min "" in js,
"": there is no function signature in a typeless language,
fn.name is probably a bit better than what you were using?
6. Re: Introspection?
- Posted by katsmeow Mar 17, 2023
- 777 views
Yanno, if type() could then know the name of the variable it was typechecking, and the name of the code block that called the typecheck, you could call code that executes if the typecheck fails, possibly fixing things up, and return something that makes less of a mess than an uncontrolled fatal error.
Or broadcast the variable has new contents. Or log time and what caused the data change. Or generate aux changes. So the Ai can know why it did that.
Kat