Age | Commit message (Collapse) | Author |
|
See also ERL-32 at bugs.erlang.org. Thanks to Ben Paxton.
|
|
Prior to this patch, the following code would not eval:
X = key,
(fun(#{X := value}) -> true end)(#{X => value})
That's because the key evaluation was using the new
list of bindings introduced on every anonymous fun.
Since keys only match on values defined prior to the
pattern and do not introduce any new binding, we must
use the full and original list of binding.
|
|
|
|
|
|
According to EEP-43 for maps, a 'badmap' exception should be
generated when an attempt is made to update non-map term such as:
<<>>#{a=>42}
That was not implemented in the OTP 17.
José Valim suggested that we should take the opportunity to
improve the errors coming from map operations:
http://erlang.org/pipermail/erlang-questions/2015-February/083588.html
This commit implement better errors from map operations similar
to his suggestion.
When a map update operation (Map#{...}) or a BIF that expects a map
is given a non-map term, the exception will be:
{badmap,Term}
This kind of exception is similar to the {badfun,Term} exception
from operations that expect a fun.
When a map operation requires a key that is not present in a map,
the following exception will be raised:
{badkey,Key}
José Valim suggested that the exception should be
{badkey,Key,Map}. We decided not to do that because the map
could potentially be huge and cause problems if the error
propagated through links to other processes.
For BIFs, it could be argued that the exceptions could be simply
'badmap' and 'badkey', because the bad map and bad key can be found in
the argument list for the BIF in the stack backtrace. However, for the
map update operation (Map#{...}), the bad map or bad key will not be
included in the stack backtrace, so that information must be included
in the exception reason itself. For consistency, the BIFs should raise
the same exceptions as update operation.
If more than one key is missing, it is undefined which of
keys that will be reported in the {badkey,Key} exception.
|
|
* egil/maps/variable-keys/OTP-12218: (22 commits)
compiler: Update test for Maps aliasing
compiler: Properly support Map aliasing
compiler: Refactor Map pairs aliasing
compiler: Fix harmless need_heap error for Maps
stdlib: Update Map tests
stdlib: Use environment bindings for Maps keys in erl_eval matching
debugger: Update Map tests
compiler: Update Map tests
compiler: Fix v3_core Maps pair chains
compiler: Use expressions in core patterns
compiler: Use variables in Map cerl inliner
compiler: Reintroduce binary limit for Map keys
compiler: Shameless v3_core hack for variables
compiler: Use variables in Map beam assmebler
compiler: Use variables in Map kernel pass
compiler: Use variables in Map core pass
compiler: Normalize unary ops on Maps key literals
stdlib: Update Map tests
stdlib: erl_lint Map key variables
compiler: Maps are always patterns never values in matching
...
|
|
|
|
* mururu/fix-typo:
Fix typo in erl_eval:exprs comments
|
|
|
|
Reported-by: José Valim
|
|
Reported-by: José Valim
|
|
|
|
* josevalim/jv-eval-guards/OTP-11747:
Fix erl_eval bug when erlang:'=='/2 is used in guards
|
|
Map fields (K := V, K => V) are not expressions and shouldn't be clauses of
erl_eval:expr/5.
|
|
Name conforms to EEP.
|
|
|
|
|
|
Prior to this commit, erl_eval did not properly evaluate
erlang:'=='/2 and friends in guard clauses because it
always flattened it to a local call ==/2. This commit
removes the flattening logic while still normalizing old
guards style.
|
|
The current code for the evaluation of ordinary funs is dependent
on the order on variables in the fun environment as returned by
erlang:fun_info(Fun, env).
To avoid the problem in the future, make sure that we only have one
free variable in the funs that we will need to inspect using
erlang:fun_info(Fun, env).
|
|
files as delimiters.
While working on a tool that processes Erlang code and testing it against this repo,
I found out about those little sneaky 0xff. I thought it may be of help to other
people build such tools to remove non-conforming-to-standard characters.
|
|
Using the low-level BEAM instructions, we can loop over each message in
the process queue and removes the first message that matches, without
receiving them all to later send them back to itself.
The function prim_eval:'receive'/2 is equivalent to the
following pseudo-code:
'receive'(F, T) ->
RESET MESSAGE QUEUE POINTER,
LOOP:
case PEEK CURRENT MESSAGE WITH TIMEOUT T of
{ok,Msg} ->
case F(Msg) of
nomatch ->
DECREMENT TIMEOUT T,
ADVANCE MESSAGE QUEUE POINTER,
GOTO LOOP;
Result ->
RESET MESSAGE QUEUE POINTER,
Result
end;
timeout ->
RESET MESSAGE QUEUE POINTER,
timeout
end.
To not break Dialyzer and other tools, we use a stub Erlang module which
abstract code is forcefully inserted into prim_inet.erl afterwards
compilation.
|
|
Tuples funs were removed in de7e01c958ff7c9e6da4034a53567a30a4ae5792,
but it was still possible to evaluate tuple funs in the shell.
|
|
|
|
|
|
|
|
|
|
Currently, the external fun syntax "fun M:F/A" only supports
literals. That is, "fun lists:reverse/1" is allowed but not
"fun M:F/A".
In many real-life situations, some or all of M, F, A are
not known until run-time, and one is forced to either use
the undocumented erlang:make_fun/3 BIF or to use a
"tuple fun" (which is deprecated).
EEP-23 suggests that the parser (erl_parse) should immediately
transform "fun M:F/A" to "erlang:make_fun(M, F, A)". We have
not followed that approach in this implementation, because we
want the abstract code to mirror the source code as closely
as possible, and we also consider erlang:make_fun/3 to
be an implementation detail that we might want to remove in
the future.
Instead, we will change the abstract format for "fun M:F/A" (in a way
that is not backwards compatible), and while we are at it, we will
move the translation from "fun M:F/A" to "erlang:make_fun(M, F, A)"
from sys_pre_expand down to the v3_core pass. We will also update
the debugger and xref to use the new format.
We did consider making the abstract format backward compatible if
no variables were used in the fun, but decided against it. Keeping
it backward compatible would mean that there would be different
abstract formats for the no-variable and variable case, and tools
would have to handle both formats, probably forever.
Reference: http://www.erlang.org/eeps/eep-0023.html
|
|
'eval_bits' is a common utility module used for evaluting binary
construction and matching. The functions that do matching
(match_bits/{6,7} and bin_gen/6) are supposed to treat the bindings as
an abstract data type, but they assume that the bindings have the same
representation as in the erl_eval module. That may cause binary
matching to fail in the debugger, because the debugger represents the
bindings as an unordered list of two-tuples, while the erl_eval
modules uses an ordered list of two-tuple (an ordset).
One way to fix the problem would be to let the debugger to use ordered
lists to represent the bindings. Unfortunately, that would also change
how the bindings are presented in the user interface. Currently, the
variable have most been recently assigned is shown first, which is
convenient.
Fix the matching problem by mending the leaky abstraction in
eval_bits. The matching functions needs to be passed two additional
operations: one for looking up a variable in the bindings and one for
adding a binding. Those operations could be passed as two more funs
(in addition to the evaluation and match fun already passed), but the
functions already have too many arguments. Therefore, change the
meaning of the match fun, so that the first argument is the operation
to perform ('match', 'binding', or 'add_binding') and second argument
is a tuple with arguments for the operation.
|
|
A specification that could cause problems for Dialyzer has been fixed.
An opaque type in erl_eval has been turned in to a ordinary type. This
is a temporary fix.
|
|
|
|
|