### 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

### 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")
```

### 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

### 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

### 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")
```

```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?

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