Skip to content

Commit

Permalink
error when the type of the function is not correct (different from or…
Browse files Browse the repository at this point in the history
…iginal PHP)
  • Loading branch information
manuel-rubio committed Jun 27, 2017
1 parent 4f40982 commit abe0298
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 10 deletions.
18 changes: 18 additions & 0 deletions src/ephp_class.erl
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,24 @@ instance(Ref, LocalCtx, GlobalCtx, RawClassName, Line) ->
{RawClassName}})
end.

-spec instance_of(mixed(), DataType::binary()) -> boolean().

instance_of(#ephp_array{}, <<"array">>) ->
true;
instance_of(Boolean, <<"boolean">>) when is_boolean(Boolean) ->
true;
instance_of(String, <<"string">>) when is_binary(String) ->
true;
instance_of(Float, <<"float">>) when is_float(Float) ->
true;
instance_of(Int, <<"integer">>) when is_integer(Int) ->
true;
% TODO:
% instance_of(Callable, <<"callable">>) ->
% false;
% TODO:
% instance_of(Self, <<"self">>) ->
% false;
instance_of(#reg_instance{class = #class{name = Name}}, Name) ->
true;
instance_of(#reg_instance{class = #class{extends = Extends,
Expand Down
7 changes: 4 additions & 3 deletions src/ephp_context.erl
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ resolve(#call{name = #function{args = RawFuncArgs, code = Code, use = Use},
global = Ref,
active_fun = ?FUNC_ANON_NAME,
active_fun_args = length(RawArgs)}),
ephp_vars:zip_args(Vars, NewVars, Args, FuncArgs, Line),
ephp_vars:zip_args(Vars, NewVars, Args, FuncArgs, ?FUNC_ANON_NAME, Line),
lists:foreach(fun
({#variable{} = K,V}) ->
ephp_vars:set(NewVars, K, V);
Expand Down Expand Up @@ -724,7 +724,7 @@ resolve(#call{type = normal, name = Fun, args = RawArgs, line = Index} = _Call,
active_fun = Fun,
active_class = <<>>,
active_fun_args = length(Args)}),
ephp_vars:zip_args(Vars, NewVars, Args, FuncArgs, Index),
ephp_vars:zip_args(Vars, NewVars, Args, FuncArgs, Fun, Index),
register_superglobals(GlobalRef, NewVars),
ephp_const:set(Const, <<"__FUNCTION__">>, Fun),
Refs = lists:map(fun
Expand Down Expand Up @@ -1041,7 +1041,8 @@ run_method(RegInstance, #call{args = RawArgs} = Call,
end,
case ClassMethod#class_method.code_type of
php ->
ephp_vars:zip_args(Vars, NewVars, Args, MethodArgs, Call#call.line),
ephp_vars:zip_args(Vars, NewVars, Args, MethodArgs, MethodName,
Call#call.line),
{ok, SubContext} = start_mirror(NState#state{
vars = NewVars,
global = Ref,
Expand Down
4 changes: 4 additions & 0 deletions src/ephp_error.erl
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ get_message(euncaught, {File, Line, Exception}) ->
get_message(enoobjectexception, {}) ->
io_lib:format("Can only throw objects", []);

get_message(errtype, {I, ReqType, GivenType, FuncName}) ->
io_lib:format("Argument ~p passed to ~s() must be an instance of ~s, "
"~s given, called", [I, FuncName, ReqType, GivenType]);

get_message(Unknown, Data) ->
io_lib:format("unknown ~p for ~p", [Unknown, Data]).

Expand Down
6 changes: 3 additions & 3 deletions src/ephp_parser_expr.erl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
]).

-import(ephp_parser_func, [
funct_args/3, st_use_or_block/3, funct_name/3
st_use_or_block/3, funct_name/3
]).

array_def_54_level({_,Row,Col}) -> {{array_def,54},Row,Col}.
Expand Down Expand Up @@ -204,8 +204,8 @@ expression(<<F:8,U:8,N:8,C:8,T:8,I:8,O:8,N:8,SP:8,Rest/binary>>,
(?IS_SPACE(SP) orelse ?IS_NEWLINE(SP) orelse SP =:= $() ->
{<<"(",Rest0/binary>>, Pos0} =
remove_spaces(<<SP:8,Rest/binary>>, add_pos(Pos, 9)),
{Rest1, Pos1, Args} = funct_args(Rest0, Pos0, []),
BaseFunction = add_line(#function{args=Args}, Pos),
{Rest1, Pos1, Args} = ephp_parser_func:funct_args(Rest0, Pos0, []),
BaseFunction = add_line(#function{args = Args}, Pos),
{Rest2, Pos2, Function} = st_use_or_block(Rest1, Pos1, BaseFunction),
expression(Rest2, copy_level(Pos, Pos2), add_op(Function, Parsed));
% INSTANCEOF
Expand Down
27 changes: 23 additions & 4 deletions src/ephp_vars.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
isset/2,
ref/4,
del/2,
zip_args/5,
zip_args/6,
destroy/1
]).

Expand Down Expand Up @@ -55,8 +55,8 @@ ref(Context, VarPath, VarsPID, RefVarPath) ->
del(Context, VarPath) ->
set(Context, VarPath, remove).

zip_args(VarsSrc, VarsDst, ValArgs, FuncArgs, Line) ->
lists:foldl(fun
zip_args(VarsSrc, VarsDst, ValArgs, FuncArgs, FunctName, Line) ->
Zip = fun
(#ref{var = VarRef}, [{#variable{} = VarName,_}|RestArgs]) ->
ref(VarsDst, VarRef, VarsSrc, VarName),
RestArgs;
Expand All @@ -70,7 +70,26 @@ zip_args(VarsSrc, VarsDst, ValArgs, FuncArgs, Line) ->
[];
(_FuncArg, []) ->
[]
end, ValArgs, FuncArgs),
end,
Check = fun
(_I, _Type, _Data, true) ->
ok;
(I, Type, Data, false) ->
ephp_error:error({error, errtype, Line, ?E_RECOVERABLE_ERROR,
{I, Type, ephp_data:gettype(Data), FunctName}})
end,
lists:foldl(fun
(#ref{var = #variable{data_type = DataType}} = Ref,
{I, [{_, Value}|_] = Acc}) when DataType =/= undefined ->
Check(I, DataType, Value, ephp_class:instance_of(Value, DataType)),
{I+1, Zip(Ref, Acc)};
(#variable{data_type = DataType} = Var,
{I, [{_, Value}|_] = Acc}) when DataType =/= undefined ->
Check(I, DataType, Value, ephp_class:instance_of(Value, DataType)),
{I+1, Zip(Var, Acc)};
(VarOrRef, {I, Acc}) ->
{I+1, Zip(VarOrRef, Acc)}
end, {1, ValArgs}, FuncArgs),
ok.

-spec destroy(ephp:vars_id()) -> ok.
Expand Down
6 changes: 6 additions & 0 deletions test/code/test_func_datatypes.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
1
2
3
4

Catchable fatal error: Argument 1 passed to data() must be an instance of array, string given, called in {{CWD}}/test/code/test_func_datatypes.php on line 10
10 changes: 10 additions & 0 deletions test/code/test_func_datatypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

function data(array $data, boolean $ok) {
foreach ($data as $i) {
print $i . "\n";
}
}

print data(array(1,2,3,4), true);
print data("5", "1");

0 comments on commit abe0298

Please sign in to comment.