diff --git a/src/luerl_emul.erl b/src/luerl_emul.erl index c1551d9..05a05d3 100644 --- a/src/luerl_emul.erl +++ b/src/luerl_emul.erl @@ -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} -> @@ -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} -> @@ -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) -> @@ -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. diff --git a/src/luerl_heap.erl b/src/luerl_heap.erl index 12ef456..8cd4f16 100644 --- a/src/luerl_heap.erl +++ b/src/luerl_heap.erl @@ -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 @@ -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. @@ -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) ->