Skip to content

Commit

Permalink
Improve handling of methodcalls, hopefully it is good now
Browse files Browse the repository at this point in the history
Also took the chance to allow a map when creating a table.
  • Loading branch information
rvirding committed Feb 25, 2022
1 parent b0f1a5d commit 7789f30
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 14 deletions.
24 changes: 18 additions & 6 deletions src/luerl_emul.erl
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,7 @@ do_get_key(Is, Cont, Lvs, Stk, Env, Cs, St0, Tab, Key) ->
%% do_op2(Instrs, LocalVars, Stack, Env, State, Op) -> ReturnFromEmul.

do_op1(Is, Cont, Lvs, [A|Stk], Env, Cs, St0, Op) ->
%% We must handle the metamethod and error here.
case op(Op, A, St0) of
{value,Res,St1} -> emul(Is, Cont, Lvs, [Res|Stk], Env, Cs, St1);
{meta,Meth,Args,St1} ->
Expand All @@ -613,6 +614,7 @@ do_op1(Is, Cont, Lvs, [A|Stk], Env, Cs, St0, Op) ->
end.

do_op2(Is, Cont, Lvs, [A2,A1|Stk], Env, Cs, St0, Op) ->
%% We must handle the metamethod and error here.
case op(Op, A1, A2, St0) of
{value,Res,St1} -> emul(Is, Cont, Lvs, [Res|Stk], Env, Cs, St1);
{meta,Meth,Args,St1} ->
Expand Down Expand Up @@ -708,11 +710,20 @@ do_mcall(Is, Cont, Lvs, [Args,Obj|Stk], Env, Cs, St, M) ->

methodcall(Is, Cont, Lvs, Stk, Env, Cs, St0, Obj, Meth, Args) ->
%% Get the function to call from object and method.
case get_table_key(Obj, Meth, St0) of
{nil,St1} -> %No method
lua_error({undefined_method,Obj,Meth}, St1#luerl{stk=Stk,cs=Cs});
{Func,St1} ->
functioncall(Is, Cont, Lvs, Stk, Env, Cs, St1, Func, [Obj|Args])
%% We must handle the metamethod and error here.
%% io:format("mc1 ~p ~p ~p\n", [Obj,Meth,Args]),
case luerl_heap:get_table_key(Obj, Meth, St0) of
{value,Func,St1} ->
%% io:format("mc2 ~p\n", [Func]),
functioncall(Is, Cont, Lvs, Stk, Env, Cs, St1, Func, [Obj|Args]);
{meta,Mmeth,Margs,St1} ->
%% io:format("mc3 ~p ~p\n", [Mmeth,Margs]),
%% Must first meta method to get function and then call it.
%% Need to swap to get arguments for call in right order.
Is1 = [?FCALL,?SINGLE,?SWAP,?FCALL|Is],
emul(Is1, Cont, Lvs, [Margs,Mmeth,[Obj|Args]|Stk], Env, Cs, St1);
{error,_Error,St1} -> %No method
lua_error({undefined_method,Obj,Meth}, St1#luerl{stk=Stk,cs=Cs})
end.

%% do_tail_mcall(Instrs, Cont, LocalVars, Stack, Env, State, Method) ->
Expand All @@ -738,7 +749,8 @@ functioncall(#erl_func{code=Func}, Args, Stk, Cs, St) ->
call_erlfunc(Func, Args, Stk, Cs, St);
functioncall(Func, Args, Stk, Cs, St) ->
case luerl_heap:get_metamethod(Func, <<"__call">>, St) of
nil -> lua_error({undefined_function,Func}, St#luerl{stk=Stk,cs=Cs});
nil ->
lua_error({undefined_function,Func}, St#luerl{stk=Stk,cs=Cs});
Meta ->
functioncall(Meta, [Func|Args], Stk, Cs, St)
end.
Expand Down
19 changes: 11 additions & 8 deletions src/luerl_heap.erl
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,16 @@ alloc_table(St) -> alloc_table([], St).

%% alloc_table(InitialTable, State) -> {Tref,State}
%%
%% The InitialTable is [{Key,Value}], there is no longer any need
%% to have it as an orddict.
%% The InitialTable is [{Key,Value}] or map, there is no longer any
%% need to have it as an orddict.

alloc_table(Itab, #luerl{tabs=Tst0}=St) ->
Tab = create_table(Itab),
{N,Tst1} = alloc_tstruct(Tab, Tst0),
{#tref{i=N},St#luerl{tabs=Tst1}}.

create_table(Itab) when is_map(Itab) ->
create_table(maps:to_list(Itab));
create_table(Itab) ->
D0 = ttdict:new(),
A0 = array:new([{default,nil}]), %Arrays with 'nil' as default
Expand Down Expand Up @@ -267,14 +269,14 @@ get_table_key(#tref{}=Tref, Key, St) when is_float(Key) ->
end;
get_table_key(#tref{}=Tref, Key, St) ->
get_table_key_key(Tref, Key, St);
get_table_key(Tab, Key, St) -> %Just find the metamethod
Meta = get_metamethod(Tab, <<"__index">>, St),
io:format("gtk ~p ~p -> ~p\n", [Tab,Key,Meta]),
get_table_key(Other, Key, St) -> %Just find the metamethod
Meta = get_metamethod(Other, <<"__index">>, St),
%% io:format("gtk ~p ~p -> ~p\n", [Other,Key,Meta]),
case Meta of
nil ->
{error,{illegal_index,Tab,Key},St};
{error,{illegal_index,Other,Key},St};
Meth when ?IS_FUNCTION(Meth) ->
{meta,Meth,[Tab,Key],St};
{meta,Meth,[Other,Key],St};
Meth -> %Recurse down the metatable
get_table_key(Meth, Key, St)
end.
Expand Down Expand Up @@ -461,7 +463,8 @@ get_metamethod(O1, O2, E, St) ->
end.

get_metamethod(O, E, St) ->
Meta = get_metatable(O, St), %Can be nil
Meta = get_metatable(O, St), %Can be nil
%% io:format("gm ~p ~p -> ~p\n", [O,E,Meta]),
get_metamethod_tab(Meta, E, St#luerl.tabs#tstruct.data).

get_metamethod_tab(#tref{i=M}, E, Ts) ->
Expand Down

0 comments on commit 7789f30

Please sign in to comment.