Summary: Add support for Erlang records, including: - Parsing record definitions, storing info in environment - Record index expressions and patterns - Record creation expression, including initializers - Record update expressions and patterns - Record field access expressions - Pulse models The key idea is to translate records to tagged tuples (just as Erlang does under the hood), but this requires some bookkeeping to figure out which field maps to which tuple element. Reviewed By: rgrig Differential Revision: D29991819 fbshipit-source-id: a1c713b41master
parent
d48855913c
commit
5f140ed91b
@ -0,0 +1,272 @@
|
|||||||
|
% Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
%
|
||||||
|
% This source code is licensed under the MIT license found in the
|
||||||
|
% LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
-module(records).
|
||||||
|
|
||||||
|
-record(person, {name, phone, address}).
|
||||||
|
|
||||||
|
-export([
|
||||||
|
test_index2_Ok/0,
|
||||||
|
test_index2_Bad/0,
|
||||||
|
test_index3_Ok/0,
|
||||||
|
test_index3_Bad/0,
|
||||||
|
test_index4_Ok/0,
|
||||||
|
test_index4_Bad/0,
|
||||||
|
test_field2_Ok/0,
|
||||||
|
test_field2_Bad/0,
|
||||||
|
test_field3_Ok/0,
|
||||||
|
test_field3_Bad/0,
|
||||||
|
test_field4_Ok/0,
|
||||||
|
test_field4_Bad/0,
|
||||||
|
test_field_rearranged_Ok/0,
|
||||||
|
test_field_rearranged_Bad/0,
|
||||||
|
test_field_all_other1_Ok/0,
|
||||||
|
test_field_all_other1_Bad/0,
|
||||||
|
test_field_all_other2_Ok/0,
|
||||||
|
test_field_all_other2_Bad/0,
|
||||||
|
test_field_all_other3_Ok/0,
|
||||||
|
test_field_all_other3_Bad/0,
|
||||||
|
test_field_update1_Ok/0,
|
||||||
|
test_field_update1_Bad/0,
|
||||||
|
test_field_update2_Ok/0,
|
||||||
|
test_field_update2_Bad/0,
|
||||||
|
test_field_update3_Ok/0,
|
||||||
|
test_field_update3_Bad/0,
|
||||||
|
test_initializer1_Ok/0,
|
||||||
|
test_initializer1_Bad/0,
|
||||||
|
test_initializer2_Ok/0,
|
||||||
|
test_initializer2_Bad/0,
|
||||||
|
test_initializer_explicit_override_Ok/0,
|
||||||
|
test_initializer_explicit_override_Bad/0,
|
||||||
|
test_initializer_update_override_Ok/0,
|
||||||
|
test_initializer_update_override_Bad/0,
|
||||||
|
test_undefined_Ok/0,
|
||||||
|
test_undefined_Bad/0
|
||||||
|
]).
|
||||||
|
|
||||||
|
% Call this method with warn(1) to trigger a warning to expect
|
||||||
|
warn(0) -> ok.
|
||||||
|
|
||||||
|
test_index2_Ok() ->
|
||||||
|
case #person.name of
|
||||||
|
2 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_index2_Bad() ->
|
||||||
|
case #person.name of
|
||||||
|
2 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_index3_Ok() ->
|
||||||
|
case #person.phone of
|
||||||
|
3 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_index3_Bad() ->
|
||||||
|
case #person.phone of
|
||||||
|
3 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_index4_Ok() ->
|
||||||
|
case #person.address of
|
||||||
|
4 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_index4_Bad() ->
|
||||||
|
case #person.address of
|
||||||
|
4 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field2_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P#person.name of
|
||||||
|
123 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field2_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P#person.name of
|
||||||
|
123 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field3_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P#person.phone of
|
||||||
|
45 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field3_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P#person.phone of
|
||||||
|
45 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field4_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P#person.address of
|
||||||
|
6789 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field4_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P#person.address of
|
||||||
|
6789 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_rearranged_Ok() ->
|
||||||
|
% Fields are set in different order
|
||||||
|
P = #person{phone = 45, address = 6789, name = 123},
|
||||||
|
case P#person.name of
|
||||||
|
123 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_rearranged_Bad() ->
|
||||||
|
% Fields are set in different order
|
||||||
|
P = #person{phone = 45, address = 6789, name = 123},
|
||||||
|
case P#person.name of
|
||||||
|
123 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_all_other1_Ok() ->
|
||||||
|
P = #person{phone = 45, _ = 123},
|
||||||
|
case P#person.name of
|
||||||
|
123 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_all_other1_Bad() ->
|
||||||
|
P = #person{phone = 45, _ = 123},
|
||||||
|
case P#person.name of
|
||||||
|
123 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_all_other2_Ok() ->
|
||||||
|
P = #person{phone = 45, _ = 123},
|
||||||
|
case P#person.address of
|
||||||
|
123 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_all_other2_Bad() ->
|
||||||
|
P = #person{phone = 45, _ = 123},
|
||||||
|
case P#person.address of
|
||||||
|
123 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_all_other3_Ok() ->
|
||||||
|
P = #person{phone = 45, _ = 123},
|
||||||
|
case P#person.phone of
|
||||||
|
45 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_all_other3_Bad() ->
|
||||||
|
P = #person{phone = 45, _ = 123},
|
||||||
|
case P#person.phone of
|
||||||
|
45 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_update1_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
Q = P#person{phone = 0},
|
||||||
|
case Q#person.phone of
|
||||||
|
0 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_update1_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
Q = P#person{phone = 0},
|
||||||
|
case Q#person.phone of
|
||||||
|
0 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_update2_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
Q = P#person{phone = 0},
|
||||||
|
case Q#person.name of
|
||||||
|
123 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_update2_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
Q = P#person{phone = 0},
|
||||||
|
case Q#person.name of
|
||||||
|
123 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_update3_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
Q = P#person{phone = 0},
|
||||||
|
case Q#person.address of
|
||||||
|
6789 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_field_update3_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
Q = P#person{phone = 0},
|
||||||
|
case Q#person.address of
|
||||||
|
6789 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
-record(rabbit, {name = 123, color = 45}).
|
||||||
|
|
||||||
|
test_initializer1_Ok() ->
|
||||||
|
R = #rabbit{},
|
||||||
|
case R#rabbit.name of
|
||||||
|
123 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_initializer1_Bad() ->
|
||||||
|
R = #rabbit{},
|
||||||
|
case R#rabbit.name of
|
||||||
|
123 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_initializer2_Ok() ->
|
||||||
|
R = #rabbit{},
|
||||||
|
case R#rabbit.color of
|
||||||
|
45 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_initializer2_Bad() ->
|
||||||
|
R = #rabbit{},
|
||||||
|
case R#rabbit.color of
|
||||||
|
45 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_initializer_explicit_override_Ok() ->
|
||||||
|
R = #rabbit{name = 6789},
|
||||||
|
case R#rabbit.name of
|
||||||
|
6789 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_initializer_explicit_override_Bad() ->
|
||||||
|
R = #rabbit{name = 6789},
|
||||||
|
case R#rabbit.name of
|
||||||
|
6789 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_initializer_update_override_Ok() ->
|
||||||
|
R = #rabbit{name = 987, color = 65},
|
||||||
|
Q = R#rabbit{name = 4321},
|
||||||
|
case Q#rabbit.name of
|
||||||
|
4321 -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_initializer_update_override_Bad() ->
|
||||||
|
R = #rabbit{name = 987, color = 65},
|
||||||
|
Q = R#rabbit{name = 4321},
|
||||||
|
case Q#rabbit.name of
|
||||||
|
4321 -> warn(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_undefined_Ok() ->
|
||||||
|
P = #person{},
|
||||||
|
case P#person.name of
|
||||||
|
undefined -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_undefined_Bad() ->
|
||||||
|
P = #person{},
|
||||||
|
case P#person.name of
|
||||||
|
undefined -> warn(1)
|
||||||
|
end.
|
@ -0,0 +1,140 @@
|
|||||||
|
% Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
%
|
||||||
|
% This source code is licensed under the MIT license found in the
|
||||||
|
% LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
-module(records).
|
||||||
|
|
||||||
|
-record(person, {name, phone, address}).
|
||||||
|
-record(rabbit, {name, color}).
|
||||||
|
|
||||||
|
-export([
|
||||||
|
test_type_Ok/0,
|
||||||
|
test_type_Bad/0,
|
||||||
|
test_index1_Ok/0,
|
||||||
|
test_index2_Ok/0,
|
||||||
|
test_index3_Bad/0,
|
||||||
|
test_index4_Bad/0,
|
||||||
|
test_match_field2_Ok/0,
|
||||||
|
test_match_field2_Bad/0,
|
||||||
|
test_match_field3_Ok/0,
|
||||||
|
test_match_field3_Bad/0,
|
||||||
|
test_match_field4_Ok/0,
|
||||||
|
test_match_field4_Bad/0,
|
||||||
|
test_match_field_multiple1_Ok/0,
|
||||||
|
test_match_field_multiple2_Bad/0,
|
||||||
|
test_match_field_multiple3_Bad/0,
|
||||||
|
test_match_as_tuple1_Ok/0,
|
||||||
|
test_match_as_tuple2_Bad/0,
|
||||||
|
test_match_as_tuple3_Bad/0,
|
||||||
|
test_match_as_tuple4_Bad/0,
|
||||||
|
test_match_as_tuple5_Bad/0
|
||||||
|
]).
|
||||||
|
|
||||||
|
accepts_rabbits(#rabbit{}) -> ok.
|
||||||
|
|
||||||
|
test_type_Ok() ->
|
||||||
|
accepts_rabbits(#rabbit{name = "bunny", color = "brown"}).
|
||||||
|
|
||||||
|
test_type_Bad() ->
|
||||||
|
accepts_rabbits(#person{name = "alice", phone = 123, address = "LON"}).
|
||||||
|
|
||||||
|
accepts_three_using_rabbit(#rabbit.color) -> ok.
|
||||||
|
|
||||||
|
accepts_four_using_person(#person.address) -> ok.
|
||||||
|
|
||||||
|
test_index1_Ok() ->
|
||||||
|
accepts_three_using_rabbit(3).
|
||||||
|
|
||||||
|
test_index2_Ok() ->
|
||||||
|
accepts_four_using_person(4).
|
||||||
|
|
||||||
|
test_index3_Bad() ->
|
||||||
|
accepts_three_using_rabbit(2).
|
||||||
|
|
||||||
|
test_index4_Bad() ->
|
||||||
|
accepts_four_using_person(5).
|
||||||
|
|
||||||
|
test_match_field2_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
#person{name = 123} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_field2_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
#person{name = 9999999} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_field3_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
#person{phone = 45} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_field3_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
#person{phone = 9999999} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_field4_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
#person{address = 6789} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_field4_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
#person{address = 9999999} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_field_multiple1_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
#person{address = 6789, name = 123} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_field_multiple2_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
#person{address = 999999, name = 123} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_field_multiple3_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
#person{address = 6789, name = 99999} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_as_tuple1_Ok() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
{person, 123, 45, 6789} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_as_tuple2_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
{rabbit, 123, 45, 6789} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_as_tuple3_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
{person, 999999, 45, 6789} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_as_tuple4_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
{person, 123, 999999, 6789} -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
test_match_as_tuple5_Bad() ->
|
||||||
|
P = #person{name = 123, phone = 45, address = 6789},
|
||||||
|
case P of
|
||||||
|
{person, 123, 45, 999999} -> ok
|
||||||
|
end.
|
Loading…
Reference in new issue