From 62d2cf4984297870b620e2cdaa1b8cb92afd34e9 Mon Sep 17 00:00:00 2001 From: Ulf Wiger Date: Mon, 6 Jun 2011 14:49:43 +0200 Subject: [PATCH] added eunit example, fixed is_record bug --- examples/exprecs_eunit.erl | 33 +++++++++++++++++++++++++++++++++ src/exprecs.erl | 17 ++++++++--------- 2 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 examples/exprecs_eunit.erl diff --git a/examples/exprecs_eunit.erl b/examples/exprecs_eunit.erl new file mode 100644 index 0000000..c3c396a --- /dev/null +++ b/examples/exprecs_eunit.erl @@ -0,0 +1,33 @@ +-module(exprecs_eunit). +-include_lib("eunit/include/eunit.hrl"). + +-export([module_test/0]). + + +module_test() -> + M = test_exprecs, + RecNames = lists:concat( + [Rs || {export_records, Rs} <- M:module_info(attributes)]), + false = M:'#is_record-'([]), + false = M:'#is_record-'([], []), + [test_record(R, M) || R <- RecNames]. + +test_record(R, M) -> + Rec = M:'#new-'(R), + Fields = M:'#info-'(R), + FieldCount = length(Fields), + InfoF = list_to_existing_atom("#info-" ++ atom_to_list(R)), + ?assertEqual(FieldCount+1, M:InfoF(size)), + ?assertEqual(true, M:'#is_record-'(Rec)), + ?assertMatch({R,true}, {R, M:'#is_record-'(R, Rec)}), + NewF = list_to_existing_atom("#new-" ++ atom_to_list(R)), + L = lists:seq(1, FieldCount), + Vals = lists:zip(Fields, L), + Rec1 = M:NewF(Vals), + Rec1 = M:'#set-'(Vals, Rec), + Rec1 = M:'#fromlist-'(Vals, M:'#new-'(R)), + L = M:'#get-'(Fields, Rec1), + ?assertError(bad_record_op, M:'#get-'(17,Rec1)), + PosL = lists:seq(2, FieldCount + 1), + PosL = [M:'#pos-'(R, A) || A <- Fields], + ?assertEqual(0, M:'#pos-'(R, 17)). diff --git a/src/exprecs.erl b/src/exprecs.erl index 7900c6c..d23ba52 100755 --- a/src/exprecs.erl +++ b/src/exprecs.erl @@ -21,23 +21,23 @@ %% File : exprecs.erl %% @author : Ulf Wiger %% @end -%% Description : +%% Description : %% %% Created : 13 Feb 2006 by Ulf Wiger %% Rewritten: Jan-Feb 2010 by Ulf Wiger %%------------------------------------------------------------------- %% @doc Parse transform for generating record access functions. -%%

This parse transform can be used to reduce compile-time +%%

This parse transform can be used to reduce compile-time %% dependencies in large systems.

%%

In the old days, before records, Erlang programmers often wrote %% access functions for tuple data. This was tedious and error-prone. %% The record syntax made this easier, but since records were implemented -%% fully in the pre-processor, a nasty compile-time dependency was +%% fully in the pre-processor, a nasty compile-time dependency was %% introduced.

-%%

This module automates the generation of access functions for -%% records. While this method cannot fully replace the utility of -%% pattern matching, it does allow a fair bit of functionality on +%%

This module automates the generation of access functions for +%% records. While this method cannot fully replace the utility of +%% pattern matching, it does allow a fair bit of functionality on %% records without the need for compile-time dependencies.

%%

Whenever record definitions need to be exported from a module, %% inserting a compiler attribute, @@ -144,7 +144,6 @@ -define(ERROR(R, F, I), begin rpt_error(R, F, I), - throw({error,get_pos(I),{unknown,R}}) end). @@ -515,7 +514,7 @@ f_info(_Acc, L) -> f_isrec_2(Acc, L) -> Fname = list_to_atom(fname_prefix(isrec)), - Info = [{R,length(As)} || {R,As} <- Acc#pass1.records], + Info = [{R,length(As) + 1} || {R,As} <- Acc#pass1.records], {function, L, Fname, 2, lists:map( fun({R, Ln}) -> @@ -575,7 +574,7 @@ f_isrec_1(Acc, L) -> [{var, L, 'X'}], [], [{'if',L, - [{clause, L, [], [[{call, L, {atom,L,is_record}, + [{clause, L, [], [[{call, L, {atom,L,is_record}, [{var,L,'X'},{atom,L,R}]}]], [{atom,L,true}]} || R <- Acc#pass1.exports] ++ [{clause,L, [], [[{atom,L,true}]],