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