Nested function: Difference between revisions

Line 641:
2. second
3. third</pre>
 
=={{header|Phix}}==
Prior to this task, Phix had no support whatsoever for nested functions.<br>
Instead I have taken the first baby steps and documented them.<br>
If your distribution does not include the following demo, you need a later version (not yet uploaded at the
time of writing). The source of that demo contains far more detailed information, and any updates.<br>
 
Yes, this is pig-ugly, and incomplete. But it is a good start for anyone that needs nested functions, and
shows what can be done in just a few (less than six) hours.
 
NB as it stands, the compiler front-end "thinks" that l_counter and sep live in the same place. They are
properly separate in the runtime/VM, but the front-end will happily emit nonsense code if you let it.
<lang Phix>--
-- demo\rosetta\Nested_function.exw
-- ================================
--
#ilASM{ jmp :fin
--
-- This is, of course, something the compiler should end up doing automatically,
-- and this assembly, or something similar, should be hidden away in builtins/VM.
--
:%opGetnlv -- [edi] := [esi] from frame edx
-- nb no reference counting (would be rqd)
[32]
sub esi,ebp -- --> frame offset
@@:
mov ecx,[ebp+20] -- ebp_prev
cmp [ecx+8],edx -- rtn
jne @b
mov eax,[esi+ecx]
mov [edi],eax
[64]
sub rsi,rbp -- --> frame offset
@@:
mov rcx,[rbp+40] -- rbp_prev
cmp [rcx+16],rdx -- rtn
jne @b
mov rax,[rsi+rcx]
mov [rdi],rax
[]
ret
 
:%opSetnlv -- [edi] in frame edx := [esi] (zeroed)
[32]
sub edi,ebp -- --> frame offset
@@:
mov ecx,[ebp+20] -- ebp_prev
cmp [ecx+8],edx -- rtn
jne @b
mov eax,[esi]
mov [edi+ecx],eax
mov [esi],ebx -- zero src
[64]
sub rdi,rbp -- --> frame offset
@@:
mov rcx,[rbp+40] -- rbp_prev
cmp [rcx+16],rdx -- rtn
jne @b
mov eax,[rsi]
mov [rdi+rcx],rax
mov [rsi],rbx -- zero src
[]
ret
::fin
}
 
function MakeList(string sep=". ")
integer counter = 0
function MakeItem()
-- -- what we'd really like to see:
-- counter += 1
-- return sprintf("%d%s%s",{counter,sep,{"first","second","third"}[counter]})
-- bar these locals, some idea of what the compiler should be doing:
integer l_counter
string l_sep
#ilASM{
[32]
mov edx,routine_id(MakeList)
lea esi,[counter]
lea edi,[l_counter]
call :%opGetnlv
lea esi,[sep]
lea edi,[l_sep]
call :%opGetnlv
[64]
mov rdx,routine_id(MakeList)
lea rsi,[counter]
lea rdi,[l_counter]
call :%opGetnlv
lea rsi,[sep]
lea rdi,[l_sep]
call :%opGetnlv
[]
}
l_counter += 1
#ilASM{
[32]
mov edx,routine_id(MakeList)
lea esi,[l_counter]
lea edi,[counter]
call :%opSetnlv
[64]
mov rdx,routine_id(MakeList)
lea rsi,[l_counter]
lea rdi,[counter]
call :%opSetnlv
[]
}
string res = sprintf("%d%s%s",{l_counter,l_sep,{"first","second","third"}[l_counter]})
#ilASM{
[32]
mov [l_sep],ebx -- (in lieu of proper refcounting)
[64]
mov [l_sep],rbx -- (in lieu of proper refcounting)
[]
}
return res
end function
sequence res = {}
for i=1 to 3 do
res = append(res,MakeItem())
end for
return res
end function
 
?MakeList()</lang>
{{out}}
<pre>
{"1. first","2. second","3. third"}
</pre>
 
=={{header|PHP}}==
7,820

edits