%%% -*- erlang-indent-level: 2 -*- %%%------------------------------------------------------------------- %%% Author: Kostis Sagonas %%% %%% Tests for correct translation of various BEAM instructions. %%%------------------------------------------------------------------- -module(basic_beam_instrs). -export([test/0]). test() -> ok = test_make_fun(), ok = test_switch_val(), ok = test_put_literal(), ok = test_set_tuple_element(), ok = test_unguarded_unsafe_element(), ok. %%-------------------------------------------------------------------- %% Tests whether the translation of make_fun works. test_make_fun() -> {F, G} = double_the_fun(), ok = F(), {ok, 42} = G(42), FV1 = {ok, free_var1}, FV2 = {also, {free, var2}}, {FV1, {ok, [bv]}, FV2} = contains_fun(FV1, ignored, FV2), ok. double_the_fun() -> {fun () -> ok end, fun (V) -> {ok, V} end}. contains_fun(X, _IGNORED_ARG, Y) -> calls_fun(fun(Term) -> {X, Term, Y} end). calls_fun(F) -> F({ok, [bv]}). %%-------------------------------------------------------------------- %% Tests whether the translation of switch_val works. test_switch_val() -> 'A' = sv(a), 'B' = sv(b), 'C' = sv(c), foo = sv(d), ok. sv(a) -> 'A'; sv(b) -> 'B'; sv(c) -> 'C'; sv(_) -> foo. %%-------------------------------------------------------------------- %% Tests correct handling of literals (statically constant terms) -define(QUADRUPLE, {a,b,c,42}). -define(DEEP_LIST, [42,[42,[42]]]). test_put_literal() -> ?QUADRUPLE = mk_literal_quadruple(), ?DEEP_LIST = mk_literal_deep_list(), ok. mk_literal_quadruple() -> ?QUADRUPLE. mk_literal_deep_list() -> ?DEEP_LIST. %%-------------------------------------------------------------------- %% Tests whether the translation of set_tuple_element works. -record(rec, {f1, f2, f3, f4, f5}). test_set_tuple_element() -> F2 = [a,b,c], F4 = {a,b}, State0 = init_rec(F2, F4), State1 = simple_set(State0, 42), #rec{f1 = foo, f2 = F2, f3 = 42, f4 = F4, f5 = 42.0} = odd_set(State1, 21), ok. init_rec(F2, F4) -> #rec{f1 = bar, f2 = F2, f3 = 10, f4 = F4, f5 = 3.14}. simple_set(State, Val) -> %% f3 = Val is the one used in set_element; State#rec{f3 = Val, f5 = Val*2}. %% this checks the case of variable odd_set(State, Val) -> %% f3 = foo is the one used in set_element; State#rec{f1 = foo, f5 = Val*2.0}. %% this checks the case of constant %%-------------------------------------------------------------------- %% Tests the handling of unguarded unsafe_element operations that BEAM %% can sometimes construct on records (when it has enough context). test_unguarded_unsafe_element() -> {badrecord, rec} = try unguarded_unsafe_element(42) catch error:E -> E end, ok. unguarded_unsafe_element(X) -> X#rec{f1 = X#rec.f3}.