1. Introspection?

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

new topic     » topic index » view message » categorize

2. Re: Introspection?

axtens_bruce said...
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") 
new topic     » goto parent     » topic index » view message » categorize

3. Re: Introspection?

ChrisB said...

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

new topic     » goto parent     » topic index » view message » categorize

4. Re: Introspection?

axtens_bruce said...

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! 

axtens_bruce said...

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

new topic     » goto parent     » topic index » view message » categorize

5. Re: Introspection?

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?

new topic     » goto parent     » topic index » view message » categorize

6. Re: Introspection?

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

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu