Introspection: Difference between revisions
Content deleted Content added
m →{{header|Retro}}: update for retro12 |
|||
Line 1,554:
Nevertheless, you can use similar code to access all the variables in any package you like,
such as the GLOBAL package, which typically has absolutely nothing in it. Since the PROCESS package is even more global than GLOBAL, we used that instead. Go figure...
=={{header|Phix}}==
Phix has a version() routine which returns a string such as "0.8.0":
<lang Phix>?version()
?scanf(version(),"%d.%d.%d")[1]</lang>
{{out}}
<pre>
"0.8.0"
{0,8,0}
</pre>
The scanf() result is probably easier to test against.
Phix has a builtin abs() routine, which will be auto-included if referenced.
<lang Phix>include pmaths.e -- (needed pre-0.8.1 to work around a compiler bug [oops])
--include complex.e -- (not an auto-include, needed in all versions)
integer r_abs = routine_id("abs")
--integer r_abs = routine_id("complex_abs")
if r_abs!=-1 then
?call_func(r_abs,{-42})
end if</lang>
Using complex_abs() is probably closer to the task requirement in that if complex.e is not included it will not be found/called.<br>
In this case it happens to give exactly the same result, however under the hood it is actually returning sqrt((-42)*(-42)+(0)*(0)).
There is (as yet) no var_id() builtin, the following is a quick cobbling-together of code from builtins\VM\prtnidN.e (routine_id)
and builtins\VM\pDiagN.e (ex.err file creation), not very pretty but it seems to work, and of course all this sort of stuff is
normally hidden away out of sight in builtins\VM.
<lang Phix>include builtins/VM/pStack.e -- :%opGetST
-- copies from pglobals.e:
constant S_Name = 1, -- const/var/rtn name
S_NTyp = 2, -- Const/GVar/TVar/Nspc/Type/Func/Proc
S_FPno = 3, -- File and Path number
S_Slink = 6, -- scope/secondary chain (see below)
S_vtype = 7, -- variable type or namespace fileno
S_GVar2 = 2, -- global or static variable
T_int = 1,
T_EBP = 22, -- compiled/listing=0, interpreted={ebp4,esp4,sym4} (set at last possible moment)
T_ds4 = 23 -- compiled = start of data section, same but /4 when interpreted ([T_EBP]!=0)
function var_id(object s)
-- hacked copy of routine_id(), for local file-level integers only
integer res, -- symidx for string s, else sum(local gvar integers)
rtn, -- routine number of callee, from callstack
cFno, -- calling fileno.
tidx,
ds4
object symtab,
si, -- copy of symtab[i], speedwise
si_name -- copy of symtab[i][S_name], speedwise/thread-sfaety
-- get copy of symtab. NB read only! may contain nuts! (unassigned vars)
enter_cs()
#ilASM{
[32]
lea edi,[symtab]
call :%opGetST -- [edi]=symtab (ie our local:=the real symtab)
mov edi,[ebp+20] -- prev_ebp
mov edi,[edi+8] -- calling routine no
mov [rtn],edi
[64]
lea rdi,[symtab]
call :%opGetST -- [rdi]=symtab (ie our local:=the real symtab)
mov rdi,[rbp+40] -- prev_ebp
mov rdi,[rdi+16] -- calling routine no
mov [rtn],rdi
[]
}
if symtab[T_EBP]=0 then -- compiled
ds4 = floor(symtab[T_ds4]/4)
else -- interpreted
ds4 = symtab[T_ds4]
end if
cFno = symtab[rtn][S_FPno] -- fileno of callee (whether routine or toplevel)
res = iff(s=0?0:-1)
for i=1 to length(symtab) do
si = symtab[i]
if sequence(si)
and si[S_NTyp]=S_GVar2
and si[S_FPno]=cFno
and si[S_vtype]=T_int then
si_name = si[S_Name]
if s=0 then
-- cut-down version of pDiagN.e/getGvarValue():
integer gidx = si[S_Slink], novalue, o
#ilASM{
mov [novalue],0
[32]
mov esi,[ds4]
mov edx,[gidx]
shl esi,2
mov esi,[esi+edx*4+16] -- ([ds+(gidx+4)*4] == gvar[gidx])
cmp esi,h4
jl @f
mov [novalue],1
xor esi,esi
@@:
mov [o],esi
[64]
mov rsi,[ds4]
mov rdx,[gidx]
shl rsi,2
mov rsi,[rsi+rdx*8+24] -- ([ds+(gidx+3)*8] == gvar[gidx])
mov r15,h4
cmp rsi,r15
jl @f
mov [novalue],1
xor rsi,rsi
@@:
mov [o],rsi
[]
}
if novalue then
?{si_name,"no_value"}
else
res += o
end if
elsif s=si_name then
res = i
exit
end if
end if
end for
si_name = 0
si = 0
symtab = 0
leave_cs()
return res
end function
{} = routine_id("blurgzmp") -- force symtab name population..
-- (alt: see rbldrqd in pDiagN.e)
integer bloop = 5,
-- barf, -- triggers {"barf","no_value"}
burp = 35
bloop = 6
burp += 1
?var_id("bloop") -- >0 === exists
?var_id("blooop") -- -1 === does not exist
?var_id(0) -- bloop+burp = 42
?bloop+burp -- "", doh</lang>
{{out}}
<pre>
1257
-1
42
42
</pre>
As-is, of course, being integer-only-and-no-routine-level-vars, the above represents very limited practical value.
Other routines of interest include
<lang Phix>?platform() -- WINDOWS=2, LINUX=3
?machine_bits() -- 32 or 64
?machine_word() -- 4 or 8
?include_paths() -- eg {"C:\\Program Files (x86)\\Phix\\builtins\\",
-- "C:\\Program Files (x86)\\Phix\\builtins\\VM\\",
-- "C:\\Program Files (x86)\\Phix\\"}
-- (plus other application-specific directories)
?get_interpreter() -- eg "C:\Program Files (x86)\Phix\p.exe"
-- or perhaps "/home/pete/phix/p" on Linux</lang>
Phix supports the absolute bare minimum use of #ifdef, for compatibility with OpenEuphoria, however it is almost always better
to use platform() and friends as normal hll code, rather than that sort of language-within-a-language stuff, imnsho, and the
compiler is pretty good at optimising away most such os-specific tests and whole branches of irrelevant code (see EmitON=0).
=={{header|PHP}}==
|