Introspection: Difference between revisions

m
→‎{{header|Phix}}: added syntax colouring the hard way
(Added Arturo implementation)
m (→‎{{header|Phix}}: added syntax colouring the hard way)
Line 1,571:
=={{header|Phix}}==
The requires procedure behaves like a compiler directive, although it is in fact just a normal executable routine.
 
<lang Phix>requires("0.8.2") -- crashes on 0.8.1 and earlier
<!--<lang Phix>-->
requires(WINDOWS) -- crashes on Linux
<span style="color: #7060A8;">requires<span style="color: #0000FF;">(<span style="color: #008000;">"0.8.2"<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- crashes on 0.8.1 and earlier </span>
requires(64) -- crashes on 32-bit</lang>
<span style="color: #7060A8;">requires<span style="color: #0000FF;">(<span style="color: #000000;">WINDOWS<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- crashes on Linux </span>
<span style="color: #7060A8;">requires<span style="color: #0000FF;">(<span style="color: #000000;">64<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- crashes on 32-bit
<!--</lang>-->
 
If passed a string it compares it (intelligently) against the interpreter/compiler version and terminates in error with a suitable message should it be too old to cope. Otherwise the parameter must be an integer: <32 checks the platform, >=32 checks the word size. In the latter case when (interpreting and) it needs to, it hunts for a suitable alternative runtime and offers to re-run with that, maybe you need bigger ints, or maybe you only ship a 32-bit libcurl.dll.
 
The version() routine used by the above can also be called directly and returns a string:
 
<lang Phix>?version() -- eg "0.8.0"</lang>
<!--<lang Phix>-->
<span style="color: #0000FF;">?<span style="color: #7060A8;">version<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- eg "0.8.0"
<!--</lang>-->
 
Normally only really useful for display, but you can of course break that down into an integer triplet with scanf(), as requires does, maybe something works on 0.7.7 and 0.7.9 but not 0.7.8.
 
Phix has a builtin abs() routine, which will be auto-included if referenced.
 
<lang Phix>--include pmaths.e -- (an auto-include, ok but not needed)
<!--<lang Phix>-->
--include complex.e -- (not an auto-include, needed if used)
<span style="color: #000080;font-style:italic;">--include pmaths.e -- (an auto-include, ok but not needed)
integer r_abs = routine_id("abs")
--include complex.e -- (not an auto-include, needed if used)</span>
--integer r_abs = routine_id("complex_abs")
<span style="color: #004080;">integer</span> <span style="color: #000000;">r_abs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">routine_id<span style="color: #0000FF;">(<span style="color: #008000;">"abs"<span style="color: #0000FF;">)</span>
if r_abs!=-1 then
<span style="color: #000080;font-style:italic;">--integer r_abs = routine_id("complex_abs")</span>
?call_func(r_abs,{-42})
<span style="color: #008080;">if</span> <span style="color: #000000;">r_abs<span style="color: #0000FF;">!=<span style="color: #0000FF;">-<span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
end if</lang>
<span style="color: #0000FF;">?<span style="color: #7060A8;">call_func<span style="color: #0000FF;">(<span style="color: #000000;">r_abs<span style="color: #0000FF;">,<span style="color: #0000FF;">{<span style="color: #0000FF;">-<span style="color: #000000;">42<span style="color: #0000FF;">}<span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">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 first promoting the -42 to -42+0i before returning sqrt((-42)*(-42)+(0)*(0)).
Line 1,594 ⟶ 1,605:
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)
 
<!--<lang Phix>-->
function var_id(object s)
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins<span style="color: #0000FF;">/<span style="color: #000000;">VM<span style="color: #0000FF;">/<span style="color: #000000;">pStack<span style="color: #0000FF;">.<span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- :%opGetST
-- hacked copy of routine_id(), for local file-level integers only
-- copies from pglobals.e:</span>
integer res, -- symidx for string s, else sum(local gvar integers)
<span style="color: #008080;">constant</span> <span style="color: #000000;">S_Name</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- const/var/rtn name</span>
rtn, -- routine number of callee, from callstack
<span style="color: #000000;">S_NTyp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- Const/GVar/TVar/Nspc/Type/Func/Proc</span>
cFno, -- calling fileno.
<span style="color: #000000;">S_FPno</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">3<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- File and Path number</span>
tidx,
<span style="color: #000000;">S_Slink</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">6<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- scope/secondary chain (see below)</span>
ds4
<span style="color: #000000;">S_vtype</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">7<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- variable type or namespace fileno</span>
object symtab,
<span style="color: #000000;">S_GVar2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- global or static variable</span>
si, -- copy of symtab[i], speedwise
<span style="color: #000000;">T_int</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1<span style="color: #0000FF;">,</span>
si_name -- copy of symtab[i][S_name], speedwise/thread-sfaety
<span style="color: #000000;">T_EBP</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">22<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- compiled/listing=0, interpreted={ebp4,esp4,sym4} (set at last possible moment)</span>
<span style="color: #000000;">T_ds4</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">23</span> <span style="color: #000080;font-style:italic;">-- compiled = start of data section, same but /4 when interpreted ([T_EBP]!=0)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">var_id<span style="color: #0000FF;">(<span style="color: #004080;">object</span> <span style="color: #000000;">s<span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- hacked copy of routine_id(), for local file-level integers only</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">res<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- symidx for string s, else sum(local gvar integers)</span>
<span style="color: #000000;">rtn<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- routine number of callee, from callstack</span>
<span style="color: #000000;">cFno<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- calling fileno.</span>
<span style="color: #000000;">tidx<span style="color: #0000FF;">,</span>
<span style="color: #000000;">ds4</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">symtab<span style="color: #0000FF;">,</span>
<span style="color: #000000;">si<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- copy of symtab[i], speedwise</span>
<span style="color: #000000;">si_name</span> <span style="color: #000080;font-style:italic;">-- copy of symtab[i][S_name], speedwise/thread-sfaety
-- get copy of symtab. NB read only! may contain nuts! (unassigned vars)</span>
<span style="color: #000000;">enter_cs<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span>
<span style="color: #000000;"> #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
[]
}</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">symtab<span style="color: #0000FF;">[<span style="color: #000000;">T_EBP<span style="color: #0000FF;">]<span style="color: #0000FF;">=<span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- compiled</span>
<span style="color: #000000;">ds4</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #000000;">symtab<span style="color: #0000FF;">[<span style="color: #000000;">T_ds4<span style="color: #0000FF;">]<span style="color: #0000FF;">/<span style="color: #000000;">4<span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">-- interpreted</span>
<span style="color: #000000;">ds4</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">symtab<span style="color: #0000FF;">[<span style="color: #000000;">T_ds4<span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">cFno</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">symtab<span style="color: #0000FF;">[<span style="color: #000000;">rtn<span style="color: #0000FF;">]<span style="color: #0000FF;">[<span style="color: #000000;">S_FPno<span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- fileno of callee (whether routine or toplevel)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff<span style="color: #0000FF;">(<span style="color: #000000;">s<span style="color: #0000FF;">=<span style="color: #000000;">0<span style="color: #0000FF;">?<span style="color: #000000;">0<span style="color: #0000FF;">:<span style="color: #0000FF;">-<span style="color: #000000;">1<span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i<span style="color: #0000FF;">=<span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length<span style="color: #0000FF;">(<span style="color: #000000;">symtab<span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">si</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">symtab<span style="color: #0000FF;">[<span style="color: #000000;">i<span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence<span style="color: #0000FF;">(<span style="color: #000000;">si<span style="color: #0000FF;">)</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">si<span style="color: #0000FF;">[<span style="color: #000000;">S_NTyp<span style="color: #0000FF;">]<span style="color: #0000FF;">=<span style="color: #000000;">S_GVar2</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">si<span style="color: #0000FF;">[<span style="color: #000000;">S_FPno<span style="color: #0000FF;">]<span style="color: #0000FF;">=<span style="color: #000000;">cFno</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">si<span style="color: #0000FF;">[<span style="color: #000000;">S_vtype<span style="color: #0000FF;">]<span style="color: #0000FF;">=<span style="color: #000000;">T_int</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">si_name</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">si<span style="color: #0000FF;">[<span style="color: #000000;">S_Name<span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">s<span style="color: #0000FF;">=<span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- cut-down version of pDiagN.e/getGvarValue():</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">gidx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">si<span style="color: #0000FF;">[<span style="color: #000000;">S_Slink<span style="color: #0000FF;">]<span style="color: #0000FF;">,</span> <span style="color: #000000;">novalue<span style="color: #0000FF;">,</span> <span style="color: #000000;">o</span>
#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
[]
}
<span style="color: #008080;">if</span> <span style="color: #000000;">novalue</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">?<span style="color: #0000FF;">{<span style="color: #000000;">si_name<span style="color: #0000FF;">,<span style="color: #008000;">"no_value"<span style="color: #0000FF;">}</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">o</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">s<span style="color: #0000FF;">=<span style="color: #000000;">si_name</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">si_name</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">si</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">symtab</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">leave_cs<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #0000FF;">{<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">routine_id<span style="color: #0000FF;">(<span style="color: #008000;">"blurgzmp"<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- force symtab name population..
-- (alt: see rbldrqd in pDiagN.e)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bloop</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5<span style="color: #0000FF;">,</span>
<span style="color: #000080;font-style:italic;">-- barf, -- triggers {"barf","no_value"}</span>
<span style="color: #000000;">burp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">35</span>
<span style="color: #000000;">bloop</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">6</span>
<span style="color: #000000;">burp</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #0000FF;">?<span style="color: #000000;">var_id<span style="color: #0000FF;">(<span style="color: #008000;">"bloop"<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- >0 === exists</span>
<span style="color: #0000FF;">?<span style="color: #000000;">var_id<span style="color: #0000FF;">(<span style="color: #008000;">"blooop"<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- -1 === does not exist</span>
<span style="color: #0000FF;">?<span style="color: #000000;">var_id<span style="color: #0000FF;">(<span style="color: #000000;">0<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- bloop+burp = 42</span>
<span style="color: #0000FF;">?<span style="color: #000000;">bloop<span style="color: #0000FF;">+<span style="color: #000000;">burp</span> <span style="color: #000080;font-style:italic;">-- "", doh
<!--</lang>-->
 
-- 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>
Line 1,717 ⟶ 1,732:
 
Other routines of interest include
 
<lang Phix>?platform() -- WINDOWS=2, LINUX=3
<!--<lang Phix>-->
?machine_bits() -- 32 or 64
<span style="color: #0000FF;">?<span style="color: #7060A8;">platform<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- WINDOWS=2, LINUX=3</span>
?machine_word() -- 4 or 8
<span style="color: #0000FF;">?<span style="color: #7060A8;">machine_bits<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- 32 or 64</span>
?include_paths() -- eg {"C:\\Program Files (x86)\\Phix\\builtins\\",
<span style="color: #0000FF;">?<span style="color: #7060A8;">machine_word<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- 4 or 8</span>
-- "C:\\Program Files (x86)\\Phix\\builtins\\VM\\",
<span style="color: #0000FF;">?<span style="color: #7060A8;">include_paths<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- eg {"C:\\Program Files (x86)\\Phix\\builtins\\",
-- "C:\\Program Files (x86)\\Phix\\"}
-- (plus other application-specific directories"C:\\Program Files (x86)\\Phix\\builtins\\VM\\",
?get_interpreter() -- eg "C:\\Program Files (x86)\\Phix\p.exe\"}
-- or perhaps(plus "/home/pete/phix/p"other onapplication-specific Linuxdirectories)</langspan>
<span style="color: #0000FF;">?<span style="color: #7060A8;">get_interpreter<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- 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
7,830

edits