[erl-frontend] Support unary minus and not expressions and patterns

Summary: Add support for *unary minus* and *logical not* in the Erlang translation, both as expression (e.g., `X = -Y`) and pattern (e.g., `case X of -3 -> ...`).

Reviewed By: rgrig

Differential Revision: D29582176

fbshipit-source-id: 17ef89496
master
Akos Hajdu 3 years ago committed by Facebook GitHub Bot
parent f0ab545594
commit 87626160aa

@ -280,6 +280,18 @@ let rec translate_pattern env (value : Ident.t) {Ast.line; simple_expression} :
let exit_failure = Node.make_if env false (Var id) in let exit_failure = Node.make_if env false (Var id) in
start |~~> [exit_success; exit_failure] ; start |~~> [exit_success; exit_failure] ;
{start; exit_success; exit_failure} {start; exit_success; exit_failure}
| UnaryOperator _ ->
(* Unary op pattern must evaluate to number, so just delegate to expression translation *)
let id = Ident.create_fresh Ident.knormal in
let expr_block =
translate_expression {env with result= Present (Exp.Var id)} {Ast.line; simple_expression}
in
let cond = Exp.BinOp (Eq, Var value, Var id) in
let start = Node.make_nop env in
let exit_success = Node.make_if env true cond in
let exit_failure = Node.make_if env false cond in
start |~~> [exit_success; exit_failure] ;
Block.all env [expr_block; {start; exit_success; exit_failure}]
| Variable vname when String.equal vname "_" -> | Variable vname when String.equal vname "_" ->
Block.make_success env Block.make_success env
| Variable vname -> | Variable vname ->
@ -298,7 +310,7 @@ let rec translate_pattern env (value : Ident.t) {Ast.line; simple_expression} :
Block.make_failure env Block.make_failure env
let rec translate_expression env {Ast.line; simple_expression} = and translate_expression env {Ast.line; simple_expression} =
let env = update_location line env in let env = update_location line env in
let any = ptr_typ_of_name Any in let any = ptr_typ_of_name Any in
let (Present result) = env.result in let (Present result) = env.result in
@ -432,6 +444,25 @@ let rec translate_expression env {Ast.line; simple_expression} =
let fun_exp = Exp.Const (Cfun BuiltinDecl.__erlang_make_nil) in let fun_exp = Exp.Const (Cfun BuiltinDecl.__erlang_make_nil) in
let instruction = Sil.Call ((ret_var, any), fun_exp, [], env.location, CallFlags.default) in let instruction = Sil.Call ((ret_var, any), fun_exp, [], env.location, CallFlags.default) in
Block.make_instruction env [instruction] Block.make_instruction env [instruction]
| UnaryOperator (op, e) ->
let id = Ident.create_fresh Ident.knormal in
let block = translate_expression {env with result= Present (Exp.Var id)} e in
let make_simple_op_block sil_op =
Block.make_load env ret_var (Exp.UnOp (sil_op, Var id, None)) any
in
let op_block =
match op with
| UMinus ->
make_simple_op_block Neg
| UNot ->
make_simple_op_block LNot
| todo ->
L.debug Capture Verbose
"@[todo ErlangTranslator.translate_expression(UnaryOperator) %s@."
(Sexp.to_string (Ast.sexp_of_unary_operator todo)) ;
Block.make_success env
in
Block.all env [block; op_block]
| Variable vname -> | Variable vname ->
let e = Exp.Lvar (Pvar.mk (Mangled.from_string vname) procname) in let e = Exp.Lvar (Pvar.mk (Mangled.from_string vname) procname) in
let load_instr = Sil.Load {id= ret_var; e; root_typ= any; typ= any; loc= env.location} in let load_instr = Sil.Load {id= ret_var; e; root_typ= any; typ= any; loc= env.location} in

@ -1,7 +1,13 @@
codetoanalyze/erlang/features/src/arithmetic.erl, test_add_Bad/0, -9, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] codetoanalyze/erlang/features/src/arithmetic.erl, test_add1_Bad/0, -9, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_idiv1_Bad/0, -54, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] codetoanalyze/erlang/features/src/arithmetic.erl, test_add2_Bad/0, -24, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_mul_Bad/0, -39, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] codetoanalyze/erlang/features/src/arithmetic.erl, test_idiv1_Bad/0, -114, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_multiple_Bad/0, -98, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] codetoanalyze/erlang/features/src/arithmetic.erl, test_mul1_Bad/0, -69, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_rem_Bad/0, -85, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] codetoanalyze/erlang/features/src/arithmetic.erl, test_mul2_Bad/0, -84, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_sub_Bad/0, -24, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] codetoanalyze/erlang/features/src/arithmetic.erl, test_mul3_Bad/0, -99, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_multiple_Bad/0, -158, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_rem_Bad/0, -145, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_sub1_Bad/0, -39, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_sub2_Bad/0, -54, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_uminus1_Bad/0, -170, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, test_uminus2_Bad/0, -183, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here]
codetoanalyze/erlang/features/src/arithmetic.erl, warn/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] codetoanalyze/erlang/features/src/arithmetic.erl, warn/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here]

@ -6,12 +6,20 @@
-module(arithmetic). -module(arithmetic).
-export([ -export([
test_add_Ok/0, test_add1_Ok/0,
test_add_Bad/0, test_add1_Bad/0,
test_sub_Ok/0, test_add2_Ok/0,
test_sub_Bad/0, test_add2_Bad/0,
test_mul_Ok/0, test_sub1_Ok/0,
test_mul_Bad/0, test_sub1_Bad/0,
test_sub2_Ok/0,
test_sub2_Bad/0,
test_mul1_Ok/0,
test_mul1_Bad/0,
test_mul2_Ok/0,
test_mul2_Bad/0,
test_mul3_Ok/0,
test_mul3_Bad/0,
test_idiv1_Ok/0, test_idiv1_Ok/0,
test_idiv1_Bad/0, test_idiv1_Bad/0,
test_idiv2_Ok/0, test_idiv2_Ok/0,
@ -19,20 +27,24 @@
test_rem_Ok/0, test_rem_Ok/0,
test_rem_Bad/0, test_rem_Bad/0,
test_multiple_Ok/0, test_multiple_Ok/0,
test_multiple_Bad/0 test_multiple_Bad/0,
test_uminus1_Ok/0,
test_uminus1_Bad/0,
test_uminus2_Ok/0,
test_uminus2_Bad/0
]). ]).
% Call this method with warn(1) to trigger a warning to expect % Call this method with warn(1) to trigger a warning to expect
warn(0) -> ok. warn(0) -> ok.
test_add_Ok() -> test_add1_Ok() ->
X = 2, X = 2,
Y = 3, Y = 3,
case X + Y of case X + Y of
5 -> ok; 5 -> ok;
_ -> warn(1) _ -> warn(1)
end. end.
test_add_Bad() -> test_add1_Bad() ->
X = 2, X = 2,
Y = 3, Y = 3,
case X + Y of case X + Y of
@ -40,14 +52,29 @@ test_add_Bad() ->
_ -> ok _ -> ok
end. end.
test_sub_Ok() -> test_add2_Ok() ->
X = 2,
Y = -3,
case X + Y of
-1 -> ok;
_ -> warn(1)
end.
test_add2_Bad() ->
X = 2,
Y = -3,
case X + Y of
-1 -> warn(1);
_ -> ok
end.
test_sub1_Ok() ->
X = 5, X = 5,
Y = 3, Y = 3,
case X - Y of case X - Y of
2 -> ok; 2 -> ok;
_ -> warn(1) _ -> warn(1)
end. end.
test_sub_Bad() -> test_sub1_Bad() ->
X = 5, X = 5,
Y = 3, Y = 3,
case X - Y of case X - Y of
@ -55,14 +82,29 @@ test_sub_Bad() ->
_ -> ok _ -> ok
end. end.
test_mul_Ok() -> test_sub2_Ok() ->
X = 3,
Y = 5,
case X - Y of
-2 -> ok;
_ -> warn(1)
end.
test_sub2_Bad() ->
X = 3,
Y = 5,
case X - Y of
-2 -> warn(1);
_ -> ok
end.
test_mul1_Ok() ->
X = 5, X = 5,
Y = 3, Y = 3,
case X * Y of case X * Y of
15 -> ok; 15 -> ok;
_ -> warn(1) _ -> warn(1)
end. end.
test_mul_Bad() -> test_mul1_Bad() ->
X = 5, X = 5,
Y = 3, Y = 3,
case X * Y of case X * Y of
@ -70,6 +112,36 @@ test_mul_Bad() ->
_ -> ok _ -> ok
end. end.
test_mul2_Ok() ->
X = -5,
Y = 3,
case X * Y of
-15 -> ok;
_ -> warn(1)
end.
test_mul2_Bad() ->
X = -5,
Y = 3,
case X * Y of
-15 -> warn(1);
_ -> ok
end.
test_mul3_Ok() ->
X = -5,
Y = -3,
case X * Y of
15 -> ok;
_ -> warn(1)
end.
test_mul3_Bad() ->
X = -5,
Y = -3,
case X * Y of
15 -> warn(1);
_ -> ok
end.
test_idiv1_Ok() -> test_idiv1_Ok() ->
X = 21, X = 21,
Y = 3, Y = 3,
@ -126,3 +198,29 @@ test_multiple_Bad() ->
30 -> warn(1); 30 -> warn(1);
_ -> ok _ -> ok
end. end.
test_uminus1_Ok() ->
X = -3,
case -X of
3 -> ok;
_ -> warn(1)
end.
test_uminus1_Bad() ->
X = -3,
case -X of
3 -> warn(1);
_ -> ok
end.
test_uminus2_Ok() ->
X = 5,
case -X of
-5 -> ok;
_ -> warn(1)
end.
test_uminus2_Bad() ->
X = 5,
case -X of
-5 -> warn(1);
_ -> ok
end.

Loading…
Cancel
Save